Implement No-Access Screen for global admins
epic-role-based-access-control-ui-and-navigation-task-005 — Build the NoAccessScreen widget displayed when a global admin authenticates. The screen must show a clear, friendly message explaining that the mobile app is not the correct entry point for global admins, provide a deep link or button directing to the admin portal URL, and meet WCAG 2.2 AA contrast and semantics requirements.
Acceptance Criteria
Technical Requirements
Implementation Notes
NoAccessScreen is intentionally simple — resist adding complexity. It is a dead-end screen for a narrow user segment (global admins who accidentally open the mobile app). The tone should be helpful and clear, not alarming — something like: 'You're set up as a global admin. To manage your organisation, please use the admin portal.' followed by a link button.
Store the admin portal URL in a constants file or app configuration (AppConfig.adminPortalUrl) so it can be environment-overridden in staging. Use url_launcher's launchUrl() with LaunchMode.externalApplication to open in the browser rather than an in-app WebView — global admins should be fully in their browser context for admin tasks. Ensure the Sign Out button uses the same logout flow as the settings screen to avoid divergence. Apply design tokens for all colors and typography — do not hardcode any hex values or font sizes.
Testing Requirements
Widget tests using flutter_test. Test: (a) screen renders with correct heading, body text, and both buttons visible, (b) portal CTA button tap calls url_launcher with the correct admin portal URL — mock url_launcher and assert the launched URL, (c) Sign Out button tap triggers auth sign out and navigates to auth screen — use NavigatorObserver and mock the auth provider, (d) bottom nav and hamburger menu are NOT present in the widget tree. Accessibility test: assert Semantics nodes exist with non-empty labels on both buttons. Contrast check: use flutter_test's finder to verify text widgets use design token color values (not hardcoded), as a proxy for contrast compliance.
Combining GoRouter's declarative redirect logic in the route guard with StatefulShellRoute's stateful branch management is known to produce subtle bugs where the shell rebuilds unnecessarily on role switches, losing tab state or causing double-navigation events.
Mitigation & Contingency
Mitigation: Implement the route guard as a GoRouter redirect callback that only evaluates role from an already-resolved Riverpod provider (not async). Use a dedicated ShellRoute navigator key per tab branch to anchor state independently of role-driven rebuilds. Write integration tests for the full navigation graph.
Contingency: If StatefulShellRoute state loss is confirmed during QA, fall back to a manual tab state preservation approach using a TabStateManager service that caches the last route per tab and restores it after role switches, decoupling tab state from the shell lifecycle.
The role-based home screen must render three significantly different layouts (coordinator dashboard, peer mentor activity summary, org admin overview). If these variants are implemented as a single widget with conditionals, the file will become unmaintainable and difficult to test in isolation, especially as each variant grows with downstream feature additions.
Mitigation & Contingency
Mitigation: Design the role-based home screen as a router/dispatcher widget that delegates to three separate variant widgets (CoordinatorHomeView, PeerMentorHomeView, OrgAdminHomeView). Each variant is independently testable and can be developed by separate team members in parallel.
Contingency: If variant coupling has already occurred before this risk is addressed, refactor to the dispatcher pattern in a dedicated cleanup task before feature handoff. The dispatcher pattern is a straightforward extraction that carries low refactoring risk.
The no-access screen must link global admin users to the correct admin portal URL, which may differ per organization (NHF, HLF, Blindeforbundet each have their own admin portals). Hardcoding a single URL will result in wrong or broken links for some global admin users.
Mitigation & Contingency
Mitigation: Source the admin portal URL from the organization's configuration record in Supabase rather than hardcoding it. The no-access screen reads the active org context and resolves the portal URL dynamically. Provide a safe fallback to a generic Norse Digital Products support page if the URL is not configured.
Contingency: If dynamic URL resolution is not ready when the no-access screen ships, display a static instruction to contact the organization's administrator along with a support email address as an interim measure, and track the URL configuration task as a follow-up.