Skip to content

Commit 0af62da

Browse files
hariombalharadevin-ai-integration[bot]Udit-takkar
authored
feat: add dry run events for SDK (dryRunBookingSuccessfulV2 and dryRunRescheduleBookingSuccessfulV2) (calcom#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>
1 parent 9b323cb commit 0af62da

2 files changed

Lines changed: 89 additions & 28 deletions

File tree

packages/embeds/embed-core/src/sdk-action-manager.ts

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@ function _fireEvent(fullName: string, detail: CustomEventDetail) {
99
window.dispatchEvent(event);
1010
}
1111

12+
type BaseBookingEventPayload = {
13+
title: string | undefined;
14+
startTime: string | undefined;
15+
endTime: string | undefined;
16+
eventTypeId: number | null | undefined;
17+
status: string | undefined;
18+
paymentRequired: boolean;
19+
isRecurring: boolean;
20+
/**
21+
* This is only used for recurring bookings
22+
*/
23+
allBookings?: { startTime: string; endTime: string }[];
24+
videoCallUrl?: string;
25+
};
26+
1227
export type EventDataMap = {
1328
eventTypeSelected: {
1429
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -24,20 +39,8 @@ export type EventDataMap = {
2439
linkReady: Record<string, never>;
2540
__connectInitiated: Record<string, never>;
2641
__connectCompleted: Record<string, never>;
27-
bookingSuccessfulV2: {
42+
bookingSuccessfulV2: BaseBookingEventPayload & {
2843
uid: string | undefined;
29-
title: string | undefined;
30-
startTime: string | undefined;
31-
endTime: string | undefined;
32-
eventTypeId: number | null | undefined;
33-
status: string | undefined;
34-
paymentRequired: boolean;
35-
isRecurring: boolean;
36-
/**
37-
* This is only used for recurring bookings
38-
*/
39-
allBookings?: { startTime: string; endTime: string }[];
40-
videoCallUrl?: string;
4144
};
4245

4346
/**
@@ -56,20 +59,11 @@ export type EventDataMap = {
5659
};
5760
confirmed: boolean;
5861
};
59-
rescheduleBookingSuccessfulV2: {
62+
rescheduleBookingSuccessfulV2: BaseBookingEventPayload & {
6063
uid: string | undefined;
61-
title: string | undefined;
62-
startTime: string | undefined;
63-
endTime: string | undefined;
64-
eventTypeId: number | null | undefined;
65-
status: string | undefined;
66-
paymentRequired: boolean;
67-
isRecurring: boolean;
68-
/**
69-
* This is only used for recurring bookings
70-
*/
71-
allBookings?: { startTime: string; endTime: string }[];
7264
};
65+
dryRunBookingSuccessfulV2: BaseBookingEventPayload;
66+
dryRunRescheduleBookingSuccessfulV2: BaseBookingEventPayload;
7367
/**
7468
* @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.
7569
*/

packages/features/bookings/Booker/components/hooks/useBookings.ts

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,17 @@ export interface IUseBookings {
5757
isBookingDryRun?: boolean;
5858
}
5959

60-
const getBookingSuccessfulEventPayload = (booking: {
60+
const getBaseBookingEventPayload = (booking: {
6161
title?: string;
6262
startTime: string;
6363
endTime: string;
6464
eventTypeId?: number | null;
6565
status?: BookingStatus;
6666
paymentRequired: boolean;
67-
uid?: string;
6867
isRecurring: boolean;
6968
videoCallUrl?: string;
7069
}) => {
7170
return {
72-
uid: booking.uid,
7371
title: booking.title,
7472
startTime: booking.startTime,
7573
endTime: booking.endTime,
@@ -81,7 +79,28 @@ const getBookingSuccessfulEventPayload = (booking: {
8179
};
8280
};
8381

82+
const getBookingSuccessfulEventPayload = (booking: {
83+
title?: string;
84+
startTime: string;
85+
endTime: string;
86+
eventTypeId?: number | null;
87+
status?: BookingStatus;
88+
paymentRequired: boolean;
89+
uid?: string;
90+
isRecurring: boolean;
91+
videoCallUrl?: string;
92+
}) => {
93+
return {
94+
uid: booking.uid,
95+
...getBaseBookingEventPayload(booking),
96+
};
97+
};
98+
8499
const getRescheduleBookingSuccessfulEventPayload = getBookingSuccessfulEventPayload;
100+
101+
export const getDryRunBookingSuccessfulEventPayload = getBaseBookingEventPayload;
102+
103+
export const getDryRunRescheduleBookingSuccessfulEventPayload = getDryRunBookingSuccessfulEventPayload;
85104
export interface IUseBookingLoadingStates {
86105
creatingBooking: boolean;
87106
creatingRecurringBooking: boolean;
@@ -196,6 +215,30 @@ export const useBookings = ({
196215
mutationFn: createBooking,
197216
onSuccess: (booking) => {
198217
if (booking.isDryRun) {
218+
const validDuration = event.data?.isDynamic
219+
? duration || event.data?.length
220+
: duration && event.data?.metadata?.multipleDuration?.includes(duration)
221+
? duration
222+
: event.data?.length;
223+
224+
if (isRescheduling) {
225+
sdkActionManager?.fire(
226+
"dryRunRescheduleBookingSuccessfulV2",
227+
getDryRunRescheduleBookingSuccessfulEventPayload({
228+
...booking,
229+
isRecurring: false,
230+
})
231+
);
232+
} else {
233+
sdkActionManager?.fire(
234+
"dryRunBookingSuccessfulV2",
235+
getDryRunBookingSuccessfulEventPayload({
236+
...booking,
237+
isRecurring: false,
238+
})
239+
);
240+
}
241+
199242
router.push("/booking/dry-run-successful");
200243
return;
201244
}
@@ -343,6 +386,30 @@ export const useBookings = ({
343386
const booking = bookings[0] || {};
344387

345388
if (booking.isDryRun) {
389+
if (isRescheduling) {
390+
sdkActionManager?.fire("dryRunRescheduleBookingSuccessfulV2", {
391+
...getDryRunRescheduleBookingSuccessfulEventPayload({
392+
...booking,
393+
isRecurring: true,
394+
}),
395+
allBookings: bookings.map((booking) => ({
396+
startTime: booking.startTime,
397+
endTime: booking.endTime,
398+
})),
399+
});
400+
} else {
401+
sdkActionManager?.fire("dryRunBookingSuccessfulV2", {
402+
...getDryRunBookingSuccessfulEventPayload({
403+
...booking,
404+
isRecurring: true,
405+
}),
406+
allBookings: bookings.map((booking) => ({
407+
startTime: booking.startTime,
408+
endTime: booking.endTime,
409+
})),
410+
});
411+
}
412+
346413
router.push("/booking/dry-run-successful");
347414
return;
348415
}

0 commit comments

Comments
 (0)