41 lines
3.0 KiB
Markdown
41 lines
3.0 KiB
Markdown
# Research: 023-clear-encounter
|
|
|
|
## R1: Empty Encounter State in Domain
|
|
|
|
**Decision**: Introduce a `clearEncounter` domain function that returns an empty encounter (`{ combatants: [], activeIndex: 0, roundNumber: 1 }`) directly, bypassing `createEncounter()` which enforces the at-least-one-combatant invariant.
|
|
|
|
**Rationale**: The domain already handles empty combatant lists at runtime — `removeCombatant` can produce an encounter with 0 combatants (tested in AS-5 of remove-combatant tests). The `createEncounter` invariant prevents *construction* of empty encounters but the `Encounter` type itself has no minimum constraint. A dedicated `clearEncounter` function makes the intent explicit.
|
|
|
|
**Alternatives considered**:
|
|
- Relax `createEncounter()` to allow empty combatants — rejected because it would weaken the invariant for normal encounter creation flows.
|
|
- Use a separate `EmptyEncounter` type — rejected as over-engineering; the existing `Encounter` type already supports the shape.
|
|
|
|
## R2: Persistence of Cleared State
|
|
|
|
**Decision**: Update `loadEncounter()` to handle empty combatant arrays by constructing the empty encounter directly (without routing through `createEncounter()`). The existing `saveEncounter()` serializes the empty encounter as normal JSON.
|
|
|
|
**Rationale**: The spec requires cleared state to persist across page refreshes (FR-007). If we remove the localStorage key, `initializeEncounter()` falls back to the demo encounter, which violates the requirement. Storing and loading the empty encounter is the simplest approach.
|
|
|
|
**Alternatives considered**:
|
|
- Remove localStorage key + add a "cleared" flag — rejected as unnecessary complexity.
|
|
- Store a sentinel JSON value — rejected as non-standard and fragile.
|
|
|
|
## R3: Confirmation UI Pattern
|
|
|
|
**Decision**: Use browser-native `window.confirm()` for the destructive action confirmation.
|
|
|
|
**Rationale**: No dialog component currently exists in the project. Building a custom dialog for a single confirmation prompt would be over-engineering for MVP. Browser `confirm()` is synchronous, universally supported, and clearly communicates the destructive nature of the action. The confirmation logic lives in the adapter layer (React hook or component), keeping the domain pure.
|
|
|
|
**Alternatives considered**:
|
|
- Custom AlertDialog component (shadcn-style) — rejected for MVP; can be added later if a richer confirmation UX is needed.
|
|
|
|
## R4: Clear Button Placement
|
|
|
|
**Decision**: Add a clear/reset button in the TurnNavigation component, near the existing round/turn controls.
|
|
|
|
**Rationale**: The TurnNavigation bar is the encounter-level control area (advance turn, retreat turn, round counter). A "clear encounter" action is encounter-level, so it belongs here. Placing it near the round counter reinforces that it resets the entire encounter state.
|
|
|
|
**Alternatives considered**:
|
|
- ActionBar (bottom) — rejected; ActionBar is for adding combatants, not encounter-level management.
|
|
- Separate menu/dropdown — rejected as over-engineering for a single action.
|