critical priority medium complexity frontend pending frontend specialist Tier 0

Acceptance Criteria

BufdirExportScreen is a StatefulWidget registered in the router and navigable from the Bufdir reporting section
ExportScreenPhase enum defines exactly three values: configuration, preview, execution
ExportScreenCubit emits a state containing the current phase and is provided via BlocProvider at the screen root
Transitioning between phases updates the cubit state and the visible widget tree without full screen rebuild
Phase state survives hot restart: reopening the screen restores the last committed phase from the wizard-draft-repository
Scaffold uses the standard app sidebar navigation; no custom Scaffold wrappers are introduced
SingleChildScrollView wraps all phase content so long forms scroll on small devices without overflow
The screen passes flutter_test goldens for each of the three phases with no layout overflow warnings
Keyboard and screen-reader focus is moved to the first interactive element when the phase changes
No inline style or hardcoded color values appear in the widget — all styling uses design tokens

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
Riverpod
data models
ExportScreenPhase (enum)
ExportScreenState
WizardDraftRepository
performance requirements
Phase transition must complete within one frame (no jank on mid-range Android devices)
Cubit state emission must be synchronous for phase changes; async only when persisting draft
security requirements
Wizard draft persisted to local secure storage — do not write draft data to plaintext SharedPreferences
Screen must not be accessible to roles without Bufdir reporting permission (guard at router level)
ui components
Standard app Scaffold with sidebar navigation
SingleChildScrollView phase container
ExportScreenCubit (BLoC)
Phase-aware AnimatedSwitcher or IndexedStack for content transitions

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Use an IndexedStack (keepAlive: true) over AnimatedSwitcher if form state must survive phase switches without re-fetching. Keep ExportScreenCubit thin: it only owns the current phase and delegates all domain logic to child cubits (ExportPreviewCubit, etc.). The wizard-draft-repository pattern should store a serialised ExportDraft JSON object using flutter_secure_storage. Register the route with a GoRouter guard that checks the user's Bufdir reporting permission before allowing navigation.

Apply the app's standard Scaffold factory method to ensure sidebar, appBar title, and back button are consistent with other screens.

Testing Requirements

Write flutter_test widget tests for: (1) initial render defaults to configuration phase, (2) cubit phase state drives widget subtree selection, (3) hot-restart simulation restores last persisted phase via a mocked WizardDraftRepository, (4) layout overflow test on 320px-wide device in each phase, (5) Semantics tree check that focus target is set on phase change. Golden tests for all three phase shells. No integration test needed for this scaffolding task alone — integration coverage is in task-012.

Component
Bufdir Export Screen
ui medium
Epic Risks (2)
medium impact medium prob technical

The preview panel requires a round-trip to the edge function to compute aggregated counts. If this call takes 5–15 seconds for large scopes, users may assume the app has frozen and navigate away, potentially triggering duplicate preview requests or leaving the export in an undefined state.

Mitigation & Contingency

Mitigation: Show an immediate skeleton loading state on the preview panel as soon as the period and scope are confirmed, with named stage labels (e.g. 'Querying activities…', 'Computing totals…') streamed from the edge function's progress events. Set a clear user-visible timeout with a retry option. Pre-warm the edge function with a lightweight ping when the scope selector is opened.

Contingency: If preview latency consistently exceeds 10 seconds for large scopes, cache the preview payload in local BLoC state and allow the coordinator to proceed to confirmation without re-fetching if scope and period have not changed since the last preview.

high impact medium prob scope

The export preview panel contains dynamic content (warning badges, loading skeletons, aggregated counts) that must be announced correctly by VoiceOver and TalkBack. Incorrect semantics annotations could make the preview unreadable for blind coordinators, violating the project's WCAG 2.2 AA accessibility mandate.

Mitigation & Contingency

Mitigation: Implement semantic annotations using Flutter's Semantics widget with explicit labels for all dynamic content. Use live region announcements for loading state transitions. Schedule a dedicated accessibility review session with a screen reader user (Blindeforbundet has relevant expertise) before marking the epic complete.

Contingency: If the preview panel cannot be made fully screen-reader-accessible in time for launch, ship a simplified text-only summary mode activated by a toggle at the top of the preview panel, which renders all data as a single readable paragraph with no interactive badges.