'use client' import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, Trash2 } from 'lucide-react' 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 { GeneratorModal } from './components/GeneratorModal' import { ControlsHeader } from './components/ControlsHeader' import { ControlListItem } from './components/ControlListItem' import { useControlLibrary } from './components/useControlLibrary' import { BACKEND_URL } from './components/helpers' export default function ControlLibraryPage() { const lib = useControlLibrary() if (lib.loading && lib.controls.length === 0) { return (
) } if (lib.error) { return

{lib.error}

} if (lib.mode === 'create') { return lib.setMode('list')} saving={lib.saving} /> } if (lib.mode === 'edit' && lib.selectedControl) { return ( 0 ? lib.selectedControl.open_anchors : [{ framework: '', ref: '', url: '' }], requirements: lib.selectedControl.requirements.length > 0 ? lib.selectedControl.requirements : [''], test_procedure: lib.selectedControl.test_procedure.length > 0 ? lib.selectedControl.test_procedure : [''], evidence: lib.selectedControl.evidence.length > 0 ? lib.selectedControl.evidence : [{ type: '', description: '' }], }} onSave={lib.handleUpdate} onCancel={() => lib.setMode('detail')} saving={lib.saving} /> ) } if (lib.compareMode && lib.compareV1Control) { return ( lib.setCompareMode(false)} onNavigateToControl={async (controlId: string) => { try { const res = await fetch(`${BACKEND_URL}?endpoint=control&id=${controlId}`) if (res.ok) { lib.setCompareMode(false); lib.setSelectedControl(await res.json()); lib.setMode('detail') } } catch { /* ignore */ } }} /> ) } if (lib.mode === 'detail' && lib.selectedControl) { const isDuplicateReview = lib.reviewMode && lib.reviewTab === 'duplicates' const reviewTabBar = lib.reviewMode ? (
) : null if (isDuplicateReview) { return (
{reviewTabBar}
{ lib.setMode('list'); lib.setSelectedControl(null); lib.setReviewMode(false) }} onReview={lib.handleReview} onEdit={() => lib.setMode('edit')} reviewIndex={lib.reviewIndex} reviewTotal={lib.reviewItems.length} onReviewPrev={() => { const idx = Math.max(0, lib.reviewIndex - 1); lib.setReviewIndex(idx); lib.setSelectedControl(lib.reviewItems[idx]) }} onReviewNext={() => { const idx = Math.min(lib.reviewItems.length - 1, lib.reviewIndex + 1); lib.setReviewIndex(idx); lib.setSelectedControl(lib.reviewItems[idx]) }} />
) } return (
{reviewTabBar}
{ lib.setMode('list'); lib.setSelectedControl(null); lib.setReviewMode(false) }} onEdit={() => lib.setMode('edit')} onDelete={lib.handleDelete} onReview={lib.handleReview} onRefresh={lib.fullReload} onCompare={(ctrl, matches) => { lib.setCompareV1Control(ctrl); lib.setCompareMatches(matches); lib.setCompareMode(true) }} onNavigateToControl={async (controlId: string) => { try { const res = await fetch(`${BACKEND_URL}?endpoint=control&id=${controlId}`) if (res.ok) { lib.setSelectedControl(await res.json()); lib.setMode('detail') } } catch { /* ignore */ } }} reviewMode={lib.reviewMode} reviewIndex={lib.reviewIndex} reviewTotal={lib.reviewItems.length} onReviewPrev={() => { const idx = Math.max(0, lib.reviewIndex - 1); lib.setReviewIndex(idx); lib.setSelectedControl(lib.reviewItems[idx]) }} onReviewNext={() => { const idx = Math.min(lib.reviewItems.length - 1, lib.reviewIndex + 1); lib.setReviewIndex(idx); lib.setSelectedControl(lib.reviewItems[idx]) }} />
) } // LIST VIEW return (
lib.setSortBy(v as 'id' | 'newest' | 'oldest' | 'source')} onRefresh={() => { lib.loadControls(); lib.loadMeta(); lib.loadFrameworks(); lib.loadReviewCount() }} onEnterReviewMode={lib.enterReviewMode} onBulkReject={lib.handleBulkReject} onToggleStats={() => { lib.setShowStats(!lib.showStats); if (!lib.showStats) lib.loadProcessedStats() }} onOpenGenerator={() => lib.setShowGenerator(true)} onCreateNew={() => lib.setMode('create')} /> {lib.showGenerator && ( lib.setShowGenerator(false)} onComplete={() => lib.fullReload()} /> )}
{lib.totalCount} Controls gefunden {lib.totalCount !== (lib.meta?.total ?? lib.totalCount) && ` (von ${lib.meta?.total} gesamt)`} {lib.loading && Lade...} {lib.stateFilter && ['needs_review', 'too_close', 'duplicate'].includes(lib.stateFilter) && lib.totalCount > 0 && ( )}
Seite {lib.currentPage} von {lib.totalPages}
{lib.controls.map((ctrl, idx) => ( 0 ? (lib.controls[idx - 1].source_citation?.source || 'Ohne Quelle') : null} onClick={() => { lib.setSelectedControl(ctrl); lib.setMode('detail') }} /> ))} {lib.controls.length === 0 && !lib.loading && (
{lib.totalCount === 0 && !lib.debouncedSearch && !lib.severityFilter && !lib.domainFilter ? 'Noch keine Controls vorhanden. Klicke auf "Neues Control" um zu starten.' : 'Keine Controls gefunden.'}
)}
{lib.totalPages > 1 && (
{Array.from({ length: lib.totalPages }, (_, i) => i + 1) .filter(p => p === 1 || p === lib.totalPages || Math.abs(p - lib.currentPage) <= 2) .reduce<(number | 'dots')[]>((acc, p, i, arr) => { if (i > 0 && p - (arr[i - 1] as number) > 1) acc.push('dots') acc.push(p); return acc }, []) .map((p, i) => p === 'dots' ? ( ... ) : ( ))}
)}
) }