- Tasks — coming in US-007
+
+ {/* Stat Cards */}
+
+ } label="Total Tasks" value={stats.total} />
+ } label="To Do" value={stats.todo} />
+ } label="In Progress" value={stats.inProgress} />
+ } label="Completed" value={stats.completed} />
+
+
+ {/* Search + Order By */}
+
+
+
+ handleSearchChange(e.target.value)}
+ className="pl-9"
+ />
+
+
+
+
+
+
+ {(Object.entries(ORDER_LABELS) as [OrderBy, string][]).map(([key, label]) => (
+ setOrderBy(key)}>
+ {label}
+
+ ))}
+
+
+
+
+ {/* Status Filter Tabs */}
+
setStatusFilter(v as StatusFilter)}>
+
+ All
+ To Do
+ In Progress
+ Completed
+
+
+
+ {/* New Task Button */}
+
+
+
+
+ {/* Task List */}
+
+ {tasksList.length === 0 ? (
+
+ No tasks found.
+
+ ) : (
+ tasksList.map((task) => (
+
+ ))
+ )}
+
+
+
+
+ );
+}
+
+function StatCard({
+ icon,
+ label,
+ value,
+}: {
+ icon: React.ReactNode;
+ label: string;
+ value: number;
+}) {
+ return (
+
+
+
+ {icon}
+
+ {label}
+
+
+
+
+ {value}
+
+
+ );
+}
+
+type TaskItem = {
+ id: string;
+ title: string;
+ description: string | null;
+ status: string | null;
+ priority: string | null;
+ assignee: string | null;
+ dueDate: number | null;
+ projectName: string | null;
+ clientName: string | null;
+ subClientName: string | null;
+};
+
+function PriorityBadge({ priority }: { priority: string | null }) {
+ switch (priority) {
+ case 'high':
+ return (
+
+
+ HIGH
+
+ );
+ case 'medium':
+ return (
+
+
+ MEDIUM
+
+ );
+ case 'low':
+ return (
+
+
+ LOW
+
+ );
+ default:
+ return null;
+ }
+}
+
+function TaskRow({
+ task,
+ onToggle,
+}: {
+ task: TaskItem;
+ onToggle: (id: string, status: string | null) => void;
+}) {
+ const isDone = task.status === 'done';
+
+ const breadcrumb: string[] = [];
+ if (task.clientName) breadcrumb.push(task.clientName);
+ if (task.subClientName) breadcrumb.push(task.subClientName);
+ if (task.projectName) breadcrumb.push(task.projectName);
+
+ return (
+
+ {/* Checkbox */}
+
onToggle(task.id, task.status)}
+ />
+
+ {/* Title + Description */}
+
+
+ {task.title}
+
+ {task.description && (
+
+ {task.description}
+
+ )}
+
+
+ {/* Priority Chip */}
+
+
+ {/* Due Date Chip */}
+ {task.dueDate && (
+
+
+ {formatDueDate(task.dueDate)}
+
+ )}
+
+ {/* Breadcrumb */}
+ {breadcrumb.length > 0 && (
+
+ {breadcrumb.map((part, i) => (
+
+ {i > 0 && }
+ {part}
+
+ ))}
+
+ )}
+
+ {/* Assignee */}
+ {task.assignee && (
+
+
+ {task.assignee}
+
+ )}
);
}