- Add @tanstack/react-query 5.101.0; wrap app with QueryClientProvider - Add AvailabilityStatus type and AvailabilityResponse to api/types.ts - Implement useAvailabilityStatus (staleTime 30s, stale-on-error preserved) - Add AvailabilityStatusBadge with green/amber/red states and stale indicator - Replace DashboardPage placeholder card with live availability widget - Add MSW availability handler; update test/utils with QueryClientProvider - 55/55 tests pass (FR-05) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
3.9 KiB
Business Logic Model — Unit 4: Dashboard
Process Overview
Unit 4 introduces TanStack Query as a shared data-fetching layer and implements the Dashboard page with a live availability widget. The logic splits into three concerns: query infrastructure setup, the availability hook, and the dashboard UI composition.
TanStack Query Setup
A QueryClient is created once at app startup and provided via QueryClientProvider wrapping the RouterProvider in main.tsx. This is a one-time global change that enables all future units to use useQuery / useMutation.
// Recommended default options for the QueryClient
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: 1,
refetchOnWindowFocus: true,
},
},
});
useAvailabilityStatus Hook
Location: frontend/src/api/useAvailability.ts
Query key: ['availability', 'status']
Fetch function: Calls GET /api/v1/Availability/status via the shared api client.
staleTime: 30_000 ms — TanStack Query refetches automatically in the background once data is 30 seconds old.
Return shape:
{
data: AvailabilityResponse | undefined; // undefined until first successful fetch
error: Error | null;
isLoading: boolean; // true only during initial fetch with no data
isFetching: boolean; // true during any in-flight refetch
isError: boolean;
refetch: () => void; // exposed for Retry button
}
Stale-with-error state: When a background refetch fails, TanStack Query preserves the previous data value while setting isError = true. This enables the dashboard to display the last known status alongside the error state (BR-U4-11).
DashboardPage Composition
The DashboardPage composes existing layout primitives with the new availability widget. No routing changes are needed — DashboardPage is already registered as the /dashboard route component in router.tsx.
Sections:
- Header — welcome message with user name (already implemented; retained as-is)
- Availability Widget — replaces the generic placeholder card
Availability Widget Logic Flow
sequenceDiagram
box rgba(99,179,237,0.4) Component Layer
participant DP as DashboardPage
participant Badge as AvailabilityStatusBadge
end
box rgba(154,230,180,0.4) Query Layer
participant Q as useAvailabilityStatus
end
box rgba(233,213,255,0.4) External
participant API as GET /availability/status
end
DP->>Q: mount — useAvailabilityStatus()
Q->>API: fetch on mount
API-->>Q: 200 AvailabilityResponse
Q-->>DP: data + isLoading=false
DP->>Badge: render with status and message
Note over Q: staleTime 30s elapses
Q->>API: background refetch
alt Refetch succeeds
API-->>Q: 200 AvailabilityResponse
Q-->>DP: updated data
DP->>Badge: re-render with fresh data
else Refetch fails
API-->>Q: network error or 5xx
Q-->>DP: isError=true data=stale
DP->>Badge: render stale badge with stale indicator
DP->>DP: show error banner with Retry button
end
Sequence showing initial fetch, badge render, background refetch on staleTime expiry, and error handling with stale data preservation.
i18n Keys (additions)
New translation keys needed for the availability widget:
| Key | English | Dutch |
|---|---|---|
availability.title |
System Status | Systeemstatus |
availability.available |
Available | Beschikbaar |
availability.maintenance |
Maintenance | Onderhoud |
availability.unavailable |
Unavailable | Niet beschikbaar |
availability.errorTitle |
Could not load status | Status kon niet worden geladen |
availability.staleLabel |
Last known status | Laatste bekende status |
availability.retry |
Retry | Opnieuw proberen |