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:
Sharang Parnerkar
2026-04-16 22:47:16 +02:00
parent 2adbacf267
commit cfd4fc347f
21 changed files with 1998 additions and 2453 deletions

View File

@@ -0,0 +1,80 @@
'use client'
import { useState, useEffect } from 'react'
import { Component, LibraryComponent, EnergySource, ComponentFormData, buildTree } from '../_components/types'
export function useComponents(projectId: string) {
const [components, setComponents] = useState<Component[]>([])
const [loading, setLoading] = useState(true)
const [showForm, setShowForm] = useState(false)
const [editingComponent, setEditingComponent] = useState<Component | null>(null)
const [addingParentId, setAddingParentId] = useState<string | null>(null)
const [showLibrary, setShowLibrary] = useState(false)
useEffect(() => { fetchComponents() }, [projectId])
async function fetchComponents() {
try {
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/components`)
if (res.ok) { const json = await res.json(); setComponents(json.components || json || []) }
} catch (err) {
console.error('Failed to fetch components:', err)
} finally {
setLoading(false)
}
}
async function handleSubmit(data: ComponentFormData) {
try {
const url = editingComponent
? `/api/sdk/v1/iace/projects/${projectId}/components/${editingComponent.id}`
: `/api/sdk/v1/iace/projects/${projectId}/components`
const method = editingComponent ? 'PUT' : 'POST'
const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) })
if (res.ok) { setShowForm(false); setEditingComponent(null); setAddingParentId(null); await fetchComponents() }
} catch (err) { console.error('Failed to save component:', err) }
}
async function handleDelete(id: string) {
if (!confirm('Komponente wirklich loeschen? Unterkomponenten werden ebenfalls entfernt.')) return
try {
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/components/${id}`, { method: 'DELETE' })
if (res.ok) await fetchComponents()
} catch (err) { console.error('Failed to delete component:', err) }
}
function handleEdit(component: Component) {
setEditingComponent(component); setAddingParentId(null); setShowForm(true)
}
function handleAddChild(parentId: string) {
setAddingParentId(parentId); setEditingComponent(null); setShowForm(true)
}
async function handleAddFromLibrary(libraryComps: LibraryComponent[], energySrcs: EnergySource[]) {
setShowLibrary(false)
const energySourceIds = energySrcs.map(e => e.id)
for (const comp of libraryComps) {
try {
await fetch(`/api/sdk/v1/iace/projects/${projectId}/components`, {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: comp.name_de, type: comp.maps_to_component_type,
description: comp.description_de, safety_relevant: false,
library_component_id: comp.id, energy_source_ids: energySourceIds, tags: comp.tags,
}),
})
} catch (err) { console.error(`Failed to add component ${comp.id}:`, err) }
}
await fetchComponents()
}
const tree = buildTree(components)
return {
components, loading, tree,
showForm, setShowForm, editingComponent, setEditingComponent,
addingParentId, setAddingParentId, showLibrary, setShowLibrary,
handleSubmit, handleDelete, handleEdit, handleAddChild, handleAddFromLibrary,
}
}