refactor(admin): split control-library, iace/mitigations, iace/components pages
Extract hooks, sub-components, and constants into colocated files to bring all three page.tsx files under the 500-LOC hard cap (225, 134, 111 LOC). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Mitigation, Hazard, ProtectiveMeasure, MitigationFormData } from '../_components/types'
|
||||
|
||||
export function useMitigations(projectId: string) {
|
||||
const [mitigations, setMitigations] = useState<Mitigation[]>([])
|
||||
const [hazards, setHazards] = useState<Hazard[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [showForm, setShowForm] = useState(false)
|
||||
const [preselectedType, setPreselectedType] = useState<'design' | 'protection' | 'information' | undefined>()
|
||||
const [hierarchyWarning, setHierarchyWarning] = useState<boolean>(false)
|
||||
const [showLibrary, setShowLibrary] = useState(false)
|
||||
const [libraryFilter, setLibraryFilter] = useState<string | undefined>()
|
||||
const [measures, setMeasures] = useState<ProtectiveMeasure[]>([])
|
||||
const [showSuggest, setShowSuggest] = useState(false)
|
||||
|
||||
useEffect(() => { fetchData() }, [projectId])
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const [mitRes, hazRes] = await Promise.all([
|
||||
fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations`),
|
||||
fetch(`/api/sdk/v1/iace/projects/${projectId}/hazards`),
|
||||
])
|
||||
if (mitRes.ok) {
|
||||
const json = await mitRes.json()
|
||||
const mits = json.mitigations || json || []
|
||||
setMitigations(mits)
|
||||
validateHierarchy(mits)
|
||||
}
|
||||
if (hazRes.ok) {
|
||||
const json = await hazRes.json()
|
||||
setHazards((json.hazards || json || []).map((h: Hazard) => ({ id: h.id, name: h.name, risk_level: h.risk_level, category: h.category })))
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch data:', err)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function validateHierarchy(mits: Mitigation[]) {
|
||||
if (mits.length === 0) return
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/validate-mitigation-hierarchy`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ mitigations: mits.map((m) => ({ reduction_type: m.reduction_type, linked_hazard_ids: m.linked_hazard_ids })) }),
|
||||
})
|
||||
if (res.ok) { const json = await res.json(); setHierarchyWarning(json.has_warning === true) }
|
||||
} catch { /* Non-critical, ignore */ }
|
||||
}
|
||||
|
||||
async function fetchMeasuresLibrary(type?: string) {
|
||||
try {
|
||||
const url = type
|
||||
? `/api/sdk/v1/iace/protective-measures-library?reduction_type=${type}`
|
||||
: '/api/sdk/v1/iace/protective-measures-library'
|
||||
const res = await fetch(url)
|
||||
if (res.ok) { const json = await res.json(); setMeasures(json.protective_measures || []) }
|
||||
} catch (err) {
|
||||
console.error('Failed to fetch measures library:', err)
|
||||
}
|
||||
}
|
||||
|
||||
function handleOpenLibrary(type?: string) {
|
||||
setLibraryFilter(type)
|
||||
fetchMeasuresLibrary(type)
|
||||
setShowLibrary(true)
|
||||
}
|
||||
|
||||
function handleSelectMeasure(measure: ProtectiveMeasure) {
|
||||
setShowLibrary(false)
|
||||
setShowForm(true)
|
||||
setPreselectedType(measure.reduction_type as 'design' | 'protection' | 'information')
|
||||
}
|
||||
|
||||
async function handleSubmit(data: MitigationFormData) {
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data),
|
||||
})
|
||||
if (res.ok) { setShowForm(false); setPreselectedType(undefined); await fetchData() }
|
||||
} catch (err) { console.error('Failed to add mitigation:', err) }
|
||||
}
|
||||
|
||||
async function handleAddSuggestedMeasure(title: string, description: string, reductionType: string, hazardId: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ title, description, reduction_type: reductionType, linked_hazard_ids: [hazardId] }),
|
||||
})
|
||||
if (res.ok) await fetchData()
|
||||
} catch (err) { console.error('Failed to add suggested measure:', err) }
|
||||
}
|
||||
|
||||
async function handleVerify(id: string) {
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations/${id}/verify`, {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
if (res.ok) await fetchData()
|
||||
} catch (err) { console.error('Failed to verify mitigation:', err) }
|
||||
}
|
||||
|
||||
async function handleDelete(id: string) {
|
||||
if (!confirm('Massnahme wirklich loeschen?')) return
|
||||
try {
|
||||
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/mitigations/${id}`, { method: 'DELETE' })
|
||||
if (res.ok) await fetchData()
|
||||
} catch (err) { console.error('Failed to delete mitigation:', err) }
|
||||
}
|
||||
|
||||
function handleAddForType(type: 'design' | 'protection' | 'information') {
|
||||
setPreselectedType(type)
|
||||
setShowForm(true)
|
||||
}
|
||||
|
||||
const byType = {
|
||||
design: mitigations.filter((m) => m.reduction_type === 'design'),
|
||||
protection: mitigations.filter((m) => m.reduction_type === 'protection'),
|
||||
information: mitigations.filter((m) => m.reduction_type === 'information'),
|
||||
}
|
||||
|
||||
return {
|
||||
mitigations, hazards, loading, byType,
|
||||
showForm, setShowForm, preselectedType, setPreselectedType,
|
||||
hierarchyWarning, setHierarchyWarning,
|
||||
showLibrary, setShowLibrary, libraryFilter, measures,
|
||||
showSuggest, setShowSuggest,
|
||||
handleOpenLibrary, handleSelectMeasure, handleSubmit,
|
||||
handleAddSuggestedMeasure, handleVerify, handleDelete, handleAddForType,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user