- ProjectEditor gained two collapsed-by-default sections: Members (add/
remove viewer/editor via the UserPicker lookup) and Status pipeline (same
add/rename/hold/done pattern as Settings' global one, scoped to the
project via the new per-project status endpoints).
- TaskDetail now resolves status pills against the task's project pipeline
(useProjectStatuses) instead of always the global one, gained a Pin
button (pinned_today), and a non-owner project 'editor' can now actually
edit a task's content/status in the drawer (checked via a project-members
lookup, since the task payload alone can't say who's an editor) --
list/project/assignment stay owner-only, matching the backend's 403s.
- TodayView now fetches every open task (not just due-dated ones) and
buckets into Overdue/Today(or pinned)/Next 7 days/Other, with "Other"
collapsed by default -- so an empty agenda reads as "nothing due" instead
of "nothing to do".
- Extracted BoardView's column rendering into a reusable TaskBoard
component (done columns collapse by default there too), and added a
List/Board view-mode toggle to both ListView and ProjectDetailView
instead of Board only existing as a separate global page you filter down
to one list/project.
- ListView and ProjectDetailView's Completed sections also collapse by
default now, same reasoning as Board's done columns.
tsc --noEmit and vite build both clean.
Sharing (tag/assign/reallocate) is now a collapsed-by-default section in
the task drawer with a one-line summary, since it's a lesser-used function
that was eating space on every task.
list_id is now optional on task creation -- the task lands unfiled (same
state assign/reallocate already use), scoped only by project_id. Projects
are a cross-cutting grouping, not a list replacement, and the only way to
add a task to a project was previously to create it elsewhere and set the
Project field from the drawer. Added a "+ New task" input directly on
ProjectDetailView. Verified against a throwaway Postgres: unfiled creation,
distinct sort_order per unfiled task, project detail lists them, and
existing validation (bad list_id, missing title) still rejects.
Typo'd addresses in the old <input type="email"> fields silently matched
nobody (assigned_to/task_tags.user_email have no FK), so a task could vanish
into an unreachable owner with no error. New UsersContext + UserPicker pull
the real user list from central auth (/api/auth/users?app=tasks), same
pattern maintenance already uses for its assignee dropdown.
- Board/List/Today views now render the admin-editable status pipeline
instead of a hardcoded todo/doing/done enum (StatusesContext)
- Category filter chip-bar on Board and List views (ported the idea from
reviewing the FD's own build, simplified to match our flat single-category
model rather than his tree)
- New Projects list + detail views, project create/edit modal
- New Dispatch view for the 'reallocate' cap -- flat cross-user task list
with an inline move action (deliberately not routed through the shared
task drawer, since GET /api/tasks/:id only grants visibility to
owner/assignee/tagged users, not dispatchers)
- Task drawer: dynamic status pills, category/project selects, tag
picker (share/watch, no cap needed), assign field (owner + assign cap),
reallocate field (reallocate cap) -- all fields disabled for non-owners
since the backend's single PATCH endpoint is owner-gated
- Settings page: status pipeline + category management (settings cap)
- Fixed missing input[type="datetime-local"]/[type="time"] styling -- the
Due/Remind fields were rendering with unstyled browser defaults
Personal-first lists/tasks/reminders/recurrence, plus an admin-editable status
pipeline, shared categories, project containers, and a three-tier permission
model for cross-user work: assign (hand off your own tasks), reallocate
(dispatcher — move anyone's tasks), admin (reserved, full manage-all).