medium priority low complexity frontend pending frontend specialist Tier 1

Acceptance Criteria

Widget fetches templates scoped to the coordinator's organization on mount via RecurringTemplateRepository
Loading skeleton is shown while templates are being fetched
Empty state is shown when no templates exist, including a text prompt guiding the coordinator to create their first template
Each template row displays: template name, activity type label, duration in human-readable format (e.g., '1 hr 30 min'), and a truncated notes preview (max 80 characters)
Tapping a template fires an `onTemplateSelected(RecurringTemplate)` callback that the parent uses to pre-fill the form
Selected template row is visually highlighted using design token accent color until a different template is selected or the form is cleared
Widget handles fetch error with an inline retry button and descriptive error message
All design token values used for spacing, color, and typography — zero hardcoded values

Technical Requirements

frameworks
Flutter
Riverpod
apis
RecurringTemplateRepository.getTemplatesForOrganization(organizationId)
data models
RecurringTemplate
ActivityType
performance requirements
Template list renders within one frame after data is available
Support up to 50 templates without pagination for initial implementation
security requirements
Templates must be filtered server-side to the coordinator's organization — RLS enforced in Supabase
Notes preview must not render HTML — treat as plain text
ui components
TemplateListTile (name, activity type chip, duration, notes preview)
LoadingSkeletonList
EmptyStateWidget (with creation prompt)
InlineErrorWidget (with retry action)

Execution Context

Execution Tier
Tier 1

Tier 1 - 540 tasks

Can start after Tier 0 completes

Implementation Notes

Use a `FutureProvider` (Riverpod) scoped to organizationId so the result is cached and not re-fetched on every widget rebuild. The widget itself should be a `ConsumerWidget`. Pass organizationId from the parent context via the provider argument, sourced from the authenticated session. The `onTemplateSelected` callback pattern keeps this widget composable and decoupled from form state management.

Duration formatting should be extracted to a shared utility function (e.g., `formatDuration(int minutes)`) rather than inlined. Empty state should include the organization's terminology label for 'template' if the org labels system is available.

Testing Requirements

Widget tests: loading skeleton renders during fetch, template list renders after successful fetch with correct field values, tapping a template calls onTemplateSelected with correct data, empty state renders with creation prompt when list is empty, error state renders with retry button when fetch fails, retry button triggers re-fetch. Verify notes longer than 80 characters are truncated. Verify selected template is visually highlighted.

Epic Risks (3)
high impact high prob scope

Partial failures in bulk registration — where some mentors succeed and others fail — create a complex UX state that is easy to mishandle. If the UI does not clearly communicate which records succeeded and which failed, coordinators may re-submit already-saved records (creating duplicates) or miss failed records entirely (creating underreporting).

Mitigation & Contingency

Mitigation: Design the per-mentor result screen as a primary deliverable of this epic, not an afterthought. Use a clear list view with success/failure indicators per mentor name, and offer a 'Retry failed' action that pre-selects only the failed mentors for resubmission.

Contingency: If partial failure UX proves too complex to deliver within scope, implement a simpler all-or-nothing submission mode for the initial release with a clear error message listing which mentors failed, and defer the partial-retry UI to a follow-up sprint.

medium impact medium prob technical

Submitting proxy records for a large group (e.g., 30+ mentors) as individual Supabase inserts may cause latency issues or hit rate limits, degrading the coordinator experience and potentially causing timeout failures that leave data in an inconsistent state.

Mitigation & Contingency

Mitigation: Implement the BulkRegistrationOrchestrator to batch inserts using a Supabase RPC call that accepts an array of proxy records, reducing round-trips to a single network call. Add progress indication using a stream of per-record results if the RPC supports it.

Contingency: If the RPC approach is blocked by Supabase limitations, fall back to chunked parallel inserts (5 records per batch) with retry logic, capping total submission time and surface a progress bar to manage coordinator expectations.

medium impact medium prob technical

Unifying state management for both single and bulk proxy flows in a single BLoC risks state leakage between flows — for example, a previously selected mentor list persisting when a coordinator switches from bulk to single mode — causing confusing UI states or incorrect submissions.

Mitigation & Contingency

Mitigation: Define separate, named state subtrees within the BLoC for single-proxy state and bulk-proxy state, with explicit reset events triggered on flow entry. Write unit tests for state isolation scenarios using the bloc_test package.

Contingency: If unified BLoC state becomes unmanageable, split into two separate BLoCs (ProxySingleRegistrationBLoC and ProxyBulkRegistrationBLoC) sharing only common events via a parent coordinator Cubit.