diff --git a/apps/web/components/booking/BookingListItem.tsx b/apps/web/components/booking/BookingListItem.tsx index e9c2e6595e..1aa309e2e8 100644 --- a/apps/web/components/booking/BookingListItem.tsx +++ b/apps/web/components/booking/BookingListItem.tsx @@ -163,6 +163,7 @@ function BookingListItem(booking: BookingItemProps) { const isConfirmed = booking.status === BookingStatus.ACCEPTED; const isRejected = booking.status === BookingStatus.REJECTED; const isPending = booking.status === BookingStatus.PENDING; + const isRescheduled = booking.fromReschedule !== null; const isRecurring = booking.recurringEventId !== null; const isTabRecurring = booking.listingStatus === "recurring"; const isTabUnconfirmed = booking.listingStatus === "unconfirmed"; @@ -730,6 +731,7 @@ function BookingListItem(booking: BookingItemProps) { recurringDates={recurringDates} userTimeFormat={userTimeFormat} userTimeZone={userTimeZone} + isRescheduled={isRescheduled} /> @@ -750,12 +752,14 @@ const BookingItemBadges = ({ recurringDates, userTimeFormat, userTimeZone, + isRescheduled, }: { booking: BookingItemProps; isPending: boolean; recurringDates: Date[] | undefined; userTimeFormat: number | null | undefined; userTimeZone: string | undefined; + isRescheduled: boolean; }) => { const { t } = useLocale(); @@ -766,6 +770,13 @@ const BookingItemBadges = ({ {t("unconfirmed")} )} + {isRescheduled && ( + + + {t("rescheduled")} + + + )} {booking.eventType?.team && ( {booking.eventType.team.name} diff --git a/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx b/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx index 0c8ceba4ca..86d74d795e 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.getServerSideProps.tsx @@ -82,6 +82,17 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { rescheduledToUid = rescheduledTo?.uid ?? null; } + let previousBooking: { + rescheduledBy: string | null; + uid: string; + } | null = null; + + if (bookingInfo.fromReschedule) { + previousBooking = await BookingRepository.findReschedulerByUid({ + uid: bookingInfo.fromReschedule, + }); + } + const eventTypeRaw = !bookingInfoRaw.eventTypeId ? getDefaultEvent(eventTypeSlug || "") : await getEventTypesFromDB(bookingInfoRaw.eventTypeId); @@ -220,6 +231,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { recurringBookings: await getRecurringBookings(bookingInfo.recurringEventId), dynamicEventName: bookingInfo?.eventType?.eventName || "", bookingInfo, + previousBooking, paymentStatus: payment, ...(tz && { tz }), userTimeFormat, diff --git a/apps/web/modules/bookings/views/bookings-single-view.tsx b/apps/web/modules/bookings/views/bookings-single-view.tsx index ed7f4922ac..0577227482 100644 --- a/apps/web/modules/bookings/views/bookings-single-view.tsx +++ b/apps/web/modules/bookings/views/bookings-single-view.tsx @@ -104,7 +104,9 @@ export default function Success(props: PageProps) { const routerQuery = useRouterQuery(); const pathname = usePathname(); const searchParams = useCompatSearchParams(); - const { eventType, bookingInfo, requiresLoginToUpdate, rescheduledToUid } = props; + + const { eventType, bookingInfo, previousBooking, requiresLoginToUpdate, rescheduledToUid } = props; + const { allRemainingBookings, isSuccessBookingPage, @@ -519,6 +521,17 @@ export default function Success(props: PageProps) {
{cancellationReason}
)} + {previousBooking && ( + <> +
{t("rescheduled_by")}
+
+

{previousBooking?.rescheduledBy}

+ + {t("original_booking")} + +
+ + )}
{t("what")}
{isRoundRobin ? bookingInfo.title : eventName} diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index 609940cf57..681492edf4 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -1361,6 +1361,8 @@ "custom": "Custom", "reminder": "Reminder", "rescheduled": "Rescheduled", + "rescheduled_by": "Rescheduled by", + "original_booking": "Original booking", "completed": "Completed", "rating": "Rating", "reminder_email": "Reminder: {{eventType}} with {{name}} at {{date}}", diff --git a/packages/features/bookings/lib/getUserBooking.ts b/packages/features/bookings/lib/getUserBooking.ts index 1a6d50e6ed..703486b85e 100644 --- a/packages/features/bookings/lib/getUserBooking.ts +++ b/packages/features/bookings/lib/getUserBooking.ts @@ -24,6 +24,7 @@ const getUserBooking = async (uid: string) => { userPrimaryEmail: true, fromReschedule: true, rescheduled: true, + rescheduledBy: true, user: { select: { id: true, diff --git a/packages/lib/server/repository/booking.ts b/packages/lib/server/repository/booking.ts index 93d5e0ef19..1ebd0e95c1 100644 --- a/packages/lib/server/repository/booking.ts +++ b/packages/lib/server/repository/booking.ts @@ -138,6 +138,18 @@ export class BookingRepository { }); } + static async findReschedulerByUid({ uid }: { uid: string }) { + return await prisma.booking.findFirst({ + where: { + uid, + }, + select: { + rescheduledBy: true, + uid: true, + }, + }); + } + static async groupByActiveBookingCounts({ users, eventTypeId, diff --git a/packages/trpc/server/routers/viewer/bookings/get.handler.ts b/packages/trpc/server/routers/viewer/bookings/get.handler.ts index 052c2fd9ea..55082026d0 100644 --- a/packages/trpc/server/routers/viewer/bookings/get.handler.ts +++ b/packages/trpc/server/routers/viewer/bookings/get.handler.ts @@ -132,6 +132,7 @@ export async function getBookings({ email: true, }, }, + fromReschedule: true, rescheduled: true, references: true, isRecorded: true, @@ -437,8 +438,24 @@ export async function getBookings({ booking.attendees = booking.attendees.filter((attendee) => attendee.email === user.email); } + let rescheduler = null; + if (booking.fromReschedule) { + const rescheduledBooking = await prisma.booking.findUnique({ + where: { + uid: booking.fromReschedule, + }, + select: { + rescheduledBy: true, + }, + }); + if (rescheduledBooking) { + rescheduler = rescheduledBooking.rescheduledBy; + } + } + return { ...booking, + rescheduler, eventType: { ...booking.eventType, recurringEvent: parseRecurringEvent(booking.eventType?.recurringEvent),