-
Notifications
You must be signed in to change notification settings - Fork 1
Range and Customization
The cockpit drives every view — charts, the bills list, and the CSV/PDF export scope — from a single date-range pref, and lets you tune each chart in place.
The range is one persisted pref (lib/prefs.tsx, localStorage) shaped as:
interface RangePref { preset: RangePreset; fromYm: number | null; toYm: number | null }resolveRange() normalizes it into concrete inclusive ym bounds (YYYYMM) so any caller can
filter both shapes the app speaks — MonthRow.ym (a YYYYMM int) and a Bill.statementDate (a
YYYY-MM-DD string) — with a single comparison. It's pure and unit-tested (test/range.test.ts).
RangePreset = all | ytd | 12mo | 24mo | 36mo | custom. The non-custom presets resolve to a
trailing-month window (all and ytd are special-cased); custom uses inclusive fromYm/toYm
bounds, where null on a side means open-ended (falls back to the data's natural edge).
components/MonthRangePicker.tsx + RangeControl.tsx replace the native month inputs with a
visual month/year picker and the preset buttons above. Because everything reads the one resolved
range, picking a range (or a preset) instantly re-scopes the charts, the bills list, and what a
CSV/bulk-PDF export contains — no per-view re-selection.
The dashboard is a responsive single-screen cockpit: on a ≥1280px desktop it fits without
page scroll (plot heights are derived from 100dvh minus the fixed chrome), and it collapses to
a scrolling single/two-column layout on smaller screens and mobile.
- Pagination: charts are shown 4 per page with prev/next arrows and a page-nav bar, so the fit-to-screen layout never has to cram every chart in at once.
-
Per-chart customization: each chart panel has a discoverable, labelled "Customize" gear
(
ConfigurableChart.tsx) — not a bare icon — that opens the chart's options. Charts stay declarative: their series/axes/colors come fromlib/chartSpec.tsand the genericConfigurableChartderives the menu, so there's no bespoke chart component to fork (Contributing).
-
Live scrape progress — a banner (
components/ScrapeProgress.tsx,lib/ngrid/progress.ts) shows phases during a scrape, which matters most on the long first run. -
Exports follow the active range: CSV (
/api/export,lib/csv.ts) and bulk-PDF (/api/export/pdfs,lib/archive.ts→ zip for Windows/macOS, tgz for Linux).