high priority medium complexity integration pending integration specialist Tier 3

Acceptance Criteria

Tapping Approve All in BulkApprovalBar invokes BulkApprovalProcessor.process() with all selectedClaimIds and ApprovalDecision.approve
Tapping Reject All invokes BulkApprovalProcessor.process() with all selectedClaimIds and ApprovalDecision.reject
isBulkProcessing state is set to true immediately on tap, before the processor completes
A progress indicator is shown on the BulkApprovalBar during processing (from isProcessing prop already built in task-004)
On BulkApprovalResult.isCompleteSuccess: a SnackBar or toast shows '{N} claims approved/rejected successfully' and the selection is cleared
On BulkApprovalResult.hasPartialFailure: a bottom sheet or dialog shows a structured summary listing succeeded count and failed count, with per-failure reason for each failed claim, and a 'Retry Failed' button if any failures are retryable
On BulkApprovalResult.isCompleteFailure: an error dialog displays with the option to retry all
Pressing 'Retry Failed' in the partial failure UI invokes BulkApprovalProcessor.retryFailedRecords() with the previous result
The coordinator review queue list refreshes (re-fetches from Supabase) after a successful or partial-success batch
All error feedback messages are in English and coordinator-appropriate (no raw error codes shown to user)
The integration does not break existing single-claim approve/reject flows on the claim detail screen
Confirmation dialog shown before executing Reject All (destructive action) — not required for Approve All

Technical Requirements

frameworks
Flutter
Riverpod
BLoC
Dart
apis
Supabase PostgreSQL 15
Supabase Edge Functions (Deno)
data models
claim_event
assignment
performance requirements
Feedback UI (SnackBar or bottom sheet) must appear within 200ms of processor returning result
Review queue re-fetch must not block the feedback display — trigger it as a fire-and-forget after result handling
security requirements
Confirm the coordinator's JWT is still valid before invoking the processor — handle Supabase session expiry gracefully with a re-authentication prompt
Reject All confirmation dialog prevents accidental mass rejection — always required
Partial failure bottom sheet must not show claim amounts or personal details of the peer mentor in error descriptions
ui components
SnackBar for complete success feedback
AlertDialog for complete failure and Reject All confirmation
BottomSheet or DraggableScrollableSheet for partial failure structured report
BulkApprovalBar (task-004) with isProcessing prop
ListTile per failed record in partial failure sheet

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Wire the action callbacks in the coordinator queue screen's ConsumerWidget (or BlocBuilder), not inside BulkApprovalBar itself — keep the bar dumb. The wiring logic (gather IDs → call processor → handle result) belongs in a use-case class (e.g., ExecuteBulkApprovalUseCase) injected via Riverpod, not inline in the widget's build method. This keeps it testable. For the partial failure bottom sheet, use DraggableScrollableSheet so coordinators can scroll through a long list of failures.

The queue refresh after completion should invalidate/refresh the existing claims list provider — if using Riverpod, call ref.invalidate(coordinatorClaimsProvider). Ensure the Reject All confirmation dialog copy is clear about the irreversibility: 'Reject {N} claims? This cannot be undone.'

Testing Requirements

Widget integration tests: (1) tap Approve All → verify processor called with correct IDs and decision, (2) verify isBulkProcessing=true while processor Future is pending, (3) complete-success result → SnackBar displayed and selectedClaimIds cleared, (4) partial-failure result → bottom sheet displayed with correct success/failure counts and Retry Failed button visible, (5) Retry Failed tap invokes retryFailedRecords() with the previous result, (6) Reject All tap shows confirmation dialog before invoking processor, (7) cancelling confirmation dialog does NOT invoke processor. Mock BulkApprovalProcessor in all widget tests. End-to-end test against Supabase test project: approve a batch of 3 real pending claims and verify claim_event rows and coordinator queue refresh. Use flutter_test for widget tests and integration_test package for E2E.

Component
Bulk Approval Action Bar
ui low
Epic Risks (2)
medium impact medium prob scope

If a bulk approval batch partially fails (some claims approved, some failed), the UI must communicate which specific claims failed without overwhelming the coordinator. A poorly designed error display could cause coordinators to re-approve already-approved claims or miss claims that still need attention.

Mitigation & Contingency

Mitigation: Design the BulkApprovalResult display to show a clear summary (e.g., '14 approved, 2 failed') with a collapsible list of failed claims including their IDs and submitter names. Failed claims should remain selected in the queue so the coordinator can retry them individually.

Contingency: If the summary UI proves insufficient, add a dedicated 'bulk action history' sheet showing the last bulk operation result, accessible from the queue screen header.

medium impact low prob technical

If the app is backgrounded or the network drops while the coordinator has the ApprovalActionSheet open mid-decision, the typed comment could be lost and the transition state could be ambiguous, potentially causing a coordinator to believe they approved a claim that was never submitted.

Mitigation & Contingency

Mitigation: Persist the in-progress action sheet state (selected action + comment text) to a local draft store keyed on claim ID. On sheet re-open for the same claim, restore the draft. After confirmed submission, verify the resulting claim status from the server before dismissing the sheet.

Contingency: On network error during submission, display a persistent retry banner within the sheet rather than dismissing it, so the coordinator can resubmit without re-entering their comment.