'use client' import { useEffect } from 'react' import { useSearchParams } from 'next/navigation' import { EMPTY_CONTROL } from './components/helpers' import { ControlForm } from './components/ControlForm' import { ControlDetail } from './components/ControlDetail' import { ReviewCompare } from './components/ReviewCompare' import { V1CompareView } from './components/V1CompareView' import { ControlListView } from './components/ControlListView' import { useControlLibraryState } from './components/useControlLibraryState' import { createCRUDHandlers } from './components/useControlCRUD' import { BACKEND_URL } from './components/helpers' export default function ControlLibraryPage() { const state = useControlLibraryState() const searchParams = useSearchParams() // Deep-link via /sdk/control-library?control= // — e.g. from /sdk/master-controls member list. useEffect(() => { const cid = searchParams?.get('control') if (!cid || state.selectedControl?.control_id === cid) return fetch(`${BACKEND_URL}?endpoint=control&id=${encodeURIComponent(cid)}`) .then(r => r.ok ? r.json() : null) .then(ctrl => { if (ctrl?.control_id) { state.setSelectedControl(ctrl) state.setMode('detail') } }) .catch(() => { /* user just sees the list */ }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchParams]) const { handleCreate, handleUpdate, handleDelete, handleReview, handleBulkReject, } = createCRUDHandlers({ selectedControl: state.selectedControl, fullReload: state.fullReload, reviewMode: state.reviewMode, reviewIndex: state.reviewIndex, reviewItems: state.reviewItems, setMode: state.setMode, setSelectedControl: state.setSelectedControl, setReviewMode: state.setReviewMode, setReviewItems: state.setReviewItems, setReviewIndex: state.setReviewIndex, setSaving: state.setSaving, setBulkProcessing: state.setBulkProcessing, reviewCount: state.reviewCount, totalCount: state.totalCount, stateFilter: state.stateFilter, }) // Loading / error screens if (state.loading && state.controls.length === 0) { return (
) } if (state.error) { return (

{state.error}

) } // CREATE mode if (state.mode === 'create') { return state.setMode('list')} saving={state.saving} /> } // EDIT mode if (state.mode === 'edit' && state.selectedControl) { return ( 0 ? state.selectedControl.open_anchors : [{ framework: '', ref: '', url: '' }], requirements: state.selectedControl.requirements.length > 0 ? state.selectedControl.requirements : [''], test_procedure: state.selectedControl.test_procedure.length > 0 ? state.selectedControl.test_procedure : [''], evidence: state.selectedControl.evidence.length > 0 ? state.selectedControl.evidence.map(e => typeof e === 'string' ? { type: '', description: e } : e) : [{ type: '', description: '' }], }} onSave={handleUpdate} onCancel={() => state.setMode('detail')} saving={state.saving} /> ) } // V1 COMPARE mode if (state.compareMode && state.compareV1Control) { return ( state.setCompareMode(false)} onNavigateToControl={async (controlId: string) => { try { const res = await fetch(`${BACKEND_URL}?endpoint=control&id=${controlId}`) if (res.ok) { state.setCompareMode(false); state.setSelectedControl(await res.json()); state.setMode('detail') } } catch { /* ignore */ } }} /> ) } // DETAIL mode if (state.mode === 'detail' && state.selectedControl) { const isDuplicateReview = state.reviewMode && state.reviewTab === 'duplicates' const reviewTabBar = state.reviewMode ? (
) : null const reviewNavProps = { reviewMode: state.reviewMode, reviewIndex: state.reviewIndex, reviewTotal: state.reviewItems.length, onReviewPrev: () => { const idx = Math.max(0, state.reviewIndex - 1) state.setReviewIndex(idx) state.setSelectedControl(state.reviewItems[idx]) }, onReviewNext: () => { const idx = Math.min(state.reviewItems.length - 1, state.reviewIndex + 1) state.setReviewIndex(idx) state.setSelectedControl(state.reviewItems[idx]) }, } if (isDuplicateReview) { return (
{reviewTabBar}
{ state.setMode('list'); state.setSelectedControl(null); state.setReviewMode(false) }} onReview={handleReview} onEdit={() => state.setMode('edit')} reviewIndex={state.reviewIndex} reviewTotal={state.reviewItems.length} onReviewPrev={reviewNavProps.onReviewPrev} onReviewNext={reviewNavProps.onReviewNext} />
) } return (
{reviewTabBar}
{ state.setMode('list'); state.setSelectedControl(null); state.setReviewMode(false) }} onEdit={() => state.setMode('edit')} onDelete={handleDelete} onReview={handleReview} onRefresh={state.fullReload} onCompare={(ctrl, matches) => { state.setCompareV1Control(ctrl); state.setCompareMatches(matches); state.setCompareMode(true) }} onNavigateToControl={async (controlId: string) => { try { const res = await fetch(`${BACKEND_URL}?endpoint=control&id=${controlId}`) if (res.ok) { state.setSelectedControl(await res.json()); state.setMode('detail') } } catch { /* ignore */ } }} reviewMode={state.reviewMode} reviewIndex={state.reviewIndex} reviewTotal={state.reviewItems.length} onReviewPrev={reviewNavProps.onReviewPrev} onReviewNext={reviewNavProps.onReviewNext} />
) } // LIST mode return ( { state.setSelectedControl(ctrl); state.setMode('detail') }} onCreateMode={() => state.setMode('create')} onEnterReview={state.enterReviewMode} onBulkReject={handleBulkReject} onRefresh={() => { state.loadControls(); state.loadMeta(); state.loadFrameworks(); state.loadReviewCount() }} onLoadStats={state.loadProcessedStats} onFullReload={state.fullReload} /> ) }