feat(iace): surface OSHA distance anchor in Maßnahmen tab (name-resolved)

Makes the OSHA minimum-distance anchor visible per measure in a project
without a DB schema change or re-seed: persisted mitigations store the
measure NAME verbatim (not the catalog ID), and measure names are unique
across the 578-entry library (pinned by test), so a name→ID resolver
bridges the gap.

Backend: MeasureIDByName + MinimumDistancesForMeasureName/LinksForMeasureName;
/iace/minimum-distances now accepts ?measure_name=; link table enriched with
measure_name for one-request UI matching.
Frontend: useMinimumDistances loads the link table once and keys it by name;
OshaDistanceNote renders the anchor (value/CFR/license/EU-hint/relation) on the
matching measure group in the Maßnahmen tab.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-06-11 13:39:48 +02:00
parent 76be96556d
commit 6b41eec176
6 changed files with 226 additions and 8 deletions
@@ -9,6 +9,8 @@ import { SuggestMeasuresModal } from './_components/SuggestMeasuresModal'
import { MitigationForm } from './_components/MitigationForm'
import { StatusBadge } from './_components/StatusBadge'
import { MitigationHints } from './_components/MitigationHints'
import { OshaDistanceNote } from './_components/OshaDistanceNote'
import { useMinimumDistances } from './_hooks/useMinimumDistances'
import { ProtectiveMeasure } from './_components/types'
import { useMitigations } from './_hooks/useMitigations'
@@ -24,6 +26,7 @@ export default function MitigationsPage() {
} = useMitigations(projectId)
const [measureNorms, setMeasureNorms] = useState<Record<string, string[]>>({})
const { byName: oshaByName } = useMinimumDistances()
useEffect(() => {
fetch('/api/sdk/v1/iace/protective-measures-library')
@@ -276,6 +279,9 @@ export default function MitigationsPage() {
{refs?.length > 0 && (
<p className="px-12 pb-2 text-[11px] text-blue-500">Normen: {refs.join(', ')}</p>
)}
{oshaByName[title.toLowerCase()] && (
<OshaDistanceNote entry={oshaByName[title.toLowerCase()]} />
)}
{instances.map((m) => {
const isDetailOpen = expandedMeasure === m.id
return (