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

10 — Interaction Specification (Dashboard Module)

Micro-interaction rules for the dashboard. Motion tokens Mo.* per 00-shared/02 §6; shared interaction patterns per 00-shared/08. State flow per 13_State_Management.md; component contracts per 07_Component_Library.md.


1. Load sequence (first open)

  1. Route push Mo-m-base slide+fade; AppBar immediately visible.
  2. KPI row area renders 5 AppSkeleton cards (value 28 dp line + label 12 dp, shimmer Mo-m-fast), charts render AppSkeleton(chart).
  3. Payload arrives → skeletons swap for values with staggered fade-in (30 ms apart, row order = service order dashboard.service.ts:31-33,34,35-37); chart blocks animate draw Mo-m-base ((planned) blocks).
  4. Failure on first load → AppErrorState.code + Retry; retry re-runs the sequence from 2. No partial numbers.

2. Pull-to-refresh

  • AppRefreshIndicator wraps the scroll view; trigger calls cubit refresh() with force: true — bypasses client cache (00-shared/06 §3.3), network fetch, cache-write on success.
  • During refresh: cards stay painted (no skeleton flash); only the indicator spins. Success → silent replace AnimatedSwitcher 200 ms. Failure with existing data → AppSnackbar(error) ≥ 4 s, numbers unchanged.
  • Double pull while in-flight → ignored (single-flight guard, 13_State_Management.md §3).

3. Background polling

  • Timer: 60 s (matches cache TTL Dashboard.md:41), active only while the dashboard route is current and app is foregrounded.
  • Tick → refresh() non-forced: if client cache age < 60 s, skip (no request). Else fetch.
  • App backgrounded (WidgetsBindingObserver) → timer paused; on resume, staleness check runs immediately.

4. WebSocket-triggered refresh

  1. Client subscribed to tenant:{tenantId} room (auto-join on connect — ws.gateway.ts:50); listens for AttendanceMarked, ResultPublished, PaymentRecorded, InvoiceGenerated (Dashboard.md:34).
  2. Event arrives → debounce 2 s (coalesce bulk event bursts) → refresh(force: true).
  3. If the overview key was invalidated server-side (planned), the fetch naturally re-reads Redis; today the service live-scans (dashboard.service.ts:24-38) so the refetch simply gets fresh numbers.
  4. Value deltas ≥ 1% animate (AnimatedSwitcher 200 ms) + live-region announcement (a11y). Sub-1% deltas update silently.
  5. Connection lost → rely on poll timer; banner AppOfflineBanner after 2 missed polls.

5. KPI card tap → drill

  • Whole card is the target (≥ 48 dp). Tap → Mo-m-base press ripple → route push to owning module: students list / teachers list / staff list / attendance day view / fees invoices filtered issued|partial|overdue (dashboard.service.ts:36-37).
  • Back → dashboard refetches on return (staleness check), preserving scroll position.
  • No permission for target module → card tap shows AppSnackbar "You don't have access to this section" (rare; hidden-by-permission prefers to omit the card entirely (planned)).

6. Stale-data surfaces

  • StaleBanner (info) slides in when rendering client-cached payload older than 60 s (Dashboard.md:41); shows age ("2 min ago") + Refresh.
  • ≥ 10 min → treated as offline: AppOfflineBanner + data kept.
  • On any successful refetch the banner animates out Mo-m-fast.

7. Customize screen (planned)

  • Entry IconButton (perm-gated dashboard.widget.managepermissions.constants.ts:38); route push.
  • Reorder: drag handle press Mo-m-fast; drop commits to list state; Save issues per-widget PATCH (Dashboard.md:27); per-item spinner; conflict → snackbar + reload. No auto-save on drag.

8. Empty-state interactions

  • Zero KPI cards: muted hint line; tap still drills (empty target screens show their own AppEmptyState).
  • All-zero dashboard: hero AppEmptyState "Your dashboard is ready — add your first data" with primary action → Students module.

9. Keyboard / focus

  • Dashboard has no text fields (except (planned) customize search); Tab order: KPI cards → charts (focusable with caption) → AppBar actions.
  • Enter activates focused card. Escape returns from detail routes.

10. Motion budget

InteractionToken
Route enter/exitMo-m-base
Skeleton shimmerMo-m-fast
Value update (WS/poll)200 ms AnimatedSwitcher
Stale/offline bannerslide-in Mo-m-fast
Chart draw (planned)Mo-m-base
Press rippleMo-m-fast