Define MentorStatusBLoC events and states
epic-peer-mentor-pause-ui-state-task-007 — Define the MentorStatusEvent sealed class (PauseMentorEvent, ReactivateMentorEvent) and MentorStatusState sealed class (MentorStatusInitial, MentorStatusLoading, MentorStatusSuccess, MentorStatusError) with typed payloads. Include error message and invalid-transition flag in the error state. Follow existing BLoC conventions in the codebase.
Acceptance Criteria
Technical Requirements
Implementation Notes
Use Dart 3 sealed classes (sealed class MentorStatusState {}) — this enables exhaustive pattern matching in switch expressions and is the modern BLoC pattern. Pair with Equatable from the equatable package for value equality; call super([...props]) with all fields in props getter. Place events and states in separate files: mentor_status_event.dart and mentor_status_state.dart, then export both from mentor_status_bloc.dart barrel. Define MentorStatus enum in a shared domain types file (e.g., mentor_domain.dart) so it can be imported by both the BLoC and the UI widgets without creating a circular dependency.
The isInvalidTransition flag distinguishes 'cannot pause an already-paused mentor' (UI should show a specific message) from generic network failures (generic retry message).
Testing Requirements
Unit tests: instantiate each event and state subclass, assert equality via Equatable. Unit tests: assert MentorStatusError.isInvalidTransition defaults to false when not provided. Static analysis: ensure all switch(state) expressions in the codebase using MentorStatusState are exhaustive (dart analyze must pass with no warnings). Unit test: verify PauseMentorEvent with identical reason strings are equal (Equatable correctness).
PauseConfirmationDialog must meet WCAG 2.2 AA focus trap requirements: when the dialog opens, focus must move to the first interactive element; when it closes, focus must return to the triggering toggle. Flutter's default showDialog does not always guarantee correct focus restoration on Android, which could trap screen-reader users.
Mitigation & Contingency
Mitigation: Use a custom modal implementation wrapping Flutter's Dialog with explicit FocusScope management and test with TalkBack on Android and VoiceOver on iOS during development, not just in final QA. Reference the accessible-modal-sheet pattern already used elsewhere in the codebase.
Contingency: If full WCAG focus management cannot be achieved within the sprint, ship the feature with a documented accessibility defect and schedule a dedicated accessibility remediation task. Communicate the known gap to the accessibility stakeholder at HLF/NHF.
If the user taps the PauseReactivateToggle rapidly before the BLoC emits a loading state, multiple PauseMentorEvents could be added to the BLoC stream, resulting in duplicate service calls and inconsistent UI state (toggle flickering between states).
Mitigation & Contingency
Mitigation: Disable the toggle widget immediately on first tap by emitting MentorStatusLoading synchronously before the async service call begins. Use BLoC's event transformer with droppable() to discard subsequent events while a transition is in progress.
Contingency: If BLoC event deduplication is not sufficient, add a debounce at the widget level (300 ms) and a server-side idempotency check in MentorStatusService that no-ops if the requested transition is already in progress.
PauseStatusBanner must conditionally render the reactivate shortcut only for users with coordinator permission. If the permission check relies on a stale role state in the Riverpod provider, a peer mentor could briefly see a reactivate action they are not authorised to use, which could cause a confusing permission-denied error if tapped.
Mitigation & Contingency
Mitigation: Source the permission check directly from the role-resolution Riverpod provider (which is kept in sync with Supabase auth) rather than from local component state. Add a widget test asserting the shortcut is absent when the user role is peer_mentor.
Contingency: If the shortcut is accidentally shown to an unauthorised user, the underlying MentorStatusService enforces role validation server-side, so the worst outcome is a visible error message rather than an actual unauthorised state change.