'use client' import { ConfidenceLevelBadge } from '../../evidence/components/anti-fake-badges' import type { TraceabilityMatrixData } from './types' import { DOMAIN_LABELS } from './types' interface TraceabilityTabProps { traceabilityMatrix: TraceabilityMatrixData | null traceabilityLoading: boolean traceabilityFilter: 'all' | 'covered' | 'uncovered' | 'fully_verified' setTraceabilityFilter: (f: 'all' | 'covered' | 'uncovered' | 'fully_verified') => void traceabilityDomainFilter: string setTraceabilityDomainFilter: (d: string) => void expandedControls: Set expandedEvidence: Set toggleControlExpanded: (id: string) => void toggleEvidenceExpanded: (id: string) => void } export function TraceabilityTab({ traceabilityMatrix, traceabilityLoading, traceabilityFilter, setTraceabilityFilter, traceabilityDomainFilter, setTraceabilityDomainFilter, expandedControls, expandedEvidence, toggleControlExpanded, toggleEvidenceExpanded, }: TraceabilityTabProps) { if (traceabilityLoading) { return (
Traceability Matrix wird geladen...
) } if (!traceabilityMatrix) { return (
Keine Daten verfuegbar. Stellen Sie sicher, dass Controls und Evidence vorhanden sind.
) } const summary = traceabilityMatrix.summary const totalControls = summary.total_controls || 0 const covered = summary.covered || 0 const fullyVerified = summary.fully_verified || 0 const uncovered = summary.uncovered || 0 const filteredControls = (traceabilityMatrix.controls || []).filter(ctrl => { if (traceabilityFilter === 'covered' && !ctrl.coverage.has_evidence) return false if (traceabilityFilter === 'uncovered' && ctrl.coverage.has_evidence) return false if (traceabilityFilter === 'fully_verified' && !ctrl.coverage.all_assertions_verified) return false if (traceabilityDomainFilter !== 'all' && ctrl.domain !== traceabilityDomainFilter) return false return true }) const domains = [...new Set(traceabilityMatrix.controls.map(c => c.domain))].sort() return (
{/* Summary Cards */}
{totalControls}
Total Controls
{covered}
Abgedeckt
{fullyVerified}
Vollst. verifiziert
{uncovered}
Unabgedeckt
{/* Filter Bar */}
{([ { key: 'all', label: 'Alle' }, { key: 'covered', label: 'Abgedeckt' }, { key: 'uncovered', label: 'Nicht abgedeckt' }, { key: 'fully_verified', label: 'Vollst. verifiziert' }, ] as const).map(f => ( ))}
{domains.map(d => ( ))}
{/* Controls List */}
{filteredControls.length === 0 ? (
Keine Controls fuer diesen Filter gefunden.
) : filteredControls.map(ctrl => { const isExpanded = expandedControls.has(ctrl.id) const coverageIcon = ctrl.coverage.all_assertions_verified ? { symbol: '\u2713', color: 'text-green-600 bg-green-50' } : ctrl.coverage.has_evidence ? { symbol: '\u25D0', color: 'text-yellow-600 bg-yellow-50' } : { symbol: '\u2717', color: 'text-red-600 bg-red-50' } return (
{/* Control Row */} {/* Expanded: Evidence list */} {isExpanded && (
{ctrl.evidence.length === 0 ? (
Kein Evidence verknuepft.
) : ctrl.evidence.map(ev => { const evExpanded = expandedEvidence.has(ev.id) return (
{/* Expanded: Assertions list */} {evExpanded && ev.assertions.length > 0 && (
{ev.assertions.map(a => ( ))}
Aussage Typ Konfidenz Status
{a.sentence_text} {a.assertion_type} = 0.8 ? 'text-green-600' : a.confidence >= 0.5 ? 'text-yellow-600' : 'text-red-600' }`}> {(a.confidence * 100).toFixed(0)}% {a.verified ? {'\u2713'} : {'\u2717'} }
)}
) })}
)}
) })}
) }