feat: Normen-Referenzen in Hazards + Massnahmen + Normenrecherche-Tab

- Hazard Log: Top 2 relevante Normen pro Kategorie unter dem Kategorie-Badge
- Massnahmen: Normen-Referenzen aus measures_library inline anzeigen
- Navigation: Neuer Normenrecherche-Tab (zwischen Grenzen und Komponenten)
- Normenrecherche-Seite: SuggestedNorms + A/B/C Erklaerung

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-05-08 00:18:45 +02:00
parent 21c01d6405
commit 136dc4d553
4 changed files with 95 additions and 1 deletions
@@ -80,6 +80,25 @@ export function RiskAssessmentTable({ projectId, hazards, onReassess, decisions,
const [mitCounts, setMitCounts] = useState<Record<string, number>>({})
const [edits, setEdits] = useState<Record<string, EditState>>({})
const [saving, setSaving] = useState<string | null>(null)
const [normsByCategory, setNormsByCategory] = useState<Record<string, string[]>>({})
// Fetch norms library and build category→norm-numbers map
useEffect(() => {
fetch(`/api/sdk/v1/iace/norms-library`)
.then(r => r.ok ? r.json() : null)
.then(json => {
if (!json?.norms) return
const map: Record<string, string[]> = {}
for (const n of json.norms) {
for (const cat of (n.hazard_cats || [])) {
if (!map[cat]) map[cat] = []
if (map[cat].length < 3) map[cat].push(n.number)
}
}
setNormsByCategory(map)
})
.catch(() => {})
}, [])
// Fetch mitigation counts per hazard
useEffect(() => {
@@ -226,6 +245,11 @@ export function RiskAssessmentTable({ projectId, hazards, onReassess, decisions,
<span className="inline-block px-1.5 py-0.5 rounded bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 text-[10px] font-medium">
{CATEGORY_LABELS[h.category] || h.category}
</span>
{normsByCategory[h.category]?.length > 0 && (
<div className="text-[9px] text-blue-500 mt-0.5 truncate" title={normsByCategory[h.category].join(', ')}>
{normsByCategory[h.category].slice(0, 2).join(', ')}
</div>
)}
</td>
{/* Initial S/E/P/RPZ/Risk */}
<td className="px-2 py-2 text-center text-gray-700 dark:text-gray-300">{initS}</td>