Build Scenario Notification Card widget shell
epic-scenario-based-follow-up-prompts-scheduler-and-ui-task-006 — Create the ScenarioPromptNotificationCard Flutter widget with Design System v3 dark-mode styling. The card must render in the notifications tab list, display scenario title, triggering activity summary snippet, a timestamp badge, and a primary CTA button. Use only CSS classes from styles.css — no inline styles.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Define the widget in lib/features/notifications/widgets/scenario_prompt_notification_card.dart. Accept ScenarioPromptNotification data class with fields: scenarioTitle (String), activitySnippet (String), dispatchedAt (DateTime), ctaLabel (String), scenarioId (String), activityId (String). Use design token constants from your token system (AppColors, AppTextStyles, AppSpacing) rather than hardcoded hex values. For the 2-line snippet truncation, use Text(snippet, maxLines: 2, overflow: TextOverflow.ellipsis).
For relative timestamp, compute in a helper: if < 60min show 'X minutes ago', if < 24h show 'X hours ago', else show formatted date. Wrap the CTA tap handler with an empty onTap: () {} stub — the actual deep-link implementation is task-007. Do not implement navigation logic in this widget.
Testing Requirements
Widget tests with flutter_test. Test cases: (1) widget renders all four elements (title, snippet, timestamp, CTA) given a fully populated ScenarioPromptNotification; (2) widget renders without error when activity snippet is empty string; (3) text scale factor 1.5 does not cause RenderFlex overflow — use MediaQuery override in test; (4) Semantics tree contains a label on the CTA button that includes the scenario title; (5) HTML tags in snippet string are stripped before render — verify rendered text contains no '<' characters; (6) golden test at 390px width in dark mode. Run goldens with: flutter test --update-goldens on first generation.
If the scheduler runs concurrently (e.g., two overlapping cron invocations due to edge function retry), duplicate prompts could be dispatched before the first run's history records are committed, breaking the deduplication guarantee.
Mitigation & Contingency
Mitigation: Use a Postgres advisory lock or unique constraint on (user_id, scenario_id, activity_ref) in the prompt history table to make concurrent writes idempotent; design the scheduler to check history inside a transaction.
Contingency: If concurrency issues persist in production, add a distributed lock via Supabase Edge Function concurrency limit (max_instances=1) for the evaluation function as a hard guard.
Coordinators may find scenario configuration unclear if trigger conditions are expressed as raw JSON or technical terminology, leading to misconfiguration and irrelevant prompts being sent to peer mentors.
Mitigation & Contingency
Mitigation: Design the ScenarioConfigurationScreen to display human-readable descriptions of each template's trigger condition (e.g., 'Send 3 days after first contact if wellbeing concern was flagged') rather than raw rule properties; validate with an HLF coordinator in a design review before implementation.
Contingency: If coordinators still misconfigure rules after launch, add a preview mode that shows a simulated prompt based on a test activity before the rule is enabled.