whisper-money/resources/js/hooks
Víctor Falcón 1cc10566a3
feat: parent/child category tree (#474)
## Summary

Adds nested categories (parent → child, up to **3 levels**) across the
app. Children inherit their parent's type and cashflow direction, and
every category selector now renders the hierarchy as an indented tree.
Gated behind the `CategoryTree` Pennant flag (off by default).

## Backend

- **Migration**: nullable self-referencing `parent_id`; uniqueness
scoped per-parent via a `parent_unique_marker` virtual column (root
names stay unique). New composite unique created before dropping the old
one so the `user_id` FK keeps a supporting index.
- **`CategoryTree` service**: descendant/ancestor resolution, depth &
cycle checks, type cascade, subtree deletion.
- **Validation**: depth limit, cycle prevention, inherited + locked
child type.
- **Delete strategies**: reparent (default), promote to root, or cascade
(uncategorizes affected transactions).
- **Transaction filter** expands a selected parent to its descendants.
- **Cashflow Sankey & breakdown** roll up to top-level parents with
click-to-drill (children + a parent "direct" node).
- **Budgets** tracking a parent also count their children's
transactions.
- **Unified** the frontend category query behind
`Category::forDisplay()` / `FRONTEND_COLUMNS` (8 call sites) so every
selector receives the full Category shape, including `parent_id`.

## Frontend

- New `category-tree.ts` helpers (build/flatten/descendants/path,
tree-aware selection toggle + tri-state).
- **Settings page**: indented tree, sortable by name/color/type
(siblings sorted, hierarchy preserved), parent picker, delete-strategy
dialog.
- **Combobox** (transaction table cell + edit/create modal + parent
picker): indented tree, search keeps matches with their ancestors.
- **Transaction filter**: indented tree, tri-state cascading selection
(parent ↔ children), themed checkboxes, selected branches float to top
on open, ancestor-aware search.
- **Categorizer palette** and **budget multi-select**: same indented
tree + ancestor-aware search.
- **Sankey**: click a parent node to drill into its children, with
breadcrumb.
- Pennant `CategoryTree` flag gates the parent UI.

## Tests

- Pest: model/validation, delete strategies, filter expansion, cashflow
rollup/drill, budget child inclusion.
- Vitest: tree-aware selection logic.
- All green; Pint / ESLint / Prettier clean.

## Rollout

Flag is off by default — enable per user with:
\`\`\`
php artisan feature:enable "App\\Features\\CategoryTree" you@example.com
\`\`\`
2026-06-03 19:30:12 +02:00
..
use-admin.tsx feat: Add privacy mode to hide monetary amounts (#28) 2025-12-14 16:03:02 +01:00
use-appearance.tsx fix: add SSR guards to localStorage/sessionStorage access 2025-12-08 18:19:20 +01:00
use-cashflow-data.ts feat: parent/child category tree (#474) 2026-06-03 19:30:12 +02:00
use-categorize-transactions.ts fix: preview categorizer rule application (#421) 2026-05-25 10:24:21 +02:00
use-chart-color-scheme.tsx Fix net worth chart config UX and color scheme issues (#250) 2026-03-31 11:19:35 +01:00
use-chart-views.ts fix(dashboard): treat loans as debt in net worth (#238) 2026-03-20 09:55:53 +00:00
use-clipboard.ts Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
use-count-up.ts User Onboarding Flow (#23) 2025-12-12 13:06:08 +01:00
use-dashboard-data.test.ts feat(settings): centralize currency options and split profile/account support (#256) 2026-04-02 19:23:10 +02:00
use-dashboard-data.ts refactor(js): use shared formatMonthFromYearMonth in dashboard (#482) 2026-06-03 19:00:46 +02:00
use-decrypt-account-names.ts Remove encryption from bank account names (#104) 2026-02-09 14:15:26 +01:00
use-decrypt-transactions.ts feat: Decrypt encrypted transactions on key unlock (#123) 2026-02-16 10:37:43 +01:00
use-initials.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
use-locale.ts feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
use-mobile-navigation.ts Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
use-mobile.tsx fix: make useIsMobile hook and utility functions SSR-safe 2025-12-08 17:33:54 +01:00
use-onboarding-state.test.tsx Hide stale onboarding plan warning (#360) 2026-05-06 15:10:32 +01:00
use-onboarding-state.ts Hide stale onboarding plan warning (#360) 2026-05-06 15:10:32 +01:00
use-online-status.ts Fix CI: Update bun.lock and fix linting errors 2025-12-01 15:16:06 +01:00
use-pwa-install.ts feat: Show PWA install button on mobile landing page (#99) 2026-02-07 09:33:12 +01:00
use-re-evaluate-all-transactions.tsx feat(rules): move automation rule evaluation to the backend (#168) 2026-03-01 10:37:12 +01:00
use-two-factor-auth.ts Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
use-web-haptics.test.tsx fix(haptics): use a local WebHaptics wrapper (#225) 2026-03-16 11:26:04 +00:00
use-web-haptics.ts fix(haptics): use a local WebHaptics wrapper (#225) 2026-03-16 11:26:04 +00:00