critical priority medium complexity frontend pending frontend specialist Tier 3

Acceptance Criteria

ProxyActivityWizardCubit exists with initial state containing peer_mentor_id and recorded_by_user_id populated from constructor arguments
Cubit exposes a nextStep() event that advances the step index and skips the peer mentor selection step in proxy mode
Cubit exposes a previousStep() event that decrements the step index, also respecting the skipped step
Cubit exposes a submit() event that assembles and returns a ProxyActivityPayload with all wizard fields plus the proxy attribution fields
State class is immutable (final fields, copyWith method) and equatable for BLoC test assertions
The current peer mentor's full name is accessible from the state for the attribution banner widget to read
If submission fails (Supabase error), state transitions to an error state with a user-readable error message
If submission succeeds, state transitions to a success state with the created activity ID
blocTest unit tests cover: initial state, nextStep on last step (no-op or triggers submit), previousStep on first step (no-op), submit success, submit failure
BLoC is provided at the correct widget tree scope so both the banner and step widgets can access the same instance

Technical Requirements

frameworks
Flutter
BLoC
Riverpod
apis
Supabase REST API (activities table insert with proxy fields)
data models
ProxyActivityPayload
ActivityRegistration
performance requirements
State transitions must complete synchronously except for the submit event which is async
No unnecessary state emissions — only emit new state when values actually change
security requirements
recorded_by_user_id must be sourced from the authenticated Supabase session, not from any UI input
peer_mentor_id must be validated against the organization's peer mentor list before being accepted into state
Submit payload must be sent over HTTPS — Supabase client handles this, but ensure no plain-HTTP fallback is configured
ui components
ProxyAttributionBanner (reads peerMentorName from state)
ActivityWizardScaffold (reads currentStep from state)

Execution Context

Execution Tier
Tier 3

Tier 3 - 413 tasks

Can start after Tier 2 completes

Implementation Notes

Use Cubit rather than full BLoC (no event classes needed) since state transitions are straightforward method calls. Define `ProxyActivityWizardState` as an immutable class with: currentStepIndex, peerMentorId, peerMentorFullName, recordedByUserId, activityType, date, duration, notes, status (enum: initial/loading/success/error), errorMessage. Implement `copyWith` for all fields. For step index management, compute the valid step list once in the Cubit constructor based on isProxyMode and store it as a final List — use the list length for boundary checks rather than hardcoded step counts.

For Riverpod integration, expose the Cubit via a `StateNotifierProvider` or `Provider` scoped to the wizard route. Ensure the repository abstraction (interface + Supabase implementation) is injected via constructor for testability.

Testing Requirements

Use bloc_test's `blocTest` function for all Cubit tests. Cover: (1) emits correct initial state with provided peer_mentor_id and recorded_by_user_id, (2) nextStep increments step index and skips peer mentor step, (3) previousStep decrements step index correctly, (4) submit with a mock Supabase repository emits loading then success state, (5) submit with a repository that throws emits loading then error state with non-empty message, (6) state equality — two states with identical fields are equal. Mock the Supabase repository using Mockito or a hand-written fake. No widget tests required in this task — those are covered in tasks 002 and 003.

Component
Proxy Activity Wizard
ui medium
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.