diff --git a/admin-compliance/app/sdk/control-library/page.tsx b/admin-compliance/app/sdk/control-library/page.tsx index d77bba9..e2ab8fa 100644 --- a/admin-compliance/app/sdk/control-library/page.tsx +++ b/admin-compliance/app/sdk/control-library/page.tsx @@ -34,6 +34,7 @@ export default function ControlLibraryPage() { const [verificationFilter, setVerificationFilter] = useState('') const [categoryFilter, setCategoryFilter] = useState('') const [audienceFilter, setAudienceFilter] = useState('') + const [sourceFilter, setSourceFilter] = useState('') // CRUD state const [mode, setMode] = useState<'list' | 'detail' | 'create' | 'edit'>('list') @@ -78,6 +79,22 @@ export default function ControlLibraryPage() { return Array.from(set).sort() }, [controls]) + // Derived: unique document sources (sorted by frequency) + const documentSources = useMemo(() => { + const counts = new Map() + let noSource = 0 + for (const c of controls) { + const src = c.source_citation?.source + if (src) { + counts.set(src, (counts.get(src) || 0) + 1) + } else { + noSource++ + } + } + const sorted = Array.from(counts.entries()).sort((a, b) => b[1] - a[1]) + return { sources: sorted, noSourceCount: noSource } + }, [controls]) + // Filtered controls const filteredControls = useMemo(() => { return controls.filter(c => { @@ -87,6 +104,14 @@ export default function ControlLibraryPage() { if (verificationFilter && c.verification_method !== verificationFilter) return false if (categoryFilter && c.category !== categoryFilter) return false if (audienceFilter && c.target_audience !== audienceFilter) return false + if (sourceFilter) { + const src = c.source_citation?.source || '' + if (sourceFilter === '__none__') { + if (src) return false + } else { + if (src !== sourceFilter) return false + } + } if (searchQuery) { const q = searchQuery.toLowerCase() return ( @@ -98,10 +123,10 @@ export default function ControlLibraryPage() { } return true }) - }, [controls, severityFilter, domainFilter, stateFilter, verificationFilter, categoryFilter, audienceFilter, searchQuery]) + }, [controls, severityFilter, domainFilter, stateFilter, verificationFilter, categoryFilter, audienceFilter, sourceFilter, searchQuery]) // Reset page when filters change - useEffect(() => { setCurrentPage(1) }, [severityFilter, domainFilter, stateFilter, verificationFilter, categoryFilter, audienceFilter, searchQuery]) + useEffect(() => { setCurrentPage(1) }, [severityFilter, domainFilter, stateFilter, verificationFilter, categoryFilter, audienceFilter, sourceFilter, searchQuery]) // Pagination const totalPages = Math.max(1, Math.ceil(filteredControls.length / PAGE_SIZE)) @@ -441,6 +466,17 @@ export default function ControlLibraryPage() { ))} +