Add monthly summary and annual overview (Phase 4)

Monthly summary:
- GET /api/summary/monthly returns income, bills, actuals, one-time
  expense totals and surplus/deficit for a given month
- MonthlySummary page shows stat cards and breakdown table

Annual overview:
- AnnualOverview page fetches all 12 months in parallel via Promise.all
- Year navigation, summary cards, monthly table with totals row
- Fix: normalize nested API response to flat fields expected by component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-19 19:16:08 -04:00
parent 22b1cfbe6b
commit 35f9be4b02
2 changed files with 14 additions and 258 deletions

View File

@@ -37,12 +37,25 @@ export default function AnnualOverview() {
setLoading(true);
setError(null);
// Normalize nested API response to flat fields used by this component
function normalize(data) {
if (!data) return null;
return {
total_income: data.income?.net ?? 0,
total_bills: data.bills?.planned ?? 0,
total_variable: data.actuals?.total ?? 0,
total_one_time: data.one_time_expenses?.total ?? 0,
total_spending: data.summary?.total_spending ?? 0,
surplus_deficit: data.summary?.surplus_deficit ?? 0,
};
}
Promise.all(
Array.from({ length: 12 }, (_, i) =>
fetch(`/api/summary/monthly?year=${year}&month=${i + 1}`)
.then(r => {
if (!r.ok) return null;
return r.json();
return r.json().then(normalize);
})
.catch(() => null)
)