diff --git a/admin-v2/app/(admin)/architecture/page.tsx b/admin-v2/app/(admin)/architecture/page.tsx index f2b77e3..f93ec1f 100644 --- a/admin-v2/app/(admin)/architecture/page.tsx +++ b/admin-v2/app/(admin)/architecture/page.tsx @@ -30,7 +30,7 @@ export default function ArchitecturePage() { databases: ['PostgreSQL', 'Qdrant'] }} relatedPages={[ - { name: 'Compliance Hub', href: '/compliance/hub', description: 'Compliance-Module' }, + { name: 'Compliance Hub', href: '/sdk/compliance-hub', description: 'Compliance-Module' }, { name: 'AI Hub', href: '/ai', description: 'KI-Module' }, ]} /> diff --git a/admin-v2/app/(admin)/compliance/ai-act/page.tsx b/admin-v2/app/(admin)/compliance/ai-act/page.tsx deleted file mode 100644 index 96177bf..0000000 --- a/admin-v2/app/(admin)/compliance/ai-act/page.tsx +++ /dev/null @@ -1,831 +0,0 @@ -'use client' - -/** - * EU-AI-Act Risk Classification Page - * - * Self-assessment and documentation of AI risk categories according to EU AI Act. - * Provides module-by-module risk assessment, warning lines, and exportable documentation. - */ - -import { useState } from 'react' -import { PagePurpose } from '@/components/common/PagePurpose' - -// ============================================================================= -// TYPES -// ============================================================================= - -type RiskLevel = 'unacceptable' | 'high' | 'limited' | 'minimal' - -interface ModuleAssessment { - id: string - name: string - description: string - riskLevel: RiskLevel - justification: string - humanInLoop: boolean - transparencyMeasures: string[] - aiActArticle: string -} - -interface WarningLine { - id: string - title: string - description: string - wouldTrigger: RiskLevel - currentStatus: 'safe' | 'approaching' | 'violated' - recommendation: string -} - -// ============================================================================= -// DATA - Breakpilot Module Assessments -// ============================================================================= - -const MODULE_ASSESSMENTS: ModuleAssessment[] = [ - { - id: 'text-suggestions', - name: 'Textvorschlaege / Formulierhilfen', - description: 'KI-generierte Textvorschlaege fuer Gutachten und Feedback', - riskLevel: 'minimal', - justification: 'Reine Assistenzfunktion ohne Entscheidungswirkung. Lehrer editieren und finalisieren alle Texte.', - humanInLoop: true, - transparencyMeasures: ['KI-Label auf generierten Texten', 'Editierbare Vorschlaege'], - aiActArticle: 'Art. 69 (Freiwillige Verhaltenskodizes)', - }, - { - id: 'rag-sources', - name: 'RAG-basierte Quellenanzeige', - description: 'Retrieval Augmented Generation fuer Lehrplan- und Erwartungshorizont-Referenzen', - riskLevel: 'minimal', - justification: 'Zitierende Referenzfunktion. Zeigt nur offizielle Quellen an, trifft keine Entscheidungen.', - humanInLoop: true, - transparencyMeasures: ['Quellenangaben', 'Direkte Links zu Originaldokumenten'], - aiActArticle: 'Art. 69 (Freiwillige Verhaltenskodizes)', - }, - { - id: 'correction-suggestions', - name: 'Korrektur-Vorschlaege', - description: 'KI-Vorschlaege fuer Bewertungskriterien und Punktevergabe', - riskLevel: 'limited', - justification: 'Vorschlaege ohne bindende Wirkung. Lehrkraft behaelt vollstaendige Entscheidungshoheit.', - humanInLoop: true, - transparencyMeasures: [ - 'Klare Kennzeichnung als KI-Vorschlag', - 'Begruendung fuer jeden Vorschlag', - 'Einfache Ueberschreibung moeglich', - ], - aiActArticle: 'Art. 52 (Transparenzpflichten)', - }, - { - id: 'eh-matching', - name: 'Erwartungshorizont-Abgleich', - description: 'Automatischer Abgleich von Schuelerantworten mit Erwartungshorizonten', - riskLevel: 'limited', - justification: 'Empfehlung, keine Entscheidung. Zeigt Uebereinstimmungen auf, bewertet nicht eigenstaendig.', - humanInLoop: true, - transparencyMeasures: [ - 'Visualisierung der Matching-Logik', - 'Confidence-Score angezeigt', - 'Manuelle Korrektur jederzeit moeglich', - ], - aiActArticle: 'Art. 52 (Transparenzpflichten)', - }, - { - id: 'report-drafts', - name: 'Zeugnis-Textentwurf', - description: 'KI-generierte Entwuerfe fuer Zeugnistexte und Beurteilungen', - riskLevel: 'limited', - justification: 'Entwurf, der von der Lehrkraft finalisiert wird. Keine automatische Uebernahme.', - humanInLoop: true, - transparencyMeasures: [ - 'Entwurf-Wasserzeichen', - 'Pflicht zur manuellen Freigabe', - 'Vollstaendig editierbar', - ], - aiActArticle: 'Art. 52 (Transparenzpflichten)', - }, - { - id: 'edu-search', - name: 'Bildungssuche (edu-search)', - description: 'Semantische Suche in Lehrplaenen und Bildungsmaterialien', - riskLevel: 'minimal', - justification: 'Informationsretrieval ohne Bewertungsfunktion. Reine Suchfunktion.', - humanInLoop: true, - transparencyMeasures: ['Quellenangaben', 'Ranking-Transparenz'], - aiActArticle: 'Art. 69 (Freiwillige Verhaltenskodizes)', - }, -] - -// ============================================================================= -// DATA - Warning Lines (What we must never build) -// ============================================================================= - -const WARNING_LINES: WarningLine[] = [ - { - id: 'auto-grading', - title: 'Automatische Notenvergabe', - description: 'KI berechnet und vergibt Noten ohne menschliche Pruefung', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Noten immer als Vorschlag, nie als finale Entscheidung', - }, - { - id: 'student-classification', - title: 'Schuelerklassifikation', - description: 'Automatische Einteilung in Leistungsgruppen (leistungsstark/schwach)', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Keine automatische Kategorisierung von Schuelern implementieren', - }, - { - id: 'promotion-decisions', - title: 'Versetzungsentscheidungen', - description: 'Automatisierte Logik fuer Versetzung/Nichtversetzung', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Versetzungsentscheidungen ausschliesslich bei Lehrkraeften belassen', - }, - { - id: 'unreviewed-assessments', - title: 'Ungeprueft freigegebene Bewertungen', - description: 'KI-Bewertungen ohne menschliche Kontrolle an Schueler/Eltern', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Immer manuellen Freigabe-Schritt vor Veroeffentlichung', - }, - { - id: 'behavioral-profiling', - title: 'Verhaltensprofilierung', - description: 'Erstellung von Persoenlichkeits- oder Verhaltensprofilen von Schuelern', - wouldTrigger: 'unacceptable', - currentStatus: 'safe', - recommendation: 'Keine Verhaltensanalyse oder Profiling implementieren', - }, - { - id: 'algorithmic-optimization', - title: 'Algorithmische Schuloptimierung', - description: 'KI optimiert Schulentscheidungen (Klassenzuteilung, Ressourcen)', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Schulorganisatorische Entscheidungen bei Menschen belassen', - }, - { - id: 'auto-accept', - title: 'Auto-Accept Funktionen', - description: 'Ein-Klick-Uebernahme von KI-Vorschlaegen ohne Pruefung', - wouldTrigger: 'high', - currentStatus: 'safe', - recommendation: 'Immer bewusste Bestaetigungsschritte einbauen', - }, - { - id: 'emotion-detection', - title: 'Emotionserkennung', - description: 'Analyse von Emotionen oder psychischem Zustand von Schuelern', - wouldTrigger: 'unacceptable', - currentStatus: 'safe', - recommendation: 'Keine biometrische oder emotionale Analyse', - }, -] - -// ============================================================================= -// HELPER FUNCTIONS -// ============================================================================= - -const getRiskLevelInfo = (level: RiskLevel) => { - switch (level) { - case 'unacceptable': - return { - label: 'Unzulaessig', - color: 'bg-black text-white', - borderColor: 'border-black', - description: 'Verboten nach EU-AI-Act', - } - case 'high': - return { - label: 'Hoch', - color: 'bg-red-600 text-white', - borderColor: 'border-red-600', - description: 'Strenge Anforderungen, Konformitaetsbewertung', - } - case 'limited': - return { - label: 'Begrenzt', - color: 'bg-amber-500 text-white', - borderColor: 'border-amber-500', - description: 'Transparenzpflichten', - } - case 'minimal': - return { - label: 'Minimal', - color: 'bg-green-600 text-white', - borderColor: 'border-green-600', - description: 'Freiwillige Verhaltenskodizes', - } - } -} - -const getStatusInfo = (status: 'safe' | 'approaching' | 'violated') => { - switch (status) { - case 'safe': - return { label: 'Sicher', color: 'bg-green-100 text-green-700', icon: 'โœ“' } - case 'approaching': - return { label: 'Annaehernd', color: 'bg-amber-100 text-amber-700', icon: 'โš ' } - case 'violated': - return { label: 'Verletzt', color: 'bg-red-100 text-red-700', icon: 'โœ—' } - } -} - -// ============================================================================= -// COMPONENT -// ============================================================================= - -export default function AIActClassificationPage() { - const [activeTab, setActiveTab] = useState<'overview' | 'modules' | 'warnings' | 'documentation'>('overview') - const [expandedModule, setExpandedModule] = useState(null) - - // Calculate statistics - const stats = { - totalModules: MODULE_ASSESSMENTS.length, - minimalRisk: MODULE_ASSESSMENTS.filter((m) => m.riskLevel === 'minimal').length, - limitedRisk: MODULE_ASSESSMENTS.filter((m) => m.riskLevel === 'limited').length, - highRisk: MODULE_ASSESSMENTS.filter((m) => m.riskLevel === 'high').length, - humanInLoop: MODULE_ASSESSMENTS.filter((m) => m.humanInLoop).length, - warningsTotal: WARNING_LINES.length, - warningsSafe: WARNING_LINES.filter((w) => w.currentStatus === 'safe').length, - } - - const generateMemo = () => { - const date = new Date().toLocaleDateString('de-DE', { - year: 'numeric', - month: 'long', - day: 'numeric', - }) - - const memo = ` -================================================================================ -EU-AI-ACT RISIKOKLASSIFIZIERUNG - BREAKPILOT -================================================================================ -Erstellungsdatum: ${date} -Version: 1.0 -Verantwortlich: Breakpilot GmbH - --------------------------------------------------------------------------------- -1. ZUSAMMENFASSUNG --------------------------------------------------------------------------------- - -System: Breakpilot KI-Assistenzsystem fuer Bildung -Gesamtrisikokategorie: LIMITED RISK (Art. 52 EU-AI-Act) - -Begruendung: -- KI liefert ausschliesslich Vorschlaege und Entwuerfe -- Kein automatisiertes Entscheiden ueber Schueler -- Mensch-in-the-Loop ist technisch erzwungen -- Keine Schuelerklassifikation oder Profiling -- Alle paedagogischen Entscheidungen verbleiben bei Lehrkraeften - --------------------------------------------------------------------------------- -2. MODUL-BEWERTUNG --------------------------------------------------------------------------------- - -${MODULE_ASSESSMENTS.map( - (m) => ` -${m.name} - Risikostufe: ${getRiskLevelInfo(m.riskLevel).label.toUpperCase()} - Begruendung: ${m.justification} - Human-in-Loop: ${m.humanInLoop ? 'JA' : 'NEIN'} - AI-Act Artikel: ${m.aiActArticle} -` -).join('')} - --------------------------------------------------------------------------------- -3. TRANSPARENZMASSNAHMEN --------------------------------------------------------------------------------- - -Alle KI-generierten Inhalte sind: -- Klar als KI-Vorschlag gekennzeichnet -- Vollstaendig editierbar durch die Lehrkraft -- Mit Quellenangaben versehen (wo zutreffend) -- Erst nach manueller Freigabe wirksam - -Zusaetzliche UI-Hinweise: -- "Dieser Text wurde durch KI vorgeschlagen" -- "Endverantwortung liegt bei der Lehrkraft" -- Confidence-Scores wo relevant - --------------------------------------------------------------------------------- -4. HUMAN-IN-THE-LOOP GARANTIEN --------------------------------------------------------------------------------- - -Technisch erzwungene Massnahmen: -- Kein Auto-Accept fuer KI-Vorschlaege -- Kein 1-Click-Bewerten -- Pflicht-Bestaetigung vor Freigabe -- Audit-Trail aller Aenderungen - --------------------------------------------------------------------------------- -5. WARNLINIEN (NICHT IMPLEMENTIEREN) --------------------------------------------------------------------------------- - -${WARNING_LINES.map( - (w) => ` -[${getStatusInfo(w.currentStatus).icon}] ${w.title} - Wuerde ausloesen: ${getRiskLevelInfo(w.wouldTrigger).label} - Status: ${getStatusInfo(w.currentStatus).label} -` -).join('')} - --------------------------------------------------------------------------------- -6. RECHTLICHE EINORDNUNG --------------------------------------------------------------------------------- - -Breakpilot faellt NICHT unter die High-Risk Kategorie des EU-AI-Act, da: - -1. Keine automatisierten Entscheidungen ueber natuerliche Personen -2. Keine Bewertung von Schuelern ohne menschliche Kontrolle -3. Keine Zugangs- oder Selektionsentscheidungen -4. Reine Assistenzfunktion mit Human-in-the-Loop - -Die Transparenzpflichten nach Art. 52 werden durch entsprechende -UI-Kennzeichnungen und Nutzerinformationen erfuellt. - --------------------------------------------------------------------------------- -7. MANAGEMENT-STATEMENT --------------------------------------------------------------------------------- - -"Breakpilot ist ein KI-Assistenzsystem mit begrenztem Risiko gemaess EU-AI-Act. -Die KI trifft keine Entscheidungen, sondern unterstuetzt Lehrkraefte transparent -und nachvollziehbar. Alle paedagogischen und rechtlichen Entscheidungen -verbleiben beim Menschen." - -================================================================================ -Dieses Dokument dient der internen Compliance-Dokumentation und kann -Auditoren auf Anfrage vorgelegt werden. -================================================================================ -` - return memo - } - - const downloadMemo = () => { - const memo = generateMemo() - const blob = new Blob([memo], { type: 'text/plain;charset=utf-8' }) - const url = URL.createObjectURL(blob) - const a = document.createElement('a') - a.href = url - a.download = `breakpilot-ai-act-klassifizierung-${new Date().toISOString().split('T')[0]}.txt` - document.body.appendChild(a) - a.click() - document.body.removeChild(a) - URL.revokeObjectURL(url) - } - - const tabs = [ - { id: 'overview', name: 'Uebersicht', icon: '๐Ÿ“Š' }, - { id: 'modules', name: 'Module', icon: '๐Ÿงฉ' }, - { id: 'warnings', name: 'Warnlinien', icon: 'โš ๏ธ' }, - { id: 'documentation', name: 'Dokumentation', icon: '๐Ÿ“„' }, - ] - - return ( -
- {/* Header */} -
-
-
-
- ๐Ÿค– -
-
-

EU-AI-Act Klassifizierung

-

Risikoklassifizierung und Compliance-Dokumentation

-
-
-
-
- -
- {/* Page Purpose */} - - - {/* Stats Cards */} -
-
-
Module gesamt
-
{stats.totalModules}
-
-
-
Minimal Risk
-
{stats.minimalRisk}
-
-
-
Limited Risk
-
{stats.limitedRisk}
-
-
-
Human-in-Loop
-
{stats.humanInLoop}/{stats.totalModules}
-
-
- - {/* Classification Banner */} -
-
-
- โš–๏ธ -
-
-

Gesamtklassifizierung: LIMITED RISK

-

- Breakpilot ist ein KI-Assistenzsystem mit begrenztem Risiko gemaess EU-AI-Act (Art. 52). - Es gelten Transparenzpflichten, aber keine Konformitaetsbewertung. -

-
- - Art. 52 Transparenz - - - Human-in-the-Loop - - - Assistiv, nicht autonom - -
-
-
-
- - {/* Tabs */} -
- {tabs.map((tab) => ( - - ))} -
- - {/* Tab Content */} -
- {/* Overview Tab */} - {activeTab === 'overview' && ( -
- {/* Risk Level Pyramid */} -
-

EU-AI-Act Risikopyramide

-
- {/* Unacceptable */} -
-
- - Unzulaessig - -
-
-
- - 0 Module - Social Scoring, Manipulation verboten - -
-
- {/* High */} -
-
- - Hoch - -
-
-
- - 0 Module - Keine automatischen Entscheidungen - -
-
- {/* Limited */} -
-
- - Begrenzt - -
-
-
- - {stats.limitedRisk} Module - Transparenzpflichten - -
-
- {/* Minimal */} -
-
- - Minimal - -
-
-
- - {stats.minimalRisk} Module - Freiwillige Kodizes - -
-
-
-
- - {/* Key Arguments */} -
-

Kernargumente fuer Limited Risk

-
-
- โœ“ -
-
Assistiv, nicht autonom
-
KI liefert Vorschlaege, keine Entscheidungen
-
-
-
- โœ“ -
-
Human-in-the-Loop
-
Lehrkraft hat immer das letzte Wort
-
-
-
- โœ“ -
-
Keine Schuelerklassifikation
-
Keine Kategorisierung oder Profiling
-
-
-
- โœ“ -
-
Transparente Kennzeichnung
-
KI-Inhalte sind klar markiert
-
-
-
-
- - {/* Management Statement */} -
-
- ๐Ÿ’ฌ -
-

Management-Statement (Pitch-faehig)

-
- “Breakpilot ist ein KI-Assistenzsystem mit begrenztem Risiko gemaess EU-AI-Act. - Die KI trifft keine Entscheidungen, sondern unterstuetzt Lehrkraefte transparent und nachvollziehbar. - Alle paedagogischen und rechtlichen Entscheidungen verbleiben beim Menschen.” -
-
-
-
-
- )} - - {/* Modules Tab */} - {activeTab === 'modules' && ( -
-
- - - - - - - - - - - - {MODULE_ASSESSMENTS.map((module) => { - const riskInfo = getRiskLevelInfo(module.riskLevel) - const isExpanded = expandedModule === module.id - return ( - <> - - - - - - - - {isExpanded && ( - - - - )} - - ) - })} - -
ModulRisikostufeHuman-in-LoopAI-Act Artikel
-
{module.name}
-
{module.description}
-
- - {riskInfo.label} - - - {module.humanInLoop ? ( - โœ“ Ja - ) : ( - โœ— Nein - )} - {module.aiActArticle} - -
-
-
-
Begruendung
-
{module.justification}
-
-
-
- Transparenzmassnahmen -
-
    - {module.transparencyMeasures.map((measure, i) => ( -
  • {measure}
  • - ))} -
-
-
-
-
-
- )} - - {/* Warnings Tab */} - {activeTab === 'warnings' && ( -
-
-
- ๐Ÿšซ -
-

- Warnlinien: Was wir NIEMALS bauen duerfen -

-

- Diese Features wuerden Breakpilot in die High-Risk oder Unzulaessig-Kategorie verschieben. - Sie sind explizit von der Roadmap ausgeschlossen. -

-
-
-
- -
- {WARNING_LINES.map((warning) => { - const statusInfo = getStatusInfo(warning.currentStatus) - const riskInfo = getRiskLevelInfo(warning.wouldTrigger) - return ( -
-
-
-
- {statusInfo.icon} -
-
-

{warning.title}

-

{warning.description}

-
-
-
- Wuerde ausloesen: - - {riskInfo.label} - -
-
-
-
- Empfehlung: - {warning.recommendation} -
-
-
- ) - })} -
- - {/* Safe Zone Indicator */} -
-
-
- โœ“ -
-
-

- Alle Warnlinien eingehalten: {stats.warningsSafe}/{stats.warningsTotal} -

-

- Breakpilot befindet sich sicher im Limited/Minimal Risk Bereich des EU-AI-Act. -

-
-
-
-
- )} - - {/* Documentation Tab */} - {activeTab === 'documentation' && ( -
-
-
-
-

Klassifizierungs-Memo exportieren

-

- Generiert ein vollstaendiges Compliance-Dokument zur Vorlage bei Auditoren oder Investoren. -

-
- -
-
- - {/* Preview */} -
-

Vorschau

-
-                  {generateMemo()}
-                
-
- - {/* Human-in-the-Loop Documentation */} -
-

Human-in-the-Loop Nachweis

-
-
-

Technische Massnahmen

-
    -
  • โ€ข Kein Auto-Accept Button fuer KI-Vorschlaege
  • -
  • โ€ข Mindestens 2 Klicks fuer Uebernahme erforderlich
  • -
  • โ€ข Alle KI-Outputs sind editierbar
  • -
  • โ€ข Pflicht-Review vor Freigabe an Schueler/Eltern
  • -
  • โ€ข Audit-Trail dokumentiert alle menschlichen Eingriffe
  • -
-
-
-

UI-Kennzeichnungen

-
    -
  • โ€ข “KI-Vorschlag” Label auf allen generierten Inhalten
  • -
  • โ€ข “Endverantwortung liegt bei der Lehrkraft” Hinweis
  • -
  • โ€ข Confidence-Scores wo relevant
  • -
  • โ€ข Quellenangaben fuer RAG-basierte Inhalte
  • -
-
-
-
-
- )} -
-
-
- ) -} diff --git a/admin-v2/app/(admin)/compliance/audit-checklist/page.tsx b/admin-v2/app/(admin)/compliance/audit-checklist/page.tsx deleted file mode 100644 index 5e9cc87..0000000 --- a/admin-v2/app/(admin)/compliance/audit-checklist/page.tsx +++ /dev/null @@ -1,775 +0,0 @@ -'use client' - -/** - * Audit Checklist Page - 476+ Requirements Interactive Checklist - * - * Features: - * - Session management (create, start, complete) - * - Paginated checklist with search & filters - * - Sign-off workflow with digital signatures - * - Progress tracking with statistics - */ - -import { useState, useEffect } from 'react' -import { PagePurpose } from '@/components/common/PagePurpose' - -// Types -interface AuditSession { - id: string - name: string - auditor_name: string - auditor_email?: string - auditor_organization?: string - status: 'draft' | 'in_progress' | 'completed' | 'archived' - regulation_ids?: string[] - total_items: number - completed_items: number - compliant_count: number - non_compliant_count: number - completion_percentage: number - created_at: string - started_at?: string - completed_at?: string -} - -interface ChecklistItem { - requirement_id: string - regulation_code: string - article: string - paragraph?: string - title: string - description?: string - current_result: string - notes?: string - is_signed: boolean - signed_at?: string - signed_by?: string - evidence_count: number - controls_mapped: number - implementation_status: string - priority: number -} - -interface AuditStatistics { - total: number - compliant: number - compliant_with_notes: number - non_compliant: number - not_applicable: number - pending: number - completion_percentage: number -} - -// Haupt-/Nebenabweichungen aus ISMS -interface FindingsData { - major_count: number // Hauptabweichungen (blockiert Zertifizierung) - minor_count: number // Nebenabweichungen (erfordert CAPA) - ofi_count: number // Verbesserungspotenziale - total: number - open_majors: number // Offene Hauptabweichungen - open_minors: number // Offene Nebenabweichungen -} - -const RESULT_COLORS: Record = { - compliant: { bg: 'bg-green-100', text: 'text-green-700', label: 'Konform' }, - compliant_notes: { bg: 'bg-green-50', text: 'text-green-600', label: 'Konform (mit Anm.)' }, - non_compliant: { bg: 'bg-red-100', text: 'text-red-700', label: 'Nicht konform' }, - not_applicable: { bg: 'bg-slate-100', text: 'text-slate-600', label: 'N/A' }, - pending: { bg: 'bg-yellow-100', text: 'text-yellow-700', label: 'Ausstehend' }, -} - -export default function AuditChecklistPage() { - const [sessions, setSessions] = useState([]) - const [selectedSession, setSelectedSession] = useState(null) - const [checklist, setChecklist] = useState([]) - const [statistics, setStatistics] = useState(null) - const [loading, setLoading] = useState(true) - const [checklistLoading, setChecklistLoading] = useState(false) - const [error, setError] = useState(null) - const [findings, setFindings] = useState(null) - - // Filters - const [search, setSearch] = useState('') - const [statusFilter, setStatusFilter] = useState('') - const [regulationFilter, setRegulationFilter] = useState('') - const [page, setPage] = useState(1) - const [totalPages, setTotalPages] = useState(1) - - // Modal states - const [showCreateModal, setShowCreateModal] = useState(false) - const [showSignOffModal, setShowSignOffModal] = useState(false) - const [selectedItem, setSelectedItem] = useState(null) - - // New session form - const [newSession, setNewSession] = useState({ - name: '', - auditor_name: '', - auditor_email: '', - auditor_organization: '', - regulation_codes: [] as string[], - }) - - useEffect(() => { - loadSessions() - loadFindings() - }, []) - - const loadFindings = async () => { - try { - const res = await fetch('/api/admin/compliance/isms/findings/summary') - if (res.ok) { - const data = await res.json() - setFindings(data) - } - } catch (err) { - console.error('Failed to load findings:', err) - } - } - - useEffect(() => { - if (selectedSession) { - loadChecklist() - } - }, [selectedSession, page, statusFilter, regulationFilter, search]) - - const loadSessions = async () => { - setLoading(true) - try { - const res = await fetch('/api/admin/audit/sessions') - if (res.ok) { - const data = await res.json() - setSessions(data) - } - } catch (err) { - console.error('Failed to load sessions:', err) - setError('Sessions konnten nicht geladen werden') - } finally { - setLoading(false) - } - } - - const loadChecklist = async () => { - if (!selectedSession) return - setChecklistLoading(true) - try { - const params = new URLSearchParams({ - page: page.toString(), - page_size: '50', - }) - if (statusFilter) params.set('status_filter', statusFilter) - if (regulationFilter) params.set('regulation_filter', regulationFilter) - if (search) params.set('search', search) - - const res = await fetch(`/api/admin/compliance/audit/checklist/${selectedSession.id}?${params}`) - if (res.ok) { - const data = await res.json() - setChecklist(data.items || []) - setStatistics(data.statistics) - setTotalPages(data.pagination?.total_pages || 1) - } - } catch (err) { - console.error('Failed to load checklist:', err) - } finally { - setChecklistLoading(false) - } - } - - const createSession = async () => { - try { - const res = await fetch('/api/admin/audit/sessions', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(newSession), - }) - if (res.ok) { - const session = await res.json() - setSessions([session, ...sessions]) - setSelectedSession(session) - setShowCreateModal(false) - setNewSession({ - name: '', - auditor_name: '', - auditor_email: '', - auditor_organization: '', - regulation_codes: [], - }) - } - } catch (err) { - console.error('Failed to create session:', err) - } - } - - const startSession = async (sessionId: string) => { - try { - const res = await fetch(`/api/admin/audit/sessions/${sessionId}/start`, { - method: 'PUT', - }) - if (res.ok) { - loadSessions() - if (selectedSession?.id === sessionId) { - setSelectedSession({ ...selectedSession, status: 'in_progress' }) - } - } - } catch (err) { - console.error('Failed to start session:', err) - } - } - - const completeSession = async (sessionId: string) => { - try { - const res = await fetch(`/api/admin/audit/sessions/${sessionId}/complete`, { - method: 'PUT', - }) - if (res.ok) { - loadSessions() - if (selectedSession?.id === sessionId) { - setSelectedSession({ ...selectedSession, status: 'completed' }) - } - } - } catch (err) { - console.error('Failed to complete session:', err) - } - } - - const signOffItem = async (result: string, notes: string, sign: boolean) => { - if (!selectedSession || !selectedItem) return - try { - const res = await fetch( - `/api/admin/compliance/audit/checklist/${selectedSession.id}/items/${selectedItem.requirement_id}`, - { - method: 'PUT', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ result, notes, sign }), - } - ) - if (res.ok) { - loadChecklist() - loadSessions() - setShowSignOffModal(false) - setSelectedItem(null) - } - } catch (err) { - console.error('Failed to sign off:', err) - } - } - - const downloadPdf = async (sessionId: string) => { - window.open(`/api/admin/audit/sessions/${sessionId}/pdf`, '_blank') - } - - return ( -
- - - {error && ( -
-

{error}

-
- )} - - {/* Haupt-/Nebenabweichungen Uebersicht */} - {findings && ( -
-
-

Audit Findings (ISMS)

- 0 - ? 'bg-red-100 text-red-700' - : 'bg-green-100 text-green-700' - }`}> - {findings.open_majors > 0 ? 'Zertifizierung blockiert' : 'Zertifizierungsfaehig'} - -
-
-
-

{findings.major_count}

-

Hauptabweichungen

-

(MAJOR)

- {findings.open_majors > 0 && ( -

- {findings.open_majors} offen -

- )} -
-
-

{findings.minor_count}

-

Nebenabweichungen

-

(MINOR)

- {findings.open_minors > 0 && ( -

- {findings.open_minors} offen -

- )} -
-
-

{findings.ofi_count}

-

Verbesserungen

-

(OFI)

-
-
-

{findings.total}

-

Gesamt Findings

-
-
-
- - {findings.open_majors === 0 ? ( - - ) : ( - - )} - -

Zertifizierung

-

- {findings.open_majors === 0 ? 'Moeglich' : 'Blockiert'} -

-
-
-
-
-

- Hauptabweichung (MAJOR): Signifikante Abweichung von Anforderungen - blockiert Zertifizierung bis zur Behebung.{' '} - Nebenabweichung (MINOR): Kleinere Abweichung - erfordert CAPA (Corrective Action) innerhalb 90 Tagen. -

-
-
- )} - -
- {/* Sessions Sidebar */} -
-
-

Audit Sessions

- -
- - {loading ? ( -
-
-
- ) : sessions.length === 0 ? ( -
-

Keine Sessions vorhanden

- -
- ) : ( -
- {sessions.map((session) => ( -
setSelectedSession(session)} - className={`p-4 rounded-lg border cursor-pointer transition-colors ${ - selectedSession?.id === session.id - ? 'border-purple-500 bg-purple-50' - : 'border-slate-200 hover:border-slate-300' - }`} - > -
- - {session.status === 'completed' ? 'Abgeschlossen' : - session.status === 'in_progress' ? 'In Bearbeitung' : - session.status === 'archived' ? 'Archiviert' : 'Entwurf'} - - {session.completion_percentage.toFixed(0)}% -
-

{session.name}

-

{session.auditor_name}

-
-
-
-
- ))} -
- )} -
- - {/* Checklist Content */} -
- {!selectedSession ? ( -
- - - -

Waehlen Sie eine Session

-

Waehlen Sie eine Audit-Session aus der Liste oder erstellen Sie eine neue.

-
- ) : ( - <> - {/* Session Header */} -
-
-
-

{selectedSession.name}

-

{selectedSession.auditor_name} {selectedSession.auditor_organization && `- ${selectedSession.auditor_organization}`}

-
-
- {selectedSession.status === 'draft' && ( - - )} - {selectedSession.status === 'in_progress' && ( - - )} - {selectedSession.status === 'completed' && ( - - )} -
-
- - {/* Statistics */} - {statistics && ( -
-
-

{statistics.total}

-

Gesamt

-
-
-

{statistics.compliant + statistics.compliant_with_notes}

-

Konform

-
-
-

{statistics.non_compliant}

-

Nicht konform

-
-
-

{statistics.not_applicable}

-

N/A

-
-
-

{statistics.pending}

-

Ausstehend

-
-
-

{statistics.completion_percentage.toFixed(0)}%

-

Fortschritt

-
-
- )} -
- - {/* Filters */} -
- { setSearch(e.target.value); setPage(1) }} - placeholder="Suche..." - className="flex-1 px-4 py-2 border border-slate-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-purple-500" - /> - -
- - {/* Checklist Table */} -
- {checklistLoading ? ( -
-
-
- ) : checklist.length === 0 ? ( -
- Keine Eintraege gefunden -
- ) : ( - - - - - - - - - - - - - {checklist.map((item) => { - const resultConfig = RESULT_COLORS[item.current_result] || RESULT_COLORS.pending - return ( - - - - - - - - - ) - })} - -
RegulationArtikelTitelControlsStatusAktion
- {item.regulation_code} - - {item.article} - {item.paragraph && {item.paragraph}} - -

{item.title}

-
- 0 ? 'bg-green-100 text-green-700' : 'bg-slate-100 text-slate-500' - }`}> - {item.controls_mapped} - - - - {resultConfig.label} - - {item.is_signed && ( - - - - )} - - -
- )} - - {/* Pagination */} - {totalPages > 1 && ( -
- - - Seite {page} von {totalPages} - - -
- )} -
- - )} -
-
- - {/* Create Session Modal */} - {showCreateModal && ( -
-
-

Neue Audit Session

-
-
- - setNewSession({ ...newSession, name: e.target.value })} - className="w-full px-3 py-2 border rounded-lg" - placeholder="z.B. Q1 2026 DSGVO Audit" - /> -
-
- - setNewSession({ ...newSession, auditor_name: e.target.value })} - className="w-full px-3 py-2 border rounded-lg" - placeholder="Dr. Max Mustermann" - /> -
-
- - setNewSession({ ...newSession, auditor_organization: e.target.value })} - className="w-full px-3 py-2 border rounded-lg" - placeholder="TรœV Rheinland" - /> -
-
-
- - -
-
-
- )} - - {/* Sign Off Modal */} - {showSignOffModal && selectedItem && ( - { setShowSignOffModal(false); setSelectedItem(null) }} - onSignOff={signOffItem} - /> - )} -
- ) -} - -// Sign Off Modal Component -function SignOffModal({ - item, - onClose, - onSignOff, -}: { - item: ChecklistItem - onClose: () => void - onSignOff: (result: string, notes: string, sign: boolean) => void -}) { - const [result, setResult] = useState(item.current_result === 'pending' ? '' : item.current_result) - const [notes, setNotes] = useState(item.notes || '') - const [sign, setSign] = useState(false) - - return ( -
-
-

Anforderung bewerten

-

- {item.regulation_code} {item.article}: {item.title} -

- -
-
- -
- {[ - { value: 'compliant', label: 'Konform', color: 'green' }, - { value: 'compliant_notes', label: 'Konform (mit Anm.)', color: 'green' }, - { value: 'non_compliant', label: 'Nicht konform', color: 'red' }, - { value: 'not_applicable', label: 'Nicht anwendbar', color: 'slate' }, - ].map((opt) => ( - - ))} -
-
- -
- -