high priority medium complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

BufdirValidationSummaryBanner is mounted at the top of BufdirPreviewScreen body, above the section list
Banner is invisible (zero height, no layout space consumed) when the validation result list is empty
Banner is visible and expanded by default when one or more validation warnings exist
Banner displays the total warning count as a headline (e.g. '3 fields require attention')
Banner contains a vertically scrollable list of field-level issue strings, each showing the field name and the issue description
Validation data flows from BufdirFieldValidationService through BufdirPreviewService to the banner — no direct provider access inside the banner widget
Banner root widget has a Semantics node with label='Validation summary' and liveRegion=true so VoiceOver/TalkBack announces it on first appearance
Each list item in the banner has a Semantics label combining field name and issue text
Banner updates reactively when the underlying validation state changes without requiring a full screen rebuild
Banner background and text colours meet WCAG 2.2 AA contrast ratio (4.5:1 minimum for normal text)

Technical Requirements

frameworks
Flutter
Riverpod
data models
BufdirValidationResult
BufdirFieldIssue
BufdirPreviewState
performance requirements
Banner appearance/disappearance must animate in under 300 ms using AnimatedSwitcher or SizeTransition
Rebuilds must be scoped — only the banner widget rebuilds when validation state changes, not the full screen
security requirements
Field names shown in the banner must not expose internal system identifiers — display human-readable labels only
ui components
BufdirValidationSummaryBanner (new widget)
AnimatedSwitcher or SizeTransition for collapse/expand
ListView (field issue list inside banner)
Semantics widget with liveRegion=true

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Create BufdirValidationSummaryBanner as a separate file in the bufdir feature directory — do not embed it inline in BufdirPreviewScreen. Accept validation results as a constructor parameter (List) rather than reading from provider inside the widget; this keeps the widget purely presentational and easier to test. Use AnimatedSize wrapping a Column to achieve smooth collapse/expand without needing explicit animation controllers. Set the liveRegion Semantics at the outermost banner container so accessibility frameworks announce the count change.

For the field issue list, constrain the banner's maximum height (e.g. 160 dp) and make the inner list scrollable — the banner should not push the section list off screen on devices with many warnings. Use design token colours for warning states (amber/warning palette from the token system) rather than hardcoded hex values.

Testing Requirements

Write widget tests for: (1) banner is not rendered when validationResults is empty list, (2) banner renders correct warning count when list has N items, (3) each field issue item displays correct text, (4) Semantics tree contains a node with liveRegion=true when banner is visible, (5) banner updates correctly when provider emits a new validation list. Use flutter_test's SemanticsHandle to assert semantics tree. Mock BufdirPreviewService via ProviderScope override. Run flutter_test accessibility checker (tester.ensureSemantics()) in each relevant test.

Component
Bufdir Report Preview Screen
ui high
Epic Risks (3)
medium impact medium prob integration

The preview screen must pass period, scope, and aggregation session state to the Bufdir Report Export screen via navigation arguments. If the export screen's navigation argument schema is not yet finalized when this epic begins, the handoff will require rework — potentially after TestFlight is already in use by coordinators.

Mitigation & Contingency

Mitigation: Define the shared BufdirExportNavigationArgs Dart class jointly with the Bufdir Report Export feature team before this epic starts. Store it in a shared models package both features depend on. Treat the class as an API contract with a minor-version bump policy.

Contingency: If the export screen's argument schema changes after the preview screen is implemented, the BufdirPreviewService session state model can be adapted with a compatibility shim. The preview screen itself requires only a one-line navigation call change.

medium impact low prob technical

The period diff view loads prior-period data on demand and renders it inline with the current report. On a large report (many sections, many fields) combined with slow Supabase connectivity, the diff overlay could block the UI or produce a janky re-render that degrades the coordinator experience during the pre-submission review.

Mitigation & Contingency

Mitigation: Load prior-period data in a background Riverpod FutureProvider that starts prefetching when the preview screen mounts (not when the user taps the diff toggle). Show a shimmer placeholder on each field row's prior-period column while loading. Cache prior-period data in BufdirPreviewRepository using the same local cache as current-period data.

Contingency: If diff view performance is unacceptable on TestFlight devices, disable the toggle for the initial TestFlight release and ship the diff view in the following sprint after profiling the Supabase query plan and adding an appropriate Postgres index on the prior-period data table.

high impact medium prob scope

The full preview screen will be reviewed by coordinators on TestFlight who will cross-reference it against their physical Bufdir reporting forms. Any section ordering difference or label mismatch discovered during UAT will require a fix before the feature can be signed off, potentially delaying the entire Bufdir reporting pipeline.

Mitigation & Contingency

Mitigation: Conduct a pre-TestFlight alignment review with at least one coordinator from NHF and one from HLF using a static screenshot of the preview screen layout. Obtain written sign-off on section order and field labels before distributing to the full test group of 5-8 people.

Contingency: If label mismatches are found during TestFlight UAT, update BufdirReportStructureMapper constants and rebuild. Since the mapper is a pure Dart class with no persisted state, corrections are deployed in the next TestFlight build with no database migration required.