opencrm/frontend/src/pages/Settings.tsx

445 lines
22 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Link } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import Card from '../components/ui/Card';
import { Settings as SettingsIcon, Code, Store, Clock, Calendar, UserCog, ChevronRight, Building2, FileType, Eye, Globe, Mail, Database, Shield, ShieldAlert, FileText, FileEdit, PackageCheck } from 'lucide-react';
export default function Settings() {
const { hasPermission, developerMode, setDeveloperMode } = useAuth();
const settingsCards = [
{
to: '/settings/users',
icon: UserCog,
title: 'Benutzer',
description: 'Verwalten Sie Benutzerkonten, Rollen und Berechtigungen.',
show: hasPermission('users:read'),
},
{
to: '/settings/platforms',
icon: Store,
title: 'Vertriebsplattformen',
description: 'Verwalten Sie die Plattformen, über die Verträge abgeschlossen werden.',
show: hasPermission('platforms:read'),
},
{
to: '/settings/cancellation-periods',
icon: Clock,
title: 'Kündigungsfristen',
description: 'Konfigurieren Sie die verfügbaren Kündigungsfristen für Verträge.',
show: hasPermission('platforms:read'),
},
{
to: '/settings/contract-durations',
icon: Calendar,
title: 'Vertragslaufzeiten',
description: 'Konfigurieren Sie die verfügbaren Laufzeiten für Verträge.',
show: hasPermission('platforms:read'),
},
{
to: '/settings/providers',
icon: Building2,
title: 'Anbieter & Tarife',
description: 'Verwalten Sie Anbieter und deren Tarife für Verträge.',
show: hasPermission('providers:read') || hasPermission('platforms:read'),
},
{
to: '/settings/contract-categories',
icon: FileType,
title: 'Vertragstypen',
description: 'Konfigurieren Sie die verfügbaren Vertragstypen (Strom, Gas, Mobilfunk, etc.).',
show: hasPermission('platforms:read'),
},
];
return (
<div>
<div className="flex items-center gap-3 mb-6">
<SettingsIcon className="w-6 h-6" />
<h1 className="text-2xl font-bold">Einstellungen</h1>
</div>
{/* Stammdaten-Konfiguration */}
<div className="mb-8">
<h2 className="text-lg font-semibold mb-4 text-gray-700">Stammdaten</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{settingsCards
.filter((card) => card.show)
.map((card) => (
<Link
key={card.to}
to={card.to}
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<card.icon className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
{card.title}
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">{card.description}</p>
</div>
</div>
</Link>
))}
</div>
</div>
{/* System-Einstellungen */}
{hasPermission('settings:update') && (
<div className="mb-8">
<h2 className="text-lg font-semibold mb-4 text-gray-700">System</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Link
to="/settings/portal"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Globe className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Kundenportal
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Konfigurieren Sie das Kundenportal und Support-Anfragen.</p>
</div>
</div>
</Link>
<Link
to="/settings/deadlines"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Clock className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Fristenschwellen
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Konfigurieren Sie die Farbkodierung für Vertragsfristen im Cockpit.</p>
</div>
</div>
</Link>
<Link
to="/settings/pdf-templates"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileText className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Auftragsvorlagen
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">PDF-Vorlagen für Auftragsformulare hochladen und Felder zuordnen.</p>
</div>
</div>
</Link>
<Link
to="/settings/email-providers"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Mail className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Email-Provisionierung
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Konfigurieren Sie die automatische E-Mail-Erstellung für Kunden-E-Mail-Adressen.</p>
</div>
</div>
</Link>
<Link
to="/settings/database-backup"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Database className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Datenbank & Zurücksetzen
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Backups erstellen, wiederherstellen oder auf Werkseinstellungen zurücksetzen.</p>
</div>
</div>
</Link>
<Link
to="/settings/factory-defaults"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<PackageCheck className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Factory-Defaults
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Stammdaten-Kataloge (Anbieter, Tarife, PDF-Vorlagen) exportieren ohne Kundendaten.</p>
</div>
</div>
</Link>
{hasPermission('audit:read') && (
<Link
to="/settings/audit-logs"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileText className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Audit-Protokoll
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Protokollierte API-Zugriffe und Änderungen einsehen.</p>
{hasPermission('developer:access') && (
<p className="text-xs text-purple-500 mt-1 flex items-center gap-1">
<Code className="w-3 h-3" />
Sichtbar durch Entwicklerzugriff
</p>
)}
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/email-logs"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Mail className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
E-Mail-Versandlog
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Alle gesendeten E-Mails mit SMTP-Details und Status einsehen.</p>
</div>
</div>
</Link>
)}
{hasPermission('settings:read') && (
<Link
to="/settings/monitoring"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-orange-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-orange-50 rounded-lg group-hover:bg-orange-100 transition-colors">
<ShieldAlert className="w-6 h-6 text-orange-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-orange-600 transition-colors flex items-center gap-2">
Sicherheits-Monitoring
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">
Login-Fehlversuche, IDOR-Abwehr, SSRF-Blocks etc. + Alert-E-Mail-Adresse konfigurieren.
</p>
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/gdpr"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Shield className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
DSGVO-Dashboard
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Löschanfragen, Datenexporte und Einwilligungen verwalten.</p>
{hasPermission('developer:access') && (
<p className="text-xs text-purple-500 mt-1 flex items-center gap-1">
<Code className="w-3 h-3" />
Sichtbar durch Entwicklerzugriff
</p>
)}
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/privacy-policy"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileEdit className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Datenschutzerklärung
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Datenschutzerklärung bearbeiten mit Platzhaltern für Kundendaten.</p>
{hasPermission('developer:access') && (
<p className="text-xs text-purple-500 mt-1 flex items-center gap-1">
<Code className="w-3 h-3" />
Sichtbar durch Entwicklerzugriff
</p>
)}
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/authorization-template"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileEdit className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Vollmacht-Vorlage
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Vollmacht-Vorlage für Vertreterregelungen bearbeiten.</p>
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/imprint"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileEdit className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Impressum
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Impressum für das Kundenportal bearbeiten.</p>
</div>
</div>
</Link>
)}
{hasPermission('gdpr:admin') && (
<Link
to="/settings/website-privacy-policy"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<FileEdit className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Website-Datenschutzerklärung
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Datenschutzerklärung für das Kundenportal bearbeiten.</p>
</div>
</div>
</Link>
)}
</div>
</div>
)}
{/* Persönliche Einstellungen */}
<div className="mb-8">
<h2 className="text-lg font-semibold mb-4 text-gray-700">Persönlich</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<Link
to="/settings/view"
className="block p-4 bg-white border border-gray-200 rounded-lg shadow-sm hover:shadow-md hover:border-blue-300 transition-all group"
>
<div className="flex items-start gap-4">
<div className="p-2 bg-blue-50 rounded-lg group-hover:bg-blue-100 transition-colors">
<Eye className="w-6 h-6 text-blue-600" />
</div>
<div className="flex-1">
<h3 className="font-semibold text-gray-900 group-hover:text-blue-600 transition-colors flex items-center gap-2">
Ansicht
<ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-100 transition-opacity" />
</h3>
<p className="text-sm text-gray-500 mt-1">Passen Sie die Darstellung der Anwendung an.</p>
</div>
</div>
</Link>
</div>
</div>
{hasPermission('developer:access') && (
<Card title="Entwickleroptionen" className="mb-6">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
<Code className="w-5 h-5 text-gray-500" />
<div>
<p className="font-medium">Entwicklermodus</p>
<p className="text-sm text-gray-500">
Aktiviert erweiterte Funktionen wie direkten Datenbankzugriff
</p>
</div>
</div>
<label className="relative inline-flex items-center cursor-pointer">
<input
type="checkbox"
checked={developerMode}
onChange={(e) => setDeveloperMode(e.target.checked)}
className="sr-only peer"
/>
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-blue-600"></div>
</label>
</div>
{developerMode && (
<div className="mt-4 p-3 bg-yellow-50 border border-yellow-200 rounded-lg">
<p className="text-sm text-yellow-800">
<strong>Warnung:</strong> Der Entwicklermodus ermöglicht direkten Zugriff auf die Datenbank.
Unsachgemäße Änderungen können zu Datenverlust oder Inkonsistenzen führen.
</p>
</div>
)}
</Card>
)}
<Card title="Über">
<dl className="space-y-3">
<div>
<dt className="text-sm text-gray-500">Version</dt>
<dd>1.0.0</dd>
</div>
<div>
<dt className="text-sm text-gray-500">System</dt>
<dd>OpenCRM</dd>
</div>
</dl>
</Card>
</div>
);
}