high priority medium complexity frontend pending frontend specialist Tier 6

Acceptance Criteria

Tapping any row in PeerMentorStatsList navigates to PeerMentorStatsScreen scoped to the tapped peer mentor's userId
The current time window selection (e.g., last 7 days, last 30 days) is passed as a route parameter and pre-selected on the drill-down screen
Pressing the system or in-app back button from the drill-down screen returns the user to CoordinatorStatsScreen with the previously selected time window intact (not reset to default)
The drill-down screen title or header clearly identifies the peer mentor by display name, not raw userId
Route parameters are type-safe (userId: String, timeWindow: TimeWindowEnum) and validated on entry; invalid parameters render an error state rather than crashing
Deep-linking directly to the peer mentor drill-down URL/route resolves correctly without requiring prior coordinator screen visit
No duplicate provider instances are created during navigation; the drill-down screen reads from a scoped provider override, not a second global instance
Rapid tap-and-back does not cause flickering, duplicate pushes, or navigation stack corruption
State is preserved correctly after app backgrounding and foregrounding mid-drill-down

Technical Requirements

frameworks
Flutter
Riverpod
go_router or Navigator 2.0
data models
PeerMentorStats
TimeWindow
UserProfile
performance requirements
Navigation transition completes within 300ms on mid-range devices
Drill-down screen renders initial shimmer within one frame of push
No jank during hero/slide transition — avoid rebuilding heavy widget trees on push
security requirements
userId passed via route must be validated against the coordinator's authorised peer mentor list before data is fetched; reject and show error if not in scope
Route parameters must not expose sensitive PII in navigation logs; use opaque userId references only
ui components
PeerMentorStatsList (onTap handler wiring)
PeerMentorStatsScreen (reused, scoped to userId)
TimeWindowSelector (pre-selected from route param)
AppBar back button with state-restoration callback

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Use Riverpod's ProviderScope override pattern to scope the peer mentor stats provider to the selected userId — wrap PeerMentorStatsScreen in an `OverrideWithValue` scope so no global state is mutated. Persist the coordinator screen's time window in a StateNotifier (not ephemeral widget state) so it survives the push/pop cycle. If using go_router, declare the drill-down as a sub-route of the coordinator stats route with typed GoRouteData for compile-time safety. Avoid passing entire model objects through routes; pass only the userId string and resolve the display name from an already-loaded provider cache.

Add a NavigatorObserver or route-aware hook to detect back-navigation and trigger a lightweight refresh check (e.g., compare last-updated timestamp) rather than a full refetch.

Testing Requirements

Widget tests: verify onTap on a PeerMentorStatsList row invokes navigation callback with correct (userId, timeWindow) arguments using a mock GoRouter/NavigatorObserver. Verify that upon pop the parent screen's TimeWindowSelector still reflects the pre-drill-down selection. Unit tests: test route parameter parsing and validation logic for invalid userId and null timeWindow. Golden tests: capture drill-down screen for a mocked peer mentor to detect unintended layout regressions.

Edge cases: test navigation with a peer mentor who has zero activities, and with the maximum allowed time window.

Component
Coordinator Stats Screen
ui high
Epic Risks (4)
high impact high prob technical

fl_chart renders chart elements on a Canvas, making individual bars and data points invisible to the Flutter Semantics tree by default. Without explicit Semantics wrappers, VoiceOver and TalkBack users receive no chart information, violating the WCAG 2.2 AA requirement mandated by all three partner organizations.

Mitigation & Contingency

Mitigation: Wrap the fl_chart widget in a Semantics node with a dynamically generated textual description of the chart data (e.g., 'Bar chart: January 12, February 8, March 15 sessions'). Implement a collapsible data table alternative beneath the chart that screen readers can navigate row by row. Validate with VoiceOver on iOS and TalkBack on Android before the epic is marked complete.

Contingency: If fl_chart's Canvas rendering cannot be made accessible within the epic timeline, ship the chart hidden from the Semantics tree with ExcludeSemantics and promote the data table alternative to first-class UI so screen reader users have full access to the information. Log a tech-debt item to revisit native chart accessibility in a future sprint.

medium impact medium prob scope

Coordinators managing up to 5 chapters (NHF requirement) require the PeerMentorStatsList to display chapter affiliation labels for each row. With large chapter lists and many peer mentors, the list could become overwhelming and cause layout overflow or scrolling performance issues on lower-end Android devices.

Mitigation & Contingency

Mitigation: Implement chapter filtering as a segmented control above the list so coordinators can scope the list to one chapter at a time. Use ListView.builder (lazy rendering) rather than a Column of all rows. Profile scroll performance on a low-end Android device (Pixel 4a equivalent) with 50 peer mentors in scope during development.

Contingency: If multi-chapter display causes unacceptable performance, ship with single-chapter scope as the default view and a chapter switcher dropdown, deferring the combined cross-chapter list to a follow-up sprint.

low impact low prob technical

Summary cards and the chart widget rebuilding simultaneously on provider state change could cause a visible jank frame on slower devices, degrading perceived quality especially since this screen is intended to feel motivating and polished for gamification purposes.

Mitigation & Contingency

Mitigation: Use AnimatedSwitcher with a short fade transition (150ms) on the stats cards and chart so that data replacement feels intentional rather than jarring. Profile with Flutter DevTools on a mid-range device and ensure no frame exceeds 16ms during a time-window switch.

Contingency: If animation introduces complexity that delays delivery, ship without animation and use a loading skeleton (shimmer effect) during re-fetch instead, which is simpler and equally effective at masking the data swap.

high impact low prob security

If the role-based screen dispatch is misconfigured, a peer mentor could navigate to the coordinator stats screen and see aggregated chapter data for all peer mentors, which is a data privacy violation and a compliance risk for all three organizations.

Mitigation & Contingency

Mitigation: Implement role guard at the router level using an existing role-route-guard component so the coordinator screen route is unreachable for peer mentor roles. Add a widget test that mounts the coordinator screen with a peer mentor session token and asserts that the guard redirects to the no-access screen.

Contingency: If a bypass is found in QA, add a secondary in-screen role assertion in the coordinator screen's initState that throws an AuthorizationException and navigates to the error screen, ensuring defence in depth regardless of router configuration.