critical priority medium complexity frontend pending frontend specialist Tier 2

Acceptance Criteria

Each mentor row flagged by BulkRegistrationService pre-check displays a visible warning indicator (icon + amber/warning color token) inline within the row
Warning tooltip or expandable sub-row shows duplicate details: conflicting date formatted as dd.MM.yyyy and activity type label
Mentor rows without duplicates render identically to the pre-warning state with no visual noise
Warning indicator has a Semantics widget with label that reads: 'Duplicate warning: [activity type] already registered on [date]' for screen readers (VoiceOver/TalkBack)
When a mentor has multiple duplicates the warning lists all conflicts, not just the first
Warning state is driven exclusively by data from BulkConfirmationCubit state — no local widget state
Tapping a warning row does not navigate away; it expands/collapses the duplicate detail inline
Warning color tokens are sourced from the design token system, not hardcoded hex values
WCAG 2.2 AA contrast ratio ≥ 4.5:1 is met for warning text against the row background
If the pre-check returns no duplicates for any mentor the warning UI elements are absent from the widget tree entirely

Technical Requirements

frameworks
Flutter
BLoC/Cubit
apis
BulkRegistrationService.preCheck() response model (duplicate field per mentor)
data models
BulkMentorPreCheckResult
DuplicateActivityDetail (date, activity_type, activity_id)
performance requirements
Warning widgets must not trigger full list rebuild; use const constructors and targeted BlocBuilder selectors
List must remain smooth at 60 fps with up to 50 mentor rows, each potentially showing duplicate details
security requirements
Duplicate detail data (dates, activity types) must not expose PII beyond what is already visible in the mentor row context
Pre-check result must be consumed from cubit state only — never fetched directly inside the widget
ui components
MentorRowWithWarning (extension of existing mentor row widget)
DuplicateWarningBadge (icon + label chip)
DuplicateDetailExpansion (collapsible sub-row listing conflicts)
Semantics wrapper for screen reader announcements

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Model the duplicate warning as a nullable List field on the BulkMentorPreCheckResult. The MentorRowWithWarning widget should accept this list and render nothing extra when it is null or empty — this keeps the widget composable without conditional branching at the screen level. Use ExpansionTile or a custom AnimatedContainer for the collapsible detail section; avoid Navigator pushes inside list rows. Source all colors from the design token system (e.g., colorWarning, colorOnWarning) to stay consistent with the app's theme layer.

Ensure Semantics widgets wrap both the badge and the expanded detail so VoiceOver reads the full context. For the expand/collapse toggle, emit a UI event to the cubit rather than managing expansion state locally — this keeps the screen fully reconstructable from cubit state, which is required for reliable widget tests.

Testing Requirements

Unit tests: verify BulkConfirmationCubit correctly maps pre-check response to per-mentor warning state, including edge cases of zero duplicates, single duplicate, and multiple duplicates per mentor. Widget tests: mount BulkConfirmationScreen with mocked cubit state containing flagged and unflagged mentors; assert DuplicateWarningBadge presence/absence per row, assert Semantics label text matches expected format, assert expand/collapse of DuplicateDetailExpansion on tap. Accessibility test: use flutter_test's SemanticsController to verify warning labels are announced correctly. Golden tests: capture mentor row in warning and non-warning states to prevent regression.

Epic Risks (3)
medium impact medium prob scope

If the batch insert RPC returns a mix of successes and failures (e.g., 3 of 10 mentors fail due to constraint violations that slipped through application-level duplicate detection), the confirmation screen result state becomes ambiguous. A coordinator who sees '7 of 10 succeeded' may not know whether to manually register the 3 failures, retry, or escalate — leading to either duplicate registrations or silent underreporting.

Mitigation & Contingency

Mitigation: Design the Bulk Registration Service to return a strongly typed BulkRegistrationResult with per-mentor RegistrationOutcome (success | duplicate_detected | constraint_violation | permission_denied). Design the result screen to list each failed mentor with a specific, plain-language reason and a one-tap 'Retry for this mentor' action that pre-fills the activity wizard with the batch template for that individual.

Contingency: If per-mentor retry UI is too complex to deliver within the epic scope, fall back to displaying failed mentors with their error codes and instructing coordinators to use single-proxy mode for the failures. Document this as a known limitation in release notes and create a follow-up ticket for per-mentor retry in the next sprint.

medium impact medium prob dependency

The Proxy Activity Wizard must reuse the existing activity wizard step widgets (type, date, duration, notes) while injecting a proxy attribution banner and a different submission payload builder. If the existing wizard is not designed for composability, the proxy variant may require forking the widget tree, creating two maintenance-diverging codebases that will drift out of sync when the base wizard is updated (e.g., new activity types added, new mandatory fields).

Mitigation & Contingency

Mitigation: Before implementing the Proxy Activity Wizard, audit the existing activity wizard's architecture. If steps are already extracted as independent StatelessWidget/ConsumerWidget classes, compose them directly with a wrapping Column that injects the attribution banner. If they are tightly coupled inside a parent widget, refactor the existing wizard to accept a nullable ProxyContext parameter before starting the proxy variant — this refactor should be a prerequisite task in this epic.

Contingency: If refactoring the base wizard is blocked by unrelated in-flight work on that component, implement the proxy wizard as a full fork but create a shared StepWidgets library file that both the base wizard and proxy wizard import. Schedule a deduplication refactor as a tech-debt ticket in the next planning cycle.

medium impact medium prob technical

The bulk registration flow spans three sequential screens (multi-select → activity form → confirmation → result) with shared mutable state: the selected mentor list, the activity template, the per-mentor duplicate warnings, and the final submission result. Managing this state across screens without a well-designed Bloc risks state leaks, stale duplicate warning data after mentor removal, and confirmation screen inconsistencies if the user navigates back and changes the mentor selection.

Mitigation & Contingency

Mitigation: Define a single BulkRegistrationBloc (or Cubit) with explicit state transitions covering: MentorsSelected → ActivityTemplateCompleted → DuplicatesChecked → ConfirmationReady → Submitting → SubmissionResult. Each backward navigation event (e.g., 'Back' from confirmation to mentor selection) dispatches a ResetToMentorSelection event that clears downstream state. Unit test every state transition with edge cases including empty mentor list, all mentors having duplicates, and network failure during submission.

Contingency: If state management complexity causes persistent bugs in testing, simplify by passing state explicitly through Navigator arguments (immutable snapshots per screen) rather than a shared Bloc. This reduces flexibility but eliminates cross-screen state mutation bugs.