From 2f769a8b8cd4f51f3471aefe3cfe478dcfed07c9 Mon Sep 17 00:00:00 2001 From: Anirban Singha <143536290+SinghaAnirban005@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:38:19 +0000 Subject: [PATCH] feat: show previous booking time in rescheduled email --- packages/emails/src/components/WhenInfo.tsx | 43 +++++++++++++++---- .../bookings/lib/BookingEmailSmsHandler.ts | 13 ++++++ packages/types/Calendar.d.ts | 2 + 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/packages/emails/src/components/WhenInfo.tsx b/packages/emails/src/components/WhenInfo.tsx index 801df21731167d..197e3763b14c10 100644 --- a/packages/emails/src/components/WhenInfo.tsx +++ b/packages/emails/src/components/WhenInfo.tsx @@ -6,8 +6,7 @@ import dayjs from "@calcom/dayjs"; import "@calcom/dayjs/locales"; import { getEveryFreqFor } from "@calcom/lib/recurringStrings"; import type { TimeFormat } from "@calcom/lib/timeFormat"; -import type { CalendarEvent, Person } from "@calcom/types/Calendar"; -import type { RecurringEvent } from "@calcom/types/Calendar"; +import type { CalendarEvent, Person, RecurringEvent } from "@calcom/types/Calendar"; import { Info } from "./Info"; @@ -40,10 +39,22 @@ export function WhenInfo(props: { }) { const { timeZone, t, calEvent: { recurringEvent } = {}, locale, timeFormat } = props; + function getPreviousRecipientStart(format: string): string | null { + if(!props.calEvent.previousStartTime) return null + return dayjs(props.calEvent.previousStartTime).tz(timeZone).locale(locale).format(format) + } + + function getPreviousRecipientEnd(format: string): string | null { + if(!props.calEvent.previousEndTime) return null + return dayjs(props.calEvent.previousEndTime).tz(timeZone).locale(locale).format(format) + } + function getRecipientStart(format: string) { return dayjs(props.calEvent.startTime).tz(timeZone).locale(locale).format(format); } + const hasPreviousTime = !!(props.calEvent.previousStartTime && props.calEvent.previousEndTime); + function getRecipientEnd(format: string) { return dayjs(props.calEvent.endTime).tz(timeZone).locale(locale).format(format); } @@ -56,16 +67,30 @@ export function WhenInfo(props: { return (
- {recurringEvent?.count ? `${t("starting")} ` : ""} - {getRecipientStart(`dddd, LL | ${timeFormat}`)} - {getRecipientEnd(timeFormat)}{" "} - ({timeZone}) - +
+ {hasPreviousTime && ( +
+ {recurringEvent?.count ? `${t("starting")} ` : ""} + {getPreviousRecipientStart(`dddd, LL | ${timeFormat}`)} -{" "} + {getPreviousRecipientEnd(timeFormat)}{" "} + ({timeZone}) +
+ )} +
+ {recurringEvent?.count ? `${t("starting")} ` : ""} + {getRecipientStart(`dddd, LL | ${timeFormat}`)} -{" "} + {getRecipientEnd(timeFormat)}{" "} + ({timeZone}) +
+
} withSpacer /> diff --git a/packages/features/bookings/lib/BookingEmailSmsHandler.ts b/packages/features/bookings/lib/BookingEmailSmsHandler.ts index 95da16025fc5d3..36be8446be9481 100644 --- a/packages/features/bookings/lib/BookingEmailSmsHandler.ts +++ b/packages/features/bookings/lib/BookingEmailSmsHandler.ts @@ -117,6 +117,7 @@ export class BookingEmailSmsHandler { private async _handleRescheduled(data: RescheduleEmailAndSmsPayload) { const { evt, + originalRescheduledBooking, eventType: { metadata }, rescheduleReason, additionalNotes, @@ -127,6 +128,12 @@ export class BookingEmailSmsHandler { await sendRescheduledEmailsAndSMS( { ...evt, + previousStartTime: originalRescheduledBooking?.startTime + ? dayjs(originalRescheduledBooking.startTime).utc().format() + : undefined, + previousEndTime: originalRescheduledBooking?.endTime + ? dayjs(originalRescheduledBooking.endTime).utc().format() + : undefined, additionalInformation, additionalNotes, cancellationReason: `$RCH$${rescheduleReason || ""}`, @@ -157,6 +164,12 @@ export class BookingEmailSmsHandler { additionalInformation, additionalNotes, cancellationReason: `$RCH$${rescheduleReason || ""}`, + previousStartTime: originalRescheduledBooking?.startTime + ? dayjs(originalRescheduledBooking.startTime).utc().format() + : undefined, + previousEndTime: originalRescheduledBooking?.endTime + ? dayjs(originalRescheduledBooking.endTime).utc().format() + : undefined, }; const cancelledRRHostEvt = cloneDeep(copyEventAdditionalInfo); this.log.debug("Emails: Sending rescheduled emails for booking confirmation"); diff --git a/packages/types/Calendar.d.ts b/packages/types/Calendar.d.ts index eb9ac6db1bea5b..1cc2d554eb87b4 100644 --- a/packages/types/Calendar.d.ts +++ b/packages/types/Calendar.d.ts @@ -219,6 +219,8 @@ export interface CalendarEvent { platformRescheduleUrl?: string | null; platformCancelUrl?: string | null; platformBookingUrl?: string | null; + previousStartTime?: string; + previousEndTime?: string; hideBranding?: boolean; oneTimePassword?: string | null; delegationCredentialId?: string | null;