fire-planner/frontend
Viktor Barzin 70101c836c
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
fire-planner: What-If gains the chart-first scenario editor
The Plan-tab editors (interactive Gantt for life events, flex spending
rules) are now available in What-If too — with local state instead of
DB persistence so users can tweak before committing to a scenario.

Architecture refactor:

- EventGantt is now a controlled component. The `scenarioId` prop +
  internal useMutation/useQueryClient hooks went away; the component
  takes a `persister: { create, patch, delete }` prop and delegates
  every mutation through it. Plan tab wires it to lifeEventsApi +
  cache invalidation; What-If wires it to React local state with
  negative ids for new events.
- FlexRulesEditor is similarly controlled. Takes `rules + onChange`
  instead of a `scenario` object. Plan tab wraps it with the PATCH
  /scenarios/:id mutation; What-If wraps it with setFlexRules.

Backend:

- New stateless POST /scenarios/spending-profile-preview endpoint
  takes base_spending_gbp + horizon + life_events + flex_rules in the
  body and returns the same SpendingProfileResponse shape as the
  read-only /scenarios/{id}/spending-profile endpoint. Used by
  What-If to render the stacked-area chart against unsaved events.
- SpendingProfileResponse.scenario_id loosened to int | None to
  support the preview variant.

Frontend:

- What-If page gains `events` + `flexRules` local state, an
  EventGantt + FlexRulesEditor wired through them, and a Visx
  spending-profile chart fed by /spending-profile-preview.
- Sim auto-refresh: a 600ms debounced effect re-fires /simulate
  whenever the form / events / flex rules change. Manual "Run
  simulation" button stays as an immediate trigger.
- "Save as scenario" still works — preserves the scenario params but
  not yet the life events / flex rules (a Wave-3 follow-up could
  POST them after the scenario is created).

247 pytest pass; mypy + ruff + frontend typecheck/test/build all clean.
2026-05-12 19:35:28 +00:00
..
src fire-planner: What-If gains the chart-first scenario editor 2026-05-12 19:35:28 +00:00
.gitignore frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00
.npmrc frontend: .npmrc with legacy-peer-deps=true so npm ci works in Docker 2026-05-10 16:51:32 +00:00
index.html frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00
package-lock.json fire-planner: Wave 2 chart-first — flex spending, categorised life 2026-05-10 16:49:04 +00:00
package.json fire-planner: Wave 2 chart-first — flex spending, categorised life 2026-05-10 16:49:04 +00:00
tsconfig.app.json frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00
tsconfig.json frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00
tsconfig.node.json frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00
vite.config.ts frontend: scaffold Vite + React 19 + TS + Tailwind v4 + TanStack Query 2026-05-09 21:53:59 +00:00