Load notification record and render contextual data
epic-scenario-push-engagement-ui-task-009 — Wire scenario-notification-detail-view to scenario-notification-repository (579) via Riverpod to load the full notification record by ID. Render the scenario type label, human-readable trigger explanation text, and contextual data fields (days inactive since last activity, certification expiry date, session count) as read-only labelled rows using WCAG 2.2 AA compliant contrast and touch target sizing.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 1 - 540 tasks
Can start after Tier 0 completes
Implementation Notes
Use a FutureProvider.family keyed on the notification ID so the provider is automatically scoped and disposed with the route. Avoid using StateNotifier for a pure load-once read; FutureProvider.family is simpler and sufficient. The LabelledDataRow widget should accept a nullable String value and render '—' when null — centralising this logic prevents scattered null checks across the screen. Format dates using the intl package's DateFormat with the device locale; do not hardcode locale strings.
Trigger explanation text copy should live in the ARB localisation file, keyed by scenario type enum value, so it is translatable. Apply design tokens for all colours and spacing — do not use hardcoded hex values. Ensure the Riverpod provider ref.watch call is inside the build method, not initState, to correctly respond to provider state changes.
Testing Requirements
Write flutter_test widget tests covering: (1) loading state renders CircularProgressIndicator; (2) success state with full data renders scenario type label, trigger text, and all three contextual rows with correct formatted values; (3) success state with null contextual fields renders '—' placeholders without exceptions; (4) error state renders error message and retry button; (5) provider is called once on mount and not re-called on hot rebuild. Use mockito or mocktail to mock scenario-notification-repository. Verify contrast compliance using Flutter's SemanticsNode tree in widget tests where possible. No integration tests required at this subtask level — covered in task-012.
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.