Build ActivityTypeSelectionScreen UI with list rendering
epic-activity-type-configuration-business-logic-task-006 — Implement the ActivityTypeSelectionScreen Flutter widget that reads active activity types from the ActivityTypeCacheProvider via Riverpod. Render each type as a tappable list tile showing the resolved label and a chevron. Handle loading, empty, and error states. On selection, return the full ActivityType object (including all metadata) to the registration wizard orchestrator via the Navigator result or a callback.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 5 - 253 tasks
Can start after Tier 4 completes
Implementation Notes
Place in lib/features/activity_type/presentation/screens/activity_type_selection_screen.dart. Use ref.watch(activityTypeListProvider(orgId)) and handle AsyncValue with .when(data:, loading:, error:). The orgId comes from an auth provider (e.g., ref.watch(currentOrgIdProvider)) — do not accept orgId as a constructor parameter to avoid stale values. Return the selected ActivityType via Navigator.pop(context, selected) so the calling wizard step can await Navigator.push
Ensure the ListTile trailing chevron uses Icon(Icons.chevron_right) styled with the app's secondary text color design token. For accessibility: ListTile already provides correct semantics by default; ensure the resolvedLabel is used as the tile title (not labelKey). Add a Semantics wrapper with label: 'Select ${type.resolvedLabel} as activity type' on each tile if the default ListTile semantics are insufficient for screen readers. This screen is a navigator push from the activity registration wizard — it is not a bottom nav tab, so include a back button in the app bar.
Testing Requirements
Widget tests using flutter_test with ProviderScope and overridden activityTypeListProvider: (1) loading state: override provider with AsyncLoading() → assert CircularProgressIndicator present, (2) error state: override with AsyncError() → assert error message visible and retry button tappable, (3) empty state: override with AsyncData([]) → assert empty message visible, (4) populated list: override with AsyncData([type1, type2, type3]) → assert 3 ListTiles with correct labels, (5) tap test: tap first ListTile → verify Navigator.pop was called with type1 as argument using NavigatorObserver mock, (6) accessibility test: run flutter_test SemanticsController to verify list items have meaningful semantics labels, (7) golden test (optional): snapshot the populated list state for visual regression detection. All tests must pass with flutter_test — no integration_test needed for this screen.
Metadata flag combination rules differ between organisations (e.g., Blindeforbundet honorarium thresholds, HLF mutual exclusion of km and transit). Encoding these as generic service-level validation may be insufficient, forcing organisation-specific branching inside the service that becomes unmaintainable as new organisations are onboarded.
Mitigation & Contingency
Mitigation: Model flag validation as a pure function that accepts an ActivityTypeMetadata object and an org configuration record, making org-specific rules data-driven rather than hardcoded. Establish the validation contract in the foundation epic so the service just delegates to the validator.
Contingency: Defer complex cross-flag validation to a lightweight edge function that can be updated without a mobile app release, accepting that initial validation in the mobile service layer is permissive and corrected server-side.
Blindeforbundet users rely on VoiceOver and JAWS. If the selection screen is built with non-semantic widgets that fail accessibility audit late in the sprint, a significant rework of the widget tree may be required, blocking the registration wizard integration.
Mitigation & Contingency
Mitigation: Build the selection screen against the project's established accessibility design tokens and semantics wrapper conventions from the start. Run Flutter's semantic tree inspector and a manual VoiceOver pass before marking any widget task complete.
Contingency: Wrap all tappable items in the project's SemanticsWrapperWidget and schedule a dedicated accessibility review session with a screen reader user from Blindeforbundet before the epic is closed.