diff --git a/.changeset/khaki-masks-tie.md b/.changeset/khaki-masks-tie.md new file mode 100644 index 0000000000..e6f15cdbd6 --- /dev/null +++ b/.changeset/khaki-masks-tie.md @@ -0,0 +1,5 @@ +--- +"@calcom/atoms": patch +--- + +This change ensures that the booking dry run flow never reserves an actual booking slot. diff --git a/packages/features/bookings/Booker/components/hooks/useBookings.ts b/packages/features/bookings/Booker/components/hooks/useBookings.ts index 633f8e4601..61556025e0 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookings.ts +++ b/packages/features/bookings/Booker/components/hooks/useBookings.ts @@ -53,6 +53,7 @@ export interface IUseBookings { bookingForm: UseBookingFormReturnType["bookingForm"]; metadata: Record; teamMemberEmail?: string | null; + isBookingDryRun?: boolean; } const getBookingSuccessfulEventPayload = (booking: { @@ -107,7 +108,14 @@ const storeInLocalStorage = ({ localStorage.setItem(STORAGE_KEY, value); }; -export const useBookings = ({ event, hashedLink, bookingForm, metadata, teamMemberEmail }: IUseBookings) => { +export const useBookings = ({ + event, + hashedLink, + bookingForm, + metadata, + teamMemberEmail, + isBookingDryRun, +}: IUseBookings) => { const router = useRouter(); const eventSlug = useBookerStore((state) => state.eventSlug); const eventTypeId = useBookerStore((state) => state.eventId); @@ -399,6 +407,7 @@ export const useBookings = ({ event, hashedLink, bookingForm, metadata, teamMemb handleInstantBooking: createInstantBookingMutation.mutate, handleRecBooking: createRecurringBookingMutation.mutate, handleBooking: createBookingMutation.mutate, + isBookingDryRun, }); const errors = { diff --git a/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx b/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx index 86ee729a47..03306bb962 100644 --- a/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx +++ b/packages/features/bookings/lib/book-event-form/booking-to-mutation-input-mapper.tsx @@ -29,6 +29,7 @@ export type BookingOptions = { crmAppSlug?: string | null; orgSlug?: string; routingFormSearchParams?: RoutingFormSearchParams; + isDryRunProp?: boolean; }; export const mapBookingToMutationInput = ({ @@ -50,6 +51,7 @@ export const mapBookingToMutationInput = ({ crmAppSlug, orgSlug, routingFormSearchParams, + isDryRunProp, }: BookingOptions): BookingCreateBody => { const searchParams = new URLSearchParams(routingFormSearchParams ?? window.location.search); const routedTeamMemberIds = getRoutedTeamMemberIdsFromSearchParams(searchParams); @@ -57,7 +59,7 @@ export const mapBookingToMutationInput = ({ const routingFormResponseId = routingFormResponseIdParam ? Number(routingFormResponseIdParam) : undefined; const skipContactOwner = searchParams.get("cal.skipContactOwner") === "true"; const reroutingFormResponses = searchParams.get("cal.reroutingFormResponses"); - const _isDryRun = isBookingDryRun(searchParams); + const _isDryRun = isDryRunProp !== undefined ? isDryRunProp : isBookingDryRun(searchParams); const _cacheParam = searchParams?.get("cal.cache"); const _shouldServeCache = _cacheParam ? _cacheParam === "true" : undefined; const dub_id = searchParams?.get("dub_id"); diff --git a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx index 218248e196..bf8f32e884 100644 --- a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx +++ b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx @@ -353,7 +353,7 @@ export const BookerPlatformWrapper = ( onReserveSlotError: props.onReserveSlotError, onDeleteSlotSuccess: props.onDeleteSlotSuccess, onDeleteSlotError: props.onDeleteSlotError, - isBookingDryRun: routingParams?.isBookingDryRun, + isBookingDryRun: props.isBookingDryRun ? props.isBookingDryRun : routingParams?.isBookingDryRun, handleSlotReservation, }); @@ -393,6 +393,7 @@ export const BookerPlatformWrapper = ( handleRecBooking: createRecBooking, locationUrl: props.locationUrl, routingFormSearchParams, + isBookingDryRun: isBookingDryRun ?? routingParams?.isBookingDryRun, }); const onOverlaySwitchStateChange = useCallback( diff --git a/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts b/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts index ed1be8a727..2f0af2fcd1 100644 --- a/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts +++ b/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts @@ -30,6 +30,7 @@ type UseHandleBookingProps = { handleRecBooking: (input: BookingCreateBody[], callbacks?: Callbacks) => void; locationUrl?: string; routingFormSearchParams?: RoutingFormSearchParams; + isBookingDryRun?: boolean; }; export const useHandleBookEvent = ({ @@ -42,6 +43,7 @@ export const useHandleBookEvent = ({ handleRecBooking, locationUrl, routingFormSearchParams, + isBookingDryRun, }: UseHandleBookingProps) => { const isPlatform = useIsPlatform(); const setFormValues = useBookerStore((state) => state.setFormValues); @@ -108,6 +110,7 @@ export const useHandleBookEvent = ({ crmAppSlug, orgSlug: orgSlug ? orgSlug : undefined, routingFormSearchParams, + isDryRunProp: isBookingDryRun, }; const tracking = getUtmTrackingParameters(searchParams);