'use client' import React, { useState, useEffect } from 'react' import { useSDK } from '@/lib/sdk' import { StepHeader } from '@/components/sdk/StepHeader' import { ExecutiveReport, RiskLevel, DeadlineSeverity, RISK_LEVEL_INFO, DEADLINE_SEVERITY_INFO, getScoreColor, getScoreBgColor, } from '@/lib/sdk/reporting/types' import { getExecutiveReport } from '@/lib/sdk/reporting/api' // ============================================================================= // TYPES // ============================================================================= type TabId = 'overview' | 'risks' | 'deadlines' | 'modules' | 'activity' interface Tab { id: TabId label: string } // ============================================================================= // HELPER COMPONENTS // ============================================================================= function TabNavigation({ tabs, activeTab, onTabChange, }: { tabs: Tab[] activeTab: TabId onTabChange: (tab: TabId) => void }) { return (
) } function ScoreCircle({ score }: { score: number }) { const circumference = 2 * Math.PI * 60 const strokeDashoffset = circumference - (score / 100) * circumference return (
= 80 ? '#22c55e' : score >= 60 ? '#eab308' : score >= 40 ? '#f97316' : '#ef4444'} strokeWidth="8" fill="none" strokeLinecap="round" strokeDasharray={circumference} strokeDashoffset={strokeDashoffset} className="transition-all duration-1000" />
{score}% Compliance
) } function StatCard({ label, value, color = 'gray', subtitle, }: { label: string value: number | string color?: 'gray' | 'blue' | 'yellow' | 'red' | 'green' | 'purple' | 'orange' subtitle?: string }) { const colorClasses: Record = { gray: 'border-gray-200 text-gray-900', blue: 'border-blue-200 text-blue-600', yellow: 'border-yellow-200 text-yellow-600', red: 'border-red-200 text-red-600', green: 'border-green-200 text-green-600', purple: 'border-purple-200 text-purple-600', orange: 'border-orange-200 text-orange-600', } return (
{label}
{value}
{subtitle &&
{subtitle}
}
) } function RiskBadge({ level }: { level: RiskLevel }) { const info = RISK_LEVEL_INFO[level] return ( {info.label} ) } function DeadlineBadge({ severity }: { severity: DeadlineSeverity }) { const info = DEADLINE_SEVERITY_INFO[severity] return ( {info.label} ) } // ============================================================================= // TAB CONTENTS // ============================================================================= function OverviewTab({ report }: { report: ExecutiveReport }) { return (
{/* Score + Key Metrics */}
Risikolevel:
= 80 ? 'green' : 'yellow'} subtitle={`${report.dsgvo.completionPercent}% vollstaendig`} /> 0 ? 'red' : 'green'} subtitle={report.dsgvo.overdueDSRs > 0 ? `${report.dsgvo.overdueDSRs} ueberfaellig` : 'Keine ueberfaelligen'} /> 0 ? 'red' : 'green'} subtitle={report.incidents.criticalIncidents > 0 ? `${report.incidents.criticalIncidents} kritisch` : 'Keine kritischen'} /> = 80 ? 'green' : 'yellow'} subtitle={`${report.academy.overdueCount} ueberfaellig`} />
{/* Deadlines Summary */} {report.upcomingDeadlines.length > 0 && (

Naechste Fristen

{report.upcomingDeadlines.slice(0, 5).map((dl, i) => (
{dl.description}
{dl.module} · {dl.type}
{dl.daysLeft <= 0 ? `${Math.abs(dl.daysLeft)} Tage ueberfaellig` : `${dl.daysLeft} Tage`}
))}
)}
) } function RisksTab({ report }: { report: ExecutiveReport }) { return (
{/* Overall Risk */}

Gesamt-Risikobewertung

5 ? 'orange' : 'gray'} /> 0 ? 'red' : 'green'} />
{/* Per-Module Risks */}

Risiken nach Modul

{report.riskOverview.moduleRisks.map((mr, i) => (
{mr.module}
{mr.score}% {mr.issues} Issues
))}
) } function DeadlinesTab({ report }: { report: ExecutiveReport }) { return (

Alle Fristen ({report.upcomingDeadlines.length})

{report.upcomingDeadlines.length === 0 ? (

Keine bevorstehenden Fristen.

) : (
{report.upcomingDeadlines.map((dl, i) => ( ))}
Status Modul Typ Beschreibung Faellig am Verbleibend
{dl.module} {dl.type} {dl.description} {new Date(dl.dueDate).toLocaleDateString('de-DE')} {dl.daysLeft <= 0 ? `${Math.abs(dl.daysLeft)}d ueberfaellig` : `${dl.daysLeft}d`}
)}
) } function ModulesTab({ report }: { report: ExecutiveReport }) { return (
{/* DSGVO Module */}

DSGVO-Compliance

= 80 ? 'green' : 'yellow'} />
{/* Vendors */}

Lieferanten-Compliance

0 ? 'yellow' : 'green'} /> 0 ? 'red' : 'green'} />
{/* Incidents */}

Datenschutzvorfaelle

0 ? 'orange' : 'green'} /> 0 ? 'red' : 'green'} /> 0 ? 'red' : 'green'} />
{/* Whistleblower */}

Hinweisgebersystem

0 ? 'yellow' : 'green'} /> 0 ? 'red' : 'green'} /> 0 ? 'red' : 'green'} />
{/* Academy */}

Compliance Academy

= 80 ? 'green' : 'yellow'} /> 0 ? 'red' : 'green'} />
) } function ActivityTab({ report }: { report: ExecutiveReport }) { return (

Letzte Aktivitaeten

{report.recentActivity.length === 0 ? (

Keine Aktivitaeten vorhanden.

) : (
{report.recentActivity.map((entry, i) => (
{entry.description}
{entry.module} · {entry.action} · {new Date(entry.timestamp).toLocaleString('de-DE')}
))}
)}
) } // ============================================================================= // MAIN COMPONENT // ============================================================================= export default function ReportingPage() { const { state } = useSDK() const [activeTab, setActiveTab] = useState('overview') const [report, setReport] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { let cancelled = false async function loadReport() { setLoading(true) setError(null) try { const data = await getExecutiveReport() if (!cancelled) setReport(data) } catch (err) { console.warn('Backend nicht erreichbar:', err) if (!cancelled) setError(err instanceof Error ? err.message : 'Verbindung zum Backend fehlgeschlagen') } finally { if (!cancelled) setLoading(false) } } loadReport() return () => { cancelled = true } }, []) const tabs: Tab[] = [ { id: 'overview', label: 'Uebersicht' }, { id: 'risks', label: 'Risiken' }, { id: 'deadlines', label: 'Fristen' }, { id: 'modules', label: 'Module' }, { id: 'activity', label: 'Aktivitaeten' }, ] return (
{loading ? (
Bericht wird generiert...
) : report ? ( <> {/* Generated timestamp */}
Generiert: {new Date(report.generatedAt).toLocaleString('de-DE')}
{activeTab === 'overview' && } {activeTab === 'risks' && } {activeTab === 'deadlines' && } {activeTab === 'modules' && } {activeTab === 'activity' && } ) : (

Bericht konnte nicht geladen werden.

{error &&

{error}

}
)}
) }