Integrate notification cards with BLoC/Riverpod state layer
epic-assignment-follow-up-reminders-ui-task-007 — Connect both ReminderNotificationCard and CoordinatorEscalationNotificationCard to the shared notification BLoC/Riverpod providers established in the foundation epic. Ensure cards react to real-time state changes (new reminders arriving, escalations resolved), handle loading and error states gracefully, and clean up subscriptions on widget disposal to prevent memory leaks.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use ConsumerWidget (Riverpod) or BlocBuilder (BLoC) — whichever matches the foundation epic's established pattern — to connect cards to state. If using Riverpod, prefer ref.watch(reminderNotificationsProvider) with select() to narrow rebuilds. If using BLoC, use BlocSelector. For Supabase Realtime, the subscription should be established in the provider/BLoC, not in the widget layer — this ensures proper lifecycle management.
The widget should only react to emitted states, never manage subscriptions directly. Use AutoDispose providers (Riverpod) or close() in BLoC's close() override to handle cleanup. For AnimatedList, maintain a local list in the widget's state synced to the provider's list, using AnimatedList.of(context).removeItem() for removal animations. Avoid calling setState after dispose by checking mounted before any async callback.
Testing Requirements
Write flutter_test widget tests covering: (1) cards render correctly when provider emits loaded state, (2) skeleton shown when provider is in loading state, (3) error widget shown when provider emits error, (4) card list updates when a new reminder is emitted, (5) escalation card is removed when escalation is resolved in state. Use Riverpod ProviderScope overrides or BLoC's MockBloc to inject controlled state sequences. Verify no lingering subscriptions by asserting provider dispose callbacks are called. Integration test (using flutter_test's integration_test package): subscribe a test Supabase Realtime channel, emit a test event, assert the card list updates.
The deep-link from the notification card to the assignment detail screen depends on the assignment detail route being stable and accepting an assignment ID parameter. If the routing contract is undocumented or changes during parallel development, the CTA will silently navigate to a fallback screen.
Mitigation & Contingency
Mitigation: Confirm the assignment detail route path and parameter contract with the team building or maintaining that screen before implementing the CTA. Add an integration test that asserts navigating from a mock notification card with a known assignment ID lands on the correct route.
Contingency: If the route is unstable, implement the deep-link as a late-bound string resolved from a central route registry, allowing the target route to be updated without changing the notification card.
Visually distinguishing escalation cards from standard reminder cards using colour alone fails WCAG 1.4.1 (use of colour). Blindeforbundet users relying on screen readers must receive equivalent contextual information through semantics, not just visual styling.
Mitigation & Contingency
Mitigation: Use both colour and an icon/label difference to distinguish card types. Add explicit Semantics widgets with descriptive labels ('Escalation alert: peer mentor has not responded') so screen readers announce the type without visual context.
Contingency: If accessibility review flags the distinction, add a text badge ('Escalation') alongside the visual treatment as a code-change-only fix with no schema or service impact.