← Files WixARCHIVED FILE

skills/wix-headless-templates/bookings/project/src/hooks/bookings/useBookingFlow.ts

2.18 KB · Oct 8, 2026 · 12:02 UTC

↓ Download file

See the change to this file →

// React binding of the booking-flow store (wix/bookings/booking-flow-store.ts) — the whole booking
// state machine for one service lives there, framework-free: the display zone, the availability
// window (day-grouped slots, week paging, staff filter, next availability), a course's seats, a
// class's sessions, participants, deposit choice, add-ons, the schema-driven form, the CTA state,
// and book(). All correctness lives in the data layer; you own how it looks. Mount the surface
// client-only: availability is timezone/session-specific.
import { useEffect, useRef, useSyncExternalStore } from "react";
import { createBookingFlowStore, type BookingFlowState, type BookingFlowStore } from "../../wix/bookings/booking-flow-store";
import type { ServiceDetail } from "../../wix/bookings/types";

export type UseBookingFlow = BookingFlowState &
  Pick<
    BookingFlowStore,
    | "nextWeek"
    | "prevWeek"
    | "jumpTo"
    | "setStaffId"
    | "setSelectedSlot"
    | "setDisplayTimeZone"
    | "setParticipants"
    | "setPayDeposit"
    | "toggleAddOn"
    | "setAddOnQuantity"
    | "canSelectMore"
    | "loadMoreSessions"
    | "setValue"
    | "book"
  >;

export function useBookingFlow(service: ServiceDetail): UseBookingFlow {
  const ref = useRef<{ serviceId: string; store: BookingFlowStore } | null>(null);
  if (!ref.current || ref.current.serviceId !== service.id) ref.current = { serviceId: service.id, store: createBookingFlowStore(service) };
  const store = ref.current.store;
  useEffect(() => {
    store.start();
    return () => store.stop();
  }, [store]);
  const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
  return {
    ...state,
    nextWeek: store.nextWeek,
    prevWeek: store.prevWeek,
    jumpTo: store.jumpTo,
    setStaffId: store.setStaffId,
    setSelectedSlot: store.setSelectedSlot,
    setDisplayTimeZone: store.setDisplayTimeZone,
    setParticipants: store.setParticipants,
    setPayDeposit: store.setPayDeposit,
    toggleAddOn: store.toggleAddOn,
    setAddOnQuantity: store.setAddOnQuantity,
    canSelectMore: store.canSelectMore,
    loadMoreSessions: store.loadMoreSessions,
    setValue: store.setValue,
    book: store.book,
  };
}

SHA-256: 715668130806712c7ddd13f87bdf6f24dff6a322b6a12e28d42ade900b1e8c83