feat: IACE CE-Compliance Module — Normen, Risikobewertung, Production Lines
Major features: - 215 norms library with section references + Beuth URLs (A/B1/B2/C norms) - 173 hazard patterns with detail fields (scenario, trigger, harm, zone) - Deterministic pattern matching: Component × Lifecycle × Pattern cross-product - SIL/PL auto-calculation from S×E×P risk graph - Risk assessment table with editable S/E/P dropdowns - Production Line Dashboard with animated station flow (Running Dots) - IACE process flow + norms coverage on start page - Non-blocking cookie banner, ProcessFlow SSR fix - 104 Playwright E2E tests passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,17 +1,21 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { HazardForm } from './_components/HazardForm'
|
||||
import { HazardTable } from './_components/HazardTable'
|
||||
import { RiskAssessmentTable } from './_components/RiskAssessmentTable'
|
||||
import { LibraryModal } from './_components/LibraryModal'
|
||||
import { AutoSuggestPanel } from './_components/AutoSuggestPanel'
|
||||
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<ViewMode>('list')
|
||||
|
||||
if (h.loading) {
|
||||
return (
|
||||
@@ -29,6 +33,16 @@ export default function HazardsPage() {
|
||||
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||
Gefaehrdungsanalyse mit 4-Faktor-Risikobewertung (S x F x P x A).
|
||||
</p>
|
||||
<div className="mt-2 flex rounded-lg border border-gray-200 dark:border-gray-600 overflow-hidden text-xs">
|
||||
<button onClick={() => setView('list')}
|
||||
className={`px-3 py-1.5 font-medium transition-colors ${view === 'list' ? 'bg-purple-600 text-white' : 'bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-50'}`}>
|
||||
Hazard-Liste
|
||||
</button>
|
||||
<button onClick={() => setView('risk')}
|
||||
className={`px-3 py-1.5 font-medium transition-colors border-l border-gray-200 dark:border-gray-600 ${view === 'risk' ? 'bg-purple-600 text-white' : 'bg-white dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-gray-50'}`}>
|
||||
Risikobewertung
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button onClick={h.handlePatternMatching} disabled={h.matchingPatterns}
|
||||
@@ -70,12 +84,12 @@ export default function HazardsPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{h.matchResult && h.matchResult.matched_patterns.length > 0 && (
|
||||
{h.matchResult && h.matchResult.matched_patterns?.length > 0 && (
|
||||
<AutoSuggestPanel projectId={projectId} matchResult={h.matchResult} applying={h.applyingPatterns}
|
||||
onApply={h.handleApplyPatterns} onClose={() => h.setMatchResult(null)} />
|
||||
)}
|
||||
|
||||
{h.matchResult && h.matchResult.matched_patterns.length === 0 && (
|
||||
{h.matchResult && (!h.matchResult.matched_patterns || h.matchResult.matched_patterns.length === 0) && (
|
||||
<div className="bg-yellow-50 border border-yellow-200 rounded-xl p-4 flex items-start gap-3">
|
||||
<svg className="w-5 h-5 text-yellow-600 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
@@ -121,7 +135,11 @@ export default function HazardsPage() {
|
||||
)}
|
||||
|
||||
{h.hazards.length > 0 ? (
|
||||
<HazardTable hazards={h.hazards} lifecyclePhases={h.lifecyclePhases} onDelete={h.handleDelete} />
|
||||
view === 'risk' ? (
|
||||
<RiskAssessmentTable projectId={projectId} hazards={h.hazards} onReassess={h.refetch} />
|
||||
) : (
|
||||
<HazardTable hazards={h.hazards} lifecyclePhases={h.lifecyclePhases} onDelete={h.handleDelete} />
|
||||
)
|
||||
) : (
|
||||
!h.showForm && (
|
||||
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-12 text-center">
|
||||
|
||||
Reference in New Issue
Block a user