Files
breakpilot-compliance/admin-compliance/app/sdk/iace/[projectId]/components/page.tsx
Sharang Parnerkar cfd4fc347f 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>
2026-04-16 22:47:16 +02:00

112 lines
5.4 KiB
TypeScript

'use client'
import { useParams } from 'next/navigation'
import { ComponentForm } from './_components/ComponentForm'
import { ComponentTreeNode } from './_components/ComponentTreeNode'
import { ComponentLibraryModal } from './_components/ComponentLibraryModal'
import { useComponents } from './_hooks/useComponents'
export default function ComponentsPage() {
const params = useParams()
const projectId = params.projectId as string
const c = useComponents(projectId)
if (c.loading) {
return (
<div className="flex items-center justify-center h-64">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-purple-600" />
</div>
)
}
return (
<div className="space-y-6">
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Komponenten</h1>
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
Erfassen Sie alle Software-, Firmware-, KI- und Hardware-Komponenten der Maschine.
</p>
</div>
{!c.showForm && (
<div className="flex items-center gap-2">
<button onClick={() => c.setShowLibrary(true)}
className="flex items-center gap-2 px-3 py-2 border border-purple-300 text-purple-700 rounded-lg hover:bg-purple-50 transition-colors text-sm">
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
Aus Bibliothek waehlen
</button>
<button
onClick={() => { c.setShowForm(true); c.setEditingComponent(null); c.setAddingParentId(null) }}
className="flex items-center gap-2 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
</svg>
Komponente hinzufuegen
</button>
</div>
)}
</div>
{c.showLibrary && (
<ComponentLibraryModal onAdd={c.handleAddFromLibrary} onClose={() => c.setShowLibrary(false)} />
)}
{c.showForm && (
<ComponentForm
onSubmit={c.handleSubmit}
onCancel={() => { c.setShowForm(false); c.setEditingComponent(null); c.setAddingParentId(null) }}
initialData={c.editingComponent} parentId={c.addingParentId}
/>
)}
{c.tree.length > 0 ? (
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 divide-y divide-gray-100 dark:divide-gray-700">
<div className="px-4 py-3 bg-gray-50 dark:bg-gray-750 rounded-t-xl">
<div className="flex items-center gap-2 text-xs font-medium text-gray-500 uppercase tracking-wider">
<span className="w-5" />
<span>Typ</span>
<span className="flex-1">Name</span>
<span className="hidden lg:block w-[200px]">Beschreibung</span>
<span className="w-24">Aktionen</span>
</div>
</div>
<div className="py-1">
{c.tree.map((component) => (
<ComponentTreeNode key={component.id} component={component} depth={0}
onEdit={c.handleEdit} onDelete={c.handleDelete} onAddChild={c.handleAddChild} />
))}
</div>
</div>
) : (
!c.showForm && (
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-12 text-center">
<div className="w-16 h-16 mx-auto bg-purple-100 dark:bg-purple-900/30 rounded-full flex items-center justify-center mb-4">
<svg className="w-8 h-8 text-purple-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
</svg>
</div>
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">Keine Komponenten erfasst</h3>
<p className="mt-2 text-gray-500 max-w-md mx-auto">
Beginnen Sie mit der Erfassung aller relevanten Komponenten Ihrer Maschine.
Erstellen Sie eine hierarchische Struktur aus Software, Firmware, KI-Modulen und Hardware.
</p>
<div className="mt-6 flex items-center justify-center gap-3">
<button onClick={() => c.setShowLibrary(true)}
className="px-6 py-3 border border-purple-300 text-purple-700 rounded-lg hover:bg-purple-50 transition-colors">
Aus Bibliothek waehlen
</button>
<button onClick={() => c.setShowForm(true)}
className="px-6 py-3 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
Manuell hinzufuegen
</button>
</div>
</div>
)
)}
</div>
)
}