/* ============================================================ page-tasks.jsx — Tasks parsed from standup check-in messages ============================================================ */ /* Re-bind parseDetail — set by primitives.jsx */ const parseDetail = window.parseDetail || ((body, status) => (body && (body.detail || body.message)) || `HTTP ${status}`); const STATUS_TABS = [ { id: 'all', label: 'All' }, { id: 'active', label: 'Active' }, // A8 fix: in-progress tasks now visible { id: 'blocked', label: 'Blocked' }, { id: 'stalled', label: 'Stalled' }, { id: 'repeated', label: 'Repeated' }, { id: 'completed', label: 'Completed' }, ]; const STATUS_COLORS = { active: { bg: 'var(--brand-dim, #4a6cf7)', text: '#fff' }, blocked: { bg: 'var(--err)', text: '#fff' }, stalled: { bg: 'var(--warn)', text: '#000' }, repeated: { bg: 'var(--brand)', text: '#fff' }, completed: { bg: 'var(--ok)', text: '#fff' }, }; function StatusPillTask({ s }) { const c = STATUS_COLORS[s] || { bg: 'var(--bg-elev-2)', text: 'var(--text-1)' }; return ( {(window.appT||(s=>s))(s)} ); } function TasksPage() { const [activeTab, setActiveTab] = useState('all'); const [days, setDays] = useState(7); const [data, setData] = useState([]); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const toast = useToast ? useToast() : { push: () => {} }; const fetchTasks = async (tab, d) => { setLoading(true); setError(null); try { const r = await fetch(`/api/tasks/by-status?status=${tab}&days=${d}`, { credentials: 'same-origin' }); if (!r.ok) { const body = await r.json().catch(() => null); throw new Error(parseDetail(body, r.status)); } setData(await r.json()); } catch (e) { setError(e.message); toast.push && toast.push({ msg: ((window.appLang&&window.appLang()==='ar') ? `فشل جلب المهام: ${e.message}` : `Tasks fetch failed: ${e.message}`), kind: 'err' }); } finally { setLoading(false); } }; useEffect(() => { fetchTasks(activeTab, days); }, [activeTab, days]); const counts = {}; STATUS_TABS.slice(1).forEach(t => { counts[t.id] = data.filter(r => r.status === t.id).length; }); const displayData = activeTab === 'all' ? data : data.filter(r => r.status === activeTab); return (
{(window.appT||(s=>s))('Tasks parsed from standup check-ins — blocked, stalled, repeated, and completed items.')}
| {(window.appT||(s=>s))(col)} | ))}|||||
|---|---|---|---|---|---|
| {row.display_name} | {row.task_text} |
|
{row.first_seen} | {row.last_seen} | 1 ? 'var(--brand)' : 'var(--text-3)', fontWeight: row.occurrences > 1 ? 600 : 400 }}> {row.occurrences} |