'use client' import React, { useState } from 'react' interface ServiceInfo { name: string category: string provider: string country: string eu_adequate: boolean requires_consent: boolean legal_ref: string in_dse: boolean status: string } interface ScanFinding { code: string severity: string text: string correction: string doc_title: string } interface DiscoveredDocument { title: string url: string doc_type: string language: string word_count: number completeness_pct: number findings_count: number } interface ScanData { pages_scanned: number pages_list: string[] services: ServiceInfo[] findings: ScanFinding[] discovered_documents?: DiscoveredDocument[] ai_detected: boolean chatbot_detected: boolean chatbot_provider: string missing_pages: Record email_status: string } const STATUS_ICON: Record = { ok: { icon: '\u2713', color: 'text-green-600' }, undocumented: { icon: '\u2717', color: 'text-red-600' }, outdated: { icon: '~', color: 'text-yellow-600' }, } const SEV_STYLE: Record = { HIGH: { bg: 'bg-red-50 border-red-200', text: 'text-red-800', dot: 'bg-red-500' }, MEDIUM: { bg: 'bg-yellow-50 border-yellow-200', text: 'text-yellow-800', dot: 'bg-yellow-500' }, LOW: { bg: 'bg-blue-50 border-blue-200', text: 'text-blue-800', dot: 'bg-blue-500' }, CRITICAL: { bg: 'bg-red-100 border-red-300', text: 'text-red-900', dot: 'bg-red-700' }, } export function ScanResult({ data }: { data: ScanData }) { const [expandedCorrection, setExpandedCorrection] = useState(null) const [expandedDoc, setExpandedDoc] = useState(null) const undocCount = data.services.filter(s => s.status === 'undocumented').length const okCount = data.services.filter(s => s.status === 'ok').length const highCount = data.findings.filter(f => f.severity === 'HIGH' || f.severity === 'CRITICAL').length const docs = data.discovered_documents || [] // Group findings by doc_title const docFindings: Record = {} const generalFindings: ScanFinding[] = [] for (const f of data.findings) { if (f.doc_title) { if (!docFindings[f.doc_title]) docFindings[f.doc_title] = [] docFindings[f.doc_title].push(f) } else { generalFindings.push(f) } } return (
{/* Summary Bar */}

{data.pages_scanned}

Seiten

{okCount}

Dokumentiert

{undocCount}

Nicht in DSE

{docs.length}

Dokumente

{/* Scanned Pages */} {data.pages_list?.length > 0 && (
{data.pages_scanned} Seiten gescannt
    {data.pages_list.map((p, i) => { const isMissing = data.missing_pages[p] return (
  • {isMissing ? '\u2717' : '\u2713'} {p}
  • ) })}
)} {/* Services Table */} {data.services.length > 0 && (

Dienstleister (SOLL/IST)

{data.services.map((s, i) => { const st = STATUS_ICON[s.status] || STATUS_ICON.ok return ( ) })}
Status Dienst Land In DSE
{st.icon} {s.name} {s.provider} {s.country} {s.in_dse ? '\u2713' : Nein}
)} {/* === Document-Centric View === */} {docs.length > 0 && (

Rechtliche Dokumente ({docs.length})

{docs.map((doc, i) => { const isExpanded = expandedDoc === doc.title const findings = docFindings[doc.title] || [] const pct = doc.completeness_pct const barColor = pct >= 80 ? 'bg-green-500' : pct >= 50 ? 'bg-yellow-500' : 'bg-red-500' const statusLabel = pct >= 80 ? 'OK' : pct >= 50 ? 'Lueckenhaft' : 'Mangelhaft' const statusColor = pct >= 80 ? 'text-green-700 bg-green-50' : pct >= 50 ? 'text-yellow-700 bg-yellow-50' : 'text-red-700 bg-red-50' return (
{isExpanded && (
{findings.length > 0 ? ( findings.map((f, fi) => { const sev = SEV_STYLE[f.severity] || SEV_STYLE.MEDIUM return (
{f.text}
) }) ) : (

Alle Pflichtangaben vorhanden.

)} {doc.url && ( Dokument oeffnen )}
)}
) })}
)} {/* General Findings (not associated with a specific document) */} {generalFindings.length > 0 && (

Allgemeine Findings ({generalFindings.length})

{generalFindings.map((f, i) => { const sev = SEV_STYLE[f.severity] || SEV_STYLE.MEDIUM const corrKey = `gen-${i}` const isExp = expandedCorrection === corrKey return (
{f.severity}

{f.text}

{f.correction && (
{isExp && (
{f.correction}
)}
)}
) })}
)} {/* Email Status */} {data.email_status && (
E-Mail: {data.email_status === 'sent' ? 'Gesendet' : data.email_status}
)}
) }