Implement search query state management in provider
epic-contact-list-management-business-logic-task-008 — Add search query state to ContactListRiverpodProvider as a separate StateProvider or internal notifier field. When the query changes, delegate to ContactSearchService and update the filtered contacts AsyncValue stream without replacing the unfiltered stream. Ensure clearing the query restores the full role-scoped list without triggering a fresh network fetch.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Model the search query as a `StateProvider
Use `ref.listen(searchQueryProvider, (prev, next) { ... })` inside the notifier if you need side effects on query change, but prefer the reactive `ref.watch` derivation where possible. Reset `searchQueryProvider` to empty string in the notifier's `ref.onDispose` to prevent stale query state if the provider is later re-initialised.
Testing Requirements
Unit tests using ProviderContainer: verify filteredContacts equals full list when query is empty, verify filteredContacts is filtered subset when query is non-empty, verify clearing query returns full list without incrementing mock service call count. Widget tests: simulate typing in AppTextField, confirm ContactListView rebuilds with filtered results, confirm clearing text restores full list. Test edge case: full list refresh while query active — filtered results update to reflect new list. Use fake ContactSearchService to make local-path tests deterministic.
Test debounce cancellation via fake async timers for the remote path scenario.
For organizations with large contact lists (NHF has 1,400 local chapters and potentially thousands of contacts), local in-memory filtering may be too slow and Supabase ILIKE queries without supporting indexes may exceed acceptable response times or accumulate excessive read costs, degrading search usability for power users.
Mitigation & Contingency
Mitigation: Define and document the list-size threshold in ContactSearchService before implementation. Confirm that indexes on name and notes columns exist in the Supabase schema before enabling server-side search. Profile ContactSearchService against realistic data volumes in the staging environment using the largest expected org.
Contingency: If response times are unacceptable in staging, introduce result-count pagination in ContactListService and add a user-visible 'showing top N results — refine your search' indicator, deferring full pagination to a follow-up task.
In NHF's multi-chapter context, when a user switches organization, Riverpod providers may emit a brief window of stale contact data scoped to the previous organization before the invalidation cycle completes, transiently exposing contacts from the wrong chapter.
Mitigation & Contingency
Mitigation: Model organization context as a Riverpod provider dependency so that any context change immediately marks contact providers as stale. Render a loading skeleton instead of the stale list during the re-fetch transition. Cover this scenario in integration tests with explicit org-switch sequences.
Contingency: If race conditions are observed during QA, add an explicit organization_id equality check in ContactListService that compares each fetched record's scope to the active session org, discarding any mismatched batch before returning results to the provider.