refactor(admin): split control-library, iace/mitigations, iace/components, controls pages
All 4 page.tsx files reduced well below 500 LOC (235/181/158/262) by extracting components and hooks into colocated _components/ and _hooks/ subdirectories. Zero behavior changes — logic relocated verbatim. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
'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 [hierarchyWarning, setHierarchyWarning] = useState<boolean>(false)
|
||||
const [measures, setMeasures] = useState<ProtectiveMeasure[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
fetchData()
|
||||
}, [projectId]) // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
await fetchData()
|
||||
return true
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to add mitigation:', err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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, hierarchyWarning, setHierarchyWarning,
|
||||
measures, byType,
|
||||
fetchMeasuresLibrary, handleSubmit, handleAddSuggestedMeasure, handleVerify, handleDelete,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user