import type { TFunction } from "next-i18next"; import { Trans } from "next-i18next"; import Link from "next/link"; import { useMemo, useState } from "react"; import type { FieldError } from "react-hook-form"; import { useIsPlatformBookerEmbed } from "@calcom/atoms/monorepo"; import type { BookerEvent } from "@calcom/features/bookings/types"; import { WEBSITE_PRIVACY_POLICY_URL, WEBSITE_TERMS_URL } from "@calcom/lib/constants"; import { getPaymentAppData } from "@calcom/lib/getPaymentAppData"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Alert, Button, EmptyScreen, Form } from "@calcom/ui"; import { useBookerStore } from "../../store"; import type { UseBookingFormReturnType } from "../hooks/useBookingForm"; import type { IUseBookingErrors, IUseBookingLoadingStates } from "../hooks/useBookings"; import { BookingFields } from "./BookingFields"; import { FormSkeleton } from "./Skeleton"; type BookEventFormProps = { onCancel?: () => void; onSubmit: () => void; errorRef: React.RefObject; errors: UseBookingFormReturnType["errors"] & IUseBookingErrors; loadingStates: IUseBookingLoadingStates; children?: React.ReactNode; bookingForm: UseBookingFormReturnType["bookingForm"]; renderConfirmNotVerifyEmailButtonCond: boolean; extraOptions: Record; isPlatform?: boolean; isVerificationCodeSending: boolean; shouldRenderCaptcha?: boolean; }; export const BookEventForm = ({ onCancel, eventQuery, rescheduleUid, onSubmit, errorRef, errors, loadingStates, renderConfirmNotVerifyEmailButtonCond, bookingForm, children, extraOptions, isVerificationCodeSending, isPlatform = false, shouldRenderCaptcha, }: Omit & { eventQuery: { isError: boolean; isPending: boolean; data?: Pick | null; }; rescheduleUid: string | null; }) => { const eventType = eventQuery.data; const setFormValues = useBookerStore((state) => state.setFormValues); const bookingData = useBookerStore((state) => state.bookingData); const timeslot = useBookerStore((state) => state.selectedTimeslot); const username = useBookerStore((state) => state.username); const isInstantMeeting = useBookerStore((state) => state.isInstantMeeting); const isPlatformBookerEmbed = useIsPlatformBookerEmbed(); const [responseVercelIdHeader] = useState(null); const { t } = useLocale(); const isPaidEvent = useMemo(() => { if (!eventType?.price) return false; const paymentAppData = getPaymentAppData(eventType); return eventType?.price > 0 && !Number.isNaN(paymentAppData.price) && paymentAppData.price > 0; }, [eventType]); if (eventQuery.isError) return ; if (eventQuery.isPending || !eventQuery.data) return ; if (!timeslot) return ( ); if (!eventType) { console.warn("No event type found for event", extraOptions); return ; } const watchedCfToken = bookingForm.watch("cfToken"); return (
{ // Form data is saved in store. This way when user navigates back to // still change the timeslot, and comes back to the form, all their values // still exist. This gets cleared when the form is submitted. const values = bookingForm.getValues(); setFormValues(values); }} form={bookingForm} handleSubmit={onSubmit} noValidate> -1)} fields={eventType.bookingFields} locations={eventType.locations} rescheduleUid={rescheduleUid || undefined} bookingData={bookingData} /> {(errors.hasFormErrors || errors.hasDataErrors) && (
)} {!isPlatform && (
Terms , Privacy Policy. , ]} />
)} {isPlatformBookerEmbed && (
{t("proceeding_agreement")}{" "} {t("terms")} {" "} {t("and")}{" "} {t("privacy_policy")} .
)}
{isInstantMeeting ? ( ) : ( <> {!!onCancel && ( )} )}
{children}
); }; const getError = ( globalError: FieldError | undefined, // It feels like an implementation detail to reimplement the types of useMutation here. // Since they don't matter for this function, I'd rather disable them then giving you // the cognitive overload of thinking to update them here when anything changes. // eslint-disable-next-line @typescript-eslint/no-explicit-any dataError: any, t: TFunction, responseVercelIdHeader: string | null ) => { if (globalError) return globalError?.message; const error = dataError; return error?.message ? ( <> {responseVercelIdHeader ?? ""} {t(error.message)} ) : ( <>{t("can_you_try_again")} ); };