whisper-money/resources/js
Víctor Falcón b9b507005f
feat(cashflow): expand income categories and fix Sankey label overlap (#672)
## Summary

Two improvements to the Cashflow Sankey chart, plus a fix reported for
real users whose chart rendered with overlapping labels.

### 1. Fix overlapping labels on small categories
recharts spaces same-column Sankey nodes by exactly `nodePadding` and
distributes the height **proportionally to value**, so tiny categories
end up separated by only that padding regardless of canvas height. It
was 24px while a two-line label is 30px tall, so adjacent labels
overlapped (e.g. *Regalos* / *Otros* in the monthly view, *Ingreso
desconocido* / *Pagos devueltos* in the yearly view).

Set `NODE_PADDING` above the label height so two adjacent labels can
never collide, whatever the bar size. This is independent of width, so
it fixes desktop and mobile alike.

### 2. Expand income categories (drill-down)
Income categories can now be drilled down into their subcategories,
mirroring the existing expense behaviour. The `sankey` endpoint already
returns both sides for a given `parent`, so this is frontend-only:

- The open drill-down is keyed by `{id, kind}` — a category can
legitimately appear on both the income and expense side.
- Income subcategories link `child -> parent` and form a column to the
**left** of the parent (expense subcategories stay on the right).
- The chart-height budget now accounts for the combined leftmost column
(income siblings + subcategories share it), so a many-source drill-down
can't drive recharts to a negative row scale and break the whole chart.
- The expand chevron points the way the column opens: income shows `<`
collapsed / `>` expanded; expense keeps `>` collapsed / `v` expanded.

The income/expense node-building was also de-duplicated into a single
helper.

## Test plan
- `sankey-chart.test.tsx`: 7 unit tests green (added income-expansion
coverage alongside the existing expense one).
- `tsc --noEmit`, `eslint`, `prettier` clean.
- Manual browser QA (Playwright) on a real account, desktop **and**
mobile: monthly + yearly views (overlap gone), expand income, switch to
expand expense (no regression), collapse, chevron direction, responsive
horizontal scroll.

## Demo

<!-- PLACEHOLDER: drag the demo video here -->
_📎 Attach the demo video here — file generated at
`~/Downloads/sankey-cashflow-demo.mp4`_
2026-07-13 07:28:14 +00:00
..
components feat(cashflow): expand income categories and fix Sankey label overlap (#672) 2026-07-13 07:28:14 +00:00
contexts Move transaction filtering from client-side to server-side (#126) 2026-02-16 12:49:04 +01:00
hooks fix(dashboard): stop negative asset balances inflating net worth (#660) 2026-07-08 15:22:16 +00:00
layouts feat(onboarding): clarify the "categorize at least 5" goal in the categorizer (#616) 2026-07-01 08:34:51 +02:00
lib fix(accounts): show credit cards as positive and exclude them from net worth (#673) 2026-07-13 07:27:52 +00:00
pages fix(accounts): show credit cards as positive and exclude them from net worth (#673) 2026-07-13 07:27:52 +00:00
providers fix: move community link to user menu (#442) 2026-05-27 17:39:26 +02:00
services fix(sync): don't crash when IndexedDB is unavailable (PHP-LARAVEL-43) (#654) 2026-07-07 04:59:10 +00:00
types refactor: consolidate duplicated financial calculations (#643) 2026-07-04 22:26:44 +02:00
utils feat(currencies): add Nigerian Naira (NGN) (#642) 2026-07-04 19:10:58 +00:00
app.tsx feat(onboarding): clarify the "categorize at least 5" goal in the categorizer (#616) 2026-07-01 08:34:51 +02:00
ssr.tsx Remove plaintext-transactions feature flag & E2E references (#116) 2026-02-13 11:10:21 +01:00