high priority medium complexity frontend pending fullstack developer Tier 2

Acceptance Criteria

Toggling a scenario template immediately updates the Switch widget to the new state (optimistic UI) without waiting for the server response
The Scenario Configuration Manager's updateTemplateState(templateId, chapterId, isEnabled) method is called after the optimistic update
If the server call succeeds, the optimistic state is confirmed — no further UI change needed (stream will confirm via Realtime)
If the server call fails, the Switch reverts to its previous state and a SnackBar error message is shown to the coordinator
The toggle handler is rate-limited or debounced — rapid toggling does not send multiple concurrent API calls for the same template
Only coordinators can toggle templates: the onChanged callback is set to null for non-coordinator users (Switch rendered as read-only)
The chapter ID used in the update call is always sourced from the authenticated session claims — not from the UI or local state
Toggle state change is recorded with an updated lastModified timestamp visible in the list item after the Realtime stream confirms
If the user is offline, the toggle reverts immediately with a 'No internet connection' SnackBar — no silent failure
The coordinator's chapter scope is enforced server-side via Supabase RLS — client role check is UX only
Toggle interactions are accessible: VoiceOver/TalkBack announces the new state after toggle ('Scenario [name] enabled' / 'Scenario [name] disabled')

Technical Requirements

frameworks
Flutter
Riverpod
apis
Supabase PostgreSQL 15
Supabase Auth
data models
activity_type
performance requirements
Optimistic UI update must render within one frame (16ms) of the toggle tap
Debounce rapid toggle calls with a 300ms window — only the last value in the window is sent to the server
Server call must complete within 3 seconds — show rollback + error SnackBar if exceeded
security requirements
Server-side RLS on the scenario configuration table must enforce that coordinators can only update templates for their own chapter
Template ID and chapter ID are UUIDs from the server — validate format (UUID regex) before sending in the API call
Role enforcement at the API call layer: include the coordinator's JWT in the Supabase client call so RLS applies — never use the service role key in mobile
ui components
Switch widget with optimistic state management via local StateProvider or equivalent
SnackBar for error feedback (rollback message) via ScaffoldMessenger
SnackBar for offline feedback
Read-only Switch (onChanged: null) for non-coordinator roles

Execution Context

Execution Tier
Tier 2

Tier 2 - 518 tasks

Can start after Tier 1 completes

Implementation Notes

Manage optimistic state with a local StateProvider> keyed by templateId overlaying the stream data. When onToggleChanged fires: (1) immediately update the local StateProvider with the new value, (2) call the Configuration Manager async, (3) on success do nothing (stream will confirm), (4) on failure revert the StateProvider entry and show SnackBar. For debouncing, use a Timer.periodic approach or the rxdart debounceTime operator on a StreamController — prefer a simple Timer-based debounce to avoid adding rxdart if not already a dependency. For offline detection, check connectivity_plus (if in the project) before making the API call rather than catching a timeout.

Coordinate with the backend definition of the scenario configuration table's chapter-scoped enable/disable model — confirm whether it uses a JOIN table (template_id, chapter_id, is_enabled) or a flag on the template row itself, as this affects the updateTemplateState method signature. Do not implement any caching layer here — rely on the Realtime stream from task-012 as the source of truth.

Testing Requirements

Write unit tests and widget tests using flutter_test. Unit test 1: updateTemplateState called with correct templateId, chapterId from session, and new isEnabled value on toggle. Unit test 2: When server call fails, optimistic state rolls back to original value. Unit test 3: Debounce logic — rapid toggles within 300ms result in only one server call.

Widget test 1: Toggle shows new state immediately after tap (before server response). Widget test 2: Switch reverts to original state and SnackBar shown on server error. Widget test 3: Switch is non-interactive (onChanged null) for non-coordinator role. Widget test 4: Offline scenario — toggle reverts with 'No internet connection' SnackBar.

Integration test: Full round-trip — toggle ON → server confirms → Realtime stream emits → lastModified updates in list item. Mock the Configuration Manager and connectivity service. Aim for 85%+ branch coverage on the toggle handler.

Component
Scenario Configuration Screen
ui medium
Epic Risks (2)
high impact medium prob technical

If the scheduler runs concurrently (e.g., two overlapping cron invocations due to edge function retry), duplicate prompts could be dispatched before the first run's history records are committed, breaking the deduplication guarantee.

Mitigation & Contingency

Mitigation: Use a Postgres advisory lock or unique constraint on (user_id, scenario_id, activity_ref) in the prompt history table to make concurrent writes idempotent; design the scheduler to check history inside a transaction.

Contingency: If concurrency issues persist in production, add a distributed lock via Supabase Edge Function concurrency limit (max_instances=1) for the evaluation function as a hard guard.

medium impact medium prob scope

Coordinators may find scenario configuration unclear if trigger conditions are expressed as raw JSON or technical terminology, leading to misconfiguration and irrelevant prompts being sent to peer mentors.

Mitigation & Contingency

Mitigation: Design the ScenarioConfigurationScreen to display human-readable descriptions of each template's trigger condition (e.g., 'Send 3 days after first contact if wellbeing concern was flagged') rather than raw rule properties; validate with an HLF coordinator in a design review before implementation.

Contingency: If coordinators still misconfigure rules after launch, add a preview mode that shows a simulated prompt based on a test activity before the rule is enabled.