Skip to content

feat(THI-50): modernize financing tab with scenario rail + editor - #20

Merged
tdody merged 1 commit into
mainfrom
thibaultdody/thi-50-financing-tab-scenario-rail-editor-sliders-amortization
Apr 19, 2026
Merged

feat(THI-50): modernize financing tab with scenario rail + editor#20
tdody merged 1 commit into
mainfrom
thibaultdody/thi-50-financing-tab-scenario-rail-editor-sliders-amortization

Conversation

@tdody

@tdody tdody commented Apr 19, 2026

Copy link
Copy Markdown
Owner

Summary

Rebuilds the Financing tab around a 280px scenario rail + 1fr editor layout, introduces the SparklineAmort primitive, and preserves the THI-26 snapshot / history integration.

New primitive

  • <SparklineAmort> (frontend/src/components/shared/SparklineAmort.tsx) — SVG line chart of remaining loan balance over term with gradient fill. Computes amortization client-side (no API call). 1.2s stroke-dashoffset draw-in animation via .sparkline-stroke + @keyframes sparklineDraw in index.css. Supports optional ioPeriodYears for DSCR/portfolio.

ScenarioCard rewritten as a rail tile

Compact, presentation-only card:

  • Click star → set active (primary)
  • Click anywhere else → select for editing
  • Selected state: border-ink bg-paper; active star: text-accent
  • Shows serif name, loan-type/term/rate subtitle, monthly P&I in mono
  • All form / save / snapshot / history logic removed from the card — moved into the FinancingTab editor

FinancingTab (shell + editor)

  • Rail (280px): scenarios list (<ScenarioCard> tiles) + "+ New scenario" outlined button at the bottom
  • Editor top bar: inline-editable serif 32px scenario name, loan-type select (bottom-rule style), Make primary button (or "Primary" accent pill when already active)
  • Purchase Price: prominent <CurrencyInput> above the summary (can't fit in the 4 sliders)
  • Live summary: <MetricStrip> with 4 <MetricCell> — Loan Amount / Monthly P&I (emphasis large serif, or "Cash Outlay" for cash loans) / Cash In / LTV
  • SparklineAmort rendered between summary and loan terms; keyed on ${scenarioId}-${term} so it re-animates when switching scenarios or changing term
  • FormSection: Loan Terms — 4 <SliderField>: interest rate, loan term, down payment %, origination points %. The sub prop shows the derived $ (down-payment amount, origination fee).
  • FormSection: Upfront Costs — 4 <CurrencyInput>: closing, renovation, furniture, other
  • Conditional fields (preserved from old card): PMI monthly field when conventional + <20% down; IO period years field when DSCR/portfolio
  • Action row: Save / Duplicate / SnapshotButton / History (with snapshot count badge) / Delete

Preserved behavior

  • Linked pct ↔ amt logic for down payment and closing costs
  • Purchase-price change recomputes dp and closing amounts proportionally
  • THI-26 snapshot dirty-tracking via JSON comparison
  • THI-26 history drawer with restore/compare
  • Delete flow via <ConfirmDialog>

Test plan

  • npm run build — passes, CSS 54.50 kB, 115 modules
  • .sparkline-stroke + @keyframes sparklineDraw emitted in built CSS
  • Dev run: add a scenario, drag sliders, confirm summary + sparkline update live
  • Switch between scenarios in rail → sparkline re-animates, form state resets
  • Primary star: clicking a non-primary scenario's star activates it; editor's Make primary button also activates
  • Snapshot flow: unsaved edit + click Save Snapshot → persists form first then snapshots
  • Delete flow: deleting the selected scenario falls through to the next active (or first) one
  • Cash loan type: hides sliders + sparkline, swaps center metric to Cash Outlay, LTV shows "—"
  • Dark mode: rail tiles, editor top bar, summary, sliders, action row all use tokens

🤖 Generated with Claude Code

Restructure the Financing tab into a 280px scenario rail + editor layout:

- ScenarioCard becomes a compact tile for the rail: serif name, loan-type
  subtitle, monthly P&I, clickable star to set primary, border-ink when
  selected. All form/save state moves out of the card.
- FinancingTab owns the editor: selects a scenario, holds its form state,
  wires snapshot + history drawer, delete with confirm, duplicate, activate.
- Editor top bar: inline-editable serif scenario name + loan-type select +
  Make primary button (or "Primary" pill when already active).
- Purchase Price as a prominent CurrencyInput above the summary.
- Live summary MetricStrip (4 cells): Loan Amount, Monthly P&I / Cash Outlay
  for cash, Cash In, LTV. Large serif emphasis on the center metric.
- SparklineAmort: new SVG sparkline of remaining balance over the loan term
  with accent gradient fill + 1.2s draw-in CSS animation. Keyed on scenario
  + term so it re-draws on scenario switch.
- FormSection "Loan Terms": 4 SliderFields — interest rate, loan term,
  down payment %, origination points %. Each slider mirrors $ alongside
  (dp amount, origination fee) via the `sub` prop.
- FormSection "Upfront Costs": 4 CurrencyInputs — closing, renovation,
  furniture, other. Linked dp/closing % ↔ $ logic preserved.
- Conditional PMI field (conventional + <20% down) and IO period field
  (DSCR/portfolio) keep parity with the old card.
- Action row: Save / Duplicate / SnapshotButton / History / Delete with
  token-based styling; THI-26 snapshot + history integrations unchanged.

Also adds `.sparkline-stroke` / `@keyframes sparklineDraw` to index.css.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tdody
tdody merged commit 32b4662 into main Apr 19, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant