'use client' import { useState } from 'react' import { Settings2, ShieldCheck, Boxes, Lock, Loader2, CheckCircle2, Circle, AlertTriangle, Database, } from 'lucide-react' import { useFetch } from '@/hooks/use-fetch' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Switch } from '@/components/ui/switch' import { Skeleton } from '@/components/ui/skeleton' import { PageHeader } from '../primitives' import { cn } from '@/lib/utils' import { toast } from 'sonner' interface ModuleData { id: string version: string enabled: boolean installed: boolean } interface ModulesResponse { modules: ModuleData[] settings: Record } const MODULE_META: Record = { crm: { label: 'CRM', desc: 'Firmen, Personen, Deals, Pipeline, Mail-Sync.', phase: 'Phase 1' }, leads: { label: 'Leads Finder', desc: 'Evidenzbasierte Website-Audits + LLM-Erklärung.', phase: 'Phase 2' }, projects: { label: 'Projekte', desc: 'Aufgaben, Zeit, Budgets, Client-Portal.', phase: 'Phase 3' }, licenses: { label: 'Lizenzverwaltung', desc: 'Ausgestellte Lizenzen + Erneuerungsregister.', phase: 'Phase 4' }, contracts: { label: 'Verträge', desc: 'Werkvertrag, AVV (Art. 28 DSGVO), NDA, SLA mit E-Signatur.', phase: 'Phase 5' }, expenses: { label: 'Ausgaben', desc: 'Belastbare Posten, Wiederkehrendes, DATEV-Export.', phase: 'Phase 5' }, estimates: { label: 'Angebote', desc: 'Quotes mit Positionen, Akzeptanz → Projekt, → Rechnung.', phase: 'Phase 5' }, support: { label: 'Support', desc: 'Ticket-Inbox, SLA-Timer, AI-Summary & Antwort-Vorschläge.', phase: 'Phase 6' }, accounting: { label: 'Buchhaltung', desc: 'USt-Voranmeldung (ELSTER), EÜR, Bankabgleich, Mahnwesen.', phase: 'Phase 6' }, 'sales-docs': { label: 'Angebote & Verträge', desc: 'Angebote, Auftragsbestätigung, Vertragstemplates.', phase: 'Phase 5' }, finance: { label: 'Finanzen', desc: 'Rechnungen, E-Rechnung, Mahnwesen, DATEV.', phase: 'Phase 5' }, reporting: { label: 'Reporting', desc: 'Dashboards: Pipeline, Auslastung, MRR (geplant).', phase: 'Later' }, } const COMPLIANCE_ITEMS = [ { id: 'gobd', label: 'GoBD: Unveränderlichkeit & Hash-Kette', desc: 'Audit-Trigger, Storno statt Edit, Aufbewahrung 8/6 J.' }, { id: 'dsgvo', label: 'DSGVO: Konsens- & Verarbeitungsprotokoll', desc: 'Art. 6/7/14 je Kontakt, Export & Löschung.' }, { id: 'erechnung', label: 'E-Rechnung: ZUGFeRD / XRechnung', desc: 'EN 16931 validiert via @e-invoice-eu/core.' }, { id: 'uwg', label: 'UWG § 7: Cold-Outreach-Gate', desc: 'Kein Auto-Versand, Suppression-Liste.' }, { id: 'tdddg', label: 'TDDDG: Cookie-/Tracking-Einwilligung', desc: 'Kein Tracking im Portal/öffentlichen Formularen.' }, { id: 'bfsg', label: 'BFSG: Barrierefreiheit (WCAG 2.1 AA)', desc: 'Launch-Checklist für Kunden-Projekte.' }, { id: 'retention', label: 'Aufbewahrungsfristen (Finanz & CRM)', desc: 'Automatische Lösch-Jobs nach Frist.' }, { id: 'encryption', label: 'Verschlüsselung: Secrets AES-256-GCM', desc: 'ENCRYPTION_KEY separat vom DB-Backup.' }, ] export function SettingsView() { const { data, loading, refetch } = useFetch('/api/aos/modules') const [toggling, setToggling] = useState(null) const toggle = async (id: string, enabled: boolean) => { setToggling(id) const t = toast.loading(enabled ? 'Modul wird aktiviert…' : 'Modul wird deaktiviert…') try { const r = await fetch('/api/aos/modules', { method: 'PATCH', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id, enabled }), }) if (!r.ok) throw new Error('toggle failed') toast.success(enabled ? 'Modul aktiviert' : 'Modul deaktiviert', { id: t }) refetch() } catch { toast.error('Umschalten fehlgeschlagen', { id: t }) } finally { setToggling(null) } } if (loading || !data) { return (
) } const enabledCount = data.modules.filter((m) => m.enabled).length const installedCount = data.modules.filter((m) => m.installed).length return (

Installierte Module

{installedCount}

Aktiviert

{enabledCount}

Compliance-Bereiche

{COMPLIANCE_ITEMS.length}

AOS-Version

1.0.0-dev

{/* Modules */} Module {data.modules.map((m) => { const meta = MODULE_META[m.id] ?? { label: m.id, desc: '', phase: '' } const busy = toggling === m.id return (

{meta.label}

{meta.phase} v{m.version}
{meta.desc &&

{meta.desc}

}
{busy && } toggle(m.id, v)} disabled={busy || m.id === 'crm'} aria-label={`${meta.label} ${m.enabled ? 'deaktivieren' : 'aktivieren'}`} />
) })}
{/* Compliance checklist */} Compliance-Checkliste {COMPLIANCE_ITEMS.map((item) => (

{item.label}

{item.desc}

))}

CI blockiert Merges ohne Audit- & Aufbewahrungs-Metadaten.

{/* Agency settings preview */} Agentur-Stammdaten
Secrets (SMTP, API-Keys, Signier-Schlüssel) sind AES-256-GCM verschlüsselt. ENCRYPTION_KEY wird separat vom DB-Backup verwahrt.
) } function SettingRow({ label, value, mono }: { label: string; value?: string; mono?: boolean }) { return (

{label}

{value ?? '—'}

) }