Add availability status filter to MentorFilterService
epic-geographic-peer-mentor-map-core-services-task-009 — Extend MentorFilterService to handle the availability status dimension: active, paused, all. Paused mentors must be excluded from results by default unless explicitly requested. The filter must compose cleanly with specialisation tag filtering. Update FilterCriteria model to include availabilityStatus. Add unit tests for all availability + specialisation combinations.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Define AvailabilityStatus as a Dart enum with a toDbValue() extension method returning the exact Postgres column string (e.g., 'active', 'paused'). This avoids magic strings in the filter translation layer. Extend FilterCriteria as an immutable class using copyWith and Equatable. Add availabilityStatus as a named parameter with a default of AvailabilityStatus.active.
In MentorFilterService.toQueryParameters(), add availability clause generation as a separate private method _availabilityClause(AvailabilityStatus status) that returns null for the all case and a typed clause object for the other two. This keeps each dimension of filtering independently testable. The 'paused' functionality directly supports the HLF and NHF workshop requirement where peer mentors can self-pause without deregistering.
Testing Requirements
Pure unit tests in flutter_test — no widget or async infrastructure needed. Write a parameterised test table covering all six combinations of AvailabilityStatus × {empty tags, non-empty tags}. Additionally test the default constructor produces active status.
Test validate() with a null status field. Test that the enum serialises to and from the database string value correctly (e.g., 'active' ↔ AvailabilityStatus.active). Target 100% line and branch coverage on the availability filter logic.
The dual BLoC state machines (map view state + filter state) may introduce subtle synchronisation bugs where filter changes do not correctly re-trigger viewport queries, causing stale data to appear on the map.
Mitigation & Contingency
Mitigation: Define all BLoC state transitions in a state diagram before implementation. Use flutter_bloc's BlocObserver in development mode to log every state transition. Write explicit unit tests for filter-change → re-query transitions.
Contingency: If state synchronisation bugs appear in integration testing, refactor to a single unified BLoC that owns both map viewport state and filter state, eliminating cross-BLoC dependencies.
Cached mentor location data may become stale (mentors move, pause, or revoke consent) and coordinators in offline mode could be shown incorrect mentor information, leading to wasted outreach.
Mitigation & Contingency
Mitigation: Display a clear timestamp on cached data indicating when it was last synced. Set cache TTL to 24 hours and show an 'offline — data from [date]' banner. Revoked consent removes the mentor from the cache on next successful sync via contact-cache-sync-repository.
Contingency: If cache staleness causes user complaints, reduce TTL to 4 hours and implement background sync on app foreground. Accept that very-recently-revoked mentors may appear briefly in offline mode — document this as a known limitation in the privacy policy.