Implement Chapter Context Persistence and Broadcast
epic-organizational-hierarchy-management-admin-portal-task-012 — Implement chapter switching persistence using secure local storage and downstream broadcast mechanism. When user switches active chapter, persist selection, update ActiveChapterState stream, and notify all registered downstream widgets (stats, contacts, activities) to refresh their scoped data. Include session restore so the last active chapter is automatically selected on app relaunch.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 6 - 158 tasks
Can start after Tier 5 completes
Implementation Notes
Model the ActiveChapterCubit with three states: ChapterLoading, ChapterLoaded(activeChapter, availableChapters), ChapterError. Initialize the cubit by calling a loadInitialChapter() method in the constructor that reads from secure storage and validates against the Supabase chapters table. Use flutter_secure_storage with the key 'active_chapter_id_{userId}' to namespace per user and avoid cross-user contamination. Broadcast via the BLoC stream — downstream widgets use BlocListener or BlocBuilder scoped to ActiveChapterCubit.
Do not use a custom event bus or StreamController for broadcast; the BLoC stream already provides this. For Supabase queries that are chapter-scoped, inject the active chapter ID via a repository layer (ChapterScopedRepository) rather than reading it directly from the BLoC in widgets.
Testing Requirements
Write unit tests for the ActiveChapterCubit/Bloc covering: (1) SwitchChapterEvent persists correct chapter ID, (2) initial state loads from storage on construction, (3) invalid persisted ID falls back to first chapter, (4) no chapter in storage falls back to first chapter. Write integration tests verifying downstream BLoC/provider rebuilds when chapter switches. Mock flutter_secure_storage in tests. Verify that removing user access to a chapter and relaunching the app correctly handles the stale stored ID.
Aim for 95%+ unit test coverage on the ActiveChapterCubit and the persistence layer.
If the AccessScopeService and the Supabase RLS policies use different logic to determine accessible units, a coordinator could see data in the client that RLS blocks server-side, causing confusing empty states, or worse, RLS could block data the scope service declares accessible.
Mitigation & Contingency
Mitigation: Define the canonical scope computation in a single Supabase Postgres function shared by both the RLS policies and the RPC endpoint called by AccessScopeService. The client-side service calls this RPC rather than reimplementing the logic, ensuring a single source of truth.
Contingency: Add integration tests that execute the same access decision through both the RLS policy path and the AccessScopeService path and assert identical results. Use these as regression guards in the CI pipeline.
When a user switches active chapter via the ChapterSwitcher, widgets that are already built may not receive the context-change event if they subscribe incorrectly to the ActiveChapterState BLoC, leading to stale data being displayed under the new chapter context.
Mitigation & Contingency
Mitigation: Use Riverpod's ref.watch on the active chapter provider at the root of each scoped data subtree rather than at individual leaf widgets. Trigger a global data refresh by invalidating all scoped providers when the chapter changes.
Contingency: Add an app-level chapter-change listener that forces a full navigation stack reset to the home screen on chapter switch, guaranteeing all widgets rebuild from scratch with the new context. Accept the UX cost of navigation reset for correctness.
Non-technical organization administrators may find the hierarchy management interface too complex for the structural changes they need to make frequently (e.g., chapter renaming, coordinator reassignment), leading to low adoption and continued reliance on manual processes.
Mitigation & Contingency
Mitigation: Conduct usability testing with at least one NHF administrator before finalizing the admin portal screen layout. Prioritize the most common operations (rename, reparent, add child) as primary actions in the UI. Include inline help text and confirmation dialogs with plain-language descriptions of consequences.
Contingency: Provide a simplified 'quick edit' mode that exposes only the three most common operations (rename, deactivate, add child) and hides advanced structural operations behind an 'Advanced' toggle.