high priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

A _CertMetadataSection private widget (or equivalent extracted widget) replaces the placeholder in the scaffold's loaded state, accepting a Certification model as its single required parameter
Issue date and expiry date are displayed in a human-readable locale-aware format (e.g., 'March 26, 2026') using the project's date formatting utility — no raw ISO strings shown to users
Certification type label (e.g., 'HLF Peer Mentor Level 1') is displayed using design token body text style
CertificationExpiryBadge is rendered in the header/top area of the metadata section; it receives the expiry date and certification status and renders the correct color (valid = green token, expiring soon = amber token, expired = red token) as defined by the foundation epic
All text elements have semanticsLabel set for screen reader accessibility (VoiceOver/TalkBack): e.g., 'Issue date: March 26, 2026', 'Expiry date: March 26, 2027', 'Certification type: HLF Peer Mentor Level 1'
Section uses only design token spacing constants (e.g., AppSpacing.md, AppSpacing.lg) — no hardcoded pixel values
Widget test verifies correct date formatting and CertificationExpiryBadge presence for each status variant (valid, expiring_soon, expired)
Section renders correctly at system font scale 1.0, 1.5, and 2.0 without text overflow or layout breakage

Technical Requirements

frameworks
Flutter
BLoC (data consumed from CertificationLoadedState)
intl package for date formatting
data models
Certification (issue_date, expiry_date, cert_type, status)
CertificationStatus enum (valid, expiring_soon, expired)
performance requirements
Section widget must be const-constructible where possible to avoid unnecessary rebuilds
security requirements
Expiry date and cert type are not considered PII — no special handling required for display
ui components
CertificationExpiryBadge (from foundation epic)
Text widgets with design token styles
Column/Row layout with design token spacing

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Extract the metadata section into a private widget _CertMetadataSection(Certification certification) to keep CertificationStatusScreen's build method readable. Use DateFormat from the intl package with the project's locale (check existing date usage in the codebase for the pattern). For semanticsLabel, wrap each Text in a Semantics widget with label set to the full human-readable string including the field name — this is critical for Blindeforbundet and NHF users who rely on screen readers. The CertificationExpiryBadge color logic should live in the badge widget, not in this section — pass only the status enum.

Check the design token file for the correct color constant names before writing — do not approximate with Color(0xFF...) literals.

Testing Requirements

Widget tests: (1) supply a Certification with status=valid — assert badge shows correct color token class and issue/expiry dates are formatted correctly; (2) status=expiring_soon — assert amber badge variant; (3) status=expired — assert expired badge variant. Test large font scale by setting MediaQuery textScaler to 2.0 and asserting no RenderFlex overflow errors. Use flutter_test's findsOneWidget for badge and date text assertions.

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.