Data Layer high complexity frontendmobiledesktop
3
Dependencies
0
Dependents
0
Entities
0
Integrations

Description

BLoC state management for the admin portal screens, coordinating dashboard stats, org hierarchy selection, user list state, and export progress. Uses Riverpod providers to expose derived state (filtered user lists, selected org node, KPI values) to UI widgets. Handles loading, error, and empty states for all admin data streams.

Feature: Organisation Admin Portal

admin-state-bloc

Summaries

The Admin Portal BLoC is the intelligent coordination layer that makes the admin portal feel responsive, consistent, and reliable for the administrators who depend on it daily. It ensures that when an admin switches their organisational scope, every piece of data on screen — statistics, user lists, export configurations — updates automatically and correctly without requiring manual page refreshes or risking stale data. A well-implemented state layer directly reduces administrator error rates and support burden, and is a prerequisite for delivering the polished, professional experience that retains confidence among national and regional administrators managing grant-funded activities.

High-complexity frontend state component that depends on three backend services (admin-statistics-service, user-management-service, admin-export-service) all being stable before full integration testing is possible. Runs across frontend, mobile, and desktop execution contexts, meaning platform-specific quirks (e.g. Flutter desktop window management, background process behaviour on mobile) must be explicitly tested. Pagination state, filter state, and export job lifecycle add significant branching to test coverage requirements.

Plan for dedicated state testing using Riverpod's testing utilities and mock service layers. Risk: scope change propagation bugs (e.g. stale data after org node switch) are subtle and easy to miss in manual testing — automate these scenarios explicitly.

Implemented using Riverpod providers and Notifier classes. `AdminDashboardNotifier` owns the selected org node state; on `selectOrgNode()`, it triggers cascading invalidation of all dependent providers (user list, stats, export config). `UserListNotifier` manages paginated fetch state with cursor-based pagination and filter accumulation — `applyFilters()` resets the page cursor and triggers a fresh fetch. `ExportNotifier` tracks async export job lifecycle, polling or subscribing to job status from admin-export-service.

`watchDashboardStats()` and `watchUserList()` expose reactive streams consumed directly by UI widgets. All notifiers should handle loading, error, and empty states explicitly. Dependencies on three backend services mean integration tests require mock service implementations. Shared state (org node selection) must be a single provider instance to avoid desync between dashboard and user list views.

Responsibilities

  • Manage selected org node and propagate scope changes to all data streams
  • Coordinate dashboard stat loading and refresh lifecycle
  • Handle user list pagination, filtering, and role assignment state transitions
  • Track export job progress and surface completion or error events

Interfaces

AdminDashboardNotifier.refresh()
AdminDashboardNotifier.selectOrgNode(nodeId)
UserListNotifier.applyFilters(filters)
UserListNotifier.loadNextPage()
ExportNotifier.startExport(config)
ExportNotifier.cancelExport()
watchDashboardStats() -> Stream<DashboardStats>
watchUserList() -> Stream<PagedResult<User>>

API Contract

View full contract →
REST /api/v1/admin/state 7 endpoints
GET /api/v1/admin/state/dashboard Fetch current dashboard state snapshot for the authenticated admin
POST /api/v1/admin/state/dashboard/refresh Trigger a dashboard state refresh
GET /api/v1/admin/state/users Get paginated user list state with current filter applied
PUT /api/v1/admin/state/users Update the active user list filters
GET /api/v1/admin/state/selected-org Get the currently selected org node in the admin's session
POST /api/v1/admin/state/selected-org Set the admin's selected org node
+1 more