whisper-money/resources/js/hooks
Víctor Falcón ae81e20a66
perf(dashboard): optimize query performance and eliminate redundant requests (#146)
## Why

### Problem

The dashboard page takes ~4 seconds to load for users with many balance
records. Profiling revealed 29 queries across the initial page load + 3
separate API calls, a 576 KB wasted payload from unused bank records,
and a critical 3.7s bottleneck in `BalanceLookup` correlated subqueries.

## What

### Changes

**Query optimizations:**
- Replace correlated `MAX()` subqueries in `BalanceLookup` with
derived-table `joinSub` pattern — **48x faster** (3,693ms → 77ms) on
accounts with thousands of balance records
- Replace `whereHas` (EXISTS subqueries) with JOINs in
`DashboardAnalyticsController` and `CashflowAnalyticsController` — ~3x
faster per query
- Cache encryption check results in `HandleInertiaRequests` middleware
to avoid 2 duplicate queries per request

**Payload & request reduction:**
- Remove dead `banks` query from `DashboardController` (2,365 records,
576 KB never used by frontend)
- Remove duplicate `categories` and `accounts` queries already provided
by middleware shared props
- Consolidate 3 separate `fetch()` API calls into Inertia v2
`Inertia::defer()` props grouped under `'dashboard'` (single follow-up
request with skeleton fallbacks)

**Frontend:**
- Replace `useDashboardData` fetch hook with `usePage()` props +
`<Deferred>` components
- Convert `CashflowSummaryCard` from internal fetch to prop-based
- Use `router.reload({ only: [...] })` for balance update refetch

### Performance summary

| Metric | Before | After |
|--------|--------|-------|
| Initial page queries | 16 | 12 |
| Follow-up HTTP requests | 3 separate API calls | 1 Inertia deferred |
| BalanceLookup time | 3,693ms | 77ms |
| Wasted payload | 576 KB | 0 |

## Verification

### Tests

All 633 feature tests pass, including 40 dashboard/cashflow-specific
tests.
2026-02-24 08:43:48 +01: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 Add Cashflow Analytics Feature (#49) 2026-01-05 13:06:50 +01:00
use-chart-views.ts feat: add multiple chart view modes for net worth evolution (#37) 2025-12-30 07:22:19 +01: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.ts perf(dashboard): optimize query performance and eliminate redundant requests (#146) 2026-02-24 08:43:48 +01: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.ts Remove plaintext-transactions feature flag & E2E references (#116) 2026-02-13 11:10:21 +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 Remove plaintext-transactions feature flag & E2E references (#116) 2026-02-13 11:10:21 +01:00
use-two-factor-auth.ts Set up a fresh Laravel app 2025-11-07 12:01:36 +00:00