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
@@ -26,6 +26,7 @@ function toTask(row: TaskRow): Task {
assigneeRole: row.assigneeRole,
due: row.due,
priority: row.priority,
status: row.status,
patient: row.patient,
notes: row.notes,
done: row.done,
@@ -74,6 +75,9 @@ export async function createTask(
assigneeRole: input.assigneeRole ?? null,
due: input.due,
priority: input.priority,
status: input.status,
// Keep the legacy `done` flag in lock-step with the board column.
done: input.status === "done",
patient: input.patient ?? null,
notes: input.notes ?? null,
createdBy: creator.id,
@@ -100,7 +104,15 @@ export async function updateTask(
if (patch.priority !== undefined) set.priority = patch.priority;
if (patch.patient !== undefined) set.patient = patch.patient ?? null;
if (patch.notes !== undefined) set.notes = patch.notes ?? null;
if (patch.done !== undefined) set.done = patch.done;
// Keep `status` and the legacy `done` flag in sync: a status patch wins and
// sets done; a bare done toggle maps to done/todo.
if (patch.status !== undefined) {
set.status = patch.status;
set.done = patch.status === "done";
} else if (patch.done !== undefined) {
set.done = patch.done;
set.status = patch.done ? "done" : "todo";
}
if (Object.keys(set).length === 0) {
const [row] = await db