fix: split firstname lastname support, phone support & timezone specific startTime in success redirect params (#17593)
* init * fixes * fix type
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { EventType } from "@prisma/client";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
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";
|
||||
@@ -24,11 +25,25 @@ function getNewSearchParams(args: {
|
||||
|
||||
type SuccessRedirectBookingType = Pick<
|
||||
BookingResponse | PaymentPageProps["booking"],
|
||||
"uid" | "title" | "description" | "startTime" | "endTime" | "location" | "attendees" | "user"
|
||||
"uid" | "title" | "description" | "startTime" | "endTime" | "location" | "attendees" | "user" | "responses"
|
||||
>;
|
||||
|
||||
type BookingResponseKey = keyof SuccessRedirectBookingType;
|
||||
|
||||
type ResultType = {
|
||||
[key in BookingResponseKey]?: SuccessRedirectBookingType[key];
|
||||
} & {
|
||||
hostName?: string[];
|
||||
attendeeName?: string | null;
|
||||
hostStartTime?: string | null;
|
||||
attendeeStartTime?: string | null;
|
||||
guestEmails?: string[] | null;
|
||||
phone?: string | null;
|
||||
attendeeFirstName?: string | null;
|
||||
attendeeLastName?: string | null;
|
||||
};
|
||||
|
||||
export const getBookingRedirectExtraParams = (booking: SuccessRedirectBookingType) => {
|
||||
type BookingResponseKey = keyof SuccessRedirectBookingType;
|
||||
const redirectQueryParamKeys: BookingResponseKey[] = [
|
||||
"title",
|
||||
"description",
|
||||
@@ -37,42 +52,80 @@ export const getBookingRedirectExtraParams = (booking: SuccessRedirectBookingTyp
|
||||
"location",
|
||||
"attendees",
|
||||
"user",
|
||||
"responses",
|
||||
];
|
||||
|
||||
type ResultType = {
|
||||
[key in BookingResponseKey]?: SuccessRedirectBookingType[key];
|
||||
} & {
|
||||
hostName?: string[];
|
||||
attendeeName?: string | null;
|
||||
};
|
||||
function getSafe<T>(obj: unknown, path: (string | number)[]): T | undefined {
|
||||
return path.reduce(
|
||||
(acc, key) => (typeof acc === "object" && acc !== null ? (acc as any)[key] : undefined),
|
||||
obj
|
||||
) as T | undefined;
|
||||
}
|
||||
|
||||
// Helper function to extract response details (e.g., phone, attendee's first and last name)
|
||||
function extractResponseDetails(booking: SuccessRedirectBookingType, obj: ResultType): ResultType {
|
||||
const result: ResultType = { ...obj };
|
||||
const phone = getSafe<string>(booking.responses, ["phone"]);
|
||||
const firstName = getSafe<string>(booking.responses, ["name", "firstName"]);
|
||||
const lastName = getSafe<string>(booking.responses, ["name", "lastName"]);
|
||||
const name = getSafe<string>(booking.responses, ["name"]);
|
||||
|
||||
if (phone) result.phone = phone;
|
||||
if (firstName) result.attendeeFirstName = firstName;
|
||||
if (lastName) result.attendeeLastName = lastName;
|
||||
else if (name && typeof name === "string") result.attendeeName = name; // Fallback if `name` is a string instead of an object
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Helper function to extract user details (e.g., host name and time zone)
|
||||
function extractUserDetails(booking: SuccessRedirectBookingType, obj: ResultType): ResultType {
|
||||
if (booking.user?.name) {
|
||||
const hostStartTime = dayjs(booking.startTime).tz(booking.user.timeZone).format();
|
||||
return {
|
||||
...obj,
|
||||
hostName: [...(obj.hostName || []), booking.user.name],
|
||||
hostStartTime,
|
||||
};
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
// Helper function to extract attendee and guest details
|
||||
function extractAttendeesAndGuests(booking: SuccessRedirectBookingType, obj: ResultType): ResultType {
|
||||
if (!Array.isArray(booking.attendees) || booking.attendees.length === 0) return obj;
|
||||
|
||||
const attendeeName = booking.attendees[0]?.name || null;
|
||||
const attendeeTimeZone = booking.attendees[0]?.timeZone || "UTC";
|
||||
const attendeeStartTime = dayjs(booking.startTime).tz(attendeeTimeZone).format();
|
||||
|
||||
const { hostNames, guestEmails } = booking.attendees.slice(1).reduce(
|
||||
(acc, attendee) => {
|
||||
if (attendee.name) {
|
||||
acc.hostNames.push(attendee.name);
|
||||
} else if (attendee.email) {
|
||||
acc.guestEmails.push(attendee.email);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ hostNames: [], guestEmails: [] } as { hostNames: string[]; guestEmails: string[] }
|
||||
);
|
||||
|
||||
return {
|
||||
...obj,
|
||||
attendeeName,
|
||||
attendeeStartTime,
|
||||
hostName: [...(obj.hostName || []), ...hostNames],
|
||||
guestEmails: guestEmails.length > 0 ? guestEmails : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const result = (Object.keys(booking) as BookingResponseKey[])
|
||||
.filter((key) => redirectQueryParamKeys.includes(key))
|
||||
.reduce<ResultType>((obj, key) => {
|
||||
if (key === "user" && booking.user?.name) {
|
||||
return { ...obj, hostName: [...(obj.hostName || []), booking.user.name] };
|
||||
}
|
||||
|
||||
if (key === "attendees" && Array.isArray(booking.attendees)) {
|
||||
const attendeeName = booking.attendees[0]?.name || null;
|
||||
const { hostNames, guestEmails } = booking.attendees.slice(1).reduce(
|
||||
(acc, attendee) => {
|
||||
if (attendee.name) {
|
||||
acc.hostNames.push(attendee.name);
|
||||
} else if (attendee.email) {
|
||||
acc.guestEmails.push(attendee.email);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{ hostNames: [], guestEmails: [] } as { hostNames: string[]; guestEmails: string[] }
|
||||
);
|
||||
return {
|
||||
...obj,
|
||||
attendeeName,
|
||||
hostName: [...(obj.hostName || []), ...hostNames],
|
||||
guestEmail: guestEmails.length > 0 ? guestEmails : undefined,
|
||||
};
|
||||
}
|
||||
if (key === "responses") return extractResponseDetails(booking, obj);
|
||||
if (key === "user") return extractUserDetails(booking, obj);
|
||||
if (key === "attendees") return extractAttendeesAndGuests(booking, obj);
|
||||
return { ...obj, [key]: booking[key] };
|
||||
}, {});
|
||||
|
||||
@@ -91,6 +144,8 @@ export const getBookingRedirectExtraParams = (booking: SuccessRedirectBookingTyp
|
||||
),
|
||||
hostName: result.hostName?.join(", "),
|
||||
attendeeName: result.attendeeName || undefined,
|
||||
hostStartTime: result.hostStartTime || undefined,
|
||||
attendeeStartTime: result.attendeeStartTime || undefined,
|
||||
};
|
||||
|
||||
return queryCompatibleParams;
|
||||
|
||||
@@ -18,15 +18,18 @@ export const paymentDataSelect = Prisma.validator<Prisma.PaymentSelect>()({
|
||||
title: true,
|
||||
startTime: true,
|
||||
endTime: true,
|
||||
responses: true,
|
||||
user: {
|
||||
select: {
|
||||
name: true,
|
||||
timeZone: true,
|
||||
},
|
||||
},
|
||||
attendees: {
|
||||
select: {
|
||||
email: true,
|
||||
name: true,
|
||||
timeZone: true,
|
||||
},
|
||||
},
|
||||
eventTypeId: true,
|
||||
|
||||
Reference in New Issue
Block a user