Extract components and hooks into _components/ and _hooks/ subdirectories to reduce each page.tsx to under 500 LOC (was 1545/1383/1316). Final line counts: evidence=213, process-tasks=304, hazards=157. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
89 lines
3.6 KiB
TypeScript
89 lines
3.6 KiB
TypeScript
'use client'
|
|
|
|
import type { EvidenceCheck, CoverageReport } from './EvidenceTypes'
|
|
|
|
export function ReportTab({
|
|
coverageReport,
|
|
checks,
|
|
displayEvidenceLength,
|
|
validCount,
|
|
expiredCount,
|
|
pendingCount,
|
|
}: {
|
|
coverageReport: CoverageReport | null
|
|
checks: EvidenceCheck[]
|
|
displayEvidenceLength: number
|
|
validCount: number
|
|
expiredCount: number
|
|
pendingCount: number
|
|
}) {
|
|
return (
|
|
<div className="bg-white rounded-xl shadow-sm border p-6">
|
|
<h3 className="text-lg font-semibold text-gray-900 mb-6">Evidence Coverage Report</h3>
|
|
|
|
{!coverageReport ? (
|
|
<div className="flex justify-center py-12">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600" />
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="mb-8">
|
|
<div className="flex items-center justify-between mb-2">
|
|
<span className="text-sm font-medium text-gray-700">Gesamt-Abdeckung</span>
|
|
<span className={`text-2xl font-bold ${
|
|
coverageReport.coverage_percent >= 80 ? 'text-green-600' :
|
|
coverageReport.coverage_percent >= 50 ? 'text-yellow-600' : 'text-red-600'
|
|
}`}>
|
|
{coverageReport.coverage_percent.toFixed(1)}%
|
|
</span>
|
|
</div>
|
|
<div className="h-4 bg-gray-200 rounded-full overflow-hidden">
|
|
<div
|
|
className={`h-full transition-all duration-500 ${
|
|
coverageReport.coverage_percent >= 80 ? 'bg-green-500' :
|
|
coverageReport.coverage_percent >= 50 ? 'bg-yellow-500' : 'bg-red-500'
|
|
}`}
|
|
style={{ width: `${coverageReport.coverage_percent}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
|
|
<div className="p-4 bg-gray-50 rounded-lg text-center">
|
|
<p className="text-3xl font-bold text-gray-900">{coverageReport.total_controls}</p>
|
|
<p className="text-sm text-gray-500">Controls gesamt</p>
|
|
</div>
|
|
<div className="p-4 bg-green-50 rounded-lg text-center">
|
|
<p className="text-3xl font-bold text-green-600">{coverageReport.controls_with_evidence}</p>
|
|
<p className="text-sm text-green-600">Mit Nachweis belegt</p>
|
|
</div>
|
|
<div className="p-4 bg-red-50 rounded-lg text-center">
|
|
<p className="text-3xl font-bold text-red-600">{coverageReport.controls_without_evidence}</p>
|
|
<p className="text-sm text-red-600">Ohne Nachweis</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t pt-6">
|
|
<h4 className="font-medium text-gray-900 mb-3">Automatische Checks</h4>
|
|
<div className="flex items-center gap-4 text-sm text-gray-600">
|
|
<span>{checks.length} Check-Definitionen</span>
|
|
<span>{checks.filter(c => c.is_active).length} aktiv</span>
|
|
<span>{checks.filter(c => c.last_run_at).length} mindestens 1x ausgefuehrt</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t pt-6 mt-6">
|
|
<h4 className="font-medium text-gray-900 mb-3">Nachweise</h4>
|
|
<div className="flex items-center gap-4 text-sm text-gray-600">
|
|
<span>{displayEvidenceLength} Nachweise gesamt</span>
|
|
<span className="text-green-600">{validCount} gueltig</span>
|
|
<span className="text-red-600">{expiredCount} abgelaufen</span>
|
|
<span className="text-yellow-600">{pendingCount} ausstehend</span>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|