critical priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

CoordinatorTeamSummaryBloc is defined with sealed state classes: CoordinatorTeamSummaryInitial, CoordinatorTeamSummaryLoading, CoordinatorTeamSummaryLoaded (with List<MentorSummaryModel> mentors, PeriodFilter activePeriod), and CoordinatorTeamSummaryError (with String message)
Events are defined: LoadTeamSummary(periodFilter), RefreshTeamSummary, and FilterByOutlier(bool showOnlyOutliers)
BLoC queries Supabase for all peer mentors in the coordinator's chapter scoped by the authenticated coordinator's organization and chapter
Each MentorSummaryModel includes: mentor_id, name, sessions_completed, hours_logged, isOutlier flag, outlier_reason (nullable string), and period reference
Outlier detection logic consumes output from the outlier detection service (dependency from task-003) and maps results onto the mentor list
Mentor list is sorted: outliers first (by severity/reason), then alphabetically by name
FilterByOutlier event toggles a filter that exposes only mentors with isOutlier == true when active
BLoC exposes a real-time stream; state updates are emitted within 300ms of receiving new Supabase data
Error state is emitted with a descriptive message on Supabase query failure, network timeout, or unexpected exception
BLoC is properly closed and stream subscription cancelled when widget is disposed
Unit tests pass for all state transitions with mocked Supabase repository

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
Dart
apis
Supabase REST/Realtime API — query peer_mentors, periodic_summaries tables filtered by coordinator chapter
data models
MentorSummaryModel
PeriodFilter
OutlierResult
CoordinatorProfile
performance requirements
Initial data load completes within 2 seconds on a standard 4G connection
State transition from LoadTeamSummary event to CoordinatorTeamSummaryLoaded emitted in under 300ms after data arrives
Supabase subscription must use selective channel filtering (chapter_id) to avoid over-fetching
security requirements
All Supabase queries must be scoped to the authenticated coordinator's chapter_id using Row Level Security (RLS)
Coordinator must not be able to access peer mentors from other chapters — RLS policy enforced server-side
No PII (full names, contact info) should be logged in BLoC debug output

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use sealed classes (Dart 3) for states to enable exhaustive pattern matching in the UI. Define an abstract TeamSummaryRepository interface injected into the BLoC constructor — do not call Supabase directly from the BLoC. This enables easy mocking in tests. The outlier detection service from task-003 should be injected as a second dependency (OutlierDetectionService) and called during data aggregation in the BLoC's _onLoadTeamSummary handler.

Use StreamSubscription stored as a field; cancel it in close(). For the real-time stream, use Supabase's .stream() or .on() channel scoped to the coordinator's chapter. Avoid emitting Loading state on refresh if data is already loaded — emit a CoordinatorTeamSummaryRefreshing sub-state or use a isRefreshing flag on the Loaded state to prevent UI flicker.

Testing Requirements

Unit tests using flutter_test and bloc_test package. Test all state transitions: Initial → Loading → Loaded (happy path), Loading → Error (Supabase failure, network timeout), Loaded → Loaded (refresh), Loaded → Loaded (filter toggle). Mock the Supabase repository using a fake/stub implementing the abstract repository interface. Verify mentor sort order: outliers first, then alphabetical.

Verify FilterByOutlier event produces a filtered sublist without mutating the full mentor list. Verify stream subscription is cancelled in close(). Target 100% branch coverage on BLoC logic.

Component
Coordinator Team Summary View
ui medium
Epic Risks (3)
medium impact medium prob technical

If the cached summary is from a prior period (e.g., previous quarter's card is still cached), the digest card could appear on the home screen with outdated numbers after a new period begins, confusing users who have already seen that data.

Mitigation & Contingency

Mitigation: In the SummaryCacheRepository, store the period_start and period_end alongside cached data. In the PeriodicSummaryCard BLoC, compare the cached record's period against the current date using PeriodCalculatorService. Only render the card if the cached summary belongs to the active period.

Contingency: If stale cards appear in production, push a hotfix that adds the period validity check to the BLoC and clears all cached summaries older than the current period boundary via a forced cache flush on next app launch.

medium impact medium prob technical

Using colour alone to distinguish underactive from overloaded mentors in the coordinator view would fail WCAG 1.4.1 (use of colour). This is especially critical for organisations serving users with colour vision deficiency.

Mitigation & Contingency

Mitigation: Always pair colour indicators with a text label or icon (e.g., a downward arrow + 'Underactive' text alongside the amber colour). Use the contrast-safe-color-palette design tokens throughout. Run the contrast-ratio-validator on all new colour combinations in CI.

Contingency: If an accessibility audit flags colour-only indicators post-launch, introduce icon-based indicators as a patch release and update the design token definitions to enforce the paired-indicator pattern going forward.

low impact medium prob integration

Inserting a new card into the role-based home screen requires changes to shared home screen widget composition, which may conflict with parallel feature branches also modifying the home screen layout, causing merge conflicts and integration delays.

Mitigation & Contingency

Mitigation: Implement the PeriodicSummaryCard as a fully self-contained widget that the home screen conditionally renders based on a BLoC state flag. Minimise changes to the home screen itself to a single conditional insertion point, reducing the surface area for merge conflicts.

Contingency: If integration conflicts block the PR, isolate the card behind the organisation-scoped feature flag so it can be toggled independently and merged without affecting other home screen changes.