foundary-test-1770784989/.sdlc/features/task-management-ui/spec.md
rdev-worker 0c5bab957c
Some checks are pending
ci/woodpecker/push/woodpecker Pipeline is pending
build: /spec-feature task-management-ui --requirements 'React UI in studio-u...
2026-02-11 05:07:32 +00:00

9.6 KiB

Feature: Task Management UI

Problem Statement

Users of the Foundary Studio currently have no visual interface for managing tasks. The backend (studio-api) is being built with full Task CRUD endpoints (via the data-models feature), but there is no frontend to interact with them. Project teams need a way to visualize task status at a glance, move tasks through workflow stages, create and edit tasks with metadata (labels, assignees), and filter their view to focus on relevant work items.

Without a UI, users would need to interact with raw API endpoints — impractical for day-to-day project management workflows.

User Stories

  • As a team member, I want to see all tasks organized by status in a Kanban board so that I can understand the state of work at a glance.
  • As a team member, I want to drag tasks between columns (To Do, In Progress, Done) so that I can quickly update task status without opening a form.
  • As a team member, I want to create a new task with title, description, labels, and assignee so that I can capture work items as they arise.
  • As a team member, I want to edit an existing task's details so that I can keep task information up to date.
  • As a team member, I want to filter the board by label so that I can focus on a specific category of work (e.g., bugs only).
  • As a team member, I want to filter the board by assignee so that I can see work assigned to a specific person.
  • As a team member, I want to delete a task from the edit modal so that I can remove work items that are no longer needed.

Acceptance Criteria

Kanban Board View

  • Board displays three columns: To Do (status=open), In Progress (status=in_progress), Done (status=done)
  • Each column shows a count of tasks it contains
  • Tasks are rendered as cards within their respective status column
  • Task cards display: title, priority badge, label badges, and assignee avatar/name
  • Board fetches tasks from GET /api/studio-api/projects/{projectId}/tasks on mount
  • Empty columns display a placeholder message (e.g., "No tasks")

Drag and Drop

  • Tasks can be dragged from one column and dropped into another
  • Dropping a task into a new column fires PUT /api/studio-api/tasks/{id} with the new status
  • The board updates optimistically (moves the card immediately, reverts on API error)
  • Visual feedback during drag: dragged card has elevated shadow, drop target column is highlighted
  • Cancelled tasks (status=cancelled) are excluded from the board view

Task Creation

  • A "New Task" button is visible above/beside the board
  • Clicking "New Task" opens a modal/dialog with fields: title (required), description (optional), label (multi-select from existing labels), assignee (select from known users/IDs)
  • Submitting the form calls POST /api/studio-api/projects/{projectId}/tasks to create the task
  • After successful creation, the new task appears in the "To Do" column without a full page refresh
  • Validation: title is required (1-200 chars); shows inline error if empty

Task Editing

  • Clicking a task card opens an edit modal/dialog pre-populated with the task's current data
  • Edit modal includes fields: title, description, status (dropdown), priority (dropdown), labels (multi-select), assignee
  • Saving calls PUT /api/studio-api/tasks/{id} with updated fields
  • After successful update, the board reflects changes (card moves columns if status changed)
  • A "Delete" action in the edit modal calls DELETE /api/studio-api/tasks/{id} after confirmation
  • Deleting a task removes it from the board without a full page refresh

Filtering

  • A filter bar is visible above the board
  • Filter by label: dropdown/multi-select populated from GET /api/studio-api/labels
  • Filter by assignee: dropdown/input populated from task data or a known user list
  • Filters apply client-side to the fetched task list (no additional API calls)
  • Active filters are visually indicated (e.g., badge count, highlighted filter chip)
  • A "Clear filters" action resets all filters

Label and Assignee Integration

  • Labels are fetched from GET /api/studio-api/labels for the filter and task form dropdowns
  • Labels display with their name and color (color swatch or colored badge)
  • Assignees are attached/detached via POST/DELETE /api/studio-api/tasks/{taskId}/assignments
  • Labels are attached/detached via POST/DELETE /api/studio-api/tasks/{taskId}/labels/{labelId}

UI/UX Quality

  • Board is responsive: on small screens, columns stack vertically or become horizontally scrollable
  • All UI uses the existing design system (@foundary-test-1770784989/ui components, CSS variables)
  • Loading states shown while data is being fetched (skeleton or spinner)
  • Error states shown when API calls fail (toast or inline alert)
  • Board integrates into the existing DashboardShell layout with sidebar navigation

Routing

  • Board is accessible at a dedicated route (e.g., /projects/{projectId}/board)
  • Route is added to the sidebar navigation
  • Uses react-router-dom for client-side routing (already installed)

Technical Constraints

  • Frontend stack: React 18 + TypeScript + Vite, using @foundary-test-1770784989/ui component library (Radix UI primitives + Tailwind CSS)
  • Drag-and-drop: Requires installing a DnD library (e.g., @dnd-kit/core + @dnd-kit/sortable) — no DnD library currently installed
  • API client: Use @foundary-test-1770784989/api-client (createClient) for all API calls
  • CSS: Must use CSS custom properties (var(--*)) from the design token system — no hardcoded colors
  • Layout: Must render inside DashboardShell with Sidebar and Header components from @foundary-test-1770784989/layout
  • Components: Use existing Dialog, Button, Input, Textarea, Select, Badge, Card, Alert from @foundary-test-1770784989/ui
  • No state management library: Use React state + context or hooks for local state; no Redux/Zustand currently in the project
  • Backend dependency: Requires data-models feature to be implemented first (provides the Task, Label, Assignment CRUD endpoints)
  • Task statuses: Board maps open → To Do, in_progress → In Progress, done → Done. The cancelled status exists in the API but is not shown on the board.
  • No pagination: Backend list endpoints return all records (per data-models spec); client renders all tasks

Dependencies

  • data-models feature (must be built first): Provides all backend REST endpoints:
    • GET/POST /api/studio-api/projects/{projectId}/tasks — list/create tasks
    • GET/PUT/DELETE /api/studio-api/tasks/{id} — read/update/delete task
    • GET /api/studio-api/labels — list labels
    • POST/DELETE /api/studio-api/tasks/{taskId}/labels/{labelId} — manage task-label associations
    • POST/DELETE /api/studio-api/tasks/{taskId}/assignments — manage assignments
  • Project selection: The board is scoped to a single project. Requires a project to exist and be selected/navigated to.
  • react-router-dom (already installed v6.23.1): For client-side routing
  • DnD library (to be installed): @dnd-kit/core and @dnd-kit/sortable recommended for accessible, modern drag-and-drop
  • Existing shared packages: @foundary-test-1770784989/ui, @foundary-test-1770784989/layout, @foundary-test-1770784989/api-client

Out of Scope

  • Project CRUD UI — This feature assumes a project already exists; creating/managing projects is a separate feature
  • User management / user picker — Assignee field will accept a user ID string; no user directory or avatar service
  • Real-time updates — No WebSocket/SSE for live board sync across clients
  • Task comments or activity log — No comment thread or history view on tasks
  • Subtasks or task dependencies — Flat task list only
  • Task reordering within a column — Cards within a column are ordered by created_at; manual sort order is out of scope
  • Board customization — Column names and statuses are fixed (To Do / In Progress / Done); no custom columns
  • Bulk operations — No multi-select, bulk status change, or bulk delete
  • Offline support — Requires network connectivity
  • Priority filtering — Only label and assignee filters are in scope; priority filter can be added later
  • Label CRUD UI — Labels are managed via API; no UI for creating/editing labels in this feature

Open Questions

  1. Project context: How does the user select which project's board to view? Is there a project list page, or should the board default to the first/only project? This affects routing and navigation design.
  2. Assignee data source: Since there is no user directory, where does the assignee dropdown get its options? Options: (a) free-text input for user ID, (b) derive from existing assignments on tasks, (c) hardcoded list for MVP.
  3. DnD library choice: @dnd-kit is recommended for its accessibility and modern API, but react-beautiful-dnd is another option. Should we standardize on one?
  4. Optimistic updates vs. refetch: Should the board use optimistic UI updates (move card immediately, revert on error) or refetch the full task list after each mutation?
  5. State management: Should task data be managed via React Context (shared across board + modals) or local component state with prop drilling? Adding React Query / TanStack Query for server state caching is another option.
  6. Board URL structure: Should the route be /projects/:projectId/board or /board?project=:projectId or something else?