All 5 files reduced below 500 LOC (hard cap) by extracting sub-components: - training/page.tsx: 780→278 LOC — imports existing _components/, adds BlocksSection - control-provenance/page.tsx: 739→145 LOC — extracts provenance-data.ts, ProvenanceHelpers, LicenseMatrix, SourceRegistry - iace/[projectId]/verification/page.tsx: 673→164 LOC — extracts VerificationForm, CompleteModal, SuggestEvidenceModal, VerificationTable - training/learner/page.tsx: 560→216 LOC — extracts AssignmentsList, ContentView, QuizView, CertificatesView - ControlDetail.tsx: 878→311 LOC — adds ControlSourceCitation, ControlTraceability, ControlRegulatorySection, ControlSimilarControls, ControlReviewActions siblings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
'use client'
|
|
|
|
import type { TrainingAssignment } from '@/lib/sdk/training/types'
|
|
|
|
interface CertificatesViewProps {
|
|
certificates: TrainingAssignment[]
|
|
onDownloadPDF: (certId: string) => void
|
|
}
|
|
|
|
export function CertificatesView({ certificates, onDownloadPDF }: CertificatesViewProps) {
|
|
if (certificates.length === 0) {
|
|
return (
|
|
<div className="text-center py-12 text-gray-400">
|
|
Noch keine Zertifikate vorhanden. Schliessen Sie eine Schulung mit Quiz ab.
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
|
{certificates.map(cert => (
|
|
<div key={cert.id} className="bg-white border border-gray-200 rounded-lg p-5">
|
|
<div className="flex items-start justify-between mb-3">
|
|
<h3 className="font-semibold text-gray-900 text-sm">{cert.module_title}</h3>
|
|
<span className="text-xs bg-green-100 text-green-700 px-2 py-0.5 rounded-full">Bestanden</span>
|
|
</div>
|
|
<div className="text-xs text-gray-500 space-y-1">
|
|
<p>Mitarbeiter: {cert.user_name}</p>
|
|
<p>Abschluss: {cert.completed_at ? new Date(cert.completed_at).toLocaleDateString('de-DE') : '-'}</p>
|
|
{cert.quiz_score != null && <p>Ergebnis: {Math.round(cert.quiz_score)}%</p>}
|
|
<p className="font-mono text-[10px] text-gray-400">ID: {cert.certificate_id?.substring(0, 12)}</p>
|
|
</div>
|
|
{cert.certificate_id && (
|
|
<button
|
|
onClick={() => onDownloadPDF(cert.certificate_id!)}
|
|
className="mt-3 w-full px-3 py-1.5 bg-indigo-600 text-white text-sm rounded-lg hover:bg-indigo-700"
|
|
>
|
|
PDF herunterladen
|
|
</button>
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
}
|