high priority low complexity backend pending backend specialist Tier 0

Acceptance Criteria

BenefitCalculationResultModel is a final/immutable Dart class with a const constructor
Personal metrics fields: hoursVolunteered (double), contactsReached (int), sessionCount (int)
Societal metrics fields: estimatedLivesImproved (double), economicValueNok (double), societalReachScore (double)
Optional metadata fields: calculationDate (DateTime), periodLabel (String?) for display in the results card
copyWith method returns a new instance with only specified fields overridden; all other fields retain original values
Dart == operator and hashCode are overridden (or generated) to compare all fields structurally
toJson() returns a Map<String, dynamic> with all fields using JSON-safe types (DateTime serialized as ISO-8601 string)
fromJson(Map<String, dynamic>) factory constructor reconstructs a full instance from the map, handling null gracefully for optional fields
toString() returns a developer-friendly multi-line or single-line representation including all field names and values
Model file contains no UI imports, no Supabase imports, and no BLoC imports — pure Dart data class

Technical Requirements

frameworks
Flutter (dart:core only)
data models
BenefitCalculationResultModel
performance requirements
Model instantiation and JSON serialization complete in under 1ms
Model must be safe to use in const contexts where possible
security requirements
Model must not store any personally identifiable information (PII) — metrics only
Economic values should be stored as doubles, not formatted strings, to avoid locale-dependent parsing bugs

Execution Context

Execution Tier
Tier 0

Tier 0 - 440 tasks

Implementation Notes

Prefer writing the model by hand over code generation (freezed/json_serializable) unless the project already uses code generation — consistency with existing patterns matters. Place the file at lib/features/benefit_calculator/models/benefit_calculation_result_model.dart. Use @immutable annotation from package:flutter/foundation.dart if the project uses Flutter; otherwise use package:meta. For DateTime serialization in toJson, use .toIso8601String() and DateTime.parse() in fromJson.

Define a static BenefitCalculationResultModel.zero() factory that returns a zeroed instance for use as BLoC initial state. Document each field with a one-line /// comment explaining what it represents and its unit (e.g., /// Economic value in NOK).

Testing Requirements

Unit tests using flutter_test: JSON round-trip for all fields including edge values (0.0, very large doubles, null optional fields), equality tests for identical and differing instances, copyWith tests for full and partial overrides, and toString format validation. Aim for 100% coverage of the model class. No mocks needed.

Component
Benefit Calculator Screen
ui low
Epic Risks (3)
high impact medium prob technical

The RepaintBoundary PNG capture approach for sharing the results card may produce blurry or oversized images on high-DPI devices, or may silently fail on certain Android OEM configurations that restrict off-screen rendering. A failed share would break one of the core use cases (recruitment tool).

Mitigation & Contingency

Mitigation: Implement the capture using the established screenshot-capture-utility pattern already present in the Wrapped summary feature (component 542-screenshot-capture-utility). Test on a range of iOS and Android devices including Samsung and Huawei OEM builds during development. Set explicit pixel ratio (3.0) when calling toImage() to guarantee resolution.

Contingency: If image capture fails on a platform, the BenefitShareService falls back to sharing the plain-text summary only, with a user-facing message explaining the image could not be generated. This ensures the share flow never fully blocks.

high impact medium prob technical

Implementing full WCAG 2.2 AA compliance for the results card and metric tiles — including live regions, focus management, and semantic labels that read naturally in Norwegian — requires deep familiarity with Flutter semantics APIs. Gaps may only surface during screen reader testing on physical devices, late in the sprint.

Mitigation & Contingency

Mitigation: Use the existing semantics-wrapper-widget (606) and live-region-announcer (608) components from the accessibility feature rather than implementing custom semantics. Assign screen reader testing on a physical iPhone with VoiceOver as a mandatory acceptance gate, not an afterthought. Write widget tests using Flutter's AccessibilityGuideline matchers early in development.

Contingency: If screen reader issues are found late, the pure semantic markup approach (no Canvas numbers, all Semantics wrappers) limits the blast radius to label text corrections. Escalate to the accessibility feature team for a pairing session to resolve complex focus management issues.

medium impact low prob integration

The BenefitResultsCard must match the Wrapped design language used in the annual summary feature. If design tokens or widget patterns are inconsistent between the two features, the results card will look out of place and undermine the intended emotional impact for sharing.

Mitigation & Contingency

Mitigation: Review the existing Wrapped summary screen (529-wrapped-summary-screen) and stat card widget (530-stat-card-widget) implementations before building the results card. Reuse design tokens from the existing design-token-theme (200) system. Involve the designer in a review of the results card mock-up against the Wrapped language before implementation begins.

Contingency: If design parity issues are discovered post-implementation, isolate visual adjustments to the BenefitResultsCard widget. The feature's business logic and accessibility compliance are unaffected by visual polish changes.