Add player character management feature
All checks were successful
CI / check (push) Successful in 45s
CI / build-image (push) Successful in 18s

Persistent player character templates (name, AC, HP, color, icon) with
full CRUD, bestiary-style search to add PCs to encounters with pre-filled
stats, and color/icon visual distinction in combatant rows. Also stops
the stat block panel from auto-opening when adding a creature.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-12 18:11:08 +01:00
parent 768e7a390f
commit 91703ddebc
38 changed files with 3055 additions and 96 deletions

View File

@@ -0,0 +1,100 @@
# Implementation Plan: Player Character Management
**Branch**: `005-player-characters` | **Date**: 2026-03-12 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/005-player-characters/spec.md`
## Summary
Add persistent player character templates with name, AC, max HP, color, and icon. Player characters are stored independently from encounters and appear in the combatant search dropdown. When added to an encounter, a combatant is created as an independent snapshot with the player character's stats, color, and icon. A management view allows editing and deleting saved characters.
## Technical Context
**Language/Version**: TypeScript 5.8 (strict mode, `verbatimModuleSyntax`)
**Primary Dependencies**: React 19, Vite 6, Tailwind CSS v4, Lucide React
**Storage**: localStorage (new key `"initiative:player-characters"`)
**Testing**: Vitest (unit tests for domain, persistence rehydration)
**Target Platform**: Web browser (single-page app, no routing)
**Project Type**: Web application (monorepo: domain → application → web adapter)
**Performance Goals**: Instant load (synchronous localStorage), <16ms search on small list
**Constraints**: Local-first, single-user, offline-capable
**Scale/Scope**: Typical party size 3-8 player characters
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Principle | Status | Notes |
|-----------|--------|-------|
| I. Deterministic Domain Core | PASS | All PC operations are pure functions, no I/O |
| II. Layered Architecture | PASS | Domain types/functions → Application use cases/ports → Web adapters/hooks/components |
| III. Clarification-First | PASS | No non-trivial assumptions; all decisions documented in research.md |
| IV. Escalation Gates | PASS | Feature has its own spec; cross-feature impacts (Combatant type extension) are documented |
| V. MVP Baseline Language | PASS | Exclusions use "MVP baseline does not include" language |
| VI. No Gameplay Rules | PASS | No game mechanics in spec or plan |
**Post-Phase 1 re-check**: PASS. Data model uses pure domain types. Color/icon are constrained string sets validated in domain. Storage adapter follows existing localStorage pattern.
## Project Structure
### Documentation (this feature)
```text
specs/005-player-characters/
├── plan.md # This file
├── spec.md # Feature specification
├── research.md # Phase 0: technical decisions
├── data-model.md # Phase 1: entity definitions
├── quickstart.md # Phase 1: implementation guide
├── contracts/
│ └── ui-contracts.md # Phase 1: UI component contracts
├── checklists/
│ └── requirements.md # Spec quality checklist
└── tasks.md # Phase 2 output (/speckit.tasks)
```
### Source Code (repository root)
```text
packages/domain/src/
├── player-character-types.ts # NEW: PlayerCharacterId, PlayerCharacter, PlayerColor, PlayerIcon
├── create-player-character.ts # NEW: Pure create function
├── edit-player-character.ts # NEW: Pure edit function
├── delete-player-character.ts # NEW: Pure delete function
├── types.ts # MODIFIED: Add color?, icon?, playerCharacterId? to Combatant
├── events.ts # MODIFIED: Add PC domain events to union
├── index.ts # MODIFIED: Re-export new types/functions
└── __tests__/
├── create-player-character.test.ts # NEW
├── edit-player-character.test.ts # NEW
└── delete-player-character.test.ts # NEW
packages/application/src/
├── ports.ts # MODIFIED: Add PlayerCharacterStore
├── create-player-character-use-case.ts # NEW
├── edit-player-character-use-case.ts # NEW
├── delete-player-character-use-case.ts # NEW
└── index.ts # MODIFIED: Re-export
apps/web/src/
├── persistence/
│ ├── player-character-storage.ts # NEW: localStorage adapter
│ ├── encounter-storage.ts # MODIFIED: Handle new Combatant fields
│ └── __tests__/
│ └── player-character-storage.test.ts # NEW
├── hooks/
│ └── use-player-characters.ts # NEW: React state + persistence
├── components/
│ ├── create-player-modal.tsx # NEW: Create/edit modal
│ ├── player-management.tsx # NEW: List/edit/delete view
│ ├── color-palette.tsx # NEW: Color selection grid
│ ├── icon-grid.tsx # NEW: Icon selection grid
│ ├── action-bar.tsx # MODIFIED: Add "Players" section to dropdown
│ └── combatant-row.tsx # MODIFIED: Render color/icon
└── App.tsx # MODIFIED: Wire usePlayerCharacters
```
**Structure Decision**: Follows existing monorepo layered architecture. New domain files for player character operations, new application use cases, new web adapter/hook/components. Modified files extend existing types and UI.
## Complexity Tracking
No constitution violations. No complexity justification needed.