More dry run fixes (#18865)
This commit is contained in:
@@ -42,7 +42,9 @@ export default function DryRunSuccessful() {
|
||||
<div className="bg-success mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-full">
|
||||
<Icon name="check" className="h-6 w-6 text-green-600 dark:text-green-400" />
|
||||
</div>
|
||||
<h1 className="text-emphasis mb-4 text-2xl font-medium">{t("booking_dry_run_successful")}</h1>
|
||||
<h1 className="text-emphasis mb-4 text-2xl font-medium" data-testid="dry-run-success-msg">
|
||||
{t("booking_dry_run_successful")}
|
||||
</h1>
|
||||
<p className="text-default mb-8 max-w-2xl text-sm">{t("booking_dry_run_successful_description")}</p>
|
||||
|
||||
{/* <div className="border-subtle text-default mt-8 grid grid-cols-3 border-t pt-8 text-left">
|
||||
|
||||
@@ -4,6 +4,8 @@ import Head from "next/head";
|
||||
|
||||
import type { inferSSRProps } from "@calcom/types/inferSSRProps";
|
||||
|
||||
import PageWrapper from "@components/PageWrapper";
|
||||
|
||||
import { getServerSideProps } from "../../server/lib/router/getServerSideProps";
|
||||
|
||||
export default function Router({ form, message }: inferSSRProps<typeof getServerSideProps>) {
|
||||
@@ -23,4 +25,6 @@ export default function Router({ form, message }: inferSSRProps<typeof getServer
|
||||
);
|
||||
}
|
||||
|
||||
Router.PageWrapper = PageWrapper;
|
||||
|
||||
export { getServerSideProps };
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
1. Navigate to Headless Router - acme.cal.com/router?formId={FORM_ID}&field1=value1&field2=value2
|
||||
1. Validate the fields types and ensure required fields are present
|
||||
2. Based on the fields values, choose a route.
|
||||
3. Records a response for the form.
|
||||
4. If the route is an eventTypeRedirect,
|
||||
- Identify the teamMembers matching that route's attribute routing rules.
|
||||
- Redirect to the booking page of the eventType, along with the `routedTeamMemberIds` query param that has the matching teamMembers' ids.
|
||||
5. Notify through emails if they are members to be notified and fire Routing form related webhooks.
|
||||
2. User reaches the booking page.
|
||||
3. Sees the available slots for the matching teamMembers only
|
||||
4. Selects a slot.
|
||||
- Selecting a slot temporarily blocks the slot for other bookers.
|
||||
5. Confirm the booking
|
||||
1. Ensures that the members are available for the slot depending on various rules like type of event(RR, Collective) and other configurations in the eventType and selected calendars
|
||||
2. Send Emails and fire webhooks
|
||||
|
||||
@@ -94,6 +94,7 @@ export function getFieldResponse({
|
||||
|
||||
/**
|
||||
* Not called in preview mode or dry run mode
|
||||
* It takes care of sending webhooks and emails for form submissions
|
||||
*/
|
||||
export async function onFormSubmission(
|
||||
form: Ensure<
|
||||
|
||||
@@ -19,7 +19,9 @@ export const DryRunMessage = ({ isEmbed }: { isEmbed?: boolean }) => {
|
||||
<div className="relative">
|
||||
<Icon name="info" className="h-5 w-5 text-orange-500" />
|
||||
</div>
|
||||
<div className="text-emphasis font-medium">{t("dry_run_mode_active")}</div>
|
||||
<div className="text-emphasis font-medium" data-testid="dry-run-msg">
|
||||
{t("dry_run_mode_active")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,14 +4,17 @@ import { shallow } from "zustand/shallow";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useBookerStore } from "@calcom/features/bookings/Booker/store";
|
||||
import { useSlotReservationId } from "@calcom/features/bookings/Booker/useSlotReservationId";
|
||||
import { isBookingDryRun } from "@calcom/features/bookings/Booker/utils/isBookingDryRun";
|
||||
import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
import { MINUTES_TO_BOOK } from "@calcom/lib/constants";
|
||||
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
|
||||
import { trpc } from "@calcom/trpc";
|
||||
|
||||
export type UseSlotsReturnType = ReturnType<typeof useSlots>;
|
||||
|
||||
export const useSlots = (event: { data?: Pick<BookerEvent, "id" | "length"> | null }) => {
|
||||
const selectedDuration = useBookerStore((state) => state.selectedDuration);
|
||||
const searchParams = useCompatSearchParams();
|
||||
const [selectedTimeslot, setSelectedTimeslot] = useBookerStore(
|
||||
(state) => [state.selectedTimeslot, state.setSelectedTimeslot],
|
||||
shallow
|
||||
@@ -45,6 +48,7 @@ export const useSlots = (event: { data?: Pick<BookerEvent, "id" | "length"> | nu
|
||||
.utc()
|
||||
.add(selectedDuration || event.data.length, "minutes")
|
||||
.format(),
|
||||
_isDryRun: isBookingDryRun(searchParams),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ interface ReserveSlotOptions {
|
||||
export const reserveSlotHandler = async ({ ctx, input }: ReserveSlotOptions) => {
|
||||
const { prisma, req, res } = ctx;
|
||||
const uid = req?.cookies?.uid || uuid();
|
||||
const { slotUtcStartDate, slotUtcEndDate, eventTypeId, bookingUid } = input;
|
||||
const { slotUtcStartDate, slotUtcEndDate, eventTypeId, bookingUid, _isDryRun } = input;
|
||||
const releaseAt = dayjs.utc().add(parseInt(MINUTES_TO_BOOK), "minutes").format();
|
||||
const eventType = await prisma.eventType.findUnique({
|
||||
where: { id: eventTypeId },
|
||||
@@ -54,7 +54,7 @@ export const reserveSlotHandler = async ({ ctx, input }: ReserveSlotOptions) =>
|
||||
}
|
||||
}
|
||||
|
||||
if (eventType && shouldReserveSlot) {
|
||||
if (eventType && shouldReserveSlot && !_isDryRun) {
|
||||
try {
|
||||
await Promise.all(
|
||||
eventType.users.map((user) =>
|
||||
|
||||
@@ -56,6 +56,7 @@ export const reserveSlotSchema = z
|
||||
// endTime ISOString
|
||||
slotUtcEndDate: z.string(),
|
||||
bookingUid: z.string().optional(),
|
||||
_isDryRun: z.boolean().optional(),
|
||||
})
|
||||
.refine(
|
||||
(data) => !!data.eventTypeId || !!data.slotUtcStartDate || !!data.slotUtcEndDate,
|
||||
|
||||
Reference in New Issue
Block a user