# Story 2.1: Municipality-to-Cycle Kanban Entry Point Status: ready-for-dev ## Story As a client services staff member, I want a kanban board showing municipalities as cards organized by election cycle lanes, so that I can see at a glance which municipalities are assigned to which cycles and initiate new cycle jobs from a familiar planning view. ## Acceptance Criteria 1. **Given** a client services user navigates to the election cycle workspace **When** the kanban loads **Then** municipalities with active cycle jobs appear as cards in their respective cycle lane columns, and municipalities with no active jobs appear in an "Unassigned" lane 2. **Given** a municipality has jobs in multiple concurrent election cycles **When** the kanban renders **Then** the municipality card appears in each relevant cycle lane independently (UX-DR16 multi-lane support) 3. **Given** a user views a municipality card **When** displayed in a cycle lane **Then** the card shows municipality name, jurisdiction code, cycle job status badge, and a quick-open action 4. **Given** a cycle lane contains many municipality cards **When** the user scrolls within the lane **Then** the lane column header remains visible and performance is maintained 5. **Given** a user interacts with the kanban via keyboard **When** navigating cards and lanes **Then** all card actions are reachable without a mouse and focus indicators are visible (UX-DR9) ## Tasks / Subtasks - [ ] Backend: expose election-cycle kanban data (AC: #1, #2, #3) - [ ] Add an extension-layer read model that returns municipalities grouped by active cycle assignments, including an "Unassigned" bucket for municipalities without an active cycle job - [ ] Project per-card fields: municipality name, jurisdiction code (`JCode`), cycle name, cycle job status, legacy join key - [ ] Support multi-lane rendering by returning one row per (municipality, active cycle) pair without mutating legacy Access tables - [ ] Authorize endpoint for client services role using existing RBAC patterns from Epic 1 - [ ] Frontend: build kanban entry view (AC: #1, #2, #3, #4) - [ ] Add kanban route to the workspace shell with cycle lane columns rendered from the read model and an Unassigned lane always present - [ ] Render a municipality card component showing name, jurisdiction code, status badge, and a quick-open action that navigates to the cycle job detail (route stub acceptable until Story 2.2 lands) - [ ] Keep lane headers sticky during column scroll and virtualize/window long lane lists to maintain interaction performance - [ ] Accessibility & keyboard support (AC: #5) - [ ] Provide keyboard navigation across lanes and cards with visible focus indicators per UX-DR9 - [ ] Ensure card actions (quick-open, future cycle assignment) are reachable via keyboard - [ ] Tests & evidence (AC: #1–#5) - [ ] Backend tests cover Unassigned bucket, multi-lane projection, RBAC, and confirm no writes hit legacy Access tables - [ ] Frontend tests cover lane rendering, card content, sticky headers under scroll, and keyboard navigation - [ ] Capture changed files and any config notes for the dev record ## Dev Notes - Follow Epic 1 architecture constraints: ASP.NET Core + React separation, RBAC-aware patterns, and immutable legacy tables. Lane data must come from extension tables joined to legacy entities (read-only). - Reuse the workspace shell, Ant Design tokens/components, and existing client services authorization patterns established in Epic 1; avoid bespoke styling or auth shims. - This story is the entry point for Epic 2 — the quick-open / assignment actions are stubbed here and fully wired by Story 2.2 (Create Election-Cycle Job). Do not pull Story 2.2 behavior forward. - Multi-lane support is a hard requirement (UX-DR16): a municipality with N concurrent cycle jobs must render N independent cards. - Treat the lane data shape as the contract for Stories 2.2–2.5; keep field names stable. ### Project Structure Notes - Backend: `Campaign_Tracker.Server/` — add cycle kanban read model under an election-cycle feature folder consistent with existing module conventions - Frontend: `campaign-tracker-client/` — add kanban view under the workspace, sharing layout primitives with existing municipality views - Story artifacts: `_bmad-output/implementation-artifacts/` ### References - Story source: `_bmad-output/planning-artifacts/epics.md` (Epic 2 / Story 2.1) - Architecture constraints: `_bmad-output/planning-artifacts/architecture.md` (extension-table write path, legacy read-only) - UX patterns: `_bmad-output/planning-artifacts/ux-design-specification.md` (UX-DR9 keyboard/focus, UX-DR16 multi-lane kanban) - Prior reference data: Story 1.13 prior-cycle defaults view (read-only municipality cycle history) ## Dev Agent Record ### Agent Model Used {{agent_model_name_version}} ### Debug Log References - Story generated from epic source and architecture/UX planning artifacts. ### Completion Notes List - Story context created and marked ready-for-dev. ### File List ### Change Log