Repository navigation
fix(frontend): plot one savings series per axis with shared formatters - #1385
Conversation
Chart axes need short labels ("$1.5K", "$12.35K", "$1.23M"). The
savings chart built them by hand with `$${(v / 1000).toFixed(1)}K`.
Add one shared helper on Intl.NumberFormat's compact notation, pinned
to en-US like formatCurrency and with the same absent-value marker, so
the chart can drop its own formatting (issue LeanerCloud#749).
Refs LeanerCloud#749
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ters
The Purchases savings chart drew period savings (left axis) and
cumulative savings (right axis) in one plot, so the points where the
lines crossed meant nothing. Its ticks read "$1500.00", and the module
had its own formatCurrency ("$1.50K") with the same name as the shared
helper in utils.ts, so the stat cards formatted money differently from
the rest of the Purchases page.
- Period savings are bars on a single y-axis with compact ticks
(formatCompactCurrency: "$1.5K"). The running total is a separate view,
chosen with a new Show: Savings per period / Cumulative savings select
(#savings-series), on the same single axis.
- Tooltips and the Period / Avg / Peak stat cards use the shared
formatCurrency with cents ("$12,840.00", "$428.00/mo"); the local
formatCurrency is removed.
- The x-axis keeps its period-start anchor (QA 2.2) with the bar chart's
default offset turned off.
Refs LeanerCloud#749
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reached
This review includes 6 billable files and costs up to $1.50. Or wait 58 minutes for your next included review. View limit details
Comment |
Conflicts: - frontend/src/__tests__/savings-history.test.ts: main (LeanerCloud#1341) replaced the "renders savings stats from summary" test, which fed the never-sent legacy summary keys, with a wire-key test and an "ignores the legacy keys" test. Took main's tests. Main's new wire-key test expected the deleted local compact formatter ('$1.80K', '$2.00K/mo'); its expectations now use this branch's shared formatCurrency output ('$1,800.00', '$2,000.00/mo'). The rest of the file (this branch's single-series/axis tests and main's wire-key fixtures) merged cleanly. savings-history.ts merged cleanly: main's server-total-first stats logic now feeds this branch's shared formatCurrency(v, '$', 2) tiles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
No textual conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): APPROVE Blocking:
|
…urrency Main's LeanerCloud#1376 (Refs LeanerCloud#739) changed formatCurrency's absent marker to NO_VALUE ("—"); formatCompactCurrency still hardcoded "--". Delegate null/NaN/Infinity to formatCurrency so the two cannot drift again. Refs LeanerCloud#749 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: - frontend/src/modules/savings-history.ts (imports): kept this branch's shared formatCompactCurrency/formatCurrency import and main's lib/chart-a11y import (LeanerCloud#1381). - frontend/src/modules/savings-history.ts (renderSavingsChart): kept this branch's single-series dataset (period bars or cumulative line) and added main's LeanerCloud#744 summary label and "View as table" disclosure after it. Combined deliberately: * main built the table from periodSavingsData/cumulativeSavingsData, which this branch replaced with one `points` array, so the rows are now built from dataPoints directly (period converted with convertFromMonthly, cumulative as-is). The table keeps both columns in either view so the series toggle hides no values. * the period column header uses unitSuffix(unit), not the branch's view-dependent `suffix` (which is '' in the cumulative view). * main used the deleted local formatter; values now use the shared formatCurrency(v, '$', 2), giving the same "$25.00" main's test expects. * the summary names the drawn series ("Bar chart of savings per period" / "Line chart of cumulative savings") instead of main's fixed "Line chart of savings over time"; count and latest cumulative value are unchanged. formatCompactCurrency still delegates absent values to formatCurrency. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Independent review (IAmJSD's agent, fresh context, given only the diff, the issue and the PR text): APPROVE Blocking:
|
|
Local verification at
|
|
Marked ready and merged by IAmJSD's agent, at IAmJSD's request (IAmJSD reviewed the before/after screenshots; cristim is traveling), after the independent review and local verification above, all at |
The Purchases savings chart drew period savings (left axis) and cumulative savings (right axis) in one plot with different scales, so line crossings meant nothing, and its ticks read
$1500.00.savings-history.tsalso had a privateformatCurrencythat shadowed the shared one, so its stat cards ($12.84K) did not match the rest of the page. This PR plots one series on one compact-currency axis, with a selector to switch to the cumulative view, and removes the local formatter.Closes #749
Closes #171
What changed
frontend/src/utils.ts: newformatCompactCurrency(value, digits = 2)onIntl.NumberFormatcompact notation ($1.5K,$12.35K,$1.23M), pinned to en-US. Absent values return--, the markerformatCurrencyused at the main commit this branch was last merged with (003170d).frontend/src/modules/savings-history.ts(43d1d5f):formatCompactCurrency; tooltips useformatCurrencywith 2 decimals. The legend is hidden since there is one series and the axis title names it. The x-axis keeps its period-start anchor withoffset: false.formatCurrencyis deleted. The Period / Avg / Peak stat cards use the sharedformatCurrency(v, '$', 2)($12,840.00,$428.00/mo).frontend/src/index.html: a new "Show:" select (#savings-series) picks the series and reloads, with the same no-duplicate-listener pattern as the unit select.utils.test.tsandsavings-history.test.tsupdated and extended. Main's fix(frontend): savings-analytics summary keys read by the client never exist on the wire #276 wire-key stats test now expects the shared formatter's$1,800.00and$2,000.00/moinstead of the deleted compact formatter's$1.80Kand$2.00K/mo;tests-e2e/savings-history-average.spec.tsexpects full figures and switches to Cumulative and back in the narrow-screen test.Why this approach
The issue suggests "bars on one compact-currency axis; cumulative as a separate small sparkline or a toggle". A toggle reuses the existing chart, needs no new layout and works on narrow screens, so it was chosen over a second sparkline canvas. Stat cards use full figures with cents (not compact) to match the Purchase History cards on the same page (the mismatch reported in #739); the compact form is used for axis ticks only. Deleting the local helper, rather than renaming it as #171 suggests, removes the shadowing and the duplicate formatter at the same time.
Screenshots
Screenshots were taken before this branch was merged with main; before = main at a14dc8f. After is this branch at that time. Both are headless Chromium at 1440x900 against the repo's mocked e2e API, with a 30-day fixture of varied daily savings.
$1500.00ticks) and cumulative (right axis) share one plot, and the stat cards read$12.84K/$1.50K/mo. On this branch, period savings are bars on one compact axis ($1.5K), there is a new Show selector, and the stat cards read$12,840.00/$1,500.00/mo.$15K).Verification
Run on this branch's head
7927c74c, merged with main6122fa24:npm run lint: 0 errors. Typecheck and build pass.savings-history+utils: 188 passed.formatCompactCurrency(abbreviation, distinct fractional ticks, absent marker); savings-history "one series on one axis (issue fix(frontend): purchases savings chart uses two y-axes and shadows formatCurrency #749)" (period view is one bar dataset on scalesx,yonly; cumulative view is one line dataset with the running total and no rate suffix; changing the series reloads once after a double init). The threey1tests are removed and the tick, tooltip and QA 2.4/2.5 tests now target the single axis.e2e-local.sh: 231 passed, 0 failed.savings-history.test.tsresolved, see the merge commits.Notes for review
$12.84K) to full with cents ($12,840.00); the hidden legend.Overlaps
modules/savings-history.tsand conflict with this branch there.utils.ts, and fix(frontend): low-severity copy, toast, confirm and stale-state fixes #728, fix(frontend): ARIA tab pattern has no keyboard model and route changes keep focus #730, chore(frontend): replace mixed Unicode glyphs with one SVG icon set #751 and fix(frontend): first-run empty state says no rows match filters with no next step #756 editindex.html; all merge cleanly with this branch.Note for the UI owner
This changes UI code that @cristim owns. IAmJSD reviewed the before/after screenshots and asked for it to be merged; any design point you disagree with can be a follow-up.
🤖 Generated with Claude Code