'use client' import React, { useEffect, useState, useCallback, use } from 'react' import { useRouter } from 'next/navigation' import { ClassificationBadge } from '../../_components/ClassificationBadge' interface CRAProject { id: string name: string cra_classification: string | null conformity_path: string | null status: string } type PathId = 'self_assessment' | 'harmonized_standard' | 'eucc' | 'notified_body' interface PathOption { id: PathId modul: string title: string short: string details: string[] } const PATHS: PathOption[] = [ { id: 'self_assessment', modul: 'Modul A', title: 'Self-Assessment', short: 'Konformitaetsbewertung durch interne Pruefung', details: [ 'Hersteller fuehrt Konformitaetsbewertung selbst durch', 'Geringster externer Aufwand, schnelle Umsetzung', 'Default fuer Standard-Produkte', 'Technische Dokumentation + DoC bleibt Pflicht', ], }, { id: 'harmonized_standard', modul: 'Modul B', title: 'Harmonized Standard', short: 'Konformitaetsvermutung durch harmonisierte Norm', details: [ 'Anwendung einer harmonisierten EU-Norm (z.B. DIN EN 40000-1-2 Entwurf)', 'Konformitaetsvermutung gemaess EU-Recht', 'Geringeres Audit-Risiko', 'Empfohlen bei verfuegbarer harmonisierter Norm', ], }, { id: 'eucc', modul: 'Modul H', title: 'EUCC Zertifizierung', short: 'European Cybersecurity Certification Scheme', details: [ 'ENISA-EUCC-Zertifizierung (Common Criteria-basiert)', 'Hoechste Anerkennung in EU + Drittstaaten', 'Hoher Aufwand, ITSEF-Pruefung erforderlich', 'Pflicht bei einigen Important Class II-Produkten', ], }, { id: 'notified_body', modul: 'Modul C', title: 'Notified Body Assessment', short: 'Drittprueforganisation pruefn die Konformitaet', details: [ 'Externe Bewertung durch akkreditierte Stelle', 'PFLICHT fuer Critical-Produkte (Annex IV)', 'Hoechste Auditierbarkeit + Vertrauen', 'Laufzeit + Kosten am hoechsten', ], }, ] const ALLOWED: Record = { STANDARD: ['self_assessment', 'harmonized_standard', 'eucc', 'notified_body'], IMPORTANT_I: ['self_assessment', 'harmonized_standard', 'eucc', 'notified_body'], IMPORTANT_II: ['harmonized_standard', 'eucc', 'notified_body'], CRITICAL: ['notified_body'], } const DEFAULT_FOR: Record = { STANDARD: 'self_assessment', IMPORTANT_I: 'self_assessment', IMPORTANT_II: 'harmonized_standard', CRITICAL: 'notified_body', } export default function PathSelectPage({ params, }: { params: Promise<{ projectId: string }> }) { const { projectId } = use(params) const router = useRouter() const [project, setProject] = useState(null) const [selected, setSelected] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [error, setError] = useState('') const tenant = '00000000-0000-0000-0000-000000000001' const load = useCallback(async () => { try { const res = await fetch(`/api/sdk/v1/cra/projects/${projectId}`, { headers: { 'X-Tenant-ID': tenant }, }) if (!res.ok) throw new Error(await res.text()) const p: CRAProject = await res.json() setProject(p) if (p.conformity_path) { setSelected(p.conformity_path as PathId) } else if (p.cra_classification && DEFAULT_FOR[p.cra_classification]) { setSelected(DEFAULT_FOR[p.cra_classification]) } } catch (e) { setError(e instanceof Error ? e.message : 'Fehler beim Laden') } finally { setLoading(false) } }, [projectId]) useEffect(() => { load() }, [load]) const submit = async () => { if (!selected) return setSaving(true) setError('') try { const res = await fetch(`/api/sdk/v1/cra/projects/${projectId}/path-select`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Tenant-ID': tenant }, body: JSON.stringify({ conformity_path: selected }), }) if (!res.ok) throw new Error(await res.text()) router.push(`/sdk/cra/${projectId}`) } catch (e) { setError(e instanceof Error ? e.message : 'Speichern fehlgeschlagen') } finally { setSaving(false) } } if (loading) return

Laedt...

if (!project) return null if (!project.cra_classification) { return (

Bitte erst den Scope-Check ausfuehren. → Zum Scope-Check

) } const allowedPaths = ALLOWED[project.cra_classification] || [] return (
← Zurueck zum Projekt

Konformitaetspfad waehlen

Schritt 3 von 3 — basierend auf der Klassifikation siehst du die zulaessigen Pfade.

Klassifikation:
{error && (
{error}
)}
{PATHS.map(path => { const allowed = allowedPaths.includes(path.id) const isSelected = selected === path.id return ( ) })}
{selected ? ( <>Ausgewaehlt: {PATHS.find(p => p.id === selected)?.title} ) : ( 'Keine Auswahl getroffen' )}
) }