'use client' import React, { useState, useMemo, useCallback } from 'react' import { useParams } from 'next/navigation' import { HazardForm } from './_components/HazardForm' import { HazardTable } from './_components/HazardTable' import { RiskAssessmentTable } from './_components/RiskAssessmentTable' import { ResidualRiskPanel, getResidualStatus } from './_components/ResidualRiskPanel' import type { ResidualFilter } from './_components/ResidualRiskPanel' import { LibraryModal } from './_components/LibraryModal' import { AutoSuggestPanel } from './_components/AutoSuggestPanel' import { CustomHazardModal } from './_components/CustomHazardModal' import { useHazards } from './_hooks/useHazards' type ViewMode = 'list' | 'risk' export default function HazardsPage() { const params = useParams() const projectId = params.projectId as string const h = useHazards(projectId) const [view, setView] = useState('risk') const [showCustomModal, setShowCustomModal] = useState(false) const [residualFilter, setResidualFilter] = useState('all') const [decisions, setDecisions] = useState>({}) const handleDecision = useCallback(async (hazardId: string, acceptable: boolean | null) => { setDecisions(prev => ({ ...prev, [hazardId]: acceptable })) if (acceptable !== null) { try { await fetch(`/api/sdk/v1/iace/projects/${projectId}/hazards/${hazardId}/reassess`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ hazard_id: hazardId, is_acceptable: acceptable }), }) } catch (err) { console.error('Decision save failed:', err) } } }, [projectId]) const filteredHazards = useMemo(() => { if (residualFilter === 'all') return h.hazards return h.hazards.filter(hz => { const status = getResidualStatus(hz, decisions[hz.id] ?? null) return status === residualFilter }) }, [h.hazards, decisions, residualFilter]) if (h.loading) { return (
) } return (

Hazard Log

Gefaehrdungsanalyse mit 4-Faktor-Risikobewertung (S x F x P x A).

{h.matchResult && h.matchResult.matched_patterns?.length > 0 && ( h.setMatchResult(null)} /> )} {h.matchResult && (!h.matchResult.matched_patterns || h.matchResult.matched_patterns.length === 0) && (

Keine Patterns erkannt. Fuegen Sie zuerst Komponenten aus der Bibliothek hinzu, damit die automatische Erkennung Gefaehrdungen ableiten kann.

)} {h.hazards.length > 0 && (
{[ { label: 'Gesamt', count: h.hazards.length, color: 'border-gray-200', textColor: 'text-gray-900 dark:text-white', labelColor: 'text-gray-500' }, { label: 'Nicht akzeptabel', count: h.hazards.filter(x => x.risk_level === 'not_acceptable').length, color: 'border-red-300', textColor: 'text-red-800', labelColor: 'text-red-800' }, { label: 'Sehr hoch/Kritisch', count: h.hazards.filter(x => x.risk_level === 'very_high' || x.risk_level === 'critical').length, color: 'border-red-200', textColor: 'text-red-600', labelColor: 'text-red-600' }, { label: 'Hoch', count: h.hazards.filter(x => x.risk_level === 'high').length, color: 'border-orange-200', textColor: 'text-orange-600', labelColor: 'text-orange-600' }, { label: 'Mittel', count: h.hazards.filter(x => x.risk_level === 'medium').length, color: 'border-yellow-200', textColor: 'text-yellow-600', labelColor: 'text-yellow-600' }, { label: 'Niedrig', count: h.hazards.filter(x => x.risk_level === 'low').length, color: 'border-green-200', textColor: 'text-green-600', labelColor: 'text-green-600' }, { label: 'Vernachlaessigbar', count: h.hazards.filter(x => x.risk_level === 'negligible').length, color: 'border-gray-200', textColor: 'text-gray-500', labelColor: 'text-gray-500' }, ].map(({ label, count, color, textColor, labelColor }) => (
{count}
{label}
))}
)} {h.showForm && ( h.setShowForm(false)} lifecyclePhases={h.lifecyclePhases} roles={h.roles} /> )} {h.showLibrary && ( h.setShowLibrary(false)} /> )} {showCustomModal && ( { await h.handleSubmit(data); setShowCustomModal(false) }} onClose={() => setShowCustomModal(false)} /> )} {h.hazards.length > 0 ? ( view === 'risk' ? ( <> ) : ( ) ) : ( !h.showForm && (

Kein Hazard Log vorhanden

Beginnen Sie mit der systematischen Erfassung von Gefaehrdungen. Nutzen Sie die Bibliothek, KI-Vorschlaege oder die automatische Erkennung als Ausgangspunkt.

) )}
) }