Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05 — Screen Inventory (Reports Module)

Every screen of the Reports module: intent, route, composition, states, permissions, behavior. Authoritative shared components in 00-shared/03; this file enumerates which each screen uses with module specifics. Format mirrors design-docs/auth/05_Screen_Inventory.md. Analytics = {module}.{screen}.{action} (proposed).


1. Report Catalog (/reports)

FieldDetail
PurposePick a report type to generate; see what exists
Entrynav "Reports"; dashboard quick action
Exit/reports/new (select template)
ContentStatic list of 3 templates (report card / attendance summary / fee summary) with description + required-param hints; (planned) rows for coaching types (BATCH_PERFORMANCE, TEST_SERIES_ANALYSIS, DPP_COMPLETION — IMPLEMENTATION_PLAN.md:646)
Permissionreport.read (permissions.constants.ts:40) — hide module without it (forward-looking)
WidgetsAppListTile per template, AppBadge "Scheduled" on summary types, FAB? none — list only
Statesidle; loading skeleton; empty (never: list is static)
Analyticsreports.catalog.open, reports.catalog.select(type) (proposed)

2. Generate Report Form (/reports/new)

FieldDetail
PurposeEnter params for one template, POST generate
Entrycatalog select
Exitsubmit → /reports/jobs/:jobId; back → catalog
Formtype (fixed, from selection), conditional params per 08
Primary CTAGenerate report (disabled while in flight)
Statesvalidation (client-side presence for report_card!), submitting (button spinner), error 400 inline, 429 countdown, offline banner
Permissionreport.generate (permissions.constants.ts:39) — submit blocked without it (forward-looking)
Analyticsreports.generate.submit(type), reports.generate.success(jobId), reports.generate.failure(code) (proposed)

3. Job List (/reports/jobs)

FieldDetail
PurposeRecent report jobs for the tenant, newest first
SourceNo list endpoint today — client gap. Server has {tenantId, createdAt:-1} index (report-job.schema.ts:48) but no GET /reports route; client keeps a local history of submitted jobIds (limit ~50, persisted) (forward-looking): add GET /reports?status= server-side
Rowtype label, status chip (queued/processing/completed/failed — report-job.schema.ts:13-18), createdAt, source badge (User/Scheduled)
Actionstap → job detail; swipe/pull-to-refresh re-polls rows in view
Empty"No reports yet — create one" + CTA to catalog
WidgetsAppListTile, AppBadge (status), AppSkeleton, RefreshIndicator, AppEmptyState

4. Job Detail / Progress (/reports/jobs/:jobId)

FieldDetail
PurposeLive status + result of one job; the polling hub
SourceGET /reports/:jobId (reports.controller.ts:20-24)
Contentheader (type, jobId short, createdAt), status area, param summary chips, result section
Status areasqueued: "Waiting in queue…" icon; processing: progress indicator (indeterminate — no % from server); completed: result card; failed: error message + Retry
Pollauto-poll 2 s while queued/processing (see 10); stop on terminal
Permissionreport.read (forward-looking)
Errors404 → "Report not found" state + back; network → banner, poll paused, manual retry
Analyticsreports.job.status(jobId,status), reports.job.retry(jobId) (proposed)

5. Result View / Download (/reports/jobs/:jobId/result)

FieldDetail
PurposeRender completed result; export/share (planned)
Entryjob detail when completed
Result renderersreport card: subject table + grade badge; attendance: status count cards + totals; fee: 4 metric cards (reports.service.ts:154-158)
CTAs"Download CSV" / "Share PDF" (planned) — no export endpoint in code; "New report from these params" (re-POST)
Permissionreport.read
Emptycompleted with empty result → empty state (e.g. zero attendance records)
Analyticsreports.result.open(jobId), reports.result.download(jobId) (proposed)

6. Scheduled Reports entry (/reports/scheduled) (planned)

  • Server side exists: scheduler enqueues generate-attendance-report (attendance-report.job.ts:15-23), actorId: 'scheduler'. Admin UI to schedule/configure is (planned); today jobs just appear via job list (no UI today — see screen 3 gap).

Shared components used

AppListTile, AppBadge, AppButton, AppSkeleton, AppEmptyState, AppSnackbar, AppBottomSheet (filter), AppOfflineBanner, AppChips (params), AppMetricCard (module: fee summary), AppProgressRow (module: job status).

Analytics events (proposed)

reports.catalog.{open,select}, reports.generate.{submit,success,failure}, reports.job.{status,retry}, reports.result.{open,download}.

Keyboard / adaptive

  • Forms: portrait-first, keyboard-avoid; tablet two-column (form | live job preview).
  • Job detail: tablet master-detail with result inline; desktop max-width card.