whisper-money/resources/js/components/ui
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
..
alert-dialog.tsx Accounts: new pages to list, and see account details (#13) 2025-12-05 14:33:18 +01:00
alert.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
amount-display.tsx fix(amount-display): eliminate float round-trip causing missing thousands separator (#191) 2026-03-03 12:40:30 +00:00
amount-input.tsx chore(frontend): add orphan component detection and remove dead components (#181) 2026-03-02 12:43:27 +01:00
avatar.tsx chore(frontend): add orphan component detection and remove dead components (#181) 2026-03-02 12:43:27 +01:00
badge.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
breadcrumb.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
button-group.tsx Bulk actions on transactions 2025-11-10 10:02:28 +00:00
button.tsx ui: add cursor pointer to the buttons 2026-01-07 11:12:03 +01:00
card.tsx feat(ui): add glowing effect to all card components (#170) 2026-03-01 10:56:59 +00:00
chart.tsx fix(chart): hide tooltip on scroll with opacity fade (#320) 2026-04-24 08:28:14 +01:00
checkbox.tsx feat: parent/child category tree (#474) 2026-06-03 19:30:12 +02:00
collapsible.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
command.tsx fix: scroll category combobox to top while searching 2026-01-09 10:02:25 +01:00
context-menu.tsx Context menu to tables 2025-11-15 13:57:10 +01:00
create-button.tsx feat: Integrate EnableBanking as open banking provider (#106) 2026-02-12 09:09:28 +01:00
data-table-pagination.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
data-table-view-options.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
data-table.tsx feat(accounts): add transaction action (#438) 2026-05-26 15:57:23 +02:00
dialog.tsx ui(fix): add hasKeyboard prop to dialogs 2025-12-30 07:22:19 +01:00
drawer.tsx Import CSV 2025-11-08 14:17:11 +00:00
dropdown-menu.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
glowing-effect.tsx chore(frontend): add orphan component detection and remove dead components (#181) 2026-03-02 12:43:27 +01:00
input-otp.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
input.tsx Add Budgeting Feature to Track and Manage Spending (#36) 2026-01-21 15:25:50 +01:00
kbd.tsx Adapt for mobile screen 2025-12-09 16:44:56 +01:00
label.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
multi-select.tsx feat: parent/child category tree (#474) 2026-06-03 19:30:12 +02:00
popover.tsx fix: keep iOS popovers below the notch (#282) 2026-04-13 15:19:56 +01:00
progress.tsx feat(dashboard): make top spending categories clickable with transaction filter link (#189) 2026-03-03 11:24:50 +00:00
radio-group.tsx Import CSV 2025-11-08 14:17:11 +00:00
select.tsx fix(ui): app icon visible on light wallpapers + country select overflow on mobile (#162) 2026-02-28 13:41:41 +00:00
separator.tsx Bulk actions on transactions 2025-11-10 10:02:28 +00:00
sheet.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
sidebar.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
skeleton.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
spinner.tsx feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
stacked-area-chart.tsx Fix net worth chart config UX and color scheme issues (#250) 2026-03-31 11:19:35 +01:00
stacked-bar-chart.test.tsx fix(chart): mask stacked bar edges (#439) 2026-05-26 17:03:06 +02:00
stacked-bar-chart.tsx fix(chart): mask stacked bar edges (#439) 2026-05-26 17:03:06 +02:00
table.tsx Refactor: Transaction Table Layout and Styling Improvements (#26) 2025-12-14 12:56:05 +01:00
textarea.tsx Transactions page 2025-11-08 23:38:35 +00:00
toggle-group.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
toggle.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00
tooltip.tsx Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00