End-to-end journeys for the dashboard. Routes/endpoints per 12_API_Mapping.md;
states per 06_Screen_Specifications.md; WS behaviour per 13_State_Management.md.
Steps marked (planned) / (forward-looking) are not implemented today.
| Step | Actor action | System / screen | Source |
| 1 | Opens app → lands on Dashboard Home | Session valid; OverviewCubit loads | 12_API_Mapping.md E1 |
| 2 | (implicit) | GET /api/v1/dashboard/overview → skeleton → KPI cards | dashboard.controller.ts:13-17 |
| 3 | Reads KPI row: students 812, teachers 34, staff 21, attendance 93%, dues ₹4.2L | Numbers + trend (planned) + stale badge | dashboard.service.ts:50-70 |
| 4 | Sees attendance 93% (summary present: …) | Taps attendance card → Attendance module (daily view) | link only; attendance data owned by Attendance module |
| 5 | Notices pending invoices count | Taps finance card → Fees module invoices list (filtered issued/partial/overdue — dashboard.service.ts:36-37) | link only |
| 6 | Pulls-to-refresh mid-morning | AppRefreshIndicator → cache-bypassing refetch | 10_Interaction_Specification.md §2 |
| 7 | Leaves tab open; worker marks attendance elsewhere | WS event AttendanceMarked (Dashboard.md:34) arrives on tenant:{id} room (ws.gateway.ts:50) → cubit invalidates overview → silent refresh | 13_State_Management.md §5 |
Happy path time: ~30 s glance; failures degrade to AppEmptyState /
AppErrorState with retry (06_Screen_Specifications.md §4).
| Step | Actor action | System / screen |
| 1 | Opens dashboard, reads finance.pendingInvoices + totalDueAmount | KPI cards (dashboard.service.ts:66-69) |
| 2 | Clicks finance card | Fees module (list) — filter mirrors service statuses issued/partial/overdue |
| 3 | Returns → dashboard refreshes on focus (didChangeDependencies re-fetch) | cache TTL 60 s (Dashboard.md:41) |
| 4 | (Accountant persona) (planned): dashboard shows finance-only layout | needs dashboard.read on accountant role (02_User_Personas.md P2) |
| Step | Actor action | System / screen |
| 1 | Dashboard open while cashier records a payment | PaymentRecorded/InvoiceGenerated broadcast (Dashboard.md:34; ws-bridge.service.ts:16-22) |
| 2 | Cubit receives event → invalidates overview key → refetches | 13_State_Management.md §5 |
| 3 | Finance card updates without manual pull | in-place animation Mo-m-base |
| Step | Actor action | System / screen |
| 1 | Opens "Customize" (only if permission dashboard.widget.manage — permissions.constants.ts:38) | Widget palette sheet (planned) |
| 2 | Toggles attendance chart off, reorders finance card | GET /dashboard/widgets + PATCH /dashboard/widgets/:id (planned) (Dashboard.md:26-27) |
| 3 | Saves → overview refetches with new order | cache invalidated server-side (planned) |
| 4 | (No permission) | "Customize" hidden — never a 403 dead-end (00-shared/06 §5) |
| Step | Actor action | System / screen |
| 1 | Fresh tenant, no data | counts 0, attendance rate 0 (dashboard.service.ts:64 returns 0 when no records), no invoices |
| 2 | Screen shows zero-state cards + AppEmptyState hint "Invite your first student" | 06_Screen_Specifications.md §4 |
| Step | Actor action | System / screen |
| 1 | No network on open | AppOfflineBanner + last-good cached KPI payload rendered (TTL-flagged) |
| 2 | Tap retry | banner persists until success (00-shared/05, offline baseline) |
flowchart LR
A[Login] --> B[Dashboard Home]
B -->|tap KPI| C[Students / Fees / Attendance module]
B -->|pull-to-refresh| D[Refetch overview, bypass cache]
B -->|WS event| E[Invalidate + silent refetch]
B -->|Customize (planned)| F[Widget palette]
B -->|no data| G[Zero-state]
B -->|offline| H[Last-good + banner]
- Cache staleness beyond 60 s (no worker yet — live scans today;
01_Product_Overview.md §3 gap).
- WS event storms on
tenant:{id} room (all events broadcast — ws-bridge.service.ts:16-22) → debounce refetch.
- Role without
dashboard.read sees nothing → (planned) role views.