Build Export Date Range Picker UI widget
epic-accounting-system-export-foundation-task-007 — Implement the ExportDateRangePicker as a self-contained Flutter widget with no upstream service dependencies. Render a start-date and end-date field using the design token system. Support preset quick-selects: current month, last month, current quarter, last quarter, and custom range. Validate that end date is not before start date. Emit a DateRange value object via a callback. Ensure full accessibility with semantic labels, minimum touch targets, and keyboard navigation support.
Acceptance Criteria
Technical Requirements
Implementation Notes
Implement as a StatefulWidget that owns the currently selected preset enum and the two DateTime? values. Use a PresetQuickSelect enum (currentMonth, lastMonth, currentQuarter, lastQuarter, custom) to drive both the chip highlights and date computation. Date boundary computation should be pure functions — extract to a DateRangePresets utility class for easy unit testing.
Use showDatePicker with Flutter's Material date picker; wrap in a helper that enforces firstDate/lastDate bounds (e.g., no future dates beyond today for export ranges). Apply design tokens via the existing AppColors/AppTextStyles/AppSpacing constants — never use literal hex or pixel values. Chip styling: use ChoiceChip Flutter widget. Keep the callback type as typedef void DateRangeChangedCallback(DateRange range) for clarity.
Avoid importing BLoC or Riverpod in this file — the widget must be testable in isolation.
Testing Requirements
Unit tests (flutter_test): verify DateRange emitted for each preset matches expected boundaries for a known reference date; verify invalid range (end < start) suppresses callback; verify custom range emits only after both dates are valid. Widget tests: render widget, tap each preset, verify field values and callback argument. Golden test: snapshot of default state, preset-selected state, and error state. Accessibility test: verify Semantics tree contains correct labels for all interactive elements.
No integration tests required for this self-contained widget.
Adding exported_at and export_run_id columns to expense_claims requires a live migration on a table shared with the approval workflow. A poorly timed migration could lock the table and block claim submissions or approvals.
Mitigation & Contingency
Mitigation: Use non-blocking ADD COLUMN with a DEFAULT of NULL (no backfill needed) executed during a low-traffic window. Test migration rollback on a staging replica before production deployment.
Contingency: If migration causes table lock contention, roll back and reschedule for a maintenance window. Use a feature flag to gate the export UI until the migration completes successfully.
Chart of accounts mapping configurations for Xledger and Dynamics may not be fully specified by stakeholders at development time, leaving the mapper with incomplete data and causing validation failures for unmapped expense categories.
Mitigation & Contingency
Mitigation: Implement the mapper to return a structured validation error (not a crash) for any unmapped field, and surface these errors clearly in the export confirmation dialog. Request full mapping tables from Blindeforbundet and HLF stakeholders as a pre-condition for this epic.
Contingency: If mappings arrive incomplete, ship the mapper with the available subset and mark unmapped categories as excluded (skipped with reason). Coordinators see which categories are skipped and can manually submit those records.
Supabase Vault configuration for storing per-org accounting credentials may require infra permissions or environment secrets not yet provisioned in staging or production, blocking development and testing of credential retrieval.
Mitigation & Contingency
Mitigation: Provision Vault secrets and environment configuration in staging as the first task of this epic. Document the exact secret naming convention and rotation procedure before implementation begins.
Contingency: If Vault is unavailable, use environment variables scoped to the Edge Function as a temporary fallback for development. Block production deployment until Vault-based storage is confirmed operational.