import type { ReactElement } from "react"; import React, { useState } from "react"; import { BookerEmbed } from "../booker-embed"; import type { BookerPlatformWrapperAtomPropsForTeam } from "../booker/types"; /** * Renders the Router component with predefined props. * Depending on the routing form either renders a custom message, redirects or display Booker embed atom. * formResponsesURLParams contains the answers to the questions fields defined in the form. * ```tsx * console.log(data), * onCreateBookingError: (err) => console.error(err) * /> * ``` */ export const Router = React.memo( ({ formId, formResponsesURLParams, onExternalRedirect, onDisplayBookerEmbed, renderMessage, onSubmitFormStart, onSubmitFormEnd, renderLoader, bookerProps, }: { formId: string; formResponsesURLParams?: URLSearchParams; onExternalRedirect?: () => void; onDisplayBookerEmbed?: () => void; onSubmitFormStart?: () => void; onSubmitFormEnd?: () => void; renderMessage?: (message?: string) => ReactElement | ReactElement[]; bookerProps?: Pick< Partial, | "customClassNames" | "bannerUrl" | "onCreateBookingSuccess" | "onCreateBookingError" | "onCreateRecurringBookingSuccess" | "onCreateRecurringBookingError" | "onReserveSlotSuccess" | "onReserveSlotError" | "onDeleteSlotSuccess" | "onDeleteSlotError" | "view" | "onDryRunSuccess" | "hostsLimit" | "metadata" | "handleCreateBooking" | "handleSlotReservation" | "preventEventTypeRedirect" >; renderLoader?: (isLoading?: boolean) => ReactElement | ReactElement[]; }) => { const [isLoading, setIsLoading] = useState(); const [routerUrl, setRouterUrl] = useState(); const [routingData, setRoutingData] = useState<{ message: string } | undefined>(); const [isError, setIsError] = useState(); React.useEffect(() => { if (!isLoading) { setIsLoading(true); setIsError(false); setRoutingData(undefined); setRouterUrl(""); const baseUrl = import.meta.env.VITE_BOOKER_EMBED_API_URL; onSubmitFormStart?.(); fetch(`${baseUrl}/router/forms/${formId}/submit`, { method: "POST", headers: { "Content-Type": "application/json", }, body: formResponsesURLParams ? JSON.stringify(Object.fromEntries(formResponsesURLParams)) : undefined, }) .then(async (response) => { const body: | { status: string; data: string; redirect: true } | { status: string; data: { message: string }; redirect: false } = await response.json(); if (body.redirect) { setRouterUrl(body.data); } else { setRoutingData({ message: body.data?.message ?? "" }); } }) .catch((err) => { console.error(err); setIsError(true); }) .finally(() => { setIsLoading(false); onSubmitFormEnd?.(); }); } }, []); const isRedirect = !!routerUrl; if (isLoading && renderLoader) { return <>{renderLoader?.(isLoading)}; } if (isLoading || isError) { return <>; } if (!isLoading && isRedirect && routerUrl) { const redirectParams = new URLSearchParams(routerUrl); if (redirectParams.get("cal.action") === "eventTypeRedirectUrl") { // display booker with redirect URL onDisplayBookerEmbed?.(); return ; } else if (redirectParams.get("cal.action") === "externalRedirectUrl") { onExternalRedirect?.(); window.location.href = routerUrl; return <>; } } if (!isRedirect && routingData?.message) { if (renderMessage) { return <>{renderMessage(routingData?.message)}; } return (
{routingData?.message}
); } return <>; } ); Router.displayName = "RouterAtom";