feat(balance): /balance page + evolution chart + sidebar (#141) #150

Merged
maximus merged 5 commits from issue-141-bilan-3 into main 2026-04-26 13:25:27 +00:00
Owner

Closes #141

Stacked on top of #149 (Issue #140). Base branch: issue-140-bilan-2. Will need rebase onto main once upstream PRs merge.

Summary

  • New /balance page with overview card (latest total + Δ% + 60-day staleness warning), evolution chart (line / stacked-area toggle), accounts table
  • Period selector: 3M / 6M / 1A / 3A / Tout — re-fetches data via useBalanceOverview reducer
  • Recharts-based chart (per the prior worker's HIGH-confidence decision in decisions-log.md: native SVG was reconsidered because the codebase has zero native SVG charts and 8 Recharts ones — reusing the established convention)
  • Sidebar entry "Bilan" with Wallet icon, between Rapports and Paramètres
  • 3 new aggregation helpers in balance.service.ts (+ a 4th getAccountsPeriodAnchor for the per-account Δ% column) + tests
  • Accounts table reserves columns for return metrics (TODO comment for #142)
  • i18n FR/EN
  • CHANGELOG entries (FR + EN) under [Unreleased]

Out of scope (per plan v2)

  • Modified Dietz return columns + transfer markers → Issue #142
  • Cross-cutting integration tests → Issue #144

Test plan

  • cargo check
  • npm run build
  • npm test (timeseries aggregators, hook reducer — 410 tests passing)
  • Manual verification — pending human

Generated autonomously by /autopilot run of 2026-04-25

Closes #141 > Stacked on top of #149 (Issue #140). Base branch: `issue-140-bilan-2`. Will need rebase onto `main` once upstream PRs merge. ## Summary - New `/balance` page with overview card (latest total + Δ% + 60-day staleness warning), evolution chart (line / stacked-area toggle), accounts table - Period selector: 3M / 6M / 1A / 3A / Tout — re-fetches data via `useBalanceOverview` reducer - Recharts-based chart (per the prior worker's HIGH-confidence decision in `decisions-log.md`: native SVG was reconsidered because the codebase has zero native SVG charts and 8 Recharts ones — reusing the established convention) - Sidebar entry "Bilan" with `Wallet` icon, between Rapports and Paramètres - 3 new aggregation helpers in `balance.service.ts` (+ a 4th `getAccountsPeriodAnchor` for the per-account Δ% column) + tests - Accounts table reserves columns for return metrics (TODO comment for #142) - i18n FR/EN - CHANGELOG entries (FR + EN) under [Unreleased] ## Out of scope (per plan v2) - Modified Dietz return columns + transfer markers → Issue #142 - Cross-cutting integration tests → Issue #144 ## Test plan - [x] cargo check - [x] npm run build - [x] npm test (timeseries aggregators, hook reducer — 410 tests passing) - [ ] Manual verification — pending human Generated autonomously by /autopilot run of 2026-04-25
maximus added 5 commits 2026-04-25 20:09:14 +00:00
Add four service helpers used by the upcoming `/balance` overview:

- getSnapshotTotalsByDate(range?) — SUM(value) GROUP BY snapshot_date
  with an optional inclusive [from, to] range. LEFT JOIN preserves
  empty snapshots as zero rows so the chart shows continuity.
- getSnapshotTotalsByCategoryAndDate(range?) — same aggregation broken
  down by balance_categories.key, returned as one row per snapshot
  date with a `byCategory` map. Powers the stacked-area variant.
- getAccountsLatestSnapshot() — one row per active account with the
  value of its most-recent snapshot line (NULL when none exists).
  Filters archived accounts via WHERE is_active = 1 AND archived_at
  IS NULL, matches the listBalanceAccounts default.
- getAccountsPeriodAnchor(range) — earliest snapshot_date >= from
  per account, with the value at that date — the anchor used to
  compute the per-account Δ% column on the accounts table.

Tests cover empty DB, single/multi snapshot, archived exclusion via
SQL inspection, date-range params (from-only, both bounds, open).

Refs: #141

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Scoped useReducer hook backing BalancePage. Tracks:
- period (3M / 6M / 1A / 3A / all) — defaults to 1A
- chartMode (line / stacked) — defaults to line
- evolutionTotals + evolutionByCategory + accountsLatest +
  accountsPeriodAnchor (parallel-fetched on mount and on every
  period change via Promise.all)
- isLoading + error

Exposes computeBalanceDateRange(period, today) as a pure helper
so the date math is unit-testable without mocking time. Anchors
on `today` rather than the latest snapshot — keeps the chart's
right edge stable as the user enters new snapshots.

Refs: #141

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three new components composed under a new BalancePage at /balance:

- BalanceOverviewCard — latest aggregate net worth, Δ% vs the
  previous chronological snapshot (rendered as "—" when only
  one snapshot exists), 60-day staleness warning, and a
  "+ Nouveau snapshot" CTA pointing at /balance/snapshot.

- BalanceEvolutionChart — Recharts-based line / stacked-area
  toggle. Line mode plots SUM(value) per snapshot_date with a
  single primary-coloured stroke. Stacked mode transposes the
  byCategory series into one Area per category_key with a
  fixed 10-color palette indexed deterministically. Tooltip
  formats CAD via Intl.NumberFormat.

- BalanceAccountsTable — one row per active account with name,
  category label, latest value, and Δ% over the active period
  (latest_value vs the period anchor). Returns columns
  (3M / 1Y / since-creation / unadjusted) reserved for #142
  with a TODO marker. Action menu includes a disabled "Detail"
  placeholder + functional "Archive" wired through reload().

BalancePage composes the three with an inline period selector
(3M / 6M / 1A / 3A / Tout) and chart-mode toggle, both styled
as segmented controls. State flows through useBalanceOverview.

Route /balance registered before /balance/accounts in App.tsx.

Refs: #141

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Insert a new "Bilan" / "Balance sheet" entry in NAV_ITEMS pointing
at /balance with the Wallet lucide-react icon. Position: between
Reports and Settings, matching the autopilot prompt instruction
and the spec-plan-bilan v2 ordering.

Sidebar.tsx imports Wallet and registers it in iconMap.

Refs: #141

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(balance): i18n + CHANGELOG for /balance page
All checks were successful
PR Check / rust (push) Successful in 22m24s
PR Check / frontend (push) Successful in 2m22s
1e261ae2ea
FR + EN translations under:
- nav.balance — sidebar label
- balance.overview.* — page title, latest total, Δ% vs previous,
  staleness warning, new-snapshot CTA, accounts table headers,
  empty/no-snapshot states
- balance.period.* — 3M / 6M / 1A / 3A / all selector labels
- balance.chart.* — empty state, mode legend, line / stacked
  toggle labels
- balance.sidebar — entry label (mirrors nav.balance)

CHANGELOG entry under [Unreleased] / Added documenting the new
page, period selector, evolution chart modes, accounts table,
sidebar entry, the four service helpers, and the new hook.

Refs: #141

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
maximus added the
autopilot:pending-human
status:approved
labels 2026-04-25 20:09:53 +00:00
maximus changed target branch from issue-140-bilan-2 to main 2026-04-26 13:25:22 +00:00
maximus merged commit 47ecf886d2 into main 2026-04-26 13:25:27 +00:00
maximus deleted branch issue-141-bilan-3 2026-04-26 13:25:27 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: maximus/Simpl-Resultat#150
No description provided.