high priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

QR code renders correctly using the mentor's unique referral code string fetched from ReferralCodeService provider
QR widget uses qr_flutter package and displays a minimum 200x200 logical pixel canvas
QR code foreground color meets WCAG 2.2 AA contrast ratio (≥4.5:1) against its background using design token colors
Loading state is displayed while the Riverpod provider is in AsyncLoading state — spinner centered in the QR placeholder area
Error state displays a descriptive message and a retry button if the provider returns AsyncError
QR code is surrounded by sufficient white/light quiet zone (minimum 4 modules) to ensure scanability
Widget has a Semantics wrapper with a meaningful label (e.g., 'QR code for your referral link') for screen reader users
QR code is not interactive by itself (no tap handler) — surrounding container meets 48x48dp minimum touch target only if wrapped in a tap action in future tasks
Widget rebuilds automatically when provider emits a new referral code value
QR code is scannable and resolves to the correct referral URL when tested with a physical device camera

Technical Requirements

frameworks
Flutter
Riverpod
apis
ReferralCodeService (internal Riverpod provider)
data models
assignment
performance requirements
QR widget renders within one frame after provider data is available (no jank)
Provider state subscription must not cause unnecessary rebuilds — use ref.watch on a scoped provider
security requirements
Referral code data is non-sensitive per qr_flutter security posture — safe to render client-side without encryption
QR data URL must be validated before encoding to prevent injection (validate URL format before passing to qr_flutter)
ui components
QrImageView (qr_flutter)
AsyncValueWidget (or equivalent pattern for Riverpod async states)
CircularProgressIndicator (loading state)
ErrorStateWidget with retry action

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use `ref.watch(referralCodeServiceProvider)` and handle all three AsyncValue states with `.when(data:, loading:, error:)`. Pass the code string directly to `QrImageView(data: code, size: 220, ...)`. Use `Theme.of(context)` design tokens for foreground/background colors rather than hardcoded hex values so the widget adapts to theme changes. Wrap the QrImageView in a `Semantics` widget with `label` set to a localized string.

Do not use `QrPainter` directly — `QrImageView` is the preferred high-level API. Ensure the quiet zone is not clipped by adding padding around the widget container.

Testing Requirements

Write widget tests using flutter_test. Test (1) QR widget renders when provider returns a valid code string, (2) loading spinner appears when provider is AsyncLoading, (3) error widget with retry button appears when provider is AsyncError, (4) Semantics tree contains the correct QR label. Use ProviderScope overrides to inject mock provider states. Manually verify WCAG contrast on both light and dark device themes.

Physically scan the rendered QR on a real device to confirm URL resolution. Target 90%+ branch coverage on ReferralCodeScreen QR section.

Component
Referral Code Screen
ui medium
Epic Risks (3)
medium impact medium prob technical

QR codes rendered at the minimum 200×200 size may fail to scan under typical indoor lighting conditions on older or lower-resolution phone cameras, causing recruitment moments to fail when a peer mentor shows the screen to a prospective member.

Mitigation & Contingency

Mitigation: Set the default QR render size to 260×260 logical pixels (not the 200px minimum) and apply a high-contrast white module background. Test scan reliability on at minimum three physical devices (budget Android, mid-range Android, iPhone SE) before marking the screen as done.

Contingency: If scan reliability remains an issue, add a 'Enlarge QR' full-screen mode triggered by tapping the code, and ensure the text referral URL with copy-to-clipboard is always visible as a fallback sharing method.

high impact medium prob integration

The onboarding screen submits attribution and then hands off to an external membership registration URL (HLF's Dynamics portal or similar). If the external URL is unavailable, changes its format, or requires authentication the new member does not have, the conversion funnel is broken at its final step.

Mitigation & Contingency

Mitigation: Confirm the external registration URL and its expected query parameters with HLF's portal team before implementing the handoff. Record the pending_signup attribution event before launching the URL so data is not lost if the external site fails. Display a fallback message with contact information if the URL launch fails.

Contingency: If the external membership URL is not available at feature launch, implement a temporary form that collects name and email and stores a pending_member record in Supabase, allowing coordinators to manually complete registration while the integration is finalised.

low impact medium prob integration

Embedding the RecruitmentStatsWidget on the peer mentor home screen may conflict with existing layout components (activity summary, badge shelf), causing overflow or requiring a redesign of the home screen that is outside this epic's scope.

Mitigation & Contingency

Mitigation: Design the widget as a horizontally constrained card with a maximum height of 96dp so it can be inserted into any vertical list without overflow. Coordinate with the home screen's existing layout owners before starting the embedding task.

Contingency: If home screen embedding creates unacceptable layout conflicts, defer embedding to a separate home-screen redesign task and make the widget accessible only via the dedicated ReferralCodeScreen for the initial release.