Build ApprovalActionSheet bottom sheet scaffold
epic-expense-approval-workflow-bulk-and-action-task-007 — Create the ApprovalActionSheet as a modal bottom sheet widget for individual claim approve/reject decisions. Scaffold includes claim summary header, approve and reject action buttons, a comment text field, and a confirmation step before any irreversible transition is committed. Sheet must be dismissible only after explicit cancel or confirmation.
Acceptance Criteria
Technical Requirements
Implementation Notes
Use showModalBottomSheet with barrierDismissible: false. Wrap the sheet body in a PopScope widget (Flutter 3.16+) with canPop: false to block back-gesture dismissal on Android. Use a DraggableScrollableSheet only if content may overflow — otherwise a simple SingleChildScrollView Column suffices. Keep widget stateless at this scaffold stage; local state (selected action, comment text, confirmation step) will be added in subsequent tasks.
Model the sheet header after the existing AppPageHeader pattern for consistency. Ensure the sheet respects the device's bottom safe area (MediaQuery.of(context).padding.bottom) so the Cancel button is never obscured by the home indicator on iPhone.
Testing Requirements
Write widget tests verifying: sheet renders with correct claim summary data passed via constructor; scrim tap does not dismiss sheet; drag gesture does not dismiss sheet; Cancel button calls Navigator.pop; Approve and Reject buttons are present and tappable. Use flutter_test with WidgetTester.tap and pumpAndSettle. Verify no overflow RenderFlex errors at standard iPhone SE viewport (375x667).
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.
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.