Peer Mentor Multi-Select screen scaffold and checkbox list rendering
epic-bulk-and-proxy-registration-mentor-selection-task-008 — Implement the Peer Mentor Multi-Select List screen that renders the coordinator's cached contact list with checkboxes, extending the same data source used by the single selector. Each row must include a clearly labelled checkbox and mentor name. Integrate loading, error, and empty state handling from the Proxy Contact List Provider.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Reuse the PeerMentorListTile widget created in task-005 and extend it to accept an onChanged callback and a isSelected boolean for the checkbox variant — this avoids duplicating row rendering logic. Manage the selection Set
The Proxy Contact List Provider should be declared as a global/family provider so both this screen and the single selector share the same cached data — do not create a second provider with the same Supabase query.
Testing Requirements
Widget tests covering: (1) loading state — mock provider returns AsyncLoading, assert loading indicator present; (2) populated state — mock provider returns 3 mentors, assert all rows rendered with unchecked checkboxes; (3) empty state — assert empty state message; (4) error state — assert error message and retry; (5) checkbox toggle — tap row 1, assert selectedMentorIds contains row 1's ID; (6) multiple selection — tap rows 1 and 3, assert both IDs are in selectedMentorIds and rows 2 and 4 are unchecked; (7) deselect — tap a checked row, assert ID is removed from set; (8) selection count display — assert count label shows '2 selected' after two taps. Use Riverpod ProviderScope overrides with stubbed providers. Verify shared provider: assert same provider family key is used as in single selector (no duplicate).
NHF coordinators may manage dozens of peer mentors across multiple chapters. If the multi-select list renders all contacts in a single unsorted ListView, performance degrades with 50+ items, and coordinators cannot efficiently locate a specific mentor, increasing the probability of selection errors and wrong-person proxy registrations.
Mitigation & Contingency
Mitigation: Use a SliverList with itemExtent for fixed-height rows to enable O(1) scroll position calculation. Implement the search filter using a debounce utility operating on an in-memory list (no extra API calls). Sort the contact list alphabetically by default. Add chapter-filter chips above the list for NHF's multi-chapter coordinators.
Contingency: If performance issues arise in testing with real data sets, introduce pagination with a 'load more' trigger at the bottom of the list and cache rendered rows using Flutter's AutomaticKeepAliveClientMixin.
NHF has a complex 12-national-association / 9-region / 1,400-chapter hierarchy. It is ambiguous whether a coordinator can proxy-register for peer mentors outside their immediately assigned chapter. If the contact list is not correctly scoped by RLS, coordinators might see — and register on behalf of — peer mentors they do not manage, creating fraudulent activity records that skew Bufdir statistics.
Mitigation & Contingency
Mitigation: The Proxy Contact List Provider must query only peer mentors linked to the coordinator's own chapter scope via RLS. Add an explicit Supabase query test asserting that a coordinator from chapter A cannot retrieve peer mentors from chapter B. Display each mentor's chapter affiliation in the list row so coordinators can visually verify scope.
Contingency: If RLS scope is found to be too permissive in testing, apply a server-side coordinator_id filter as a secondary guard on the query. Block the feature release until the scope test passes consistently.