Files
breakpilot-compliance/admin-compliance/app/sdk/control-library/components/useControlCRUD.ts
Sharang Parnerkar 083792dfd7 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>
2026-04-17 12:24:58 +02:00

117 lines
4.4 KiB
TypeScript

'use client'
import { CanonicalControl, BACKEND_URL } from './helpers'
export interface ControlFormData {
[key: string]: unknown
}
interface CRUDDeps {
selectedControl: CanonicalControl | null
fullReload: () => Promise<void>
reviewMode: boolean
reviewIndex: number
reviewItems: CanonicalControl[]
setMode: (m: 'list' | 'detail' | 'create' | 'edit') => void
setSelectedControl: (c: CanonicalControl | null) => void
setReviewMode: (v: boolean) => void
setReviewItems: (items: CanonicalControl[]) => void
setReviewIndex: (i: number) => void
setSaving: (v: boolean) => void
setBulkProcessing: (v: boolean) => void
reviewCount: number
totalCount: number
stateFilter: string
}
export function createCRUDHandlers(deps: CRUDDeps) {
const {
selectedControl, fullReload, reviewMode, reviewIndex, reviewItems,
setMode, setSelectedControl, setReviewMode, setReviewItems, setReviewIndex,
setSaving, setBulkProcessing, reviewCount, totalCount, stateFilter,
} = deps
const handleCreate = async (data: ControlFormData) => {
setSaving(true)
try {
const res = await fetch(`${BACKEND_URL}?endpoint=create-control`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!res.ok) { const err = await res.json(); alert(`Fehler: ${err.error || err.details || 'Unbekannt'}`); return }
await fullReload()
setMode('list')
} catch { alert('Netzwerkfehler') } finally { setSaving(false) }
}
const handleUpdate = async (data: ControlFormData) => {
if (!selectedControl) return
setSaving(true)
try {
const res = await fetch(`${BACKEND_URL}?endpoint=update-control&id=${selectedControl.control_id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!res.ok) { const err = await res.json(); alert(`Fehler: ${err.error || err.details || 'Unbekannt'}`); return }
await fullReload()
setSelectedControl(null)
setMode('list')
} catch { alert('Netzwerkfehler') } finally { setSaving(false) }
}
const handleDelete = async (controlId: string) => {
if (!confirm(`Control ${controlId} wirklich loeschen?`)) return
try {
const res = await fetch(`${BACKEND_URL}?id=${controlId}`, { method: 'DELETE' })
if (!res.ok && res.status !== 204) { alert('Fehler beim Loeschen'); return }
await fullReload()
setSelectedControl(null)
setMode('list')
} catch { alert('Netzwerkfehler') }
}
const handleReview = async (controlId: string, action: string) => {
try {
const res = await fetch(`${BACKEND_URL}?endpoint=review&id=${controlId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action }),
})
if (res.ok) {
await fullReload()
if (reviewMode) {
const remaining = reviewItems.filter(c => c.control_id !== controlId)
setReviewItems(remaining)
if (remaining.length > 0) {
const nextIdx = Math.min(reviewIndex, remaining.length - 1)
setReviewIndex(nextIdx)
setSelectedControl(remaining[nextIdx])
} else { setReviewMode(false); setSelectedControl(null); setMode('list') }
} else { setSelectedControl(null); setMode('list') }
}
} catch { /* ignore */ }
}
const handleBulkReject = async (sourceState: string) => {
const count = stateFilter === sourceState ? totalCount : reviewCount
if (!confirm(`Alle ${count} Controls mit Status "${sourceState}" auf "deprecated" setzen? Diese Aktion kann nicht rueckgaengig gemacht werden.`)) return
setBulkProcessing(true)
try {
const res = await fetch(`${BACKEND_URL}?endpoint=bulk-review`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ release_state: sourceState, action: 'reject' }),
})
if (res.ok) {
const data = await res.json()
alert(`${data.affected_count} Controls auf "deprecated" gesetzt.`)
await fullReload()
} else { const err = await res.json(); alert(`Fehler: ${err.error || err.details || 'Unbekannt'}`) }
} catch { alert('Netzwerkfehler') } finally { setBulkProcessing(false) }
}
return { handleCreate, handleUpdate, handleDelete, handleReview, handleBulkReject }
}