Description
The current list and table views of invoices do not provide a workflow-oriented perspective that lets creators quickly move invoices across statuses by dragging them. This issue adds a Kanban board view to /dashboard with columns for Draft, Pending, Partially Paid, Fully Paid, and Disputed, supporting drag-and-drop reordering within and between columns to trigger status transitions where the new status is a valid transition from the current one. Invalid transitions must be rejected with a toast and the card snapped back.
Technical Context
Add a view-mode toggle to app/dashboard/page.tsx that conditionally renders components/dashboard/KanbanBoard.tsx. Use @dnd-kit/core and @dnd-kit/sortable for accessible drag-and-drop. Each column maps to an invoice status; moving a card between columns triggers PATCH /api/invoices/[id] with the new status. Implement a statusTransitionGuard utility in lib/invoiceStateMachine.ts that encodes the allowed transitions and is shared with unit tests. Cards should display invoice ID, recipient count, amount, and due-date pill. Board state must be kept in sync with the server via optimistic updates that roll back on API failure. Column scroll must be independent so long columns do not overflow the viewport.
Acceptance Criteria
Description
The current list and table views of invoices do not provide a workflow-oriented perspective that lets creators quickly move invoices across statuses by dragging them. This issue adds a Kanban board view to
/dashboardwith columns for Draft, Pending, Partially Paid, Fully Paid, and Disputed, supporting drag-and-drop reordering within and between columns to trigger status transitions where the new status is a valid transition from the current one. Invalid transitions must be rejected with a toast and the card snapped back.Technical Context
Add a view-mode toggle to
app/dashboard/page.tsxthat conditionally renderscomponents/dashboard/KanbanBoard.tsx. Use@dnd-kit/coreand@dnd-kit/sortablefor accessible drag-and-drop. Each column maps to an invoice status; moving a card between columns triggersPATCH /api/invoices/[id]with the new status. Implement astatusTransitionGuardutility inlib/invoiceStateMachine.tsthat encodes the allowed transitions and is shared with unit tests. Cards should display invoice ID, recipient count, amount, and due-date pill. Board state must be kept in sync with the server via optimistic updates that roll back on API failure. Column scroll must be independent so long columns do not overflow the viewport.Acceptance Criteria
lib/invoiceStateMachine.tshas 100% branch coverage in unit tests for all defined status transitions