Implement AggregationSummaryWidget core layout
epic-bufdir-data-aggregation-ui-task-005 — Build the read-only AggregationSummaryWidget Flutter widget with sections for: participant count card, activity hours by Bufdir category table, and geographic distribution breakdown by region and chapter. Use design token card and table CSS classes. Widget is purely presentational, receiving AggregationSummaryData as a constructor parameter. All numeric values must be properly formatted for Norwegian locale (e.g., thousands separator).
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Use Dart's intl package with NumberFormat.decimalPattern('nb_NO') for all numeric formatting — instantiate once as a static/final field. The AggregationSummaryData model should be a pure Dart class (no fromJson complexity needed here — the BLoC state provides it). Structure the widget as a Column of three named sections: _buildParticipantCard(), _buildActivityHoursTable(), _buildGeographicDistribution() — each returning a Widget. This keeps the build method readable and each section independently testable.
For the activity hours table, avoid Flutter's built-in DataTable if the design token table classes are custom-rendered HTML-style; instead use a Column of Row widgets styled with design tokens. Ensure the widget is exported from the feature barrel file so BLoC-connected parent screens can import it cleanly.
Testing Requirements
Widget tests using flutter_test: (1) render with fully populated AggregationSummaryData — assert all three sections are present via find.byType and find.text; (2) render with zero-value data — assert no RenderFlex overflow or null errors; (3) locale formatting — assert '1 234' appears for value 1234 using nb_NO locale; (4) large geographic list (25 entries) — assert ListView.builder is used and no overflow errors; (5) golden tests for visual regression of the complete widget in light and dark themes. Target 90%+ line coverage for the widget file.
For NHF with 1,400 local chapters, rendering a geographic breakdown as a flat list in the AggregationSummaryWidget would produce an unscrollable wall of data that is unusable on a mobile screen. Coordinators need to verify geographic completeness before export, but the raw chapter list is too long to review.
Mitigation & Contingency
Mitigation: Design the geographic distribution section as a collapsible two-level hierarchy: regions are shown expanded by default with their aggregate count, individual chapters are collapsed under each region and expandable on tap. Show only non-zero regions by default with a 'show empty regions' toggle.
Contingency: If the hierarchical display is too complex to implement before the submission deadline, fall back to a region-only summary view with a total count of active chapters per region and a note that chapter-level detail is available in the full export file.
The aggregation BLoC must handle a multi-stage async pipeline with partial success states, warning accumulation across stages, and retry logic for individual failed stages. If the state model is too simplistic (e.g., loading/success/error), warning states and partial results will be lost on retry, confusing coordinators who see warnings disappear and reappear.
Mitigation & Contingency
Mitigation: Model the BLoC state as a rich sealed class hierarchy: AggregationIdle, AggregationRunning(stage, completedStages, accumulatedWarnings), AggregationComplete(result, warnings), AggregationFailed(failedStage, accumulatedWarnings, error). Accumulated warnings persist across retry attempts so coordinators see the full warning history.
Contingency: If state management complexity causes repeated bugs near the deadline, simplify to a single AggregationResult value object that captures success, warnings, and error as nullable fields, and drive both UI components from that single object rather than a live BLoC stream.