critical priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Tapping an OrgCardWidget emits a SelectOrg event to the BLoC/Cubit with the selected org's ID and metadata
A full-screen loading overlay (non-dismissible, blocks all interaction) is rendered when the Cubit is in OrgSelectionLoading state
Double-tap is prevented: subsequent taps while loading are no-ops (Cubit ignores events in loading state)
On success (OrgSelectionSuccess state), the loading overlay is removed and GoRouter navigates to the role-appropriate home screen
Navigation target is determined by the user's role returned from OrgSelectionService (coordinator, org admin, peer mentor)
On failure, the Cubit transitions to OrgSelectionError state — the loading overlay is removed and the error state is surfaced (handled in task-004)
The loading indicator meets WCAG 2.2 AA: includes a Semantics widget with a meaningful label (e.g., 'Loading organization, please wait')
No direct async calls exist in widget build methods or gesture handlers — all logic is delegated to the Cubit
OrgSelectionService is injected via the Cubit constructor and is mockable in tests
State transitions are tested: idle → loading → success and idle → loading → error paths both pass

Technical Requirements

frameworks
Flutter
flutter_bloc
go_router
apis
OrgSelectionService.selectOrg(orgId)
TenantContextService (set active tenant)
data models
Organization
UserRole
TenantContext
performance requirements
Loading overlay must appear within one frame of the tap event (< 16ms)
OrgSelectionService call must not block the UI thread — must be awaited inside Cubit emit pattern
security requirements
Tenant context must be validated server-side in OrgSelectionService before being stored locally
No org ID or tenant token must be logged or exposed in error messages shown to the user
ui components
Full-screen Stack overlay with CircularProgressIndicator
AbsorbPointer wrapping the overlay to block gestures
Semantics widget wrapping the loading indicator
BlocConsumer or BlocListener for navigation side-effects on success/error

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Use a BlocConsumer in OrgSelectionScreen: the builder renders the overlay conditionally based on state, and the listener handles GoRouter navigation on success to avoid calling context.go() inside build. Wrap the entire screen content in a Stack with the overlay on top. Use AbsorbPointer(absorbing: state is OrgSelectionLoading) to block gestures without unmounting the card list (preserving scroll position). In the Cubit, guard the event handler with an early return if the current state is already OrgSelectionLoading to prevent race conditions.

Keep OrgSelectionService as an abstract class so widget tests can inject a fake. The role-based navigation target should be resolved in a RouteGuard or inside the Cubit's success emission — do not hardcode route strings in the widget.

Testing Requirements

Write unit tests for the OrgSelectionCubit covering: (1) emits [loading, success] when OrgSelectionService returns successfully, (2) emits [loading, error] when OrgSelectionService throws, (3) ignores duplicate SelectOrg events while in loading state. Write widget tests for OrgSelectionScreen verifying: (4) loading overlay appears on tap, (5) overlay blocks further taps, (6) GoRouter receives the correct navigation call on success. Use flutter_test and bloc_test packages. Mock OrgSelectionService with Mockito or manual fakes.

Target 100% branch coverage on the Cubit.

Epic Risks (2)
low impact high prob technical

OrgSelectionScreen and OrgContextSwitcher render partner-specific logos, colors, and text from dynamic data. Golden tests (pixel-comparison screenshots) will fail whenever branding assets are updated in the backend, causing CI failures that block unrelated PRs and eroding developer trust in the test suite.

Mitigation & Contingency

Mitigation: Use fixture-based golden tests with static mock Organization models containing embedded test assets rather than network-fetched assets. Separate branding asset acceptance tests into a dedicated CI job that only runs on branding-related PRs and is maintained by the design team.

Contingency: If golden test maintenance overhead becomes excessive, replace pixel-comparison goldens with semantic widget tests that assert widget tree structure and key property values, reserving golden tests for only the most stable, design-critical elements.

high impact medium prob scope

Several partner organizations (especially Blindeforbundet) have users who rely entirely on VoiceOver or TalkBack. Complex branded card layouts with overlaid logos, names, and selection states are notoriously difficult to make fully accessible; missing semantics or incorrect focus order could make the selection screen completely unusable for screen reader users before launch.

Mitigation & Contingency

Mitigation: Involve an accessibility specialist in the design review before any widget implementation begins. Use Flutter's Semantics widget with explicit label, hint, and button role on OrgCardWidget. Conduct manual screen reader testing on both iOS (VoiceOver) and Android (TalkBack) for every sprint that touches these screens, not just before release.

Contingency: If full WCAG compliance cannot be achieved within the sprint, implement a simplified text-list fallback mode that activates when the system detects an active screen reader, presenting orgs as plain accessible list tiles instead of the branded card layout.