high priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

An 'Acknowledge' button is present on CoordinatorEscalationNotificationCard and is visually distinct from the 'View Assignment' CTA (different label, secondary button style)
Tapping 'Acknowledge' calls the Riverpod provider's acknowledge method with the correct notification ID
On successful acknowledgement, the Riverpod provider updates the notification record's status to 'acknowledged' in the in-app notification repository
The card is removed from the coordinator's notifications list immediately after successful acknowledgement (no stale card remaining)
Tapping 'View Assignment' invokes the onNavigate callback — it does NOT acknowledge the escalation automatically
Optimistic UI: the card is optimistically removed on acknowledge tap; if the repository call fails, the card is restored and an error message is shown
The acknowledge action is idempotent: calling it twice on the same notification ID does not produce an error or duplicate repository writes
A loading indicator (e.g., button spinner) is shown on the Acknowledge button during the async repository call
Widget tests confirm: acknowledge button dispatches the correct provider method, card is removed from list on success, card is restored on failure, loading state is displayed during async operation
No coordinator can acknowledge a notification belonging to another coordinator's scope — enforced via repository-level RLS in Supabase

Technical Requirements

frameworks
Flutter
Dart
Riverpod
apis
In-app notification repository API (acknowledgeEscalation)
data models
EscalationNotification (id, status, assignmentId)
EscalationNotificationState
performance requirements
Acknowledge button must show loading state within one frame of tap
Card removal animation must complete within 300 ms
security requirements
Acknowledge API call must include the authenticated coordinator's user ID — the backend (Supabase RLS) must reject cross-coordinator acknowledgements
Notification ID must be validated as a UUID before dispatching to the repository — reject malformed IDs client-side
ui components
Acknowledge AppButton (secondary style with loading state)
View Assignment AppButton (primary CTA)
Loading indicator (CircularProgressIndicator or button-embedded spinner)
Error SnackBar / Toast (project shared component)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Model the loading state directly in the Riverpod notifier: `AsyncValue` or a custom `EscalationAcknowledgementState` enum (idle, loading, success, error). The widget watches this state and renders the button accordingly — no `setState` in the widget. For the idempotency requirement, the repository's `acknowledgeEscalation` should use an upsert (Supabase `upsert` with `onConflict`) rather than a plain insert, so a double-tap is handled gracefully at the database level. Ensure the Acknowledge button is disabled (not just showing a spinner) during the in-flight request to prevent double submissions.

File location: extend `lib/features/notifications/widgets/coordinator_escalation_notification_card.dart` and update the corresponding Riverpod notifier under `lib/features/notifications/providers/escalation_notification_notifier.dart`.

Testing Requirements

Widget tests using flutter_test with a mocked Riverpod provider and mocked in-app notification repository (mocktail/ProviderScope override): (1) tapping Acknowledge dispatches acknowledgeEscalation with the correct notification ID; (2) loading spinner appears during async call; (3) card is removed from the notifications list on success; (4) card is restored and error snackbar shown when repository throws; (5) tapping View Assignment does not call acknowledgeEscalation. Use `ProviderScope` with overrides to inject mock providers in widget tests. All tests pass without a live Supabase connection.

Epic Risks (2)
medium impact medium prob integration

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.

medium impact medium prob technical

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.