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
updateZonemutation
Implementation Plan
Phase 1: Schema Extension ✅ (Completed)
-
Add fields to
reservationstable:experience: v.optional(v.string())- Selected experience IDbundle: v.optional(v.string())- Selected bundle IDbookingStep: v.optional(v.union("EXPERIENCE", "SHOW", "TICKETS", "BUNDLE", "ADDONS", "CUSTOMER_INFO", "PAYMENT", "CONFIRMATION"))- Current step
-
Create mutations (
apps/backend/convex/functions/reservations.ts):updateBundle(reservationId, bundle)- Update bundle selectionupdateBookingStep(reservationId, step)- Track current step
Phase 2: Frontend Migration (In Progress)
-
Simplify
lib/booking-context.tsx✅:- Removed Zone type and setZone action
- Keeps ephemeral UI state only
-
Update booking components:
components/booking/step-tickets.tsx- UsescreatePendingmutation ✅components/booking/step-addons.tsx- UsesupdateWithAddOnsmutation ✅components/booking/checkout-form.tsx- UsesupdateCustomerInfomutation ✅app/[locale]/booking/experience/page.tsx- Experience selectionapp/[locale]/booking/bundle/page.tsx- UsesupdateBundlemutation ✅app/[locale]/booking/reservation/page.tsx- UsesupdateCustomerInfomutation
-
Removed zone-related pages:
zone/page.tsx- Now redirects to bundle page ✅
Phase 3: Admin Dashboard (Future)
- View incomplete/pending reservations via
bookingStepfield - See which step user abandoned
- Follow up with users who didn't complete payment
Booking Flow (Current)
experience → show → bundle → addons → customer_info → payment → confirmationCritical Files
| File | Status |
|---|---|
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
- Start booking flow, select experience, refresh page - state persists in Convex
- Abandon a booking mid-flow - admin can see incomplete reservation via bookingStep
- Complete booking - data flows correctly to payment
- Run
npx convex env pullto update types after schema changes - 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