plans
2026-05-04
2026 05 04 Convex Booking Flow Migration

Plan: Migrate Booking Flow to Convex-First Architecture

Context

The booking flow previously used React Context (BookingContext) for state, with zones as a booking step. User selections were stored only in context until final submission. This meant:

  • No tracking of abandoned bookings
  • Data loss on page refresh
  • Can't show incomplete booking progress in admin

User's insight: Using Convex for booking state enables tracking which step user completed before submission, with server-side persistence.

Note: Zone step has been removed from the business model entirely.

Current State (Post-Zone-Removal)

BookingContext (frontend/lib/booking-context.tsx)

Holds: experience, occurrenceId, ticketType, quantity, addOns, bundle, guests, customerInfo, reservationId, bookingExpiresAt

Reservations Table (convex/schema.ts)

Stores: occurrenceId, customerFirstName, customerLastName, customerEmail, customerPhone, ticketType, quantity, addOns, subtotal, totalAmount, paymentStatus, bookingExpiresAt, experience, bundle, bookingStep

Removed

  • Zone concept entirely (zoneOptions, zone type, setZone action)
  • Zone step from booking flow
  • Zone field from tables schema
  • updateZone mutation

Implementation Plan

Phase 1: Schema Extension ✅ (Completed)

  1. Add fields to reservations table:

    • experience: v.optional(v.string()) - Selected experience ID
    • bundle: v.optional(v.string()) - Selected bundle ID
    • bookingStep: v.optional(v.union("EXPERIENCE", "SHOW", "TICKETS", "BUNDLE", "ADDONS", "CUSTOMER_INFO", "PAYMENT", "CONFIRMATION")) - Current step
  2. Create mutations (apps/backend/convex/functions/reservations.ts):

    • updateBundle(reservationId, bundle) - Update bundle selection
    • updateBookingStep(reservationId, step) - Track current step

Phase 2: Frontend Migration (In Progress)

  1. Simplify lib/booking-context.tsx ✅:

    • Removed Zone type and setZone action
    • Keeps ephemeral UI state only
  2. Update booking components:

    • components/booking/step-tickets.tsx - Uses createPending mutation ✅
    • components/booking/step-addons.tsx - Uses updateWithAddOns mutation ✅
    • components/booking/checkout-form.tsx - Uses updateCustomerInfo mutation ✅
    • app/[locale]/booking/experience/page.tsx - Experience selection
    • app/[locale]/booking/bundle/page.tsx - Uses updateBundle mutation ✅
    • app/[locale]/booking/reservation/page.tsx - Uses updateCustomerInfo mutation
  3. Removed zone-related pages:

    • zone/page.tsx - Now redirects to bundle page ✅

Phase 3: Admin Dashboard (Future)

  • View incomplete/pending reservations via bookingStep field
  • See which step user abandoned
  • Follow up with users who didn't complete payment

Booking Flow (Current)

experience → show → bundle → addons → customer_info → payment → confirmation

Critical Files

FileStatus
apps/backend/convex/schema.ts✅ Updated - added experience, bundle, bookingStep
apps/backend/convex/functions/reservations.ts✅ Updated - added updateBundle, updateBookingStep
apps/frontend/lib/booking-context.tsx✅ Simplified - removed Zone
apps/frontend/lib/data/booking.ts✅ Removed zoneOptions
apps/frontend/app/[locale]/booking/zone/page.tsx✅ Redirects to bundle
apps/frontend/components/booking/step-addons.tsx✅ Uses Convex mutation
apps/frontend/app/[locale]/booking/bundle/page.tsx✅ Uses Convex mutation

Verification

  1. Start booking flow, select experience, refresh page - state persists in Convex
  2. Abandon a booking mid-flow - admin can see incomplete reservation via bookingStep
  3. Complete booking - data flows correctly to payment
  4. Run npx convex env pull to update types after schema changes
  5. Run tests: npx vitest run

Why Context + Convex Hybrid?

Some UI state (modal open/close, dropdown visibility, local form validation) should stay in React state - no server sync needed. The rule: Convex for data that needs to persist, context for purely UI state.

Changelog

2026-05-04:
- Removed zone concept entirely (zoneOptions, Zone type, setZone action)
- Zone page now redirects to bundle
- Zone removed from tables schema, by_zone index
- Removed updateZone mutation
- Added experience, bundle, bookingStep fields to reservations

feat(booking): Migrate booking flow from context to Convex-first architecture
- Add experience, bundle, bookingStep fields to reservations table
- Create update mutations for booking steps
- Track incomplete bookings for admin visibility
- Simplify BookingContext to only ephemeral UI state