feat: added rescheduled UI to Booking page and Booking Listing page (#20401)
* feat: add rescheduling to UI - Introduced displaying the original booking information. - Updated UI components to show rescheduling status and details. * fix: update link styling in booking single view - Changed link text size to small for better UI consistency in the booking details section. * refactor, type fixes * added missing margin * added rescheduled under other badges * optimised getting booking * updated namings and perf --------- Co-authored-by: amrit <iamamrit27@gmail.com>
This commit is contained in:
1 parent
5ae50f8670
commit
d3d4a90776
7 files changed
+69
-1
No files matched your search
@@ -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}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -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")}
|
||||
</Badge>
|
||||
)}
|
||||
{isRescheduled && (
|
||||
<Tooltip content={`${t("rescheduled_by")} ${booking.rescheduler}`}>
|
||||
<Badge variant="orange" className="ltr:mr-2 rtl:ml-2">
|
||||
{t("rescheduled")}
|
||||
</Badge>
|
||||
</Tooltip>
|
||||
)}
|
||||
{booking.eventType?.team && (
|
||||
<Badge className="ltr:mr-2 rtl:ml-2" variant="gray">
|
||||
{booking.eventType.team.name}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
<div className="col-span-2 mb-6 last:mb-0">{cancellationReason}</div>
|
||||
</>
|
||||
)}
|
||||
{previousBooking && (
|
||||
<>
|
||||
<div className="font-medium">{t("rescheduled_by")}</div>
|
||||
<div className="col-span-2 mb-6 last:mb-0">
|
||||
<p className="break-words">{previousBooking?.rescheduledBy}</p>
|
||||
<Link className="text-sm underline" href={`/booking/${previousBooking?.uid}`}>
|
||||
{t("original_booking")}
|
||||
</Link>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="font-medium">{t("what")}</div>
|
||||
<div className="col-span-2 mb-6 last:mb-0" data-testid="booking-title">
|
||||
{isRoundRobin ? bookingInfo.title : eventName}
|
||||
|
||||
@@ -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}}",
|
||||
|
||||
@@ -24,6 +24,7 @@ const getUserBooking = async (uid: string) => {
|
||||
userPrimaryEmail: true,
|
||||
fromReschedule: true,
|
||||
rescheduled: true,
|
||||
rescheduledBy: true,
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in new issue
Block a user