Extract components and hooks from 4 oversized pages (518–508 LOC each) to bring each page.tsx under 300 LOC (hard cap 500). Zero behavior changes. - dsr/new: TypeSelector, SourceSelector → _components/; useNewDSRForm → _hooks/ - compliance-hub: QuickActions, StatsRow, DomainChart, MappingsAndFindings, RegulationsTable → _components/; useComplianceHub → _hooks/ - iace/[projectId]/monitoring: Badges, EventForm, ResolveModal, TimelineEvent → _components/; useMonitoring → _hooks/ - cookie-banner: BannerPreview, CategoryCard → _components/; useCookieBanner → _hooks/ Result: page.tsx LOC: dsr/new=259, compliance-hub=95, monitoring=157, cookie-banner=212 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
92 lines
4.1 KiB
TypeScript
92 lines
4.1 KiB
TypeScript
'use client'
|
|
|
|
import Link from 'next/link'
|
|
import { DashboardData, MappingsData, FindingsData } from '../_hooks/useComplianceHub'
|
|
|
|
export function MappingsAndFindings({
|
|
dashboard,
|
|
mappings,
|
|
findings,
|
|
}: {
|
|
dashboard: DashboardData | null
|
|
mappings: MappingsData | null
|
|
findings: FindingsData | null
|
|
}) {
|
|
return (
|
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
<div className="bg-white rounded-xl shadow-sm border p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-slate-900">Control-Mappings</h3>
|
|
<Link href="/sdk/controls" className="text-sm text-purple-600 hover:text-purple-700">
|
|
Alle anzeigen →
|
|
</Link>
|
|
</div>
|
|
<div className="flex items-center gap-6 mb-4">
|
|
<div>
|
|
<p className="text-4xl font-bold text-purple-600">{mappings?.total || 0}</p>
|
|
<p className="text-sm text-slate-500">Mappings gesamt</p>
|
|
</div>
|
|
<div className="flex-1 h-16 bg-slate-50 rounded-lg p-3">
|
|
<p className="text-xs text-slate-500 mb-1">Nach Verordnung</p>
|
|
<div className="flex gap-1 flex-wrap">
|
|
{mappings?.by_regulation && Object.entries(mappings.by_regulation).slice(0, 5).map(([reg, count]) => (
|
|
<span key={reg} className="px-2 py-0.5 bg-purple-100 text-purple-700 rounded text-xs">
|
|
{reg}: {count}
|
|
</span>
|
|
))}
|
|
{!mappings?.by_regulation && (
|
|
<span className="px-2 py-0.5 bg-slate-100 text-slate-500 rounded text-xs">Keine Mappings vorhanden</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<p className="text-sm text-slate-600">
|
|
Automatisch generierte Verknuepfungen zwischen {dashboard?.total_controls || 0} Controls
|
|
und {dashboard?.total_requirements || 0} Anforderungen aus {dashboard?.total_regulations || 0} Verordnungen.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="bg-white rounded-xl shadow-sm border p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h3 className="text-lg font-semibold text-slate-900">Audit Findings</h3>
|
|
<Link href="/sdk/audit-checklist" className="text-sm text-purple-600 hover:text-purple-700">
|
|
Audit Checkliste →
|
|
</Link>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-4 mb-4">
|
|
<div className="p-4 bg-red-50 border border-red-200 rounded-lg">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<div className="w-3 h-3 bg-red-500 rounded-full" />
|
|
<span className="text-sm font-medium text-red-800">Hauptabweichungen</span>
|
|
</div>
|
|
<p className="text-3xl font-bold text-red-600">{findings?.open_majors || 0}</p>
|
|
<p className="text-xs text-red-600">offen (blockiert Zertifizierung)</p>
|
|
</div>
|
|
<div className="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
|
<div className="flex items-center gap-2 mb-1">
|
|
<div className="w-3 h-3 bg-yellow-500 rounded-full" />
|
|
<span className="text-sm font-medium text-yellow-800">Nebenabweichungen</span>
|
|
</div>
|
|
<p className="text-3xl font-bold text-yellow-600">{findings?.open_minors || 0}</p>
|
|
<p className="text-xs text-yellow-600">offen (erfordert CAPA)</p>
|
|
</div>
|
|
</div>
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-500">
|
|
Gesamt: {findings?.total || 0} Findings ({findings?.major_count || 0} Major, {findings?.minor_count || 0} Minor, {findings?.ofi_count || 0} OFI)
|
|
</span>
|
|
{(findings?.open_majors || 0) === 0 ? (
|
|
<span className="px-2 py-1 bg-green-100 text-green-700 rounded-full text-xs font-medium">
|
|
Zertifizierung moeglich
|
|
</span>
|
|
) : (
|
|
<span className="px-2 py-1 bg-red-100 text-red-700 rounded-full text-xs font-medium">
|
|
Zertifizierung blockiert
|
|
</span>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|