65d98cf674
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.
72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
import { create } from "zustand";
|
|
import {
|
|
sampleActivity,
|
|
sampleClaims,
|
|
sampleProviders,
|
|
sampleRemittances,
|
|
} from "@/data/sampleData";
|
|
import type {
|
|
Activity,
|
|
Claim,
|
|
ParsedBatch,
|
|
Provider,
|
|
Remittance,
|
|
} from "@/types";
|
|
|
|
interface AppState {
|
|
// Legacy in-memory store used by the existing pages.
|
|
claims: Claim[];
|
|
providers: Provider[];
|
|
remittances: Remittance[];
|
|
activity: Activity[];
|
|
|
|
addClaim: (claim: Claim) => void;
|
|
addActivity: (entry: Activity) => void;
|
|
|
|
// Parsed-batch slice — populated by the Upload page when the user uploads
|
|
// a real EDI file through the FastAPI backend. Independent of the legacy
|
|
// store above so the existing pages keep working with sample data.
|
|
parsedBatches: ParsedBatch[];
|
|
activeBatchId: string | null;
|
|
addParsedBatch: (batch: ParsedBatch) => void;
|
|
setActiveBatchId: (id: string | null) => void;
|
|
}
|
|
|
|
export const useAppStore = create<AppState>((set) => ({
|
|
claims: sampleClaims,
|
|
providers: sampleProviders,
|
|
remittances: sampleRemittances,
|
|
activity: sampleActivity,
|
|
|
|
addClaim: (claim) =>
|
|
set((s) => ({
|
|
claims: [claim, ...s.claims],
|
|
activity: [
|
|
{
|
|
id: `ACT-${claim.id}`,
|
|
kind: "claim_submitted",
|
|
message: `Submitted ${claim.id} · ${claim.patientName}`,
|
|
timestamp: claim.submissionDate,
|
|
npi: claim.providerNpi,
|
|
amount: claim.billedAmount,
|
|
// SP21 Task 2.5: mirror the backend wire shape so the
|
|
// Dashboard routing helper finds the claim id.
|
|
claimId: claim.id,
|
|
remittanceId: null,
|
|
},
|
|
...s.activity,
|
|
],
|
|
})),
|
|
|
|
addActivity: (entry) => set((s) => ({ activity: [entry, ...s.activity] })),
|
|
|
|
parsedBatches: [],
|
|
activeBatchId: null,
|
|
addParsedBatch: (batch) =>
|
|
set((s) => ({
|
|
parsedBatches: [batch, ...s.parsedBatches],
|
|
activeBatchId: batch.id,
|
|
})),
|
|
setActiveBatchId: (id) => set({ activeBatchId: id }),
|
|
}));
|