feat: add dry run events for SDK (dryRunBookingSuccessfulV2 and dryRunRescheduleBookingSuccessfulV2) (#23072)
* feat: add dry run events for SDK (dryRunBookingSuccessfulV2 and dryRunRescheduleBookingSuccessfulV2) - Add new event types dryRunBookingSuccessfulV2 and dryRunRescheduleBookingSuccessfulV2 to EventDataMap - Create payload functions that exclude uid field for dry run events - Fire dry run events when isDryRun is true in both regular and recurring booking flows - Add unit tests to verify dry run event payloads are correct and exclude uid field - Ensures dry run mode no longer skips event firing but uses appropriate dry run variants Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: make dry run events more DRY by reusing types and payload logic - Create BaseBookingEventPayload type to eliminate duplication between regular and dry run events - Use intersection types to compose final event types in sdk-action-manager.ts - Create getBaseBookingEventPayload function for common payload generation logic - Export dry run payload functions and import them in tests instead of redefining - Fix missing videoCallUrl field in rescheduleBookingSuccessfulV2 type Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * Remove test file --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
co-authored by
Devin AI
Udit Takkar
parent
9b323cbcc8
commit
0af62da16b
@@ -9,6 +9,21 @@ function _fireEvent(fullName: string, detail: CustomEventDetail) {
|
||||
window.dispatchEvent(event);
|
||||
}
|
||||
|
||||
type BaseBookingEventPayload = {
|
||||
title: string | undefined;
|
||||
startTime: string | undefined;
|
||||
endTime: string | undefined;
|
||||
eventTypeId: number | null | undefined;
|
||||
status: string | undefined;
|
||||
paymentRequired: boolean;
|
||||
isRecurring: boolean;
|
||||
/**
|
||||
* This is only used for recurring bookings
|
||||
*/
|
||||
allBookings?: { startTime: string; endTime: string }[];
|
||||
videoCallUrl?: string;
|
||||
};
|
||||
|
||||
export type EventDataMap = {
|
||||
eventTypeSelected: {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
@@ -24,20 +39,8 @@ export type EventDataMap = {
|
||||
linkReady: Record<string, never>;
|
||||
__connectInitiated: Record<string, never>;
|
||||
__connectCompleted: Record<string, never>;
|
||||
bookingSuccessfulV2: {
|
||||
bookingSuccessfulV2: BaseBookingEventPayload & {
|
||||
uid: string | undefined;
|
||||
title: string | undefined;
|
||||
startTime: string | undefined;
|
||||
endTime: string | undefined;
|
||||
eventTypeId: number | null | undefined;
|
||||
status: string | undefined;
|
||||
paymentRequired: boolean;
|
||||
isRecurring: boolean;
|
||||
/**
|
||||
* This is only used for recurring bookings
|
||||
*/
|
||||
allBookings?: { startTime: string; endTime: string }[];
|
||||
videoCallUrl?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -56,20 +59,11 @@ export type EventDataMap = {
|
||||
};
|
||||
confirmed: boolean;
|
||||
};
|
||||
rescheduleBookingSuccessfulV2: {
|
||||
rescheduleBookingSuccessfulV2: BaseBookingEventPayload & {
|
||||
uid: string | undefined;
|
||||
title: string | undefined;
|
||||
startTime: string | undefined;
|
||||
endTime: string | undefined;
|
||||
eventTypeId: number | null | undefined;
|
||||
status: string | undefined;
|
||||
paymentRequired: boolean;
|
||||
isRecurring: boolean;
|
||||
/**
|
||||
* This is only used for recurring bookings
|
||||
*/
|
||||
allBookings?: { startTime: string; endTime: string }[];
|
||||
};
|
||||
dryRunBookingSuccessfulV2: BaseBookingEventPayload;
|
||||
dryRunRescheduleBookingSuccessfulV2: BaseBookingEventPayload;
|
||||
/**
|
||||
* @deprecated Use `rescheduleBookingSuccessfulV2` instead. We restrict the data heavily there, only sending what is absolutely needed and keeping it light as well. Plus, more importantly that can be documented well.
|
||||
*/
|
||||
|
||||
@@ -57,6 +57,28 @@ export interface IUseBookings {
|
||||
isBookingDryRun?: boolean;
|
||||
}
|
||||
|
||||
const getBaseBookingEventPayload = (booking: {
|
||||
title?: string;
|
||||
startTime: string;
|
||||
endTime: string;
|
||||
eventTypeId?: number | null;
|
||||
status?: BookingStatus;
|
||||
paymentRequired: boolean;
|
||||
isRecurring: boolean;
|
||||
videoCallUrl?: string;
|
||||
}) => {
|
||||
return {
|
||||
title: booking.title,
|
||||
startTime: booking.startTime,
|
||||
endTime: booking.endTime,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
status: booking.status,
|
||||
paymentRequired: booking.paymentRequired,
|
||||
isRecurring: booking.isRecurring,
|
||||
videoCallUrl: booking.videoCallUrl,
|
||||
};
|
||||
};
|
||||
|
||||
const getBookingSuccessfulEventPayload = (booking: {
|
||||
title?: string;
|
||||
startTime: string;
|
||||
@@ -70,18 +92,15 @@ const getBookingSuccessfulEventPayload = (booking: {
|
||||
}) => {
|
||||
return {
|
||||
uid: booking.uid,
|
||||
title: booking.title,
|
||||
startTime: booking.startTime,
|
||||
endTime: booking.endTime,
|
||||
eventTypeId: booking.eventTypeId,
|
||||
status: booking.status,
|
||||
paymentRequired: booking.paymentRequired,
|
||||
isRecurring: booking.isRecurring,
|
||||
videoCallUrl: booking.videoCallUrl,
|
||||
...getBaseBookingEventPayload(booking),
|
||||
};
|
||||
};
|
||||
|
||||
const getRescheduleBookingSuccessfulEventPayload = getBookingSuccessfulEventPayload;
|
||||
|
||||
export const getDryRunBookingSuccessfulEventPayload = getBaseBookingEventPayload;
|
||||
|
||||
export const getDryRunRescheduleBookingSuccessfulEventPayload = getDryRunBookingSuccessfulEventPayload;
|
||||
export interface IUseBookingLoadingStates {
|
||||
creatingBooking: boolean;
|
||||
creatingRecurringBooking: boolean;
|
||||
@@ -196,6 +215,30 @@ export const useBookings = ({
|
||||
mutationFn: createBooking,
|
||||
onSuccess: (booking) => {
|
||||
if (booking.isDryRun) {
|
||||
const validDuration = event.data?.isDynamic
|
||||
? duration || event.data?.length
|
||||
: duration && event.data?.metadata?.multipleDuration?.includes(duration)
|
||||
? duration
|
||||
: event.data?.length;
|
||||
|
||||
if (isRescheduling) {
|
||||
sdkActionManager?.fire(
|
||||
"dryRunRescheduleBookingSuccessfulV2",
|
||||
getDryRunRescheduleBookingSuccessfulEventPayload({
|
||||
...booking,
|
||||
isRecurring: false,
|
||||
})
|
||||
);
|
||||
} else {
|
||||
sdkActionManager?.fire(
|
||||
"dryRunBookingSuccessfulV2",
|
||||
getDryRunBookingSuccessfulEventPayload({
|
||||
...booking,
|
||||
isRecurring: false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
router.push("/booking/dry-run-successful");
|
||||
return;
|
||||
}
|
||||
@@ -343,6 +386,30 @@ export const useBookings = ({
|
||||
const booking = bookings[0] || {};
|
||||
|
||||
if (booking.isDryRun) {
|
||||
if (isRescheduling) {
|
||||
sdkActionManager?.fire("dryRunRescheduleBookingSuccessfulV2", {
|
||||
...getDryRunRescheduleBookingSuccessfulEventPayload({
|
||||
...booking,
|
||||
isRecurring: true,
|
||||
}),
|
||||
allBookings: bookings.map((booking) => ({
|
||||
startTime: booking.startTime,
|
||||
endTime: booking.endTime,
|
||||
})),
|
||||
});
|
||||
} else {
|
||||
sdkActionManager?.fire("dryRunBookingSuccessfulV2", {
|
||||
...getDryRunBookingSuccessfulEventPayload({
|
||||
...booking,
|
||||
isRecurring: true,
|
||||
}),
|
||||
allBookings: bookings.map((booking) => ({
|
||||
startTime: booking.startTime,
|
||||
endTime: booking.endTime,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
router.push("/booking/dry-run-successful");
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user