feat: improve overview page with sum of credit cards
Frontend CI / build (push) Successful in 1m57s

This commit is contained in:
2026-07-08 21:08:34 +02:00
parent 1be964a7b4
commit 75419f0da2
2 changed files with 30 additions and 20 deletions
+22
View File
@@ -71,6 +71,28 @@ Verified via Playwright: a linked card with zero transactions shows no
on the viewed month); adding a real $25 charge makes it appear correctly
with the real amount.
**Follow-up in the same session: Overview's "Credit card debt" didn't
match the per-card "next bill" tiles right below it.** User asked why the
top total showed $0 while a card's tile showed a real upcoming amount.
Root cause: the two figures used genuinely different logic —
`totalCardDebt` summed real debt *as of today* while excluding anything
dated in the future or explicitly tagged outside the current calendar
month (from the earlier "should consider only current month" fix), while
the per-card tiles use `nextBillFor`, which shows whichever bill is
chronologically next regardless of month or the transaction's date.
Confirmed with the user (their call, given the tension with the earlier
fix): the total should just be the sum of the tiles, always consistent by
construction. `totalCardDebt` now sums `nextBillFor(...).amountOwed` per
card directly — same function, same result as what's rendered below.
This does mean a transaction explicitly deferred to a future bill counts
toward the total again when it's that card's only/next open bill (no
longer zeroed out for not being "this month's" bill) — that's the
accepted tradeoff for the total always matching what's on screen.
Verified via Playwright: a card whose only transaction is a $80 charge
explicitly tagged to next month's bill now shows "$80.00" in both the top
total and its own tile (previously $0 vs $80 — the reported mismatch).
## Status as of end of session (2026-07-08)
**Done, not yet committed: Credit card overhaul** (requested 2026-07-08 via
+8 -20
View File
@@ -126,26 +126,14 @@ export default function Overview() {
const ccAccounts = accounts.filter((a) => a.kind === 'CREDIT_CARD');
const totalBalance = liquidAccounts.reduce((sum, a) => sum + (accountBalances.get(a.id) ?? Number(a.balance)), 0);
// Real debt as of today, except a charge the user explicitly tagged (via
// the Bill dropdown) to a bill outside the current month is excluded —
// that's a deliberate "count this toward next month instead" choice, not
// this month's debt. A charge with no such override still counts even if
// its *natural* due-day rollover lands next month (e.g. the due day has
// already passed this cycle) — it happened today/this month and is real,
// current debt regardless of which statement it'll appear on.
const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);
const monthEnd = new Date(today.getFullYear(), today.getMonth() + 1, 0);
const totalCardDebt = ccAccounts.reduce((sum, a) => {
const adjustedBalance = (txnsByAccountId.get(a.id) || []).reduce((bal, t) => {
if (parseLocalDate(t.occurredOn) > today) return bal;
if (t.billDueDate) {
const due = parseLocalDate(t.billDueDate);
if (due < monthStart || due > monthEnd) return bal;
}
return bal + Number(t.amount);
}, Number(a.openingBalance ?? 0));
return sum + Math.max(-adjustedBalance, 0);
}, 0);
// Sum of each card's next open bill (same nextBillFor call the "Credit
// cards" tiles below use) — so the total always matches what's shown on
// screen, regardless of which calendar month that next bill happens to
// land in. A card with nothing owed yet contributes 0.
const totalCardDebt = ccAccounts.reduce(
(sum, a) => sum + Math.max(nextBillFor(a, txnsByAccountId.get(a.id) || [], today)?.amountOwed ?? 0, 0),
0
);
const { start, end } = rangeBounds(range);
const recent = txnQueries
.flatMap((q) => q.data || [])