// Sessions list view — with filters (incl. project filter) and a detail row. function Sessions() { const [filter, setFilter] = React.useState('all'); const [project, setProject] = React.useState('all'); // project filter const [projectMenuOpen, setProjectMenuOpen] = React.useState(false); const projectMenuRef = React.useRef(); React.useEffect(() => { function onDoc(e) { if (projectMenuRef.current && !projectMenuRef.current.contains(e.target)) { setProjectMenuOpen(false); } } if (projectMenuOpen) { document.addEventListener('mousedown', onDoc); return () => document.removeEventListener('mousedown', onDoc); } }, [projectMenuOpen]); const filters = [ { id: 'all', label: 'All', count: 847 }, { id: 'today', label: 'Today', count: 24 }, { id: 'starred', label: 'Starred', count: 6 }, ]; const allRows = [ { id: 1, project: 'scarf', title: 'Cron diagnostics', model: 'sonnet-4.5', msgs: 14, tokens: '12,847', cost: '$0.04', time: '14m ago', status: 'active' }, { id: 2, project: 'hermes-blog', title: 'Release notes draft', model: 'haiku-4.5', msgs: 8, tokens: '3,210', cost: '$0.01', time: '42m ago', status: 'idle' }, { id: 3, project: 'hermes-blog', title: 'PR review summary', model: 'sonnet-4.5', msgs: 22, tokens: '24,108', cost: '$0.08', time: '2h ago', status: 'idle' }, { id: 4, project: '—', title: 'What model handles function calls best?', model: 'haiku-4.5', msgs: 4, tokens: '284', cost: '$0.00', time: '3h ago', status: 'idle' }, { id: 5, project: 'scarf', title: 'Memory layout question', model: 'sonnet-4.5', msgs: 11, tokens: '4,892', cost: '$0.02', time: 'yesterday', status: 'idle' }, { id: 6, project: 'scarf', title: 'Refactor SidebarSection enum', model: 'sonnet-4.5', msgs: 31, tokens: '38,221', cost: '$0.13', time: 'yesterday', status: 'errored' }, { id: 7, project: 'hermes-blog', title: 'Twitter recap thread', model: 'haiku-4.5', msgs: 6, tokens: '1,247', cost: '$0.00', time: '2 days ago', status: 'idle' }, { id: 8, project: '—', title: 'Find a good local TTS model', model: 'sonnet-4.5', msgs: 19, tokens: '8,743', cost: '$0.03', time: '3 days ago', status: 'idle' }, ]; // Build project facet — counts per project, plus an "Unscoped" bucket. const projectCounts = allRows.reduce((acc, r) => { acc[r.project] = (acc[r.project] || 0) + 1; return acc; }, {}); const projects = [ { id: 'all', label: 'All projects', icon: 'layers', count: allRows.length }, ...Object.keys(projectCounts).filter(k => k !== '—').sort().map(k => ({ id: k, label: k, icon: 'folder', count: projectCounts[k], })), { id: '—', label: 'Unscoped', icon: 'ghost', count: projectCounts['—'] || 0 }, ]; const rows = allRows.filter(r => project === 'all' ? true : r.project === project); const activeProject = projects.find(p => p.id === project) || projects[0]; return (