'use client' import React, { useState, useEffect } from 'react' import Link from 'next/link' import { useParams } from 'next/navigation' interface ProjectOverview { id: string machine_name: string machine_type: string manufacturer: string status: string completeness_pct: number created_at: string updated_at: string gates: Gate[] risk_summary: { critical: number high: number medium: number low: number total: number } component_count: number hazard_count: number mitigation_count: number } interface Gate { id: string name: string description: string passed: boolean | null required: boolean } const QUICK_ACTIONS = [ { href: '/components', label: 'Komponenten verwalten', icon: 'cube', description: 'SW/FW/AI/HMI Baum bearbeiten' }, { href: '/classification', label: 'Klassifikation pruefen', icon: 'tag', description: 'AI Act, MVO, CRA, NIS2' }, { href: '/hazards', label: 'Hazard Log oeffnen', icon: 'warning', description: 'Gefaehrdungen und Risiken' }, { href: '/mitigations', label: 'Massnahmen planen', icon: 'shield', description: 'Design, Schutz, Information' }, { href: '/verification', label: 'Verifikationsplan', icon: 'check', description: 'Nachweise zuordnen' }, { href: '/evidence', label: 'Nachweise hochladen', icon: 'document', description: 'Dokumente und Berichte' }, { href: '/tech-file', label: 'CE-Akte generieren', icon: 'folder', description: 'Technische Dokumentation' }, { href: '/monitoring', label: 'Monitoring', icon: 'activity', description: 'Post-Market Ueberwachung' }, ] function GateIndicator({ gate }: { gate: Gate }) { const color = gate.passed === true ? 'bg-green-500' : gate.passed === false ? 'bg-red-500' : 'bg-gray-300' const textColor = gate.passed === true ? 'text-green-700' : gate.passed === false ? 'text-red-700' : 'text-gray-500' return (
{gate.name}
{gate.description}
{gate.required && ( Pflicht )}
) } function RiskGauge({ label, value, max, color }: { label: string; value: number; max: number; color: string }) { const pct = max > 0 ? Math.round((value / max) * 100) : 0 return (
{value}
{label}
) } const STATUS_WORKFLOW = [ { key: 'draft', label: 'Entwurf' }, { key: 'in_progress', label: 'In Bearbeitung' }, { key: 'review', label: 'In Pruefung' }, { key: 'approved', label: 'Freigegeben' }, ] export default function ProjectOverviewPage() { const params = useParams() const projectId = params.projectId as string const [project, setProject] = useState(null) const [loading, setLoading] = useState(true) useEffect(() => { fetchProject() }, [projectId]) async function fetchProject() { try { const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}`) if (res.ok) { const json = await res.json() setProject(json) } } catch (err) { console.error('Failed to fetch project:', err) } finally { setLoading(false) } } if (loading) { return (
) } if (!project) { return (

Projekt nicht gefunden

Zurueck zur Uebersicht
) } const currentStatusIndex = STATUS_WORKFLOW.findIndex((s) => s.key === project.status) return (
{/* Header */}

{project.machine_name}

{project.machine_type} {project.manufacturer ? `-- ${project.manufacturer}` : ''}

{/* Status Workflow */}

Projektstatus

{STATUS_WORKFLOW.map((step, index) => (
{index < currentStatusIndex ? ( ) : index === currentStatusIndex ? (
) : (
)} {step.label}
{index < STATUS_WORKFLOW.length - 1 && (
)} ))}
{/* Machine Info */}

Maschineninformationen

Maschinenname
{project.machine_name}
Typ
{project.machine_type || '--'}
Hersteller
{project.manufacturer || '--'}
Vollstaendigkeit
{project.completeness_pct}%
{/* Risk Summary */}

Risikozusammenfassung

{project.component_count}
Komponenten
{project.hazard_count}
Gefaehrdungen
{project.mitigation_count}
Massnahmen
{/* Completeness Gates */}

Completeness Gates

{project.gates && project.gates.length > 0 ? ( project.gates.map((gate) => ) ) : (

Keine Gates definiert

)}
{/* Quick Actions */}

Schnellzugriff

{QUICK_ACTIONS.map((action) => (
{action.label}
{action.description}
))}
) }