* migrate availability/[schedule] * add use client directive * migrate main availability page * migrate availability/troubleshoot page * add env var * extract AvailabilitySettingsWebWrapper into /modules * fix build * add missing default * add missing export * fix troubleshoot * use params, not searchParams in generateMetadata * fix schedule page in app router
102 lines
3.5 KiB
TypeScript
102 lines
3.5 KiB
TypeScript
import type { EventType } from "@prisma/client";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
import type { PaymentPageProps } from "@calcom/ee/payments/pages/payment";
|
|
import { useIsEmbed } from "@calcom/embed-core/embed-iframe";
|
|
import type { BookingResponse } from "@calcom/features/bookings/types";
|
|
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
|
import { navigateInTopWindow } from "@calcom/lib/navigateInTopWindow";
|
|
|
|
function getNewSearchParams(args: {
|
|
query: Record<string, string | null | undefined | boolean>;
|
|
searchParams?: URLSearchParams;
|
|
}) {
|
|
const { query, searchParams } = args;
|
|
const newSearchParams = new URLSearchParams(searchParams);
|
|
Object.entries(query).forEach(([key, value]) => {
|
|
if (value === null || value === undefined) {
|
|
return;
|
|
}
|
|
newSearchParams.append(key, String(value));
|
|
});
|
|
return newSearchParams;
|
|
}
|
|
|
|
type SuccessRedirectBookingType = Pick<
|
|
BookingResponse | PaymentPageProps["booking"],
|
|
"uid" | "title" | "description" | "startTime" | "endTime" | "location"
|
|
>;
|
|
|
|
export const getBookingRedirectExtraParams = (booking: SuccessRedirectBookingType) => {
|
|
type BookingResponseKey = keyof SuccessRedirectBookingType;
|
|
const redirectQueryParamKeys: BookingResponseKey[] = [
|
|
"title",
|
|
"description",
|
|
"startTime",
|
|
"endTime",
|
|
"location",
|
|
];
|
|
|
|
return (Object.keys(booking) as BookingResponseKey[])
|
|
.filter((key) => redirectQueryParamKeys.includes(key))
|
|
.reduce((obj, key) => ({ ...obj, [key]: booking[key] }), {});
|
|
};
|
|
|
|
export const useBookingSuccessRedirect = () => {
|
|
const router = useRouter();
|
|
const searchParams = useCompatSearchParams();
|
|
const isEmbed = useIsEmbed();
|
|
const bookingSuccessRedirect = ({
|
|
successRedirectUrl,
|
|
query,
|
|
booking,
|
|
forwardParamsSuccessRedirect,
|
|
}: {
|
|
successRedirectUrl: EventType["successRedirectUrl"];
|
|
forwardParamsSuccessRedirect: EventType["forwardParamsSuccessRedirect"];
|
|
query: Record<string, string | null | undefined | boolean>;
|
|
booking: SuccessRedirectBookingType;
|
|
}) => {
|
|
if (successRedirectUrl) {
|
|
const url = new URL(successRedirectUrl);
|
|
// Using parent ensures, Embed iframe would redirect outside of the iframe.
|
|
if (!forwardParamsSuccessRedirect) {
|
|
navigateInTopWindow(url.toString());
|
|
return;
|
|
}
|
|
const bookingExtraParams = getBookingRedirectExtraParams(booking);
|
|
const newSearchParams = getNewSearchParams({
|
|
query: {
|
|
...query,
|
|
...bookingExtraParams,
|
|
},
|
|
searchParams: searchParams ?? undefined,
|
|
});
|
|
|
|
newSearchParams.forEach((value, key) => {
|
|
url.searchParams.append(key, value);
|
|
});
|
|
|
|
navigateInTopWindow(url.toString());
|
|
return;
|
|
}
|
|
|
|
// TODO: Abstract it out and reuse at other places where we navigate within the embed. Though this is needed only in case of hard navigation happening but we aren't sure where hard navigation happens and where a soft navigation
|
|
// This is specially true after App Router it seems
|
|
const headersRelatedSearchParams = searchParams
|
|
? {
|
|
"flag.coep": searchParams.get("flag.coep") ?? "false",
|
|
}
|
|
: undefined;
|
|
|
|
// We don't want to forward all search params, as they could possibly break the booking page.
|
|
const newSearchParams = getNewSearchParams({
|
|
query,
|
|
searchParams: new URLSearchParams(headersRelatedSearchParams),
|
|
});
|
|
return router.push(`/booking/${booking.uid}${isEmbed ? "/embed" : ""}?${newSearchParams.toString()}`);
|
|
};
|
|
|
|
return bookingSuccessRedirect;
|
|
};
|