high priority low complexity frontend pending frontend specialist Tier 4

Acceptance Criteria

Navigating to the peer mentor detail screen always triggers a LoadPeerMentorDetail event with the correct mentorId from route parameters
BlocProvider wrapping PeerMentorDetailScreenWidget creates a fresh BLoC instance per navigation push — no singleton BLoC shared across screens
Navigating away from the screen disposes the BLoC — confirmed by override of BLoC close() logging in debug mode
Navigating back and then to the same mentor re-creates the BLoC and re-fetches data (no stale state from previous visit)
mentorId is extracted from the GoRouter route parameter, not from navigator arguments, for consistency with the app's routing architecture
If mentorId is missing or empty in route params, the screen navigates back or shows an error state rather than crashing
BLoC creation is performed in the BlocProvider.create callback, not in a StatefulWidget's initState, to follow flutter_bloc best practices
The LoadPeerMentorDetail dispatch is triggered via a BlocProvider lazy-false pattern or via the screen widget's initState using context.read<PeerMentorDetailBLoC>().add()

Technical Requirements

frameworks
Flutter
flutter_bloc
go_router
Riverpod
data models
PeerMentorDetailEvent
performance requirements
BLoC creation and initial event dispatch must complete within the first frame of screen mount — no deferred initialization
security requirements
mentorId from route parameters must not be trusted as an authorization token — the BLoC/service layer enforces RLS via the authenticated Supabase client
ui components
BlocProvider
BlocBuilder
PeerMentorDetailScreenWidget

Execution Context

Execution Tier
Tier 4

Tier 4 - 323 tasks

Can start after Tier 3 completes

Implementation Notes

In GoRouter, define the route as: `GoRoute(path: '/peer-mentor/:mentorId', builder: (context, state) { final mentorId = state.pathParameters['mentorId']!; return BlocProvider(create: (_) => PeerMentorDetailBLoC(service: ...) ..add(LoadPeerMentorDetail(mentorId)), child: PeerMentorDetailScreenWidget()); })`. The `..add()` cascade on `create` is the idiomatic flutter_bloc pattern for auto-triggering the initial load. Obtain the `PeerMentorAggregationService` inside the `create` callback using `context.read()` if using Riverpod+BLoC hybrid, or via a Riverpod `ref` passed from the route. If the app uses `ConsumerWidget` for Riverpod at the route level, wrap the builder in a `Consumer` to access `ref` for service injection.

Do not use `context.read` inside the widget's build method for BLoC operations.

Testing Requirements

Widget tests (flutter_test): (1) Mount screen with a valid mentorId route param — assert BLoC receives LoadPeerMentorDetail event with matching mentorId. (2) Mount screen with empty mentorId — assert navigation back or error state displayed, no crash. (3) Dispose test — pump screen, then remove from tree; assert BLoC.isClosed is true. (4) Re-navigate test — push screen twice for different mentorIds; assert each instance has its own BLoC with the correct mentorId.

Use a mock BLoC (via mocktail or manual) to intercept events without running real service logic.

Component
Peer Mentor Detail BLoC
service medium
Epic Risks (3)
medium impact medium prob technical

The parallel Future.wait aggregation pattern may produce race conditions or incorrect merged state when some repositories resolve significantly faster than others, particularly if the BLoC receives a RefreshDetail event while a prior fetch is still in flight.

Mitigation & Contingency

Mitigation: Implement cancellation token pattern in the aggregation service to abort in-flight fetches on new events. Add BLoC test scenarios for rapid successive refresh events to validate state consistency.

Contingency: If race conditions persist, switch to a sequential-with-timeout fetch strategy for the first release and profile the performance impact before deciding whether parallel fetch optimization is worth the complexity.

medium impact medium prob integration

Integrating PeerMentorDetailScreenWidget into the existing StatefulShellRoute navigation structure may conflict with the Contacts tab's existing route hierarchy, requiring changes to navigation-route-config that could affect other teams' features.

Mitigation & Contingency

Mitigation: Coordinate with the Contact List and Contact Detail feature teams before adding the new route. Review the existing StatefulShellRoute configuration and confirm the peer mentor detail route can be nested under the Contacts branch without path conflicts.

Contingency: If route conflicts arise, temporarily implement the peer mentor detail as a modal overlay (push route) rather than a shell route child, preserving functionality while the navigation architecture conflict is resolved.

low impact high prob dependency

The course enrollment screen that the certification alert banner links to may not yet exist or may be implemented in a separate feature epic, leaving a broken navigation tap for HLF users in the initial release.

Mitigation & Contingency

Mitigation: Check the certification management feature implementation status before finalizing Epic 4 scope. If the enrollment screen is not available, design the tap action to open the HLF course enrollment URL in an external browser as an interim solution.

Contingency: Implement the CTA as a configurable action: if the enrollment route exists in the router, push it; otherwise, launch the configured org-specific enrollment URL via url_launcher, ensuring HLF users can always take action on expired certifications.