fix: reschedule flow is broken for seated booking (#23987)
* fix: reschedule flow is broken for seated booking * Update BookingListItem.tsx * Update * tweak
This commit is contained in:
1 parent
2ba571d230
commit
bcc433ba9a
5 files changed
+134
-8
No files matched your search
@@ -185,6 +185,10 @@ function BookingListItem(booking: BookingItemProps) {
|
||||
const isTabUnconfirmed = booking.listingStatus === "unconfirmed";
|
||||
const isBookingFromRoutingForm = isBookingReroutable(parsedBooking);
|
||||
|
||||
const userSeat = booking.seatsReferences.find((seat) => !!userEmail && seat.attendee?.email === userEmail);
|
||||
|
||||
const isAttendee = !!userSeat;
|
||||
|
||||
const paymentAppData = getPaymentAppData(booking.eventType);
|
||||
|
||||
const location = booking.location as ReturnType<typeof getEventLocationValue>;
|
||||
@@ -223,10 +227,7 @@ function BookingListItem(booking: BookingItemProps) {
|
||||
};
|
||||
|
||||
const getSeatReferenceUid = () => {
|
||||
if (!booking.seatsReferences[0]) {
|
||||
return undefined;
|
||||
}
|
||||
return booking.seatsReferences[0].referenceUid;
|
||||
return userSeat?.referenceUid;
|
||||
};
|
||||
|
||||
const actionContext: BookingActionContext = {
|
||||
@@ -250,6 +251,7 @@ function BookingListItem(booking: BookingItemProps) {
|
||||
booking.location === "integrations:daily" ||
|
||||
(typeof booking.location === "string" && booking.location.trim() === ""),
|
||||
showPendingPayment: paymentAppData.enabled && booking.payment.length && !booking.paid,
|
||||
isAttendee,
|
||||
cardCharged,
|
||||
attendeeList,
|
||||
getSeatReferenceUid,
|
||||
|
||||
@@ -21,6 +21,7 @@ export interface BookingActionContext {
|
||||
isDisabledRescheduling: boolean;
|
||||
isCalVideoLocation: boolean;
|
||||
showPendingPayment: boolean;
|
||||
isAttendee: boolean;
|
||||
cardCharged: boolean;
|
||||
attendeeList: Array<{
|
||||
name: string;
|
||||
@@ -102,6 +103,7 @@ export function getEditEventActions(context: BookingActionContext): ActionType[]
|
||||
isDisabledRescheduling,
|
||||
isBookingFromRoutingForm,
|
||||
getSeatReferenceUid,
|
||||
isAttendee,
|
||||
t,
|
||||
} = context;
|
||||
|
||||
@@ -111,7 +113,7 @@ export function getEditEventActions(context: BookingActionContext): ActionType[]
|
||||
icon: "clock",
|
||||
label: t("reschedule_booking"),
|
||||
href: `/reschedule/${booking.uid}${
|
||||
booking.seatsReferences.length ? `?seatReferenceUid=${getSeatReferenceUid()}` : ""
|
||||
booking.seatsReferences.length && isAttendee ? `?seatReferenceUid=${getSeatReferenceUid()}` : ""
|
||||
}`,
|
||||
disabled:
|
||||
(isBookingInPast && !booking.eventType.allowReschedulingPastBookings) || isDisabledRescheduling,
|
||||
|
||||
@@ -5,8 +5,8 @@ import { z } from "zod";
|
||||
|
||||
import { getServerSession } from "@calcom/features/auth/lib/getServerSession";
|
||||
import { determineReschedulePreventionRedirect } from "@calcom/features/bookings/lib/reschedule/determineReschedulePreventionRedirect";
|
||||
import { buildEventUrlFromBooking } from "@calcom/lib/bookings/buildEventUrlFromBooking";
|
||||
import { getDefaultEvent } from "@calcom/features/eventtypes/lib/defaultEvents";
|
||||
import { buildEventUrlFromBooking } from "@calcom/lib/bookings/buildEventUrlFromBooking";
|
||||
import { maybeGetBookingUidFromSeat } from "@calcom/lib/server/maybeGetBookingUidFromSeat";
|
||||
import { UserRepository } from "@calcom/lib/server/repository/user";
|
||||
import prisma, { bookingMinimalSelect } from "@calcom/prisma";
|
||||
@@ -39,7 +39,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
|
||||
uid,
|
||||
seatReferenceUid: maybeSeatReferenceUid,
|
||||
bookingSeat,
|
||||
} = await maybeGetBookingUidFromSeat(prisma, bookingUid);
|
||||
} = await maybeGetBookingUidFromSeat(prisma, seatReferenceUid ? seatReferenceUid : bookingUid);
|
||||
|
||||
const booking = await prisma.booking.findUnique({
|
||||
where: {
|
||||
|
||||
@@ -458,5 +458,128 @@ test.describe("Reschedule for booking with seats", () => {
|
||||
await expect(page.locator('[data-testid="confirm-reschedule-button"]')).toHaveCount(1);
|
||||
});
|
||||
|
||||
test("Host reschedule from /upcoming page should have rescheduleUid parameter set to bookingUid", async ({
|
||||
page,
|
||||
users,
|
||||
bookings,
|
||||
}) => {
|
||||
const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [
|
||||
{ name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
{ name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
]);
|
||||
await user.apiLogin();
|
||||
|
||||
const bookingAttendees = await prisma.attendee.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
const bookingSeats = bookingAttendees.map((attendee) => ({
|
||||
bookingId: booking.id,
|
||||
attendeeId: attendee.id,
|
||||
referenceUid: uuidv4(),
|
||||
data: {
|
||||
responses: {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
await prisma.bookingSeat.createMany({
|
||||
data: bookingSeats,
|
||||
});
|
||||
|
||||
await page.goto("/bookings/upcoming");
|
||||
await page.waitForSelector('[data-testid="bookings"]');
|
||||
|
||||
await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click();
|
||||
await page.locator('[data-testid="reschedule"]').click();
|
||||
|
||||
await page.waitForURL((url) => {
|
||||
const rescheduleUid = url.searchParams.get("rescheduleUid");
|
||||
return !!rescheduleUid && rescheduleUid === booking.uid;
|
||||
});
|
||||
});
|
||||
|
||||
test("Second attendee reschedule from /upcoming page should use correct seatReferenceUid and show attendee info", async ({
|
||||
page,
|
||||
users,
|
||||
bookings,
|
||||
}) => {
|
||||
const { user, booking } = await createUserWithSeatedEventAndAttendees({ users, bookings }, [
|
||||
{ name: "John First", email: "first+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
{ name: "Jane Second", email: "second+seats@cal.com", timeZone: "Europe/Berlin" },
|
||||
]);
|
||||
|
||||
const bookingAttendees = await prisma.attendee.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
});
|
||||
|
||||
const bookingSeats = bookingAttendees.map((attendee) => ({
|
||||
bookingId: booking.id,
|
||||
attendeeId: attendee.id,
|
||||
referenceUid: uuidv4(),
|
||||
data: {
|
||||
responses: {
|
||||
name: attendee.name,
|
||||
email: attendee.email,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
await prisma.bookingSeat.createMany({
|
||||
data: bookingSeats,
|
||||
});
|
||||
|
||||
const references = await prisma.bookingSeat.findMany({
|
||||
where: { bookingId: booking.id },
|
||||
orderBy: { id: "asc" },
|
||||
});
|
||||
|
||||
const secondUser = await users.create({
|
||||
name: "Jane Second",
|
||||
email: "second+seats@cal.com",
|
||||
});
|
||||
await secondUser.apiLogin();
|
||||
|
||||
await page.goto("/bookings/upcoming");
|
||||
await page.waitForSelector('[data-testid="bookings"]');
|
||||
|
||||
await page.locator('[data-testid="booking-actions-dropdown"]').nth(0).click();
|
||||
await page.locator('[data-testid="reschedule"]').click();
|
||||
|
||||
await page.waitForURL((url) => {
|
||||
const rescheduleUid = url.searchParams.get("rescheduleUid");
|
||||
return !!rescheduleUid && rescheduleUid === references[1].referenceUid;
|
||||
});
|
||||
|
||||
await selectFirstAvailableTimeSlotNextMonth(page);
|
||||
|
||||
const nameElement = page.locator("input[name=name]");
|
||||
const name = await nameElement.inputValue();
|
||||
expect(name).toBe("Jane Second");
|
||||
|
||||
const emailElement = page.locator("input[name=email]");
|
||||
const email = await emailElement.inputValue();
|
||||
expect(email).toBe("second+seats@cal.com");
|
||||
|
||||
// Complete the reschedule
|
||||
await confirmReschedule(page);
|
||||
|
||||
// Verify successful reschedule
|
||||
await page.waitForURL(/\/booking\/.*/);
|
||||
await expect(page).toHaveURL(/\/booking\/.*/);
|
||||
});
|
||||
|
||||
// @TODO: force 404 when rescheduleUid is not found
|
||||
});
|
||||
@@ -578,7 +578,6 @@ export async function getBookings({
|
||||
.selectFrom("Attendee")
|
||||
.select(["Attendee.email"])
|
||||
.whereRef("BookingSeat.attendeeId", "=", "Attendee.id")
|
||||
.where("Attendee.email", "=", user.email)
|
||||
).as("attendee"),
|
||||
])
|
||||
.whereRef("BookingSeat.bookingId", "=", "Booking.id")
|
||||
|
||||
Reference in new issue
Block a user