Screens & Widgets topic

Screens & Widgets

The presentation layer is organized by feature area under lib/presentation/screens/. Navigation uses GoRouter with shell routes for persistent chrome.

Routing

The route table is declared in lib/config/routes.dart. Key patterns:

  • Named routes for every destination (/, /domains, /tutor, /review, /lesson/:id, /org, /settings/:section, …).
  • Auth guards via a redirect that inspects authStateProvider — unauthenticated users hit /auth/login, authenticated but onboarding-incomplete users hit /onboarding/<step>.
  • Shell routes wrap the post-auth tree in OrgShellScaffold, which owns the bottom nav / side rail and the AppBar. Routes that live outside the shell (auth, onboarding, lesson full-screen) declare themselves at the top level.
  • Deep links route into the same tree via Uri parsing — push notifications and OAuth redirects land directly on the right screen.

Screen categories

presentation/screens/
├── admin_onboarding/   Org admin 4-step setup wizard
├── auth/               Login, signup, MFA, password reset
├── backoffice/         Platform-admin-only views
├── domains/            Curriculum domain list + detail
├── goals/              Learning goals
├── home/               Landing screen with recent activity
├── lesson/             The core learning loop (Socratic + quiz + review)
├── notes/              User notes
├── onboarding/         5-step first-connection flow
├── org/                Organization admin screens
├── progress/           Progress dashboards (mastery, XP, streaks)
├── review/             Spaced-repetition review queue
├── settings/           User + org settings
├── setup/              BYO Supabase bootstrap (Management API)
└── tutor/              Free-form Socratic dialogue

Responsive layout

OrgShellScaffold swaps navigation primitives based on viewport width:

  • < 800 px — bottom NavigationBar (mobile / narrow web).
  • ≥ 800 px — side NavigationRail (tablet / desktop / wide web).

The viewport threshold is exported as a constant so pages can mirror it for their own responsive choices.

Key reusable widgets

Widget Purpose
web_content_frame.dart Centers + max-widths content on web so the app doesn't stretch across 4K screens. The most-imported widget in the codebase.
role_gate.dart Conditional render based on entitlement lookups. RoleGate(roles: [Role.admin], child: …).
notification_bell.dart AppBar bell icon with unread badge. Watches notificationProvider.
app_mode_toggle.dart Switch between learner and admin modes (the AppBar control shown in org mode).

Testing patterns

Widget tests live in test/presentation/ and use alchemist for golden-file comparisons (tagged golden). Integration tests (test/integration/, tagged integration) run against a local Supabase and exercise the full stack — see test/integration/ for the datasource-level test suite pattern.

Classes

OrgShellScaffold Screens & Widgets
Responsive shell for admin/manager org mode. Mirrors the personal ScaffoldWithNavBar layout but routes to /org/:orgId/* destinations.
RoleGate Screens & Widgets
Conditionally renders child based on the current user's org role.
WebContentFrame Screens & Widgets
Constrains content width on desktop while passing through on mobile.