Dashboard.tsx was reading claims/providers/activity directly from the
zustand `useAppStore`, which returns the hardcoded sample fixtures
(sampleClaims / sampleProviders / sampleActivity) regardless of whether
a backend session is active. The hooks useClaims / useProviders /
useActivity are wired correctly to /api/* when api.isConfigured, so
the fix is to swap the three direct store reads for the hooks.
buildMonthly's parameter is now typed as Claim[] (the live Claim
shape) instead of the store's heterogeneous slice, and the
`useAppStore` import is gone.
Verified end-to-end: after logging in as admin via the live server,
the Dashboard now shows $0 KPIs, "0 events / No activity yet.",
and the live operator name in the greeting — proving the hooks are
hitting /api/* and not falling back to the sample store.
Two issues surfaced by going live against the dev backend:
1. Dashboard greeting was hardcoded 'Good morning, Jordan.' in
src/pages/Dashboard.tsx. The sidebar already pulls from useAuth()
but the dashboard had been missed. Replace with a time-of-day
greeting ('morning' / 'afternoon' / 'evening') plus the live
operator's username from useAuth(). Falls back to 'there' while
/api/auth/me is in flight so we never flash 'undefined' at the
operator.
2. api.isConfigured was returning false whenever VITE_API_BASE_URL
was empty, which is the default in .env.example and the
recommended setting for the Vite dev proxy / nginx. With the flag
false, every hook (useClaims, useBatches, useActivity, ...)
threw notConfiguredError() and silently fell back to the
in-memory zustand store's hardcoded sample data — so 'files not
serving' was actually the Dashboard rendering fixtures, not the
real DB. With the flag now true, joinUrl('') produces relative
URLs that the proxy intercepts and forwards to FastAPI on :8000.
Set VITE_API_BASE_URL=disabled to opt out (useful for Storybook
/ offline UI work).
Also installs @radix-ui/react-tabs which was listed in package.json
but missing from node_modules — Vite was failing pre-transform on
tabs.tsx and refusing to compile downstream pages until deps were
re-installed via 'npm install'.
SP21 Task 2.5 — the Dashboard's 'Recent activity' card now routes clicks
to the matching entity drawer / page by event kind:
- claim_* → /claims?claim=<id> (drawer in Phase 5)
- provider_added → /providers?provider=<npi> (ProviderDrawer)
- remit_received → toast 'coming in a later phase' (RemitDrawer in Phase 4)
- anything else → toast (manual_match, unknown kinds)
Implementation:
- New src/lib/event-routing.ts with the eventKindToUrl() helper,
plus a unit test covering all 6 + default branches.
- src/components/ActivityFeed.tsx gains an optional onItemClick
prop; when set, each row gets role='button', tabIndex=0, the
drillable hover affordance (chevron + tint), and an Enter/Space
keybinding. e.stopPropagation() is called before the handler so a
parent row click can't double-fire (same fix as Task 2.4).
- src/pages/Dashboard.tsx wires the handler on the 'Recent activity'
card via eventKindToUrl + sonner toast for unhandled kinds.
- Backend: CycloneStore.recent_activity() now exposes claimId and
remittanceId on each row (read from ActivityEvent.claim_id /
remittance_id) so the routing helper has the entity ids it needs.
- The frontend Activity interface gains optional claimId /
remittanceId fields; the in-memory sample data and the
addClaim store action populate them so the dashboard works in
both API-configured and sample-data modes.