import { useState } from 'react' import { AlertTriangle, CalendarDays, Check, Clock, Globe, Plus, UserX } from 'lucide-react' import { Link } from 'react-router-dom' import { ToolHeader } from '../../components/ToolHeader' import { Modal, Panel } from '../../components/ui' import type { RTask } from '../../lib/types' import { recruitBrand } from './brand' import { useCreateTask, useTaskQueue, useUpdateTask } from './taskQueries' const inputCls = 'w-full rounded-lg border border-line/70 bg-navy-900 px-3 py-2 text-sm text-ink outline-none focus:border-recruit' const chip = (on: boolean) => `rounded-full px-3 py-1 text-xs font-semibold transition ${ on ? 'bg-recruit/25 text-recruit shadow-[inset_0_0_0_1px_var(--color-recruit)]' : 'bg-navy-900 text-faint hover:text-muted border border-line/60' }` const BUCKETS = [ { key: 'overdue', label: 'Overdue', color: 'var(--color-risk)' }, { key: 'today', label: 'Today', color: 'var(--color-warn)' }, { key: 'soon', label: 'This week', color: 'var(--color-blue-soft)' }, { key: 'later', label: 'Later', color: 'var(--color-muted)' }, { key: 'none', label: 'No date', color: 'var(--color-faint)' }, ] as const // How a due date should read. Absent is not zero, and an overdue task says how late plainly rather than // showing a negative number. function dueText(t: RTask): string { if (t.due_in_days === undefined || t.due_in_days === null) return 'No due date' const d = t.due_in_days if (d < 0) return `${Math.abs(d)} day${Math.abs(d) === 1 ? '' : 's'} overdue` if (d === 0) return 'Due today' if (d === 1) return 'Due tomorrow' return `Due in ${d} days` } function Stat({ label, value, color }: { label: string; value: number; color: string }) { return (

{label}

0 ? color : undefined }}> {value}

) } export function Tasks() { const [assignee, setAssignee] = useState('me') const [includeClosed, setIncludeClosed] = useState(false) const q = useTaskQueue(assignee, includeClosed) const create = useCreateTask() const update = useUpdateTask() const [open, setOpen] = useState(false) const [title, setTitle] = useState('') const [detail, setDetail] = useState('') const [priority, setPriority] = useState('normal') const [due, setDue] = useState('') const data = q.data return (
{/* Unassigned work is what is left behind when someone leaves. It is a queue, not a footnote. */} {data && ( {data.time_zone} )}
{data && (
)} {q.isLoading ? ( Loading your work… ) : q.isError ? ( Could not load tasks. {(q.error as Error)?.message} ) : ( BUCKETS.map((b) => { const rows = (data?.tasks ?? []).filter((t) => t.bucket === b.key && (includeClosed || t.status === 'open')) if (rows.length === 0) return null return ( ) }) )} {data && data.tasks.length === 0 && ( {assignee === 'unassigned' ? 'No unassigned work. Nothing has been left behind.' : assignee === 'me' ? 'Nothing on your queue. Add a task or pick one up from Unassigned.' : 'No open tasks anywhere.'} )} {update.isError && (

{(update.error as Error).message}

)} setOpen(false)} title="New task">