fix: split firstname lastname support, phone support & timezone specific startTime in success redirect params (#17593)

* init

* fixes

* fix type
This commit is contained in:
Syed Ali Shahbaz
2024-11-12 11:16:41 +00:00
committed by GitHub
parent 6889592d4f
commit dc400d80d0
2 changed files with 90 additions and 32 deletions
+87 -32
View File
@@ -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;
+3
View File
@@ -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,