Scaffold scenario notification detail view screen
epic-scenario-push-engagement-ui-task-008 — Create the read-only scenario-notification-detail-view screen reachable from the notification centre or a push tap. Build the layout with a page header, scenario type label section, human-readable trigger explanation section, contextual data section (days inactive, certification expiry date, session count), and a primary CTA button placeholder. Use HtmlGenerationUtils-equivalent Flutter layout patterns and design token spacing.
Acceptance Criteria
Technical Requirements
Implementation Notes
Define a ScenarioNotificationDetailArgs data class (scenario_type, trigger_explanation, days_inactive int?, certification_expiry_date DateTime?, session_count int?) to type-safe the route arguments. Pass the full args object via GoRouter's extra field to avoid URI-encoding complex data. If the notification detail must be fetched from Supabase (args only contains an ID), use a FutureProvider
The CTA button should fire a no-op onTap in this scaffold task; wire real navigation in the subsequent epic task. Register the route in the project's GoRouter configuration file under the authenticated shell route so the auth guard applies automatically.
Testing Requirements
Write widget tests: render the screen with a full ScenarioNotificationDetailArgs object and assert all five sections are present in the widget tree. Render with null days_inactive and assert the days-inactive row is absent. Render with all contextual data null and assert no 'null' text is visible anywhere. Test that the CTA button is present and tappable (onTap fires without error in placeholder state).
Test the route: navigate to /notifications/scenario/test-id via GoRouter test harness and assert the screen is pushed. Golden test for light and dark themes. Manual accessibility check: run Flutter DevTools Accessibility inspector and confirm no contrast violations on both themes.
The in-app notification banner depends on a Supabase Realtime subscription to detect new notification records. If the subscription reconnects slowly after an app resume from background, or if Realtime delivery is delayed under high load, the banner may not appear within the 2-second acceptance criterion.
Mitigation & Contingency
Mitigation: Implement an explicit subscription reconnect handler on app foreground events using Flutter's AppLifecycleState.resumed hook, and add a polling fallback that queries for unread notifications once per app foreground event as a safety net against missed Realtime events.
Contingency: If Realtime proves unreliable in production, promote the polling fallback to the primary mechanism with a 30-second interval, accepting slight latency in exchange for reliability.
Cold-start deep linking (app not running when push notification is tapped) requires deferred navigation after the Flutter engine and Supabase session are fully initialised. If the deep link is consumed before authentication completes, the router may navigate to a protected route without a valid session, causing an error or redirect loop.
Mitigation & Contingency
Mitigation: Implement a deferred navigation queue in scenario-deep-link-router that holds the parsed deep-link target until the auth session restoration lifecycle event fires, following the existing deep-link-handler pattern used in the BankID and Vipps authentication flows.
Contingency: If deferred navigation is not achievable within the epic's scope, fall back to navigating the user to the notification centre (which is always accessible post-login) where the relevant notification record is visible and tappable.