'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 (
)
}
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}
))}
)
}