high priority medium complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

ActivityLogViewer renders as a scrollable ListView with a sticky filter bar at the top containing date range picker, activity type dropdown, and chapter selector
Filter controls are pre-populated: date range defaults to current month, activity type to 'All', chapter to the currently selected scope
Each ActivityLogItem displays: activity type label, chapter name, peer mentor name (or 'Coordinator' for proxy registrations), date/time, duration, and a chevron icon linking to the activity detail screen
Tapping any list item navigates to the correct activity registration detail screen using the activity's ID
The list supports paginated loading: an initial page is shown on mount, and a 'Load more' trigger at the bottom of the list fetches the next page from AdminPortalBloc
Changing any filter resets the list to page 1 and shows a loading indicator while the first page loads
Empty state: when no activities match the filter, a centred empty-state illustration and message ('No activities found for this period') is shown
Error state: if the data fetch fails, an inline error banner with a Retry button is shown below the filter bar; existing items remain visible if this is a pagination failure
The chapter selector only lists chapters within the admin's current privilege scope
The widget is fully accessible: list items have semantic labels combining type, name, and date; date range picker uses accessible date input; minimum touch targets 48×48dp
WCAG 2.2 AA contrast ratios for all text and interactive elements

Technical Requirements

frameworks
Flutter
flutter_bloc
BLoC
apis
AdminStatisticsService.getActivityLog(scopeId, page, pageSize, filters)
AdminStatisticsService.getActivityTypes()
AdminStatisticsService.getChaptersInScope(scopeId)
data models
ActivityLogEntry
ActivityFilter
ActivityType
Chapter
PaginatedResult<ActivityLogEntry>
performance requirements
Initial page (20 items) must render within 2 seconds on standard mobile network
Filter changes must debounce by 400ms before triggering a new fetch to avoid excessive API calls
ListView must use itemExtent or SliverFixedExtentList where possible to improve scroll performance with large lists
Images/avatars in list items (if any) must be lazy-loaded
security requirements
Chapter list must be fetched server-side filtered to admin's scope — no client-side filtering of a full chapter list
Activity log entries must not expose fields beyond the admin's read permission (Supabase RLS enforced server-side)
ui components
FilterBar (date range picker, activity type dropdown, chapter selector)
ActivityLogItem (list tile with metadata and navigation chevron)
PaginationFooter (load more button or automatic scroll trigger)
EmptyStateView (illustration + message)
InlineErrorBanner (error with retry)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Structure ActivityLogViewer as a StatelessWidget consuming AdminPortalBloc via BlocBuilder — avoid local StatefulWidget state for filter values; store filter state in BLoC (handled in task-009). For the date range picker, use Flutter's built-in showDateRangePicker which is accessible out of the box; wrap it in a TextButton showing the formatted range. Use a CustomScrollView with a SliverAppBar (pinned: false, floating: true) for the filter bar so it disappears on scroll and re-appears on scroll-up, maximising visible list area. Each ActivityLogItem should be a const-constructible widget for list performance.

The navigation to activity detail must use the app's existing router (GoRouter or Navigator) with the activity ID as a path parameter — do not pass entire ActivityLogEntry objects between routes. Apply org labels system for activity type display names.

Testing Requirements

Widget tests: (1) renders filter bar with correct defaults, (2) list renders correct number of ActivityLogItem widgets for mock page data, (3) tapping an item triggers correct navigation route with activity ID, (4) changing date filter emits ActivityLogFilterChanged event to BLoC, (5) empty state shows when BLoC emits empty list, (6) error banner shows when BLoC emits error state, (7) load more trigger emits LoadMoreActivities event. Golden tests for both populated list and empty state. Accessibility test: verify Semantics tree for list items. Integration test: full scroll-to-bottom triggers pagination.

Component
Activity Log Viewer
ui medium
Epic Risks (3)
high impact medium prob technical

If org node selection in AdminStateBLoC does not correctly propagate to all dependent data streams (statistics, activity log, user list, certification panel), some panels may show data from the previously selected org scope, creating a confusing and potentially dangerous mixed-scope view.

Mitigation & Contingency

Mitigation: Model org node selection as a single source of truth in AdminStateBLoC. All downstream providers derive their query parameters from this single stream via Riverpod's watch pattern. Write integration tests that verify every data stream emits a reload event when the selected node changes.

Contingency: If scope propagation bugs are detected in QA, add an explicit full-state reset on org node change (clear all cached data and refetch from scratch) as a safe but less efficient fallback until the targeted propagation is fixed.

medium impact medium prob technical

The Admin Dashboard Screen must adapt its layout for Flutter Web (wider viewports, mouse interaction, larger grid) and mobile embedding. Flutter Web responsive layout support has historically required non-trivial workarounds, and the adaptive grid may introduce significant additional development time.

Mitigation & Contingency

Mitigation: Define breakpoints and grid behaviour in the design system before implementation. Use LayoutBuilder with explicit breakpoint constants rather than MediaQuery scattered across widgets. Prototype the web layout with a skeleton screen before implementing live data binding.

Contingency: If web layout proves intractable within sprint, deliver a mobile-first layout for all platforms initially and track a dedicated web-optimisation task for the next sprint.

high impact low prob security

A bug in the Role Assignment Panel's permission scope validation could allow an org_admin to assign roles beyond their authority (e.g., assigning super_admin to a user), representing a serious privilege escalation vulnerability.

Mitigation & Contingency

Mitigation: Enforce role assignment scope on both the client (disable unavailable roles in the panel UI) and the server (UserManagementService validates the target role is within the admin's permitted scope before persisting). Write security-focused tests that attempt out-of-scope role assignments and assert rejection.

Contingency: If an escalation vulnerability is discovered, immediately disable the role assignment panel via feature flag, revoke any incorrectly assigned roles, and deploy a server-side fix before re-enabling.