critical priority low complexity frontend pending frontend specialist Tier 14

Acceptance Criteria

Cancel button is present, tapping it dispatches CancelConflictResolution BLoC event and closes the dialog (Navigator.pop)
Override button is present, tapping it dispatches ConfirmOverrideSubmission BLoC event and closes the dialog
Override button has a visually distinct style (e.g., warning/destructive color) to signal it is a non-default action
Cancel is the visually prominent/default action (left or bottom of Override) following destructive-action UX conventions
Both buttons are disabled and show a loading indicator while the BLoC is in a submitting state (SubmittingOverride)
Semantic labels: Cancel button has Semantics(label: 'Cancel, return to form'), Override button has Semantics(label: 'Override and submit despite duplicate')
On dialog open, initial focus is placed on the Cancel button (safe default) via FocusScope.of(context).requestFocus()
Tab/focus order is: Cancel → Override — not reversed
Screen reader users hear the full dialog title and both button labels when navigating with VoiceOver/TalkBack
WCAG 2.2 AA: both buttons meet minimum touch target size (48×48dp) and color contrast requirements

Technical Requirements

frameworks
Flutter
BLoC (flutter_bloc)
data models
BLoC events: CancelConflictResolution, ConfirmOverrideSubmission
BLoC states: ConflictDetected, SubmittingOverride, SubmissionSuccess, SubmissionFailure
performance requirements
Button tap response within one frame (no async delay before BLoC event dispatch)
Loading state transition renders within 16ms
security requirements
Override action must only be dispatchable when a valid ConflictDetected state is active — guard against stale state triggers
Double-tap protection: disable buttons immediately on first tap to prevent duplicate BLoC event dispatch
ui components
AppButton (existing reusable widget) — Cancel variant (secondary/outlined)
AppButton — Override variant (destructive/warning fill)
Row action button container with design token spacing
CircularProgressIndicator for loading state overlay on Override button
FocusNode for initial focus management

Execution Context

Execution Tier
Tier 14

Tier 14 - 3 tasks

Can start after Tier 13 completes

Dependencies (21)
epic-proxy-activity-registration-orchestration-task-001 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-002 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-003 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-004 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-005 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-010 component Cross-Epic Component duplicate-warning-dialog depends on proxy-registration-service
epic-proxy-activity-registration-orchestration-task-006 component Cross-Epic Component duplicate-warning-dialog depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-007 component Cross-Epic Component duplicate-warning-dialog depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-008 component Cross-Epic Component duplicate-warning-dialog depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-009 component Cross-Epic Component duplicate-warning-dialog depends on bulk-registration-service
epic-proxy-activity-registration-orchestration-task-011 component Cross-Epic Component duplicate-warning-dialog depends on bulk-registration-service
epic-proxy-activity-registration-core-services-task-001 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-002 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-003 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-008 component Cross-Epic Component duplicate-warning-dialog depends on proxy-duplicate-detection-service
epic-proxy-activity-registration-core-services-task-004 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-005 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-006 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-007 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-009 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service
epic-proxy-activity-registration-core-services-task-010 component Cross-Epic Component duplicate-warning-dialog depends on activity-attribution-service

Implementation Notes

Use BlocConsumer or BlocBuilder to read submitting state for button disable logic. Create a FocusNode in the widget's State (or use autofocus: true on the Cancel button) to ensure correct initial focus. The Override button should use a destructive color from AppColors (e.g., AppColors.warning or AppColors.error) — coordinate with design system. Use the existing AppButton widget passing a loading parameter if supported, otherwise wrap in AbsorbPointer + Opacity when in SubmittingOverride state.

Ensure the action row uses MainAxisAlignment.end or spaceBetween with adequate spacing (AppSpacing.sm between buttons). After BLoC emits SubmissionSuccess or SubmissionFailure following override, the parent BlocListener (not this dialog) should handle navigation or error toast — keep the dialog's responsibility limited to event dispatch and self-dismissal.

Testing Requirements

Unit/BLoC tests: verify CancelConflictResolution and ConfirmOverrideSubmission events are emitted correctly. Widget tests: (1) tap Cancel and assert Navigator.pop is called and correct BLoC event fired; (2) tap Override and assert BLoC event fired; (3) set BLoC state to SubmittingOverride and assert both buttons are disabled; (4) verify FocusNode is attached to Cancel button on dialog open. Accessibility: use flutter_test's tester.getSemantics() to verify semantic labels on both buttons.

Epic Risks (4)
medium impact high prob scope

The bulk registration screen combines pre-filled defaults, a dynamic multi-select participant list, per-participant conflict badges, and a batch submission confirmation — making it one of the most complex screens in the application. Scope creep or underestimated interaction complexity could cause the epic to exceed its estimate significantly.

Mitigation & Contingency

Mitigation: Implement the bulk screen in two vertical slices: (1) participant selection and form submission without conflict handling, (2) conflict badge rendering and override flow. Validate slice 1 with coordinators before building slice 2.

Contingency: If the full conflict review UI cannot be completed within the epic, ship the bulk screen with a simplified 'skip all duplicates' fallback mode and defer per-participant override toggles to a follow-up sprint.

medium impact medium prob technical

The proxy-registration-bloc must manage state across two distinct flows (single proxy and bulk) with branching conflict paths, intermediate buffering of bulk participant selections, and reliable state reset. Incorrect state transitions could leave the UI in a loading or stale-conflict state after submission.

Mitigation & Contingency

Mitigation: Model the BLoC state as a sealed class hierarchy with exhaustive pattern matching in the UI. Write state-machine unit tests that exercise every valid transition and assert that invalid transitions are no-ops. Use flutter_bloc's BlocObserver in debug builds to log all transitions.

Contingency: If BLoC state bugs surface in QA, introduce an explicit ResetToIdle event triggered on screen disposal to guarantee clean state, and add a 'Start over' affordance visible to the coordinator at any conflict step.

high impact medium prob technical

The typeahead peer mentor selector with multi-select mode may be difficult to operate with VoiceOver/TalkBack, particularly the dynamic search results list and the selected-chip removal controls, risking WCAG 2.2 AA non-compliance for screen reader users.

Mitigation & Contingency

Mitigation: Wrap all search result items and selected chips with explicit Semantics widgets providing role, label, and selected-state announcements. Test the selector with VoiceOver on iOS and TalkBack on Android during development, not only at QA time.

Contingency: If the multi-select typeahead cannot be made fully accessible within the sprint, provide an alternative flat scrollable list with checkboxes as a fallback mode, toggled by an accessibility-settings flag.

high impact medium prob security

The peer mentor selector must apply RLS chapter-scope filtering to show only mentors the coordinator is responsible for. If the Supabase query for the selector does not correctly join against the coordinator's chapter assignments, coordinators may see mentors from other chapters, violating data isolation.

Mitigation & Contingency

Mitigation: Implement the selector's data query using the same RLS-aware Supabase client used by the contact list feature, which already handles chapter-scope filtering. Write an integration test with a multi-chapter coordinator fixture asserting cross-chapter mentors are not returned.

Contingency: If a data isolation breach is discovered, immediately add a client-side chapter_id filter as a defence-in-depth measure and audit selector query logs for any unauthorised cross-chapter results.