high priority medium complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

CertificationStatusScreen is a StatelessWidget that uses BlocBuilder<CertificationBLoC, CertificationState> as its top-level builder
Loading state renders a centred CircularProgressIndicator with a semantics label 'Loading certification status' for screen reader compatibility
Error state renders an error message widget using the design token error color, a retry button that dispatches LoadCertificationEvent to the BLoC, and the error message string from the state
Loaded state renders placeholder Container widgets (or SizedBox with labeled Text) for: metadata section, renewal history section, and action buttons section — each with a TODO comment referencing the task that will fill it
AppBar uses the project's shared AppBar widget/pattern, displays the title 'Certification Status', and includes a back navigation button
Widget tree passes flutter_test widget tests: loading, error, and loaded state each render without throwing; error retry button triggers the correct BLoC event
No hardcoded colors or text styles — all styling uses design token references
Screen is navigable via the existing router (add a named route or GoRouter path for CertificationStatusScreen)
Widget file is placed at lib/features/certification/screens/certification_status_screen.dart following the project's feature-based folder structure

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc package)
GoRouter for navigation
apis
CertificationBLoC — consume LoadCertificationEvent, CertificationLoadingState, CertificationLoadedState, CertificationErrorState
data models
CertificationState (BLoC state hierarchy)
performance requirements
Widget build method must be pure — no side effects; BLoC event dispatch only in callbacks or initState equivalents
Screen must render first frame within 16ms on mid-range device (no heavy synchronous work in build)
security requirements
Screen must only be accessible to authenticated users — ensure route is guarded by the existing auth guard/redirect in GoRouter
ui components
AppBar (shared)
CircularProgressIndicator (loading)
AppButton (retry, from shared widgets)
Placeholder Containers for metadata/history/actions sections

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Follow the existing screen pattern in the codebase (e.g., how ContactDetailScreen or PeerMentorDetailScreen wires BLoC). Use BlocBuilder rather than BlocConsumer at the top level since this screen has no one-off side effects in the scaffold — side effects (snackbars, navigation) will be added in later tasks via BlocListener wrapping the BlocBuilder. Keep the widget file under 150 lines at this stage — the scaffold should be thin. Place all BLoC state classes (CertificationLoadingState, CertificationLoadedState, CertificationErrorState) in a separate certification_state.dart file if they don't already exist, following the BLoC convention.

Register the GoRouter route in the appropriate router configuration file, using a path like /certification/:mentorId/status.

Testing Requirements

Widget tests using flutter_test. Write three widget tests: (1) pump CertificationStatusScreen with BLoC emitting CertificationLoadingState — assert CircularProgressIndicator is present and has correct semantics label; (2) pump with CertificationErrorState — assert error text is visible and tapping retry dispatches LoadCertificationEvent; (3) pump with CertificationLoadedState — assert none of the loading/error widgets are present and placeholder sections exist. Use a MockCertificationBLoC (via mocktail) to control emitted states. No golden tests required at this scaffold stage.

Component
Certification Status Screen
ui medium
Epic Risks (3)
high impact medium prob technical

Flutter date pickers have historically poor screen reader support (VoiceOver/TalkBack), which is especially critical for this feature given that HLF peer mentors may have hearing impairment and the broader user base includes people with visual impairments. An inaccessible date picker on RecordRenewalScreen could block coordinator workflows entirely.

Mitigation & Contingency

Mitigation: Evaluate and adopt a third-party accessible date picker widget with verified WCAG 2.2 AA support, or build a custom picker using Flutter Semantics wrappers following the pattern established by the accessibility epic. Test all date pickers against VoiceOver on iOS and TalkBack on Android before UI sign-off.

Contingency: If no accessible date picker is available in time, provide a manual text field fallback for date entry (ISO format with clear labelling) alongside the picker, ensuring keyboard and screen reader users are never blocked.

medium impact high prob scope

Course enrolment initiation may redirect the user to the external HLF course portal (deep link or browser), which breaks the in-app flow and may confuse users expecting a seamless experience. The course data structure from Dynamics may also not be available in a machine-readable format in time for the initial release.

Mitigation & Contingency

Mitigation: Agree with HLF on whether enrolment is in-app or via deep link before UI design begins. If course data is not available from Dynamics at launch, design the enrolment prompt as a placeholder CTA that links to the HLF course portal homepage with a clear label indicating the user is leaving the app.

Contingency: Ship the course enrolment prompt as a configurable deep link per org. If Dynamics integration is delayed, the feature flag for the enrolment section can be disabled without affecting the rest of the certification status screen.

medium impact medium prob scope

Coordinators may attempt to record a renewal with an expiry date earlier than the previous certification's expiry (e.g., data entry error), or attempt to back-date a renewal. Without strict validation, the renewal history timeline could become chronologically inconsistent and mislead peer mentors about their coverage.

Mitigation & Contingency

Mitigation: CertificationManagementService validates that new expiry_date > current date and new issue_date >= previous renewal's issue_date before persisting. Surface validation errors as plain-language messages on RecordRenewalScreen using the error_message_registry pattern.

Contingency: If invalid renewal entries are discovered in production (from pre-validation data), provide a coordinator-only correction flow (edit renewal entry) behind an admin feature flag to fix historical records without requiring a full reset.