high priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

DriverAssignmentListBloc exposes states: initial, loading, loaded(assignments, hasNextPage), loadingMore, refreshing, and error
On first build the BLoC dispatches a LoadAssignments event and fetches the first page from DriverAssignmentService
Scrolling to within 200px of the bottom of the list triggers a LoadMoreAssignments event that appends the next page without replacing existing items
A pull-to-refresh gesture dispatches RefreshAssignments, resets pagination cursor, and re-fetches from page 1
Tapping the pending declaration badge on a list item navigates to DeclarationSendScreen via named route, passing the assignment ID and driver ID as arguments
Tapping the main row area (outside the badge) navigates to the assignment detail screen via named route
After popping back from DeclarationSendScreen or DeclarationAcknowledgementScreen, the BLoC automatically dispatches RefreshAssignments so badge counts reflect the latest declaration status
The list renders a loading skeleton during the initial load state and a bottom spinner during loadingMore state
The error state displays a retry button that re-dispatches LoadAssignments
An empty assignments list renders the designated empty-state widget, not a blank screen
All navigation calls use the app's centralized router and do not use direct MaterialPageRoute pushes
No business logic or service calls exist inside the DriverAssignmentList widget itself — all data flows through the BLoC

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
Dart
apis
DriverAssignmentService (paginated list endpoint)
DeclarationStatusService (status query on return)
data models
DriverAssignment
DeclarationStatus
PaginationCursor
performance requirements
Initial page load must complete within 2 seconds on a standard 4G connection
Pagination append must not cause a visible full-list rebuild — use ListView.builder with a stable key per assignment ID
Badge refresh after navigation pop must not trigger a full page reload; only mutate the affected item's status in the BLoC state
security requirements
Assignment data must only be fetched for the authenticated coordinator's scope — pass the current user's org/role context to the service
Navigation arguments (assignment ID, driver ID) must be typed and validated before route push to prevent injection via malformed deep links
ui components
DriverAssignmentList
DeclarationStatusBadge
AssignmentListItemTile
LoadingSkeletonList
EmptyStateWidget
BottomPaginationSpinner

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use flutter_bloc BlocBuilder for rendering and BlocListener for navigation side-effects — never trigger navigation inside build(). Store the pagination cursor in the BLoC state, not in the widget. For post-navigation refresh, use a RouteObserver or override the didPopNext lifecycle on the parent route to dispatch RefreshAssignments — avoid using async gaps between push and await pop to keep the BLoC as the single source of truth. When appending paginated items, emit a new state with the concatenated list rather than mutating the existing list in place, to preserve Flutter's immutable state contract.

Ensure the BLoC is provided above the navigation boundary (e.g., at the route level) so it survives tab switching if the list is inside a StatefulShellRoute tab.

Testing Requirements

Write Flutter widget tests covering: (1) BLoC emits loading → loaded sequence on LoadAssignments event; (2) tapping badge navigates to DeclarationSendScreen with correct route arguments; (3) tapping row navigates to assignment detail; (4) returning from DeclarationSendScreen triggers RefreshAssignments; (5) pagination appends items on LoadMore; (6) error state shows retry button and retry dispatches LoadAssignments. Write unit tests for DriverAssignmentListBloc covering all state transitions and edge cases (empty page, last page flag). Use mockito or mocktail to stub DriverAssignmentService. Target 85%+ line coverage for the BLoC class.

Component
Driver Assignment History List
ui medium
Epic Risks (3)
high impact medium prob technical

The declaration acknowledgement screen has the most complex accessibility requirements of any screen in this feature: scrollable long-form legal text, a conditional checkbox that is only enabled after reading, and a timestamp capture. Incorrect focus management or missing semantics annotations could fail VoiceOver navigation or cause the screen reader to announce the checkbox as available before the driver has scrolled, undermining the legal validity of the acknowledgement.

Mitigation & Contingency

Mitigation: Build the acknowledgement screen against the WCAG 2.2 AA checklist from the start, not as a post-hoc audit. Use semantics-wrapper-widget and live-region-announcer from the platform's accessibility toolkit. Include a VoiceOver test session in the acceptance criteria with a tester using the screen reader.

Contingency: If WCAG compliance cannot be fully achieved within the sprint, ship the screen with a documented list of accessibility gaps and a follow-up sprint commitment. Do not block the declaration workflow launch if the core interaction works but a non-critical semantics annotation is missing.

medium impact medium prob integration

Drivers receive a push notification with a deep link to the declaration acknowledgement screen for a specific assignment. If the deep link handler does not correctly route to the right screen and assignment context — particularly when the app is launched cold from the notification — the driver may see a blank screen or the wrong declaration.

Mitigation & Contingency

Mitigation: Implement and test all three notification scenarios: app foregrounded, app backgrounded, and cold start. Use the platform's existing deep-link-handler infrastructure. Add integration tests that simulate notification tap events and assert correct screen and data loading.

Contingency: If cold-start deep link routing proves unreliable, implement a notification-centre fallback where the driver can find the pending declaration from the notification centre screen, ensuring the workflow can always complete even if the direct deep link fails.

medium impact low prob technical

If the driver-feature-flag-guard has any rendering edge case — such as a brief flash of driver UI before the flag value is loaded, or a guard that fails open on a flag service error — driver-specific UI elements could be momentarily visible to coordinators in organizations that have not opted in, causing confusion and potentially a support escalation.

Mitigation & Contingency

Mitigation: Default the guard to rendering nothing (not a loading indicator) until the flag value is definitively resolved. Treat flag service errors as flag-disabled to fail closed. Write widget tests covering the loading, disabled, and enabled states including the error case.

Contingency: If fail-closed cannot be guaranteed within the sprint, add a server-side RLS check on the driver assignment endpoints so that even if the UI guard leaks, the data layer refuses to return driver data for organizations without the flag enabled.