feat(iace-frontend): Risikobewertung tab with dual risk model + live formula
CI / detect-changes (push) Successful in 7s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 11s
CI / nodejs-build (push) Successful in 2m23s
CI / test-go (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / loc-budget (push) Successful in 14s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
CI / detect-changes (push) Successful in 7s
CI / branch-name (push) Has been skipped
CI / guardrail-integrity (push) Has been skipped
CI / secret-scan (push) Has been skipped
CI / sbom-scan (push) Has been skipped
CI / dep-audit (push) Has been skipped
CI / build-sha-integrity (push) Failing after 4s
CI / validate-canonical-controls (push) Successful in 11s
CI / nodejs-build (push) Successful in 2m23s
CI / test-go (push) Has been skipped
CI / test-python-backend (push) Has been skipped
CI / test-python-document-crawler (push) Has been skipped
CI / loc-budget (push) Successful in 14s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / iace-gt-coverage (push) Has been skipped
CI / test-python-dsms-gateway (push) Has been skipped
New tab /sdk/iace/[projectId]/risikobewertung. Per hazard it shows BOTH models side by side — EN-62061-style (S/F/W/P) and Fine-Kinney (P/E/C) — with BreakPilot's justified suggested values from public data, the visible formula, and editable fields that recompute the score + risk band live. The professional adjusts the values (e.g. from his own licensed DIN/Beuth data); we only supply the formula + inputs, reproduce no norm table. Consumes GET .../hazards/:hid/risk-suggestion. Registered in IACE_NAV_ITEMS. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export interface SuggestedValue {
|
||||
value: number
|
||||
justification: string
|
||||
}
|
||||
|
||||
export interface RiskSuggestion {
|
||||
hazard_id: string
|
||||
contact_mode: string
|
||||
en62061: {
|
||||
severity: SuggestedValue
|
||||
frequency: SuggestedValue
|
||||
probability: SuggestedValue
|
||||
avoidance: SuggestedValue
|
||||
score: number
|
||||
level: string
|
||||
formula: string
|
||||
}
|
||||
fine_kinney: {
|
||||
probability: SuggestedValue
|
||||
exposure: SuggestedValue
|
||||
consequence: SuggestedValue
|
||||
score: number
|
||||
band: string
|
||||
action: string
|
||||
formula: string
|
||||
}
|
||||
note: string
|
||||
}
|
||||
|
||||
export interface HazardLite {
|
||||
id: string
|
||||
name: string
|
||||
category: string
|
||||
scenario?: string
|
||||
}
|
||||
|
||||
export function useRiskAssessment(projectId: string) {
|
||||
const [hazards, setHazards] = useState<HazardLite[]>([])
|
||||
const [suggestions, setSuggestions] = useState<Record<string, RiskSuggestion>>({})
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false
|
||||
async function load() {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/hazards`)
|
||||
const json = res.ok ? await res.json() : {}
|
||||
const hz: HazardLite[] = json.hazards || json || []
|
||||
if (cancelled) return
|
||||
setHazards(hz)
|
||||
const entries = await Promise.all(
|
||||
hz.map(async (h) => {
|
||||
try {
|
||||
const r = await fetch(
|
||||
`/api/sdk/v1/iace/projects/${projectId}/hazards/${h.id}/risk-suggestion`,
|
||||
)
|
||||
return r.ok ? ([h.id, (await r.json()) as RiskSuggestion] as const) : null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}),
|
||||
)
|
||||
if (cancelled) return
|
||||
const map: Record<string, RiskSuggestion> = {}
|
||||
for (const e of entries) if (e) map[e[0]] = e[1]
|
||||
setSuggestions(map)
|
||||
} catch (err) {
|
||||
console.error('Failed to load risk assessment:', err)
|
||||
} finally {
|
||||
if (!cancelled) setLoading(false)
|
||||
}
|
||||
}
|
||||
load()
|
||||
return () => {
|
||||
cancelled = true
|
||||
}
|
||||
}, [projectId])
|
||||
|
||||
return { hazards, suggestions, loading }
|
||||
}
|
||||
Reference in New Issue
Block a user