high priority low complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

Widget renders a filled circle indicator using design token colors: active → success color token, paused → warning color token, expired_cert → error color token
Compact mode: circle indicator (12px) + short status label (e.g. 'Paused') in a single Row — suitable for list tiles
Expanded mode: circle indicator (16px) + full status label + optional return date line (e.g. 'Expected return: 15 Apr 2026') in a Column
When expectedReturnDate is null and status is 'paused', expanded mode displays 'Indefinite pause' as the return date line
Semantics widget wraps the entire indicator with a label string combining status and return date (e.g. 'Status: Paused, expected return 15 April 2026') for screen readers
Widget accepts DisplayMode enum parameter (compact / expanded) with compact as default
All text uses design token typography — no hardcoded font sizes
Contrast ratio between indicator color and background meets WCAG 2.2 AA (4.5:1 for text, 3:1 for UI components)
Widget is stateless — receives PauseStatus and DateTime? as constructor parameters
Golden tests exist for all three status states in both compact and expanded modes (6 golden images total)

Technical Requirements

frameworks
Flutter
flutter_test (for golden tests)
data models
PauseStatus (enum)
PauseRecord (for expectedReturnDate extraction)
performance requirements
Widget build time must not cause jank — ensure no expensive operations in build()
Widget must rebuild correctly when status prop changes (stateless, no internal state)
security requirements
Do not display mentor PII (name, ID) within the indicator widget itself — it is a status indicator only
ui components
PauseStatusIndicator (this widget)
Design token color constants (AppColors.success, AppColors.warning, AppColors.error)
Design token typography (AppTextStyles.labelSmall, AppTextStyles.labelMedium)
Semantics (Flutter built-in)

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Keep this widget purely presentational — it must not read from any BLoC, Riverpod provider, or Supabase directly. Pass all data as constructor parameters. Use a switch expression on PauseStatus to resolve colors and labels cleanly. For the Semantics label, build a descriptive string in the widget's build method: 'Status: ${_statusLabel(status)}${_returnDateLabel(expectedReturnDate)}'.

Store status label strings in a constants file or use the organisation labels system if localised terminology is needed per organisation. The compact/expanded distinction should be controlled by a DisplayMode enum, not a bool, to allow future addition of a third mode (e.g. 'badge'). Reference the existing AppButton and AppTextField for design token usage patterns.

Testing Requirements

Write widget tests using flutter_test. Test: (1) Compact active renders green dot and 'Active' label. (2) Compact paused renders amber dot and 'Paused' label. (3) Compact expired_cert renders red dot and 'Expired Certificate' label.

(4) Expanded paused with return date shows date string. (5) Expanded paused without return date shows 'Indefinite pause'. (6) Semantics label is correct for each state (use find.bySemanticsLabel). (7) Widget renders correctly when wrapped in a dark theme.

Generate golden test images for all 6 state/mode combinations and commit them as baseline. Verify WCAG contrast ratios using a contrast-checking utility or manual inspection against design tokens.

Component
Pause Status Indicator
ui low
Epic Risks (3)
medium impact medium prob technical

Concurrent status transitions (e.g., coordinator and automated scheduler both attempting to update the same mentor's status simultaneously) may produce race conditions or inconsistent state in the database, leading to audit log gaps or incorrect notifications.

Mitigation & Contingency

Mitigation: Implement all status transitions as atomic Postgres RPC functions with optimistic locking (version column or updated_at check). Use database-level constraints rather than application-level guards as the final enforcement point.

Contingency: Add a compensation job that reconciles status and log table consistency on each nightly scheduler run, surfacing any discrepancies to coordinator dashboards.

medium impact medium prob integration

The coordinator-to-mentor assignment relationship may not always be 1:1 or may be stale (coordinator reassigned after a pause was set), causing notifications to be sent to the wrong coordinator or not sent at all.

Mitigation & Contingency

Mitigation: Query the assignment relationship at notification dispatch time rather than caching it at pause creation time. Add a fallback to notify the chapter administrator if no active coordinator assignment exists.

Contingency: Log all undeliverable notification attempts with the originating mentor ID so administrators can manually follow up, and surface undelivered notification counts on the coordinator dashboard.

medium impact low prob technical

The CoordinatorPauseRosterScreen may load slowly for coordinators managing large rosters with many concurrent certification expiry queries, degrading usability on low-bandwidth mobile connections.

Mitigation & Contingency

Mitigation: Use a single Supabase RPC that joins mentor status, certification expiry, and assignment data in one query rather than N+1 individual calls. Implement pagination with a configurable page size and skeleton loading states.

Contingency: Add an offline cache of the last-fetched roster state using Riverpod with SharedPreferences, ensuring coordinators can at minimum view stale data when connectivity is poor.