critical priority high complexity frontend pending frontend specialist Tier 6

Acceptance Criteria

BlocBuilder<PeerMentorDetailBLoC, PeerMentorDetailState> wraps the entire screen body and rebuilds on every state change
Loading state renders a centered CircularProgressIndicator with a Semantics label 'Loading peer mentor details'
Full-error state renders a full-screen error widget displaying the error message and a retry button that dispatches LoadPeerMentorDetail
Loaded state renders the full assembled section layout with all sub-component sections visible
Partial-error state renders the assembled layout with per-section fallback widgets for each failed data slice (e.g., 'Assignment data unavailable', 'Profile data unavailable')
Fallback widgets for partial errors are visually distinct (muted color, italic or secondary text style) but do not collapse adjacent sections
No section is conditionally hidden solely because its data slice has a partial error — the section container always renders with either real data or fallback
State transitions from Loading → Loaded and Loading → Error are visually smooth with no layout jumps
BlocProvider is scoped above PeerMentorDetailScreenWidget so that BLoC lifetime matches the route
Widget does not directly call any repository or service — all data access is exclusively through BLoC events and states

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
data models
PeerMentorDetailModel
PeerMentorDetailState
PeerMentorDetailLoading
PeerMentorDetailLoaded
PeerMentorDetailError
PeerMentorDetailPartialError
performance requirements
BlocBuilder must use buildWhen to skip rebuilds when the state subtype and data reference are unchanged
Loading indicator must appear within one frame of the Loading state being emitted
Full error widget must not trigger any additional network calls on mount
security requirements
Error messages displayed in the full-error widget must not expose raw Supabase error codes or stack traces to the user
Partial-error fallback text must not leak which backend data source failed
ui components
CircularProgressIndicator (centered, with Semantics wrapper)
Full-screen error widget (icon + message + retry AppButton)
Per-section fallback widget (text with secondary styling)
BlocBuilder wrapper

Execution Context

Execution Tier
Tier 6

Tier 6 - 158 tasks

Can start after Tier 5 completes

Implementation Notes

Use a sealed class hierarchy for PeerMentorDetailState so that the BlocBuilder switch expression is exhaustive and the compiler enforces all branches. The partial-error state should carry a Map of sectionKey → errorMessage so the screen widget can look up fallback text per section without embedding error logic in BlocBuilder. Avoid nesting multiple BlocBuilders for different sections — use a single top-level BlocBuilder and derive all section data from the single emitted state. For the full-error retry button, dispatch the same LoadPeerMentorDetail event that the BLoC handles on initial load.

Do not use BlocListener for UI rendering — keep rendering purely in BlocBuilder. The fallback widget should be a small, reusable SectionFallbackWidget(message: String) so it can be tested independently.

Testing Requirements

Unit-test PeerMentorDetailScreenWidget using flutter_test and bloc_test. Pump the widget with a fake BLoC stub emitting each state in turn (Loading, Loaded, PartialError, Error) and assert the correct child widget tree is rendered using find.byType and find.text. Verify that the retry button in Error state dispatches LoadPeerMentorDetail. Verify that each partial-error section shows its fallback text while sibling sections still render their real data.

Use mockito or mocktail to mock the BLoC. Target 100% branch coverage across all four state branches.

Component
Peer Mentor Detail Screen
ui 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.