Scaffold Proxy Peer Mentor Selector Widget
epic-proxy-activity-registration-ui-task-007 — Create the base ProxyPeerMentorSelector widget with a TextField-based typeahead input, dropdown result overlay, and loading/empty/error states. Define the widget's public API: selectedMentor (single-select) or selectedMentors (multi-select), onChanged callback, and chapterScope parameter.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 12 - 5 tasks
Can start after Tier 11 completes
Implementation Notes
Use Riverpod (AsyncNotifierProvider or StateNotifierProvider) to manage search state — this keeps the widget stateless and testable. The Overlay approach (OverlayEntry + LayerLink/CompositedTransformFollower) is preferred over Stack because it does not affect surrounding widget layout. Store the OverlayEntry reference in widget State and call remove() on disposal to prevent memory leaks. Use a TextEditingController and FocusNode in widget State — dispose both in dispose().
The SelectorMode enum should be defined in a shared types file (e.g., selector_types.dart) for reuse. Scaffold all state branches (loading/empty/error/results) now even if only loading/empty/error are wired — results list rendering will be completed in task-008. Follow existing naming patterns in the codebase for widget constructors.
Testing Requirements
Widget tests: (1) widget renders in single and multi mode without errors; (2) overlay is not visible on initial render (no query); (3) overlay shows loading indicator when state is loading; (4) overlay shows 'No results' when state is empty; (5) overlay shows error message when state is error; (6) tapping outside widget dismisses overlay. Use Riverpod ProviderScope with override to inject mock search state for each test scenario.
The bulk registration screen combines pre-filled defaults, a dynamic multi-select participant list, per-participant conflict badges, and a batch submission confirmation — making it one of the most complex screens in the application. Scope creep or underestimated interaction complexity could cause the epic to exceed its estimate significantly.
Mitigation & Contingency
Mitigation: Implement the bulk screen in two vertical slices: (1) participant selection and form submission without conflict handling, (2) conflict badge rendering and override flow. Validate slice 1 with coordinators before building slice 2.
Contingency: If the full conflict review UI cannot be completed within the epic, ship the bulk screen with a simplified 'skip all duplicates' fallback mode and defer per-participant override toggles to a follow-up sprint.
The proxy-registration-bloc must manage state across two distinct flows (single proxy and bulk) with branching conflict paths, intermediate buffering of bulk participant selections, and reliable state reset. Incorrect state transitions could leave the UI in a loading or stale-conflict state after submission.
Mitigation & Contingency
Mitigation: Model the BLoC state as a sealed class hierarchy with exhaustive pattern matching in the UI. Write state-machine unit tests that exercise every valid transition and assert that invalid transitions are no-ops. Use flutter_bloc's BlocObserver in debug builds to log all transitions.
Contingency: If BLoC state bugs surface in QA, introduce an explicit ResetToIdle event triggered on screen disposal to guarantee clean state, and add a 'Start over' affordance visible to the coordinator at any conflict step.
The typeahead peer mentor selector with multi-select mode may be difficult to operate with VoiceOver/TalkBack, particularly the dynamic search results list and the selected-chip removal controls, risking WCAG 2.2 AA non-compliance for screen reader users.
Mitigation & Contingency
Mitigation: Wrap all search result items and selected chips with explicit Semantics widgets providing role, label, and selected-state announcements. Test the selector with VoiceOver on iOS and TalkBack on Android during development, not only at QA time.
Contingency: If the multi-select typeahead cannot be made fully accessible within the sprint, provide an alternative flat scrollable list with checkboxes as a fallback mode, toggled by an accessibility-settings flag.
The peer mentor selector must apply RLS chapter-scope filtering to show only mentors the coordinator is responsible for. If the Supabase query for the selector does not correctly join against the coordinator's chapter assignments, coordinators may see mentors from other chapters, violating data isolation.
Mitigation & Contingency
Mitigation: Implement the selector's data query using the same RLS-aware Supabase client used by the contact list feature, which already handles chapter-scope filtering. Write an integration test with a multi-chapter coordinator fixture asserting cross-chapter mentors are not returned.
Contingency: If a data isolation breach is discovered, immediately add a client-side chapter_id filter as a defence-in-depth measure and audit selector query logs for any unauthorised cross-chapter results.