diff --git a/apps/web/public/static/locales/fr/common.json b/apps/web/public/static/locales/fr/common.json index 9d7cb5be31..6aa814498a 100644 --- a/apps/web/public/static/locales/fr/common.json +++ b/apps/web/public/static/locales/fr/common.json @@ -1600,6 +1600,7 @@ "options": "Options", "enter_option": "Entrer l'option {{index}}", "add_an_option": "Ajouter une option", + "location_already_exists": "Ce lieu existe déjà. Veuillez en sélectionner un nouveau.", "radio": "Radio", "google_meet_warning": "Pour utiliser Google Meet, vous devez définir votre calendrier de destination sur un calendrier Google", "individual": "Particulier", diff --git a/packages/features/bookings/Booker/components/EventMeta.tsx b/packages/features/bookings/Booker/components/EventMeta.tsx index 6a6fb5ee78..83bcfc6312 100644 --- a/packages/features/bookings/Booker/components/EventMeta.tsx +++ b/packages/features/bookings/Booker/components/EventMeta.tsx @@ -1,6 +1,5 @@ import { m } from "framer-motion"; import dynamic from "next/dynamic"; -import { useEffect } from "react"; import { shallow } from "zustand/shallow"; import { useEmbedUiConfig, useIsEmbed } from "@calcom/embed-core/embed-iframe"; @@ -38,13 +37,6 @@ export const EventMeta = () => { const isEmbed = useIsEmbed(); const hideEventTypeDetails = isEmbed ? embedUiConfig.hideEventTypeDetails : false; - useEffect(() => { - if (!selectedDuration && event?.length) { - setSelectedDuration(event.length); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [event?.length, selectedDuration]); - if (hideEventTypeDetails) { return null; } diff --git a/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx b/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx index 118265be69..f5731fd17d 100644 --- a/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx +++ b/packages/features/bookings/Booker/components/OverlayCalendar/OverlayCalendarSettingsModal.tsx @@ -47,7 +47,7 @@ export function OverlayCalendarSettingsModal(props: IOverlayCalendarContinueModa const searchParams = useSearchParams(); const setOverlayBusyDates = useOverlayCalendarStore((state) => state.setOverlayBusyDates); const { data, isLoading } = trpc.viewer.connectedCalendars.useQuery(undefined, { - enabled: !!props.open || !!searchParams.get("overlayCalendar"), + enabled: !!props.open || Boolean(searchParams?.get("overlayCalendar")), }); const { toggleValue, hasItem, set } = useLocalSet<{ credentialId: number; diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 509056d5a3..1daa55e284 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -11,6 +11,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale"; import { Button, SkeletonText } from "@calcom/ui"; import { useBookerStore } from "../Booker/store"; +import { useEvent } from "../Booker/utils/event"; import { getQueryParam } from "../Booker/utils/query-param"; import { useTimePreferences } from "../lib"; import { useCheckOverlapWithOverlay } from "../lib/useCheckOverlapWithOverlay"; @@ -51,9 +52,9 @@ const SlotItem = ({ const overlayCalendarToggled = getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault"); const [timeFormat, timezone] = useTimePreferences((state) => [state.timeFormat, state.timezone]); - const selectedDuration = useBookerStore((state) => state.selectedDuration); const bookingData = useBookerStore((state) => state.bookingData); const layout = useBookerStore((state) => state.layout); + const { data: event } = useEvent(); const hasTimeSlots = !!seatsPerTimeSlot; const computedDateWithUsersTimezone = dayjs.utc(slot.time).tz(timezone); @@ -67,11 +68,12 @@ const SlotItem = ({ const offset = (usersTimezoneDate.utcOffset() - nowDate.utcOffset()) / 60; - const { isOverlapping, overlappingTimeEnd, overlappingTimeStart } = useCheckOverlapWithOverlay( - computedDateWithUsersTimezone, - selectedDuration, - offset - ); + const { isOverlapping, overlappingTimeEnd, overlappingTimeStart } = useCheckOverlapWithOverlay({ + start: computedDateWithUsersTimezone, + selectedDuration: event?.length ?? 0, + offset, + }); + const [overlapConfirm, setOverlapConfirm] = useState(false); const onButtonClick = useCallback(() => { diff --git a/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx b/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx index a1a3020da8..ba994ee7f7 100644 --- a/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx +++ b/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx @@ -9,7 +9,15 @@ function getCurrentTime(date: Date) { return `${hours}:${minutes}`; } -export function useCheckOverlapWithOverlay(start: Dayjs, selectedDuration: number | null, offset: number) { +export function useCheckOverlapWithOverlay({ + start, + selectedDuration, + offset, +}: { + start: Dayjs; + selectedDuration: number | null; + offset: number; +}) { const overlayBusyDates = useOverlayCalendarStore((state) => state.overlayBusyDates); let overlappingTimeStart: string | null = null; diff --git a/packages/features/ee/payments/components/Payment.tsx b/packages/features/ee/payments/components/Payment.tsx index 4311e9036c..dc575e6320 100644 --- a/packages/features/ee/payments/components/Payment.tsx +++ b/packages/features/ee/payments/components/Payment.tsx @@ -94,7 +94,7 @@ const PaymentForm = (props: Props) => { location?: string; } = { uid: props.booking.uid, - email: searchParams.get("email"), + email: searchParams?.get("email"), }; if (paymentOption === "HOLD" && "setupIntent" in props.payment.data) { payload = await stripe.confirmSetup({ diff --git a/packages/features/ee/workflows/api/scheduleEmailReminders.ts b/packages/features/ee/workflows/api/scheduleEmailReminders.ts index 3ce801fb0f..5755d7149e 100644 --- a/packages/features/ee/workflows/api/scheduleEmailReminders.ts +++ b/packages/features/ee/workflows/api/scheduleEmailReminders.ts @@ -14,6 +14,7 @@ import { parseRecurringEvent } from "@calcom/lib"; import { defaultHandler } from "@calcom/lib/server"; import { getTimeFormatStringFromUserTimeFormat } from "@calcom/lib/timeFormat"; import prisma from "@calcom/prisma"; +import type { User } from "@calcom/prisma/client"; import { WorkflowActions, WorkflowMethods, WorkflowTemplates } from "@calcom/prisma/enums"; import { bookingMetadataSchema } from "@calcom/prisma/zod-utils"; @@ -29,14 +30,14 @@ sgMail.setApiKey(sendgridAPIKey); type Booking = Prisma.BookingGetPayload<{ include: { eventType: true; - user: true; attendees: true; }; }>; function getiCalEventAsString( - booking: Pick & { + booking: Pick & { eventType: { recurringEvent?: Prisma.JsonValue; title?: string } | null; + user: Partial | null; } ) { let recurrenceRule: string | undefined = undefined; @@ -234,7 +235,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { endTime: true, location: true, description: true, - user: true, + user: { + select: { + email: true, + name: true, + timeZone: true, + locale: true, + username: true, + timeFormat: true, + hideBranding: true, + }, + }, metadata: true, uid: true, customInputs: true, diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index 69df6baaf6..2a39590dc9 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -61,7 +61,7 @@ function useRouterHelpers() { const pathname = usePathname(); const goto = (newSearchParams: Record) => { - const newQuery = new URLSearchParams(searchParams); + const newQuery = new URLSearchParams(searchParams ?? undefined); Object.keys(newSearchParams).forEach((key) => { newQuery.set(key, newSearchParams[key]); }); @@ -70,7 +70,7 @@ function useRouterHelpers() { }; const removeQueryParams = (queryParams: string[]) => { - const params = new URLSearchParams(searchParams); + const params = new URLSearchParams(searchParams ?? undefined); queryParams.forEach((param) => { params.delete(param); @@ -529,7 +529,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({ ); const s = (href: string) => { - const _searchParams = new URLSearchParams(searchParams); + const _searchParams = new URLSearchParams(searchParams ?? undefined); const [a, b] = href.split("="); _searchParams.set(a, b); return `${pathname?.split("?")[0] ?? ""}?${_searchParams.toString()}`; diff --git a/packages/lib/payment/handlePayment.ts b/packages/lib/payment/handlePayment.ts index 9b3aa85be2..7f096a1e30 100644 --- a/packages/lib/payment/handlePayment.ts +++ b/packages/lib/payment/handlePayment.ts @@ -2,13 +2,13 @@ import type { AppCategories, Prisma } from "@prisma/client"; import appStore from "@calcom/app-store"; import type { EventTypeAppsList } from "@calcom/app-store/utils"; -import type { EventTypeModel } from "@calcom/prisma/zod"; +import type { CompleteEventType } from "@calcom/prisma/zod"; import type { CalendarEvent } from "@calcom/types/Calendar"; import type { IAbstractPaymentService, PaymentApp } from "@calcom/types/PaymentService"; const handlePayment = async ( evt: CalendarEvent, - selectedEventType: Pick, "metadata" | "title">, + selectedEventType: Pick, paymentAppCredentials: { key: Prisma.JsonValue; appId: EventTypeAppsList; diff --git a/packages/prisma/index.ts b/packages/prisma/index.ts index 071f6fdbbe..b045ff8fb6 100644 --- a/packages/prisma/index.ts +++ b/packages/prisma/index.ts @@ -6,9 +6,16 @@ import { bookingReferenceMiddleware } from "./middleware"; const prismaOptions: Prisma.PrismaClientOptions = {}; +const globalForPrisma = global as unknown as { + prismaWithoutClientExtensions: PrismaClientWithoutExtension; + prismaWithClientExtensions: PrismaClientWithExtensions; +}; + if (!!process.env.NEXT_PUBLIC_DEBUG) prismaOptions.log = ["query", "error", "warn"]; -const prismaWithoutClientExtensions = new PrismaClientWithoutExtension(prismaOptions); +// Prevents flooding with idle connections +const prismaWithoutClientExtensions = + globalForPrisma.prismaWithoutClientExtensions || new PrismaClientWithoutExtension(prismaOptions); export const customPrisma = (options?: Prisma.PrismaClientOptions) => new PrismaClientWithoutExtension({ ...prismaOptions, ...options }).$extends(withAccelerate()); @@ -50,16 +57,15 @@ const prismaWithClientExtensions = prismaWithoutClientExtensions // }, // }) -// const prismaWithClientExtensions = prismaWithoutClientExtensions; - -export const prisma = - ((globalThis as any).prisma as typeof prismaWithClientExtensions) || prismaWithClientExtensions; +export const prisma = globalForPrisma.prismaWithClientExtensions || prismaWithClientExtensions; if (process.env.NODE_ENV !== "production") { - (globalThis as any).prisma = prisma; + globalForPrisma.prismaWithoutClientExtensions = prismaWithoutClientExtensions; + globalForPrisma.prismaWithClientExtensions = prisma; } -export type PrismaClient = typeof prismaWithClientExtensions; +type PrismaClientWithExtensions = typeof prismaWithClientExtensions; +export type PrismaClient = PrismaClientWithExtensions; export default prisma; export * from "./selects";