9.6 KiB
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}/taskson 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}/tasksto 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/labelsfor 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/uicomponents, 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
DashboardShelllayout 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-domfor client-side routing (already installed)
Technical Constraints
- Frontend stack: React 18 + TypeScript + Vite, using
@foundary-test-1770784989/uicomponent 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
DashboardShellwithSidebarandHeadercomponents from@foundary-test-1770784989/layout - Components: Use existing
Dialog,Button,Input,Textarea,Select,Badge,Card,Alertfrom@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-modelsfeature to be implemented first (provides the Task, Label, Assignment CRUD endpoints) - Task statuses: Board maps
open→ To Do,in_progress→ In Progress,done→ Done. Thecancelledstatus 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-modelsfeature (must be built first): Provides all backend REST endpoints:GET/POST /api/studio-api/projects/{projectId}/tasks— list/create tasksGET/PUT/DELETE /api/studio-api/tasks/{id}— read/update/delete taskGET /api/studio-api/labels— list labelsPOST/DELETE /api/studio-api/tasks/{taskId}/labels/{labelId}— manage task-label associationsPOST/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/coreand@dnd-kit/sortablerecommended 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
- 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.
- 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.
- DnD library choice:
@dnd-kitis recommended for its accessibility and modern API, butreact-beautiful-dndis another option. Should we standardize on one? - 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?
- 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.
- Board URL structure: Should the route be
/projects/:projectId/boardor/board?project=:projectIdor something else?