Skip to content

Refactor coverage guidelines wizard: Zustand persist → RHF + React Query #188

@jcleow

Description

@jcleow

Context

The coverage guidelines questionnaire wizard (coverageGuidelinesStore.ts) currently uses Zustand with persist middleware (localStorage) for both form state and cross-component shared state. This works but has several issues:

  • No form validation — inputs accept any value with no error feedback
  • Stale localStorage bugs — adding new fields causes NaN for users with old persisted data (see ?? 0 guards throughout GuidelinesTab.tsx)
  • Doesn't follow project conventions — CLAUDE.md specifies RHF for forms + Zod for validation
  • Will be redundant — once backend persistence is implemented (#TBD), localStorage persistence should be removed entirely

Current Architecture

Wizard steps (5 components)
  → Zustand store actions (setLifeTpdAnswers, setCriticalIllnessAnswers, etc.)
    → persist middleware → localStorage
      → consumed by: CoverageJourney, JourneyTab, ConfiguredGuidelinesView, etc.

Target Architecture

Wizard steps (5 components)
  → React Hook Form useForm() per step
    → Zod schema validation per step
      → on step complete: React Query mutation → backend API
        → React Query cache = shared state for all consumers

Migration Steps

Phase 1: Add RHF + Zod to wizard steps (can do before backend)

  • Create Zod schemas for each questionnaire section (hospitalizationSchema, lifeTpdSchema, etc.)
  • Wrap each wizard step component with useForm() + the relevant schema
  • Add inline validation errors (required fields, min/max ranges)
  • On "Continue", validate step → sync to Zustand store (keep store as intermediate)

Phase 2: Backend persistence (separate issue/PR)

  • Implement insurance backend CRUD APIs (see spec/insurance-backend-persistence.md)
  • Add React Query hooks: useCoverageGuidelinesQuery, useCoverageGuidelinesMutation
  • Replace Zustand persist → React Query as source of truth

Phase 3: Remove Zustand store

  • Consumers (CoverageJourney, JourneyTab, etc.) read from React Query cache instead of Zustand
  • Remove coverageGuidelinesStore.ts entirely
  • Remove coverage-guidelines-storage from localStorage

Files Involved

File Change
frontend/src/stores/coverageGuidelinesStore.ts Eventually remove
frontend/src/components/insurance/tabs/GuidelinesTab.tsx Add RHF per wizard step
frontend/src/hooks/queries/useCoverageGuidelinesQuery.ts New — React Query hooks
frontend/src/types/insurance-schemas.ts New — Zod validation schemas

Related

  • Backend persistence spec: spec/insurance-backend-persistence.md
  • Similar pattern already used in: OnboardingWizardModal (RHF + Zod)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions