feat(tasks): kanban board with To Do / In Progress / Done columns

- add a `status` field to tasks (backend schema/validation/service/types
  + frontend types), kept in sync with the legacy `done` flag
- migration 0017 adds the column and backfills done tasks to "done"
- rewrite the tasks page as a three-column board: per-column add buttons,
  draggable cards, and a status mover in the detail sheet

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Khalid Abdi
2026-06-15 18:35:48 +03:00
parent 6e5598262e
commit 6fdb7bdb46
11 changed files with 3444 additions and 144 deletions
+13 -1
View File
@@ -542,6 +542,16 @@
"empty": "No tasks here.",
"markDone": "Mark as done",
"markNotDone": "Mark as not done",
"status": {
"todo": "To Do",
"in_progress": "In Progress",
"done": "Done"
},
"board": {
"addTask": "Add task",
"moveTo": "Move to",
"emptyColumn": "No tasks."
},
"filters": {
"all": "All",
"open": "Open",
@@ -566,6 +576,7 @@
"due": "Due",
"duePlaceholder": "e.g. Today",
"priorityLabel": "Priority",
"statusLabel": "Status",
"cancel": "Cancel",
"add": "Add task"
},
@@ -588,7 +599,8 @@
"patient": "Patient",
"details": "Details",
"reopen": "Reopen task",
"complete": "Mark complete"
"complete": "Mark complete",
"moveTo": "Move to"
},
"toast": {
"needSubjectTitle": "Add a subject",
+4
View File
@@ -3,6 +3,8 @@ import { apiFetch } from "@/lib/api-client";
// A care-team task. Mirrors the backend `src/types/task.ts`. Scoped to the active
// clinic (shared across the care team).
export type Priority = "high" | "medium" | "low";
// Board column the task sits in. `done` mirrors `status === "done"`.
export type TaskStatus = "todo" | "in_progress" | "done";
export type Task = {
id: string;
@@ -12,6 +14,7 @@ export type Task = {
assigneeRole: string | null;
due: string;
priority: Priority;
status: TaskStatus;
patient: string | null;
notes: string | null;
done: boolean;
@@ -28,6 +31,7 @@ export type TaskInput = {
assigneeRole?: string | null;
due?: string;
priority?: Priority;
status?: TaskStatus;
patient?: string | null;
notes?: string | null;
};