Integrate Confirmation Dialog into Export Flow
epic-bufdir-reporting-export-ui-task-007 — Wire BufdirExportConfirmationDialog into the ExportTriggerScreen so that tapping the export button dispatches a ConfirmExportRequested event and opens the dialog populated with live state values (scope, period, record count, format). Confirming triggers ExportInitiated; cancelling returns to idle. Ensure focus returns to the trigger button on cancel.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Use showDialog with barrierDismissible: false to prevent accidental dismissal during confirmation. Pass a FocusNode to the trigger button widget and call node.requestFocus() inside the onCancel callback before popping the dialog. Use BlocBuilder inside the dialog to read live state — avoid capturing state in a local variable before showDialog as it may become stale. Keep ExportTriggerBloc state transitions deterministic: ConfirmExportRequested → AwaitingConfirmation, ExportInitiated → Exporting, cancel → Idle.
Do not use Navigator.pop inside the BLoC — the UI layer owns navigation; the BLoC only emits state.
Testing Requirements
Write widget tests using flutter_test and bloc_test covering: (1) button tap emits ConfirmExportRequested and dialog appears, (2) dialog displays correct scope/period/count/format from mocked BLoC state, (3) confirm tap emits ExportInitiated and dialog dismisses, (4) cancel tap returns to idle state and dialog dismisses, (5) focus node is restored after cancel. Use MockExportTriggerBloc to control state. Aim for 100% branch coverage of the dialog integration logic.
For large exports that run for 10–30 seconds, a static loading spinner will feel broken to users on slow mobile connections. If the UI cannot display meaningful progress during the export pipeline, coordinators may abandon the flow or trigger duplicate exports by pressing the button multiple times.
Mitigation & Contingency
Mitigation: Implement streaming progress events from the orchestrator BLoC through named pipeline stages (querying, mapping, generating, uploading). Display each stage label with a progress indicator on the trigger screen. Disable the generate button immediately on first tap to prevent duplicates.
Contingency: If streaming pipeline progress is not feasible in the first release, implement a deterministic stage-based progress animation (10% querying, 50% generating, 90% uploading) that gives users feedback without requiring real server events.
Custom date range pickers are among the most common accessibility failures in mobile apps. Blindeforbundet users rely on VoiceOver, and NHF users include people with cognitive impairments. A non-accessible period picker could make the entire export workflow unusable for a significant portion of the intended user base.
Mitigation & Contingency
Mitigation: Build the period picker using Flutter's native date picker semantics as the foundation, with preset shortcuts as primary navigation (reducing the need to interact with the custom range picker at all). Test with VoiceOver on iOS and TalkBack on Android before UI epic sign-off. Engage Blindeforbundet's test contact for accessibility validation.
Contingency: If the custom date range picker cannot be made fully accessible before release, ship only the preset period shortcuts (covering the majority of use cases) and add the custom range picker in a follow-up sprint after dedicated accessibility remediation.