Implement Period Selector Widget — Presets
epic-bufdir-reporting-export-ui-task-001 — Build the BufdirPeriodSelectorWidget Flutter widget with preset shortcut buttons for quarter, half-year, and full-year reporting periods. Widget must expose a selected period value via a callback and render accessible tap targets meeting WCAG 2.2 AA touch-target size requirements.
Acceptance Criteria
Technical Requirements
Implementation Notes
Model each preset as a BufdirPresetPeriod enum (q1, q2, q3, q4, h1, h2, fullYear) with a toPeriodRange(int year) extension method that returns DateTimeRange. This isolates date logic from UI and makes unit testing trivial. Use design token spacing (AppSpacing.sm, AppSpacing.md) for padding so the widget adapts to accessibility text-scale changes. Wrap each ElevatedButton or OutlinedButton in a Semantics node — set label to a human-readable string including computed dates so screen-reader users hear the actual date range, not just 'Q1'.
Avoid Row with Expanded children that overflow at large text scale; prefer Wrap with runSpacing from design tokens. Export the widget from a barrel file so downstream screens import a single path.
Testing Requirements
Write flutter_test widget tests covering: (1) correct DateTimeRange emitted for each of the 7 presets (Q1–Q4, H1, H2, full year), (2) callback not invoked on render — only on tap, (3) active-state visual indicator changes on selection, (4) widget accepts controlled selectedPeriod prop and highlights correct button, (5) no overflow at text scale 2.0×. All tests must pass on both Material (Android) and Cupertino (iOS) themes. Target 100% branch coverage for date arithmetic helpers.
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.