feat: custom conditions per campaign

DM can add freeform custom conditions alongside built-ins. Persists to
campaign doc, survives across encounters, shared with display view.

Implementation:
- ParticipantManager subscribes campaign doc via useFirestoreDocument
- customConditions[] merged with built-in CONDITIONS at render
- Input field + Add button in conditions picker (Enter or click)
- Dedup case-insensitive vs built-ins + existing custom
- maxLength 40
- addCustomCondition writes to campaigns/{id}.customConditions
- Badge render: custom conditions show raw label (no emoji)
- DisplayView: same fallback render for custom ids
- toggleCondition unchanged (already accepts any string id)
- campaignId prop passed from EncounterManager -> ParticipantManager

243 tests green. Build clean.
This commit is contained in:
david raistrick
2026-07-04 18:20:32 -04:00
parent 9c90c1500c
commit 1ad4b660a4
2 changed files with 78 additions and 7 deletions
+6 -1
View File
@@ -45,7 +45,12 @@ Backlog of bugs + long-term items. Milestones live in REWORK_PLAN.md.
Old single-counter broken (successes missing, treated saves as fails).
Old data lost (user OK — feature didn't work). UI: green ✓ row + red ✕ row.
### Custom condition field
### Custom conditions field (DONE)
- FIXED — per-campaign freeform conditions. Input field in picker → persists to
`campaigns/{id}.customConditions[]`. Merged with built-ins at render.
ParticipantManager subscribes campaign doc. DisplayView renders custom as
raw label. toggleCondition unchanged (any string id). Dedup case-insensitive.
Enter or button to add. maxLength 40.
- Conditions hardcoded list. No way for DM to add custom.
### Test integrated timeouts