Build the All-Time Summary Calculations
Open:
client/src/pages/SummaryPage.jsx
client/src/lib/finance.js
The Ledger page summarizes the selected month. The Summary page answers the broader question: what has happened across all transactions recorded so far?
Keep the arithmetic outside the JSX. A named calculation can be reused by multiple views and tested without rendering the page.
First calculate total income and expenses from the complete transaction collection:
const totals = useMemo(() => {
return transactions.reduce(
(result, transaction) => {
if (transaction.type === "income") {
result.income += transaction.amount;
}
if (transaction.type === "expense") {
result.expense += transaction.amount;
}
return result;
},
{ income: 0, expense: 0 }
);
}, [transactions]);
reduce() visits each transaction and carries two running totals. useMemo() tells React to keep the calculated result until transactions changes.
Derive the net balance separately:
const balance = totals.income - totals.expense;
Keeping the balance formula separate makes the relationship obvious:
balance = income − expenses
Now calculate savings rate only when there is income to divide by:
const savingsRate =
totals.income > 0
? (balance / totals.income) * 100
: null;
For example, $5,200 of income and $1,366.50 of expenses produce a balance of $3,833.50 and a savings rate of about 73.7%.
Use the existing helpers for historical information instead of rebuilding grouping logic in the component:
const months = useMemo(
() => computeMonthlyTotals(transactions),
[transactions]
);
const categoryTotals = useMemo(
() => computeCategoryTotals(transactions, categories),
[transactions, categories]
);
The first value gives the page month-by-month totals. The second gives category totals and ordering. The component should consume those values and render them; it should not create a second set of financial rules.
Test it
Open Summary and compare total income, total expenses, and balance with the records in server/data/db.json.
Add a transaction on the Ledger, return to Summary, and confirm that the all-time values update automatically.
Checkpoint
The Summary page derives all-time financial values from shared transaction data and keeps reusable calculations out of the presentation markup.