7.9 KiB
Tasks: Turn Navigation
Input: Design documents from /specs/012-turn-navigation/
Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
Organization: Tasks are grouped by user story to enable independent implementation and testing of each story.
Format: [ID] [P?] [Story] Description
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions
Phase 1: Setup (Shared Infrastructure)
Purpose: No new project setup needed -- existing monorepo structure is in place. This phase is empty.
Checkpoint: Existing infrastructure is sufficient. Proceed directly to foundational work.
Phase 2: Foundational (Blocking Prerequisites)
Purpose: Add new domain event types. These are shared by US1 (domain logic) and US2/US3 (UI).
CRITICAL: No user story work can begin until this phase is complete.
- T001 Add TurnRetreated and RoundRetreated event interfaces to the DomainEvent union in
packages/domain/src/events.ts
Checkpoint: Foundation ready -- event types defined, user story implementation can begin.
Phase 3: User Story 1 - Go Back to the Previous Turn (Priority: P1) MVP
Goal: Implement the RetreatTurn pure domain function and its application use case so that turns can be reversed programmatically.
Independent Test: Call retreatTurn with various encounter states and verify correct activeIndex, roundNumber, and emitted events. All tests are pure-function assertions with no I/O.
Implementation for User Story 1
- T003 [US1] Create retreatTurn pure function in
packages/domain/src/retreat-turn.tsimplementing: decrement activeIndex, wrap to last combatant on round boundary, decrement roundNumber on wrap, error on empty encounter, error on round 1 index 0 - T004 [US1] Write acceptance scenario tests for retreatTurn in
packages/domain/src/__tests__/retreat-turn.test.tscovering all 5 spec scenarios: mid-round retreat, round-boundary retreat, start-of-encounter error, single-combatant retreat, empty-encounter error - T005 [US1] Re-export retreatTurn from domain index in
packages/domain/src/index.ts - T006 [US1] Create retreatTurnUseCase in
packages/application/src/retreat-turn-use-case.tsfollowing the advanceTurnUseCase pattern (get encounter from store, call retreatTurn, save result or return error) - T007 [US1] Export retreatTurnUseCase from application index in
packages/application/src/index.ts - T008 [US1] Run
pnpm checkto verify all tests pass, types check, and no lint/format issues
Checkpoint: RetreatTurn domain logic is fully functional and tested. UI work can proceed.
Phase 4: User Story 2 - Turn Navigation Controls at the Top (Priority: P1)
Goal: Create a turn navigation bar at the top of the tracker with Previous and Next Turn buttons, relocating Next Turn from the bottom action bar.
Independent Test: Load the tracker with combatants, verify Previous/Next buttons appear above the combatant list, click Next to advance, click Previous to retreat, verify disabled states.
Implementation for User Story 2
- T009 [US2] Add retreatTurn handler to the encounter hook in
apps/web/src/hooks/use-encounter.ts(mirror the existing advanceTurn handler pattern) - T010 [US2] Create TurnNavigation component in
apps/web/src/components/turn-navigation.tsxwith Previous/Next buttons, round number display, active combatant name, and disabled states (Previous disabled at round 1 index 0 or no combatants; Next disabled when no combatants) - T011 [US2] Wire TurnNavigation into App between header and combatant list in
apps/web/src/App.tsx, passing encounter state, onAdvanceTurn, and onRetreatTurn - T012 [US2] Remove Next Turn button from ActionBar in
apps/web/src/components/action-bar.tsx(keep only the Add Combatant form)
Checkpoint: Turn navigation is fully functional at the top of the tracker. Previous and Next Turn work correctly with proper disabled states.
Phase 5: User Story 3 - Modern, Sleek Turn Navigation Design (Priority: P2)
Goal: Polish the turn navigation bar with clear visual hierarchy, directional icons, and a clean modern design consistent with the existing shadcn/ui-style components.
Independent Test: Visually inspect the turn navigation area -- buttons have directional icons, round/combatant info is clearly displayed, disabled state is visually distinct, layout is balanced and clean.
Implementation for User Story 3
- T014 [US3] Add directional icons (e.g., ChevronLeft, ChevronRight from Lucide React) to the Previous/Next buttons in
apps/web/src/components/turn-navigation.tsx - T015 [US3] Style the turn navigation bar with proper spacing, border, background, and visual hierarchy consistent with existing card/action-bar styling in
apps/web/src/components/turn-navigation.tsx - T016 [US3] Ensure disabled button state has reduced opacity and no hover effects, visually distinct from active state in
apps/web/src/components/turn-navigation.tsx
Checkpoint: Turn navigation is visually polished with clear directional indicators and modern design.
Phase 6: Polish & Cross-Cutting Concerns
Purpose: Final validation across all stories.
- T018 Verify layer boundary compliance -- retreatTurn in domain has no application/adapter imports (covered by existing
layer-boundaries.test.ts) - T019 Run full quality gate with
pnpm checkand verify clean pass - T020 Verify localStorage persistence handles retreat correctly (existing persistence should work transparently since it saves the Encounter state)
Dependencies & Execution Order
Phase Dependencies
- Foundational (Phase 2): No dependencies -- can start immediately
- User Story 1 (Phase 3): Depends on Phase 2 (event types must exist)
- User Story 2 (Phase 4): Depends on Phase 3 (retreatTurn domain + use case must exist)
- User Story 3 (Phase 5): Depends on Phase 4 (TurnNavigation component must exist to polish)
- Polish (Phase 6): Depends on all user stories being complete
User Story Dependencies
- User Story 1 (P1): Can start after Foundational (Phase 2) -- pure domain work, no UI dependency
- User Story 2 (P1): Depends on US1 completion -- needs retreatTurn use case to wire into the UI
- User Story 3 (P2): Depends on US2 completion -- polishes the component created in US2
Within Each User Story
- Domain function before tests (or TDD: tests first, then function)
- Domain before application use case
- Application use case before adapter/UI wiring
- UI component creation before styling polish
Parallel Opportunities
- T014, T015, T016 can run in parallel (same file but independent style concerns -- may be done in one pass)
Implementation Strategy
MVP First (User Story 1 Only)
- Complete Phase 2: Foundational (event types)
- Complete Phase 3: User Story 1 (retreatTurn domain + tests + use case)
- STOP and VALIDATE: All acceptance scenarios pass as pure-function tests
- Domain logic is fully verified before any UI work
Incremental Delivery
- Phase 2: Foundation -> Event types defined
- Phase 3: US1 -> RetreatTurn domain logic tested and working (MVP domain!)
- Phase 4: US2 -> Turn navigation bar at top, Previous/Next buttons functional (MVP UI!)
- Phase 5: US3 -> Visual polish with icons and consistent styling
- Phase 6: Polish -> Final cross-cutting validation
Notes
- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story for traceability
- US2 depends on US1 (needs the domain function); US3 depends on US2 (polishes the component)
- This feature has a linear dependency chain, limiting parallel opportunities
- Commit after each phase checkpoint
- The existing advance-turn pattern (domain -> use case -> hook -> component) serves as the reference implementation for all new code