// CIL[BEGIN chunk_id="WorkBacklogPage_module_header_1784761401" type="module_header" identity="module_header" parent="none"] // CIL[DOC-MACRO purpose="Render a list view of backlog work items"] // CIL[DOC-RESPONSIBILITY responsibility="Fetch workbench_work_item records and show those not assigned to an epic"] // CIL[DOC-CONTEXT module="workbench.pages.work.WorkBacklogPage" layer="frontend-page" related_files="[\"custom/apps/workbench/pages/work/WorkItemDetailPage.tsx\",\"custom/apps/workbench/components/work/badges.tsx\"]"] // CIL[DOC-CONTRACT inputs="none" outputs="JSX list page" errors="fetch errors rendered inline" side_effects="calls /api/admin-data, navigates on row click"] // CIL[DOC-MICRO logic_summary="Loads work items, filters to items without an epic, and renders a sortable table" notable_decisions="[]"] // CIL[DOC-CONFIDENCE pass="first" score="0.9" flags="none"] // CIL[DOC-STABILITY stability="experimental"] // CIL[DOC-AUDIENCE audience="developer"] import { useEffect, useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' import { useAppPath } from '@core/hooks/useAppPath' import { apiFetch } from '@core/lib/api' import { Input } from '@core/components/ui/input' import { Card, CardContent } from '@core/components/ui/card' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@core/components/ui/table' import { Search } from 'lucide-react' import { StatusBadge, PriorityBadge, SeverityBadge, WorkTypeBadge } from '../../components/work/badges' import { useWorkbenchRole } from '../../hooks/useWorkbenchRole' // CIL[END chunk_id="WorkBacklogPage_module_header_1784761401"] // CIL[BEGIN chunk_id="WorkBacklogPage_workBacklogPage_1784761401" type="function" identity="WorkBacklogPage" parent="none"] // CIL[DOC-MACRO description="Implementation of WorkBacklogPage" macro="Renders and manages WorkBacklogPage UI state"] // CIL[DOC-CONTRACT input_spec="none" output_spec="JSX" side_effects="none"] // CIL[DOC-STABILITY stability="experimental"] function matchesTeam(team: any, role: string) { const t = team || 'unassigned' return t === role || t === '*' || t === 'unassigned' } export default function WorkBacklogPage() { const navigate = useNavigate() const appPath = useAppPath() const { role } = useWorkbenchRole() const [items, setItems] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [filter, setFilter] = useState('') const [sort, setSort] = useState<{ key: string; direction: 'asc' | 'desc' }>({ key: 'updated_at', direction: 'desc' }) useEffect(() => { const load = async () => { setLoading(true) setError(null) try { const res = await apiFetch('/api/admin-data?entity=items&type_slug=workbench_work_item&limit=500') const json = await res.json() const data = Array.isArray(json?.data) ? json.data : [] setItems(data) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load backlog') } finally { setLoading(false) } } load() }, []) const backlogItems = useMemo(() => items.filter(i => i.data?.work_type !== 'idea' && i.status !== 'parking' && !i.data?.sprint_id && matchesTeam(i.data?.team, role)), [items, role]) const filtered = useMemo(() => { const term = filter.trim().toLowerCase() let rows = backlogItems if (term) { rows = rows.filter(r => [r.title, r.description, r.status, r.id] .concat(Object.values(r.data || {})) .some(v => String(v || '').toLowerCase().includes(term)) ) } rows = [...rows].sort((a, b) => { const av = a[sort.key] ?? a.data?.[sort.key] ?? '' const bv = b[sort.key] ?? b.data?.[sort.key] ?? '' if (av < bv) return sort.direction === 'asc' ? -1 : 1 if (av > bv) return sort.direction === 'asc' ? 1 : -1 return 0 }) return rows }, [backlogItems, filter, sort]) const handleSort = (key: string) => { setSort(prev => ({ key, direction: prev.key === key && prev.direction === 'asc' ? 'desc' : 'asc', })) } return (

Backlog

setFilter(e.target.value)} placeholder="Filter backlog…" className="pl-9 w-64" />
{loading ? (
Loading backlog…
) : error ? (
{error}
) : filtered.length === 0 ? (
No backlog items.
) : ( handleSort('title')}>Title Status Type Priority Severity handleSort('updated_at')}>Updated {filtered.map(item => ( navigate(appPath(`/work/${role}/items/${item.id}`))} > {item.title || 'Untitled'} {item.updated_at} ))}
)}
) } // CIL[END chunk_id="WorkBacklogPage_workBacklogPage_1784761401"]