'use client' import { useState, useEffect } from 'react' // ============================================================================= // TYPES // ============================================================================= export interface SecurityItem { id: string title: string description: string | null type: 'vulnerability' | 'misconfiguration' | 'compliance' | 'hardening' severity: 'critical' | 'high' | 'medium' | 'low' status: 'open' | 'in-progress' | 'resolved' | 'accepted-risk' source: string | null cve: string | null cvss: number | null affected_asset: string | null assigned_to: string | null created_at: string due_date: string | null remediation: string | null } export interface Stats { open: number in_progress: number critical: number high: number overdue: number total: number } export interface NewItem { title: string description: string type: string severity: string source: string cve: string cvss: string affected_asset: string assigned_to: string remediation: string } export const EMPTY_NEW_ITEM: NewItem = { title: '', description: '', type: 'vulnerability', severity: 'medium', source: '', cve: '', cvss: '', affected_asset: '', assigned_to: '', remediation: '', } // ============================================================================= // HOOK // ============================================================================= const API = '/api/sdk/v1/compliance/security-backlog' export function useSecurityBacklog() { const [items, setItems] = useState([]) const [stats, setStats] = useState({ open: 0, in_progress: 0, critical: 0, high: 0, overdue: 0, total: 0 }) const [loading, setLoading] = useState(true) useEffect(() => { loadData() }, []) async function loadData() { setLoading(true) try { const [itemsRes, statsRes] = await Promise.all([ fetch(`${API}?limit=200`), fetch(`${API}/stats`), ]) if (itemsRes.ok) { const data = await itemsRes.json() setItems(Array.isArray(data.items) ? data.items : []) } if (statsRes.ok) { const data = await statsRes.json() setStats(data) } } catch (err) { console.error('Failed to load security backlog:', err) } finally { setLoading(false) } } async function handleCreate(form: NewItem) { try { const res = await fetch(API, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...form, cvss: form.cvss ? parseFloat(form.cvss) : null, }), }) if (res.ok) { const created = await res.json() setItems(prev => [created, ...prev]) setStats(prev => ({ ...prev, open: prev.open + 1, total: prev.total + 1 })) return true } } catch (err) { console.error('Failed to create item:', err) } return false } async function handleUpdate(editItemId: string, form: NewItem) { try { const res = await fetch(`${API}/${editItemId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ...form, cvss: form.cvss ? parseFloat(form.cvss) : null, }), }) if (res.ok) { const updated = await res.json() setItems(prev => prev.map(i => i.id === updated.id ? updated : i)) return true } } catch (err) { console.error('Failed to update item:', err) } return false } async function handleDelete(id: string) { try { const res = await fetch(`${API}/${id}`, { method: 'DELETE' }) if (res.ok || res.status === 204) { setItems(prev => prev.filter(i => i.id !== id)) loadData() } } catch (err) { console.error('Failed to delete item:', err) } } async function handleStatusChange(id: string, status: string) { try { const res = await fetch(`${API}/${id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status }), }) if (res.ok) { const updated = await res.json() setItems(prev => prev.map(i => i.id === updated.id ? updated : i)) loadData() } } catch (err) { console.error('Failed to update status:', err) } } return { items, stats, loading, handleCreate, handleUpdate, handleDelete, handleStatusChange, } }