From ac68838f68d7d0582a45eeb7a36af5463ee8e6f1 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 2 Apr 2025 17:51:48 -0400 Subject: [PATCH 01/39] refactor [user]/[type] server logic --- .../lib/[user]/[type]/getServerSideProps.ts | 88 +++++-------------- 1 file changed, 23 insertions(+), 65 deletions(-) diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index f7074ad42d43c4..fc577000b6bd4e 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -1,4 +1,3 @@ -import { createRouterCaller } from "app/_trpc/context"; import { type GetServerSidePropsContext } from "next"; import type { Session } from "next-auth"; import { z } from "zod"; @@ -9,33 +8,16 @@ import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { getUsernameList } from "@calcom/lib/defaultEvents"; +import { EventRepository } from "@calcom/lib/server/repository/event"; import { UserRepository } from "@calcom/lib/server/repository/user"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; import { RedirectType } from "@calcom/prisma/client"; -import { publicViewerRouter } from "@calcom/trpc/server/routers/publicViewer/_router"; import { getTemporaryOrgRedirect } from "@lib/getTemporaryOrgRedirect"; type Props = { - eventData: Omit< - Pick< - NonNullable>>, - "id" | "length" | "metadata" | "entity" | "profile" | "title" | "subsetOfUsers" | "hidden" - >, - "profile" | "subsetOfUsers" - > & { - profile: { - image: string | undefined; - name: string | null; - username: string | null; - }; - users: { - username: string; - name: string; - }[]; - }; - + eventData: NonNullable>>; booking?: GetBookingType; rescheduleUid: string | null; bookingUid: string | null; @@ -133,13 +115,16 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const caller = await createRouterCaller(publicViewerRouter); - const eventData = await caller.event({ - username: usernames.join("+"), - eventSlug: slug, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }); + + const eventData = await EventRepository.getPublicEvent( + { + username: usernames.join("+"), + eventSlug: slug, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + }, + session?.user?.id + ); if (!eventData) { return { @@ -149,24 +134,11 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { const props: Props = { eventData: { - id: eventData.id, - entity: eventData.entity, - length: eventData.length, + ...eventData, metadata: { ...eventData.metadata, multipleDuration: [15, 30, 45, 60, 90], }, - profile: { - image: eventData.profile.image, - name: eventData.profile.name ?? null, - username: eventData.profile.username ?? null, - }, - title: eventData.title, - users: eventData.subsetOfUsers.map((user) => ({ - username: user.username ?? "", - name: user.name ?? "", - })), - hidden: eventData.hidden, }, user: usernames.join("+"), slug, @@ -227,13 +199,15 @@ async function getUserPageProps(context: GetServerSidePropsContext) { const org = isValidOrgDomain ? currentOrgDomain : null; // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we can show a 404 otherwise. - const caller = await createRouterCaller(publicViewerRouter); - const eventData = await caller.event({ - username, - eventSlug: slug, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }); + const eventData = await await EventRepository.getPublicEvent( + { + username, + eventSlug: slug, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + }, + session?.user?.id + ); if (!eventData) { return { @@ -248,23 +222,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { : user?.allowSEOIndexing; const props: Props = { - eventData: { - id: eventData.id, - entity: eventData.entity, - length: eventData.length, - metadata: eventData.metadata, - profile: { - image: eventData.profile.image, - name: eventData.profile.name ?? null, - username: eventData.profile.username ?? null, - }, - title: eventData.title, - users: eventData.subsetOfUsers.map((user) => ({ - username: user.username ?? "", - name: user.name ?? "", - })), - hidden: eventData.hidden, - }, + eventData: eventData, user: username, slug, isBrandingHidden: user?.hideBranding, From b32a680e27e8c26731f921f541c6702e3f501e54 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 2 Apr 2025 17:52:04 -0400 Subject: [PATCH 02/39] refactor useSlot --- .../bookings/Booker/components/hooks/useSlots.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/features/bookings/Booker/components/hooks/useSlots.ts b/packages/features/bookings/Booker/components/hooks/useSlots.ts index aebb77c3bddfa7..0cd139d53a311a 100644 --- a/packages/features/bookings/Booker/components/hooks/useSlots.ts +++ b/packages/features/bookings/Booker/components/hooks/useSlots.ts @@ -5,7 +5,6 @@ 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, PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS, @@ -78,7 +77,7 @@ const useQuickAvailabilityChecks = ({ export type UseSlotsReturnType = ReturnType; -export const useSlots = (event: { data?: Pick | null }) => { +export const useSlots = (event: { id: number; length: number } | null) => { const selectedDuration = useBookerStore((state) => state.selectedDuration); const searchParams = useCompatSearchParams(); const [selectedTimeslot, setSelectedTimeslot, tentativeSelectedTimeslots, setTentativeSelectedTimeslots] = @@ -107,13 +106,13 @@ export const useSlots = (event: { data?: Pick | nu }); const handleRemoveSlot = () => { - if (event?.data) { + if (event) { removeSelectedSlot.mutate({ uid: slotReservationId }); } }; - const eventTypeId = event.data?.id; - const eventDuration = selectedDuration || event.data?.length || 0; + const eventTypeId = event?.id; + const eventDuration = selectedDuration || event?.length || 0; const allSelectedTimeslots = [...tentativeSelectedTimeslots, selectedTimeslot].filter( (slot): slot is string => slot !== null ); @@ -153,7 +152,7 @@ export const useSlots = (event: { data?: Pick | nu clearInterval(interval); }; // eslint-disable-next-line react-hooks/exhaustive-deps - }, [event?.data?.id, timeSlotToBeBooked]); + }, [event?.id, timeSlotToBeBooked]); return { setSelectedTimeslot, From 71939a62f9db8e330b96b94bbab487b9645262e9 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 2 Apr 2025 17:52:10 -0400 Subject: [PATCH 03/39] refactor --- .../users/views/users-type-public-view.tsx | 1 + .../features/bookings/Booker/utils/event.ts | 4 ++-- .../atoms/booker/BookerWebWrapper.tsx | 19 ++++++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/web/modules/users/views/users-type-public-view.tsx b/apps/web/modules/users/views/users-type-public-view.tsx index 7104580858c13e..197ae7be9e326d 100644 --- a/apps/web/modules/users/views/users-type-public-view.tsx +++ b/apps/web/modules/users/views/users-type-public-view.tsx @@ -35,6 +35,7 @@ function Type({ slug, user, isEmbed, booking, isBrandingHidden, eventData, orgBa eventSlug={slug} bookingData={booking} hideBranding={isBrandingHidden} + eventData={eventData} entity={{ ...eventData.entity, eventTypeId: eventData?.id }} durationConfig={eventData.metadata?.multipleDuration} orgBannerUrl={orgBannerUrl} diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index eea28b3b7bd5ec..97dd1e48d34317 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -18,7 +18,7 @@ export type useScheduleForEventReturnType = ReturnType { +export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean; disabled?: boolean }) => { const [username, eventSlug, isTeamEvent, org] = useBookerStore( (state) => [state.username, state.eventSlug, state.isTeamEvent, state.org], shallow @@ -34,7 +34,7 @@ export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean }) => { }, { refetchOnWindowFocus: false, - enabled: Boolean(username) && Boolean(eventSlug), + enabled: !props?.disabled && Boolean(username) && Boolean(eventSlug), } ); diff --git a/packages/platform/atoms/booker/BookerWebWrapper.tsx b/packages/platform/atoms/booker/BookerWebWrapper.tsx index b70781b1177c09..62b6b97d6165cd 100644 --- a/packages/platform/atoms/booker/BookerWebWrapper.tsx +++ b/packages/platform/atoms/booker/BookerWebWrapper.tsx @@ -22,19 +22,32 @@ import { useBookerStore, useInitializeBookerStore } from "@calcom/features/booki import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import { getLastBookingResponse } from "@calcom/features/bookings/Booker/utils/lastBookingResponse"; import { useBrandColors } from "@calcom/features/bookings/Booker/utils/use-brand-colors"; +import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { DEFAULT_LIGHT_BRAND_COLOR, DEFAULT_DARK_BRAND_COLOR, WEBAPP_URL } from "@calcom/lib/constants"; import { useRouterQuery } from "@calcom/lib/hooks/useRouterQuery"; import { BookerLayouts } from "@calcom/prisma/zod-utils"; -type BookerWebWrapperAtomProps = BookerProps; +type BookerWebWrapperAtomProps = BookerProps & { + eventData?: NonNullable>>; +}; export const BookerWebWrapper = (props: BookerWebWrapperAtomProps) => { const router = useRouter(); const pathname = usePathname(); const searchParams = useSearchParams(); - const event = useEvent({ + const clientFetchedEvent = useEvent({ + disabled: !!props.eventData, fromRedirectOfNonOrgLink: props.entity.fromRedirectOfNonOrgLink, }); + const event = props.eventData + ? { + data: props.eventData, + isSuccess: true, + isError: false, + isPending: false, + } + : clientFetchedEvent; + const bookerLayout = useBookerLayout(event.data); const selectedDate = searchParams?.get("date"); @@ -110,7 +123,7 @@ export const BookerWebWrapper = (props: BookerWebWrapperAtomProps) => { requiresBookerEmailVerification: event?.data?.requiresBookerEmailVerification, onVerifyEmail: bookerForm.beforeVerifyEmail, }); - const slots = useSlots(event); + const slots = useSlots(event?.data ? { id: event.data.id, length: event.data.length } : null); const isEmbed = useIsEmbed(); From 9cec7eaa4cc9fa760db1c264b9191f4e633f6a34 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 2 Apr 2025 17:57:00 -0400 Subject: [PATCH 04/39] fix --- apps/web/server/lib/[user]/[type]/getServerSideProps.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index fc577000b6bd4e..4e32c79d3de100 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -199,7 +199,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { const org = isValidOrgDomain ? currentOrgDomain : null; // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we can show a 404 otherwise. - const eventData = await await EventRepository.getPublicEvent( + const eventData = await EventRepository.getPublicEvent( { username, eventSlug: slug, From b6cf29bf702d0bf0cb27e9ee3fc4e5f20d0861fb Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 2 Apr 2025 18:03:31 -0400 Subject: [PATCH 05/39] fix OG images --- apps/web/app/(booking-page-wrapper)/[user]/[type]/page.tsx | 2 +- .../org/[orgSlug]/[user]/[type]/page.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/web/app/(booking-page-wrapper)/[user]/[type]/page.tsx b/apps/web/app/(booking-page-wrapper)/[user]/[type]/page.tsx index deb6762d32e1e9..d9a727318b9c34 100644 --- a/apps/web/app/(booking-page-wrapper)/[user]/[type]/page.tsx +++ b/apps/web/app/(booking-page-wrapper)/[user]/[type]/page.tsx @@ -25,7 +25,7 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => { title, profile: { name: profileName, image: profileImage }, users: [ - ...(eventData?.users || []).map((user) => ({ + ...(eventData?.subsetOfUsers || []).map((user) => ({ name: `${user.name}`, username: `${user.username}`, })), diff --git a/apps/web/app/(booking-page-wrapper)/org/[orgSlug]/[user]/[type]/page.tsx b/apps/web/app/(booking-page-wrapper)/org/[orgSlug]/[user]/[type]/page.tsx index c07628f4cc8c67..7125f1a1d25c99 100644 --- a/apps/web/app/(booking-page-wrapper)/org/[orgSlug]/[user]/[type]/page.tsx +++ b/apps/web/app/(booking-page-wrapper)/org/[orgSlug]/[user]/[type]/page.tsx @@ -30,7 +30,11 @@ export const generateMetadata = async ({ params, searchParams }: PageProps) => { title, profile: { name: profileName, image: profileImage }, users: [ - ...(eventData?.users || []).map((user) => ({ + ...( + (eventData as UserTypePageProps["eventData"])?.subsetOfUsers ?? + (eventData as TeamTypePageProps["eventData"])?.users ?? + [] + ).map((user) => ({ name: `${user.name}`, username: `${user.username}`, })), From 839641873ad0b7750cbfae9501039e5fd9cb2785 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 18:45:33 -0400 Subject: [PATCH 06/39] fix --- packages/features/bookings/Booker/components/hooks/useSlots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/features/bookings/Booker/components/hooks/useSlots.ts b/packages/features/bookings/Booker/components/hooks/useSlots.ts index 0cd139d53a311a..fa055aabba3f4b 100644 --- a/packages/features/bookings/Booker/components/hooks/useSlots.ts +++ b/packages/features/bookings/Booker/components/hooks/useSlots.ts @@ -106,7 +106,7 @@ export const useSlots = (event: { id: number; length: number } | null) => { }); const handleRemoveSlot = () => { - if (event) { + if (event?.id && slotReservationId) { removeSelectedSlot.mutate({ uid: slotReservationId }); } }; From 5365d9d5ef93add8d33cd6cf2e460698131a116b Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 21:12:14 -0400 Subject: [PATCH 07/39] remove event repository --- .../lib/[user]/[type]/getServerSideProps.ts | 6 +++--- packages/lib/server/repository/event.ts | 18 ------------------ packages/lib/server/repository/eventType.ts | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 21 deletions(-) delete mode 100644 packages/lib/server/repository/event.ts diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index 4e32c79d3de100..36e34bd877321e 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -8,7 +8,7 @@ import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { getUsernameList } from "@calcom/lib/defaultEvents"; -import { EventRepository } from "@calcom/lib/server/repository/event"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { UserRepository } from "@calcom/lib/server/repository/user"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; @@ -116,7 +116,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const eventData = await EventRepository.getPublicEvent( + const eventData = await EventTypeRepository.getPublicEvent( { username: usernames.join("+"), eventSlug: slug, @@ -199,7 +199,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { const org = isValidOrgDomain ? currentOrgDomain : null; // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we can show a 404 otherwise. - const eventData = await EventRepository.getPublicEvent( + const eventData = await EventTypeRepository.getPublicEvent( { username, eventSlug: slug, diff --git a/packages/lib/server/repository/event.ts b/packages/lib/server/repository/event.ts deleted file mode 100644 index e1d2fa222391d5..00000000000000 --- a/packages/lib/server/repository/event.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; -import prisma from "@calcom/prisma"; -import type { TEventInputSchema } from "@calcom/trpc/server/routers/publicViewer/event.schema"; - -export class EventRepository { - static async getPublicEvent(input: TEventInputSchema, userId?: number) { - const event = await getPublicEvent( - input.username, - input.eventSlug, - input.isTeamEvent, - input.org, - prisma, - input.fromRedirectOfNonOrgLink, - userId - ); - return event; - } -} diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index cc4a457492b6ae..f0adb60001d113 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -1,11 +1,13 @@ import type { EventType as PrismaEventType } from "@prisma/client"; import { Prisma } from "@prisma/client"; +import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import logger from "@calcom/lib/logger"; import { prisma, availabilityUserSelect } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { EventTypeMetaDataSchema, rrSegmentQueryValueSchema } from "@calcom/prisma/zod-utils"; +import type { TEventInputSchema } from "@calcom/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema"; import type { Ensure } from "@calcom/types/utils"; import { TRPCError } from "@trpc/server"; @@ -909,4 +911,17 @@ export class EventTypeRepository { }) { return user.allSelectedCalendars.filter((calendar) => calendar.eventTypeId === eventTypeId); } + + static async getPublicEvent(input: TEventInputSchema, userId?: number) { + const event = await getPublicEvent( + input.username, + input.eventSlug, + input.isTeamEvent, + input.org, + prisma, + input.fromRedirectOfNonOrgLink, + userId + ); + return event; + } } From 851eaa1ae5f8c24f9b43e1da29d9a1bcf717711c Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 21:12:42 -0400 Subject: [PATCH 08/39] remove publicViewer router event --- .../server/routers/publicViewer/event.handler.ts | 14 -------------- .../server/routers/publicViewer/event.schema.ts | 15 --------------- .../routers/publicViewer/procedures/event.ts | 13 ------------- 3 files changed, 42 deletions(-) delete mode 100644 packages/trpc/server/routers/publicViewer/event.handler.ts delete mode 100644 packages/trpc/server/routers/publicViewer/event.schema.ts delete mode 100644 packages/trpc/server/routers/publicViewer/procedures/event.ts diff --git a/packages/trpc/server/routers/publicViewer/event.handler.ts b/packages/trpc/server/routers/publicViewer/event.handler.ts deleted file mode 100644 index 1902468fec0107..00000000000000 --- a/packages/trpc/server/routers/publicViewer/event.handler.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { EventRepository } from "@calcom/lib/server/repository/event"; - -import type { TEventInputSchema } from "./event.schema"; - -interface EventHandlerOptions { - input: TEventInputSchema; - userId?: number; -} - -export const eventHandler = async ({ input, userId }: EventHandlerOptions) => { - return await EventRepository.getPublicEvent(input, userId); -}; - -export default eventHandler; diff --git a/packages/trpc/server/routers/publicViewer/event.schema.ts b/packages/trpc/server/routers/publicViewer/event.schema.ts deleted file mode 100644 index d10a5965cccbef..00000000000000 --- a/packages/trpc/server/routers/publicViewer/event.schema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import z from "zod"; - -export const ZEventInputSchema = z.object({ - username: z.string(), - eventSlug: z.string(), - isTeamEvent: z.boolean().optional(), - org: z.string().nullable(), - /** - * Informs that the event request has been sent from a page that was reached by a redirect from non-org link(i.e. app.cal.com/username redirected to acme.cal.com/username) - * Based on this decision like whether to allow unpublished organization's event to be served or not can be made. - */ - fromRedirectOfNonOrgLink: z.boolean().optional().default(false), -}); - -export type TEventInputSchema = z.infer; diff --git a/packages/trpc/server/routers/publicViewer/procedures/event.ts b/packages/trpc/server/routers/publicViewer/procedures/event.ts deleted file mode 100644 index 6f96bc68562255..00000000000000 --- a/packages/trpc/server/routers/publicViewer/procedures/event.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { getUserSession } from "../../../middlewares/sessionMiddleware"; -import publicProcedure from "../../../procedures/publicProcedure"; -import { importHandler } from "../../../trpc"; -import { ZEventInputSchema } from "../event.schema"; - -const NAMESPACE = "publicViewer"; -const namespaced = (s: string) => `${NAMESPACE}.${s}`; - -export const event = publicProcedure.input(ZEventInputSchema).query(async (opts) => { - const { user } = await getUserSession(opts.ctx); - const handler = await importHandler(namespaced("event"), () => import("../event.handler")); - return handler({ input: opts.input, userId: user?.id }); -}); From 7fd35a7e2f787355d3fe5c7de27bc488593a269d Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 21:12:52 -0400 Subject: [PATCH 09/39] add getPublicEvent to eventTypes router --- .../features/bookings/Booker/utils/event.ts | 2 +- .../server/routers/publicViewer/_router.tsx | 2 -- .../routers/viewer/eventTypes/_router.ts | 26 +++++++++++++++++++ .../eventTypes/getPublicEvent.handler.ts | 25 ++++++++++++++++++ .../eventTypes/getPublicEvent.schema.ts | 15 +++++++++++ 5 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts create mode 100644 packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index 97dd1e48d34317..f16023d4ed91a6 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -24,7 +24,7 @@ export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean; disabled? shallow ); - const event = trpc.viewer.public.event.useQuery( + const event = trpc.viewer.eventTypes.getPublicEvent.useQuery( { username: username ?? "", eventSlug: eventSlug ?? "", diff --git a/packages/trpc/server/routers/publicViewer/_router.tsx b/packages/trpc/server/routers/publicViewer/_router.tsx index b6aa0b3f744c6b..1a415643bf1667 100644 --- a/packages/trpc/server/routers/publicViewer/_router.tsx +++ b/packages/trpc/server/routers/publicViewer/_router.tsx @@ -2,7 +2,6 @@ import publicProcedure from "../../procedures/publicProcedure"; import { importHandler, router } from "../../trpc"; import { ZUserEmailVerificationRequiredSchema } from "./checkIfUserEmailVerificationRequired.schema"; import { ZMarkHostAsNoShowInputSchema } from "./markHostAsNoShow.schema"; -import { event } from "./procedures/event"; import { session } from "./procedures/session"; import { ZSamlTenantProductInputSchema } from "./samlTenantProduct.schema"; import { ZStripeCheckoutSessionInputSchema } from "./stripeCheckoutSession.schema"; @@ -44,7 +43,6 @@ export const publicViewerRouter = router({ ); return handler(opts); }), - event, ssoConnections: publicProcedure.query(async () => { const handler = await importHandler( namespaced("ssoConnections"), diff --git a/packages/trpc/server/routers/viewer/eventTypes/_router.ts b/packages/trpc/server/routers/viewer/eventTypes/_router.ts index 852646c46e5ed9..c99588dc375ed7 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/_router.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/_router.ts @@ -8,6 +8,7 @@ import { ZCreateInputSchema } from "./create.schema"; import { ZDeleteInputSchema } from "./delete.schema"; import { ZDuplicateInputSchema } from "./duplicate.schema"; import { ZEventTypeInputSchema, ZGetEventTypesFromGroupSchema } from "./getByViewer.schema"; +import { ZEventInputSchema } from "./getPublicEvent.schema"; import { ZGetTeamAndEventTypeOptionsSchema } from "./getTeamAndEventTypeOptions.schema"; import { get } from "./procedures/get"; import { ZUpdateInputSchema } from "./update.schema"; @@ -22,6 +23,7 @@ type BookingsRouterHandlerCache = { listWithTeam?: typeof import("./listWithTeam.handler").listWithTeamHandler; create?: typeof import("./create.handler").createHandler; get?: typeof import("./get.handler").getHandler; + getPublicEvent?: typeof import("./getPublicEvent.handler").getPublicEventHandler; update?: typeof import("./update.handler").updateHandler; delete?: typeof import("./delete.handler").deleteHandler; duplicate?: typeof import("./duplicate.handler").duplicateHandler; @@ -182,6 +184,30 @@ export const eventTypesRouter = router({ get, + getPublicEvent: authedProcedure.input(ZEventInputSchema).query(async ({ ctx, input }) => { + if (!UNSTABLE_HANDLER_CACHE.getPublicEvent) { + UNSTABLE_HANDLER_CACHE.getPublicEvent = await import("./getPublicEvent.handler").then( + (mod) => mod.getPublicEventHandler + ); + } + + // Unreachable code but required for type safety + if (!UNSTABLE_HANDLER_CACHE.getPublicEvent) { + throw new Error("Failed to load handler"); + } + + const timer = logP(`getByViewer(${ctx.user.id})`); + + const result = await UNSTABLE_HANDLER_CACHE.getPublicEvent({ + ctx, + input, + }); + + timer(); + + return result; + }), + update: eventOwnerProcedure.input(ZUpdateInputSchema).mutation(async ({ ctx, input }) => { if (!UNSTABLE_HANDLER_CACHE.update) { UNSTABLE_HANDLER_CACHE.update = await import("./update.handler").then((mod) => mod.updateHandler); diff --git a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts new file mode 100644 index 00000000000000..c616b5ba1d9c7c --- /dev/null +++ b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts @@ -0,0 +1,25 @@ +import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; +import type { PrismaClient } from "@calcom/prisma"; + +import type { TrpcSessionUser } from "../../../types"; +import type { TEventInputSchema } from "./getPublicEvent.schema"; + +type GetOptions = { + ctx: { + user: NonNullable; + prisma: PrismaClient; + }; + input: TEventInputSchema; +}; + +export const getPublicEventHandler = async ({ ctx, input }: GetOptions) => { + return await getPublicEvent( + input.username, + input.eventSlug, + input.isTeamEvent, + input.org, + ctx.prisma, + input.fromRedirectOfNonOrgLink, + ctx.user.id + ); +}; diff --git a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts new file mode 100644 index 00000000000000..d10a5965cccbef --- /dev/null +++ b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts @@ -0,0 +1,15 @@ +import z from "zod"; + +export const ZEventInputSchema = z.object({ + username: z.string(), + eventSlug: z.string(), + isTeamEvent: z.boolean().optional(), + org: z.string().nullable(), + /** + * Informs that the event request has been sent from a page that was reached by a redirect from non-org link(i.e. app.cal.com/username redirected to acme.cal.com/username) + * Based on this decision like whether to allow unpublished organization's event to be served or not can be made. + */ + fromRedirectOfNonOrgLink: z.boolean().optional().default(false), +}); + +export type TEventInputSchema = z.infer; From b5c2010f61401320f611b8f3d11ada74bb61896c Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 21:51:53 -0400 Subject: [PATCH 10/39] fix type checks --- .../bookings/Booker/components/BookEventForm/BookingFields.tsx | 2 +- packages/features/bookings/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx index 313bee12877d8b..c17d0b545b7240 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx @@ -18,7 +18,7 @@ export const BookingFields = ({ isDynamicGroupBooking, bookingData, }: { - fields: NonNullable["bookingFields"]; + fields: NonNullable["bookingFields"]; locations: LocationObject[]; rescheduleUid?: string; bookingData?: GetBookingType | null; diff --git a/packages/features/bookings/types.ts b/packages/features/bookings/types.ts index 464b4545829953..2060769dfce44e 100644 --- a/packages/features/bookings/types.ts +++ b/packages/features/bookings/types.ts @@ -7,7 +7,7 @@ import type { AppsStatus } from "@calcom/types/Calendar"; import type { DatePickerProps } from "../calendars/DatePicker"; -export type PublicEvent = NonNullable; +export type PublicEvent = NonNullable; export type BookerEventQuery = { isSuccess: boolean; From 938fdb7b5e06d341e2f0d439d8c495c33516250a Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 22:16:33 -0400 Subject: [PATCH 11/39] fix --- apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx | 6 +++--- .../team/[slug]/[type]/getServerSideProps.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index 073d95f1d6e2ba..ee4b2bb3635bc3 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -11,7 +11,7 @@ import { UserRepository } from "@calcom/lib/server/repository/user"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; import { RedirectType } from "@calcom/prisma/enums"; -import { publicViewerRouter } from "@calcom/trpc/server/routers/publicViewer/_router"; +import { eventTypesRouter } from "@calcom/trpc/server/routers/viewer/eventTypes/_router"; import { getTemporaryOrgRedirect } from "@lib/getTemporaryOrgRedirect"; import type { inferSSRProps } from "@lib/types/inferSSRProps"; @@ -114,9 +114,9 @@ async function getUserPageProps(context: GetServerSidePropsContext) { // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const caller = await createRouterCaller(publicViewerRouter); + const caller = await createRouterCaller(eventTypesRouter); - const eventData = await caller.event({ + const eventData = await caller.getPublicEvent({ username: name, eventSlug: slug, isTeamEvent, diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index 487ccc1b915c97..816edfdb14e76d 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -7,7 +7,7 @@ import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/or import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; -import { publicViewerRouter } from "@calcom/trpc/server/routers/publicViewer/_router"; +import { eventTypesRouter } from "@calcom/trpc/server/routers/viewer/eventTypes/_router"; const paramsSchema = z.object({ type: z.string().transform((s) => slugify(s)), @@ -39,9 +39,9 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const org = isValidOrgDomain ? currentOrgDomain : null; - const caller = await createRouterCaller(publicViewerRouter); + const caller = await createRouterCaller(eventTypesRouter); - const eventData = await caller.event({ + const eventData = await caller.getPublicEvent({ username: teamSlug, eventSlug: meetingSlug, isTeamEvent: true, From c53a93ac49f10987aaf998ac4538a342a1b2933d Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Thu, 3 Apr 2025 22:56:56 -0400 Subject: [PATCH 12/39] fix --- packages/trpc/server/routers/viewer/eventTypes/_router.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/trpc/server/routers/viewer/eventTypes/_router.ts b/packages/trpc/server/routers/viewer/eventTypes/_router.ts index c99588dc375ed7..674e537a0930b2 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/_router.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/_router.ts @@ -196,7 +196,7 @@ export const eventTypesRouter = router({ throw new Error("Failed to load handler"); } - const timer = logP(`getByViewer(${ctx.user.id})`); + const timer = logP(`getPublicEvent(${ctx.user.id})`); const result = await UNSTABLE_HANDLER_CACHE.getPublicEvent({ ctx, From 9bf31062d94260e554a64dda11c190d23a5dd53c Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Fri, 4 Apr 2025 18:32:20 -0400 Subject: [PATCH 13/39] fix --- .../viewer/eventTypes/getPublicEvent.handler.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts index c616b5ba1d9c7c..ee6b27e831c3f3 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts @@ -1,4 +1,4 @@ -import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import type { PrismaClient } from "@calcom/prisma"; import type { TrpcSessionUser } from "../../../types"; @@ -13,13 +13,5 @@ type GetOptions = { }; export const getPublicEventHandler = async ({ ctx, input }: GetOptions) => { - return await getPublicEvent( - input.username, - input.eventSlug, - input.isTeamEvent, - input.org, - ctx.prisma, - input.fromRedirectOfNonOrgLink, - ctx.user.id - ); + return await EventTypeRepository.getPublicEvent(input, ctx.user.id); }; From cc279b37a3dabc4b26257810c053c52fe7962239 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Fri, 4 Apr 2025 18:36:08 -0400 Subject: [PATCH 14/39] refactor --- .../d/[link]/[slug]/getServerSideProps.tsx | 30 +++++++++++-------- .../team/[slug]/[type]/getServerSideProps.ts | 30 +++++++++++-------- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index ee4b2bb3635bc3..091f06825d573c 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -1,17 +1,17 @@ import type { EmbedProps } from "app/WithEmbedSSR"; -import { createRouterCaller } from "app/_trpc/context"; import type { GetServerSidePropsContext } from "next"; +import { redirect } from "next/navigation"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getBookingForReschedule, getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { UserRepository } from "@calcom/lib/server/repository/user"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; import { RedirectType } from "@calcom/prisma/enums"; -import { eventTypesRouter } from "@calcom/trpc/server/routers/viewer/eventTypes/_router"; import { getTemporaryOrgRedirect } from "@lib/getTemporaryOrgRedirect"; import type { inferSSRProps } from "@lib/types/inferSSRProps"; @@ -20,6 +20,11 @@ export type PageProps = inferSSRProps & EmbedProps; async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); + if (!session?.user?.id) { + redirect("/auth/login"); + } + const sessionUserId = session.user.id; + const { link, slug } = paramsSchema.parse(context.params); const { rescheduleUid, duration: queryDuration } = context.query; const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req); @@ -107,22 +112,23 @@ async function getUserPageProps(context: GetServerSidePropsContext) { let booking: GetBookingType | null = null; if (rescheduleUid) { - booking = await getBookingForReschedule(`${rescheduleUid}`, session?.user?.id); + booking = await getBookingForReschedule(`${rescheduleUid}`, sessionUserId); } const isTeamEvent = !!hashedLink.eventType?.team?.id; // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const caller = await createRouterCaller(eventTypesRouter); - - const eventData = await caller.getPublicEvent({ - username: name, - eventSlug: slug, - isTeamEvent, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }); + const eventData = await EventTypeRepository.getPublicEvent( + { + username: name, + eventSlug: slug, + isTeamEvent, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + }, + sessionUserId + ); if (!eventData) { return notFound; diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index 816edfdb14e76d..77ca5eacb9e6b3 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -1,13 +1,14 @@ -import { createRouterCaller } from "app/_trpc/context"; import type { GetServerSidePropsContext } from "next"; +import { redirect } from "next/navigation"; import { z } from "zod"; +import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getMultipleDurationValue } from "@calcom/features/bookings/lib/get-booking"; import { getSlugOrRequestedSlug } from "@calcom/features/ee/organizations/lib/orgDomains"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import slugify from "@calcom/lib/slugify"; import prisma from "@calcom/prisma"; -import { eventTypesRouter } from "@calcom/trpc/server/routers/viewer/eventTypes/_router"; const paramsSchema = z.object({ type: z.string().transform((s) => slugify(s)), @@ -15,6 +16,11 @@ const paramsSchema = z.object({ }); export const getServerSideProps = async (context: GetServerSidePropsContext) => { + const session = await getServerSession({ req: context.req }); + if (!session?.user?.id) { + redirect("/auth/login"); + } + const sessionUserId = session.user.id; const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params); const { duration: queryDuration } = context.query; @@ -39,16 +45,16 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const org = isValidOrgDomain ? currentOrgDomain : null; - const caller = await createRouterCaller(eventTypesRouter); - - const eventData = await caller.getPublicEvent({ - username: teamSlug, - eventSlug: meetingSlug, - isTeamEvent: true, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }); - + const eventData = await EventTypeRepository.getPublicEvent( + { + username: teamSlug, + eventSlug: meetingSlug, + isTeamEvent: true, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + }, + sessionUserId + ); if (!eventData || !org) { return { notFound: true, From 2669bb156bc42e9c459e942bf7be19436692e16f Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Fri, 4 Apr 2025 18:38:14 -0400 Subject: [PATCH 15/39] fix --- .../server/lib/[user]/[type]/getServerSideProps.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index a218cf16356d0c..268d1f439c0d9a 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -1,5 +1,6 @@ import { type GetServerSidePropsContext } from "next"; import type { Session } from "next-auth"; +import { redirect } from "next/navigation"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; @@ -93,6 +94,10 @@ async function processSeatedEvent({ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); + if (!session?.user?.id) { + redirect("/auth/login"); + } + const sessionUserId = session.user.id; const { user: usernames, type: slug } = paramsSchema.parse(context.params); const { rescheduleUid, bookingUid } = context.query; @@ -134,7 +139,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - session?.user?.id + sessionUserId ); if (!eventData) { @@ -177,6 +182,11 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); + if (!session?.user?.id) { + redirect("/auth/login"); + } + const sessionUserId = session.user.id; + const { user: usernames, type: slug } = paramsSchema.parse(context.params); const username = usernames[0]; const { rescheduleUid, bookingUid } = context.query; @@ -217,7 +227,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - session?.user?.id + sessionUserId ); if (!eventData) { From 0421aedbd2e5ea0a161ffd071802d27367b67ba0 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Fri, 4 Apr 2025 18:39:37 -0400 Subject: [PATCH 16/39] fix --- apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx | 3 +-- .../instant-meeting/team/[slug]/[type]/getServerSideProps.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index 091f06825d573c..c40d2e37241e49 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -1,6 +1,5 @@ import type { EmbedProps } from "app/WithEmbedSSR"; import type { GetServerSidePropsContext } from "next"; -import { redirect } from "next/navigation"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; @@ -21,7 +20,7 @@ export type PageProps = inferSSRProps & EmbedProps; async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); if (!session?.user?.id) { - redirect("/auth/login"); + return { redirect: { permanent: false, destination: "/auth/login" } }; } const sessionUserId = session.user.id; diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index 77ca5eacb9e6b3..9e19b266edba6a 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -1,5 +1,4 @@ import type { GetServerSidePropsContext } from "next"; -import { redirect } from "next/navigation"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; @@ -18,7 +17,7 @@ const paramsSchema = z.object({ export const getServerSideProps = async (context: GetServerSidePropsContext) => { const session = await getServerSession({ req: context.req }); if (!session?.user?.id) { - redirect("/auth/login"); + return { redirect: { permanent: false, destination: "/auth/login" } }; } const sessionUserId = session.user.id; const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params); From 8f844bbcfa714f09df1899e9c5f5f7a575341b88 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Fri, 4 Apr 2025 18:40:50 -0400 Subject: [PATCH 17/39] fix --- apps/web/server/lib/[user]/[type]/getServerSideProps.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index 268d1f439c0d9a..8c82a23bb21b5a 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -1,6 +1,5 @@ import { type GetServerSidePropsContext } from "next"; import type { Session } from "next-auth"; -import { redirect } from "next/navigation"; import { z } from "zod"; import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; @@ -95,7 +94,7 @@ async function processSeatedEvent({ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); if (!session?.user?.id) { - redirect("/auth/login"); + return { redirect: { permanent: false, destination: "/auth/login" } }; } const sessionUserId = session.user.id; const { user: usernames, type: slug } = paramsSchema.parse(context.params); @@ -183,7 +182,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); if (!session?.user?.id) { - redirect("/auth/login"); + return { redirect: { permanent: false, destination: "/auth/login" } }; } const sessionUserId = session.user.id; From 620c90f3cd1e006adf0bfe33b96e2e208e05a438 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:32:19 -0400 Subject: [PATCH 18/39] wip --- packages/features/bookings/Booker/Booker.tsx | 3 +- .../BookEventForm/BookFormAsModal.tsx | 35 +++++++++++------ .../features/bookings/Booker/utils/event.ts | 38 ------------------- .../bookings/components/AvailableTimes.tsx | 10 ++--- packages/features/embed/Embed.tsx | 24 ++++++++---- packages/lib/getPaymentAppData.ts | 7 +--- .../routers/viewer/eventTypes/_router.ts | 26 ------------- 7 files changed, 47 insertions(+), 96 deletions(-) diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index f54395e553aaf8..3bd0ee34fa582a 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -576,7 +576,8 @@ const BookerComponent = ({ setSelectedTimeslot(null)} - visible={bookerState === "booking" && shouldShowFormInDialog}> + visible={bookerState === "booking" && shouldShowFormInDialog} + eventDuration={event?.data?.length}> {EventBooker} diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx index dce506f198846f..9a57f0e9f6ed05 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx @@ -11,13 +11,18 @@ import { DialogContent } from "@calcom/ui/components/dialog"; import { getDurationFormatted } from "../../../components/event-meta/Duration"; import { useBookerStore } from "../../store"; import { FromTime } from "../../utils/dates"; -import { useEvent } from "../../utils/event"; import { useBookerTime } from "../hooks/useBookerTime"; -const BookEventFormWrapper = ({ children, onCancel }: { onCancel: () => void; children: ReactNode }) => { - const { data } = useEvent(); - - return ; +const BookEventFormWrapper = ({ + children, + onCancel, + eventDuration, +}: { + onCancel: () => void; + children: ReactNode; + eventDuration?: number; +}) => { + return ; }; const PlatformBookEventFormWrapper = ({ @@ -31,17 +36,21 @@ const PlatformBookEventFormWrapper = ({ const { data } = useEventTypeById(eventId); return ( - + ); }; export const BookEventFormWrapperComponent = ({ child, - eventLength, + eventDuration, }: { onCancel: () => void; child: ReactNode; - eventLength?: number; + eventDuration?: number; }) => { const { i18n, t } = useLocale(); const selectedTimeslot = useBookerStore((state) => state.selectedTimeslot); @@ -62,9 +71,9 @@ export const BookEventFormWrapperComponent = ({ language={i18n.language} /> - {(selectedDuration || eventLength) && ( + {(selectedDuration || eventDuration) && ( - {getDurationFormatted(selectedDuration || eventLength, t)} + {getDurationFormatted(selectedDuration || eventDuration, t)} )} @@ -77,10 +86,12 @@ export const BookFormAsModal = ({ visible, onCancel, children, + eventDuration, }: { visible: boolean; onCancel: () => void; children: ReactNode; + eventDuration?: number; }) => { const isPlatform = useIsPlatform(); @@ -91,7 +102,9 @@ export const BookFormAsModal = ({ enableOverflow className="[&_.modalsticky]:border-t-subtle [&_.modalsticky]:bg-default max-h-[80vh] pb-0 [&_.modalsticky]:sticky [&_.modalsticky]:bottom-0 [&_.modalsticky]:left-0 [&_.modalsticky]:right-0 [&_.modalsticky]:-mx-8 [&_.modalsticky]:border-t [&_.modalsticky]:px-8 [&_.modalsticky]:py-4"> {!isPlatform ? ( - {children} + + {children} + ) : ( {children} )} diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index f16023d4ed91a6..e0ceb544417d36 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -2,50 +2,12 @@ import { shallow } from "zustand/shallow"; import { useSchedule } from "@calcom/features/schedules"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; -import { trpc } from "@calcom/trpc/react"; import { useBookerTime } from "../components/hooks/useBookerTime"; import { useBookerStore } from "../store"; -export type useEventReturnType = ReturnType; export type useScheduleForEventReturnType = ReturnType; -/** - * Wrapper hook around the trpc query that fetches - * the event currently viewed in the booker. It will get - * the current event slug and username from the booker store. - * - * Using this hook means you only need to use one hook, instead - * of combining multiple conditional hooks. - */ -export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean; disabled?: boolean }) => { - const [username, eventSlug, isTeamEvent, org] = useBookerStore( - (state) => [state.username, state.eventSlug, state.isTeamEvent, state.org], - shallow - ); - - const event = trpc.viewer.eventTypes.getPublicEvent.useQuery( - { - username: username ?? "", - eventSlug: eventSlug ?? "", - isTeamEvent, - org: org ?? null, - fromRedirectOfNonOrgLink: props?.fromRedirectOfNonOrgLink, - }, - { - refetchOnWindowFocus: false, - enabled: !props?.disabled && Boolean(username) && Boolean(eventSlug), - } - ); - - return { - data: event?.data, - isSuccess: event?.isSuccess, - isError: event?.isError, - isPending: event?.isPending, - }; -}; - /** * Gets schedule for the current event and current month. * Gets all values right away and not the store because it increases network timing, only for the first render. diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 0eee6a9e86ba48..0182a96f7b19a6 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -7,12 +7,12 @@ import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; import dayjs from "@calcom/dayjs"; import { OutOfOfficeInSlots } from "@calcom/features/bookings/Booker/components/OutOfOfficeInSlots"; import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; -import type { BookerEvent } from "@calcom/features/bookings/types"; import type { Slot } from "@calcom/features/schedules"; import { getPaymentAppData } from "@calcom/lib/getPaymentAppData"; import type { IOutOfOfficeData } from "@calcom/lib/getUserAvailability"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { localStorage } from "@calcom/lib/webstorage"; +import type { RouterOutputs } from "@calcom/trpc/react"; import classNames from "@calcom/ui/classNames"; import { Button } from "@calcom/ui/components/button"; import { Icon } from "@calcom/ui/components/icon"; @@ -60,9 +60,7 @@ type SlotItemProps = { onTimeSelect?: TOnTimeSelect; onTentativeTimeSelect?: TOnTentativeTimeSelect; showAvailableSeatsCount?: boolean | null; - event: { - data?: Pick | null; - }; + eventData: Pick; customClassNames?: string; confirmStepClassNames?: { confirmButton?: string; @@ -84,7 +82,7 @@ const SlotItem = ({ selectedSlots, onTimeSelect, showAvailableSeatsCount, - event, + eventData, customClassNames, loadingStates, renderConfirmNotVerifyEmailButtonCond, @@ -100,8 +98,6 @@ const SlotItem = ({ }: SlotItemProps) => { const { t } = useLocale(); - const { data: eventData } = event; - const isPaidEvent = useMemo(() => { if (!eventData?.price) return false; const paymentAppData = getPaymentAppData(eventData); diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index 4c5a67f7cd41bf..b6ea2545f568e3 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -12,7 +12,7 @@ import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; import { AvailableTimes, AvailableTimesHeader } from "@calcom/features/bookings"; import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; -import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; +import { useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import DatePicker from "@calcom/features/calendars/DatePicker"; import { Dialog } from "@calcom/features/components/controlled-dialog"; import { TimezoneSelect } from "@calcom/features/components/timezone-select"; @@ -44,7 +44,6 @@ import { useEmbedDialogCtx } from "./lib/hooks/useEmbedDialogCtx"; import { useEmbedParams } from "./lib/hooks/useEmbedParams"; import type { EmbedTabs, EmbedType, EmbedTypes, PreviewState } from "./types"; -type EventType = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"] | undefined; type EmbedDialogProps = { types: EmbedTypes; tabs: EmbedTabs; @@ -223,7 +222,7 @@ const ChooseEmbedTypesDialogContent = ({ }; const EmailEmbed = ({ - eventType, + eventTypeData, username, orgSlug, isTeamEvent, @@ -231,7 +230,7 @@ const EmailEmbed = ({ setSelectedDuration, userSettingsTimezone, }: { - eventType?: EventType; + eventTypeData?: RouterOutputs["viewer"]["eventTypes"]["get"]; username: string; orgSlug?: string; isTeamEvent: boolean; @@ -240,6 +239,7 @@ const EmailEmbed = ({ userSettingsTimezone?: string; }) => { const { t, i18n } = useLocale(); + const eventType = eventTypeData?.eventType; const { timezoneFromBookerStore, timezoneFromTimePreferences } = useBookerTime(); const timezone = chooseTimezone({ timezoneFromBookerStore, @@ -271,7 +271,6 @@ const EmailEmbed = ({ ], shallow ); - const event = useEvent(); const schedule = useScheduleForEvent({ orgSlug, eventId: eventType?.id, @@ -367,7 +366,7 @@ const EmailEmbed = ({ locale={i18n.language} browsingDate={month ? dayjs(month) : undefined} selected={dayjs(selectedDate)} - weekStart={weekdayToWeekIndex(event?.data?.subsetOfUsers?.[0]?.weekStart)} + weekStart={weekdayToWeekIndex(eventTypeData?.users?.[0]?.weekStart)} eventSlug={eventType?.slug} /> @@ -391,7 +390,16 @@ const EmailEmbed = ({ handleSlotClick={handleSlotClick} slots={slots} showAvailableSeatsCount={eventType.seatsShowAvailabilityCount} - event={event} + eventTypeData={ + eventTypeData + ? { + price: eventTypeData.price, + currency: eventTypeData.currency, + metadata: eventTypeData.metadata, + length: eventTypeData.length, + } + : undefined + } /> ) : null} @@ -917,7 +925,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({

{embed.subtitle}

{eventTypeData?.eventType && embedType === "email" ? ( & { - metadata: z.infer; - }, + _eventType: Pick, forcedGet?: boolean ) { const eventType = { diff --git a/packages/trpc/server/routers/viewer/eventTypes/_router.ts b/packages/trpc/server/routers/viewer/eventTypes/_router.ts index 674e537a0930b2..852646c46e5ed9 100644 --- a/packages/trpc/server/routers/viewer/eventTypes/_router.ts +++ b/packages/trpc/server/routers/viewer/eventTypes/_router.ts @@ -8,7 +8,6 @@ import { ZCreateInputSchema } from "./create.schema"; import { ZDeleteInputSchema } from "./delete.schema"; import { ZDuplicateInputSchema } from "./duplicate.schema"; import { ZEventTypeInputSchema, ZGetEventTypesFromGroupSchema } from "./getByViewer.schema"; -import { ZEventInputSchema } from "./getPublicEvent.schema"; import { ZGetTeamAndEventTypeOptionsSchema } from "./getTeamAndEventTypeOptions.schema"; import { get } from "./procedures/get"; import { ZUpdateInputSchema } from "./update.schema"; @@ -23,7 +22,6 @@ type BookingsRouterHandlerCache = { listWithTeam?: typeof import("./listWithTeam.handler").listWithTeamHandler; create?: typeof import("./create.handler").createHandler; get?: typeof import("./get.handler").getHandler; - getPublicEvent?: typeof import("./getPublicEvent.handler").getPublicEventHandler; update?: typeof import("./update.handler").updateHandler; delete?: typeof import("./delete.handler").deleteHandler; duplicate?: typeof import("./duplicate.handler").duplicateHandler; @@ -184,30 +182,6 @@ export const eventTypesRouter = router({ get, - getPublicEvent: authedProcedure.input(ZEventInputSchema).query(async ({ ctx, input }) => { - if (!UNSTABLE_HANDLER_CACHE.getPublicEvent) { - UNSTABLE_HANDLER_CACHE.getPublicEvent = await import("./getPublicEvent.handler").then( - (mod) => mod.getPublicEventHandler - ); - } - - // Unreachable code but required for type safety - if (!UNSTABLE_HANDLER_CACHE.getPublicEvent) { - throw new Error("Failed to load handler"); - } - - const timer = logP(`getPublicEvent(${ctx.user.id})`); - - const result = await UNSTABLE_HANDLER_CACHE.getPublicEvent({ - ctx, - input, - }); - - timer(); - - return result; - }), - update: eventOwnerProcedure.input(ZUpdateInputSchema).mutation(async ({ ctx, input }) => { if (!UNSTABLE_HANDLER_CACHE.update) { UNSTABLE_HANDLER_CACHE.update = await import("./update.handler").then((mod) => mod.updateHandler); From 38726d046f95d7f4fdfa6ae633afa1dc8a68981f Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:33:46 -0400 Subject: [PATCH 19/39] remove --- .../viewer/eventTypes/getPublicEvent.handler.ts | 17 ----------------- .../viewer/eventTypes/getPublicEvent.schema.ts | 15 --------------- 2 files changed, 32 deletions(-) delete mode 100644 packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts delete mode 100644 packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts diff --git a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts deleted file mode 100644 index ee6b27e831c3f3..00000000000000 --- a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.handler.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; -import type { PrismaClient } from "@calcom/prisma"; - -import type { TrpcSessionUser } from "../../../types"; -import type { TEventInputSchema } from "./getPublicEvent.schema"; - -type GetOptions = { - ctx: { - user: NonNullable; - prisma: PrismaClient; - }; - input: TEventInputSchema; -}; - -export const getPublicEventHandler = async ({ ctx, input }: GetOptions) => { - return await EventTypeRepository.getPublicEvent(input, ctx.user.id); -}; diff --git a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts b/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts deleted file mode 100644 index d10a5965cccbef..00000000000000 --- a/packages/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema.ts +++ /dev/null @@ -1,15 +0,0 @@ -import z from "zod"; - -export const ZEventInputSchema = z.object({ - username: z.string(), - eventSlug: z.string(), - isTeamEvent: z.boolean().optional(), - org: z.string().nullable(), - /** - * Informs that the event request has been sent from a page that was reached by a redirect from non-org link(i.e. app.cal.com/username redirected to acme.cal.com/username) - * Based on this decision like whether to allow unpublished organization's event to be served or not can be made. - */ - fromRedirectOfNonOrgLink: z.boolean().optional().default(false), -}); - -export type TEventInputSchema = z.infer; From 905f6dc8dfd27c5ccffa189e56e2f234093fc844 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:35:27 -0400 Subject: [PATCH 20/39] fix types --- .../Booker/components/BookEventForm/BookingFields.tsx | 4 ++-- packages/features/bookings/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx index c17d0b545b7240..86ef336f63c04c 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx @@ -5,9 +5,9 @@ import { getOrganizerInputLocationTypes } from "@calcom/app-store/locations"; import { useBookerStore } from "@calcom/features/bookings/Booker/store"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import getLocationOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect"; +import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { FormBuilderField } from "@calcom/features/form-builder/FormBuilderField"; import { useLocale } from "@calcom/lib/hooks/useLocale"; -import type { RouterOutputs } from "@calcom/trpc/react"; import { SystemField } from "../../../lib/SystemField"; @@ -18,7 +18,7 @@ export const BookingFields = ({ isDynamicGroupBooking, bookingData, }: { - fields: NonNullable["bookingFields"]; + fields: NonNullable>>["bookingFields"]; locations: LocationObject[]; rescheduleUid?: string; bookingData?: GetBookingType | null; diff --git a/packages/features/bookings/types.ts b/packages/features/bookings/types.ts index 2060769dfce44e..386176cf2c09b4 100644 --- a/packages/features/bookings/types.ts +++ b/packages/features/bookings/types.ts @@ -1,13 +1,13 @@ import type { SchedulingType } from "@prisma/client"; import type { ErrorOption, FieldPath } from "react-hook-form"; +import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import type { BookingCreateBody } from "@calcom/prisma/zod/custom/booking"; -import type { RouterOutputs } from "@calcom/trpc/react"; import type { AppsStatus } from "@calcom/types/Calendar"; import type { DatePickerProps } from "../calendars/DatePicker"; -export type PublicEvent = NonNullable; +type PublicEvent = NonNullable>>; export type BookerEventQuery = { isSuccess: boolean; From 05f07e96caf6ee6129b068203fd9c882bd602b43 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:49:04 -0400 Subject: [PATCH 21/39] restore --- .../trpc/server/routers/publicViewer/_router.tsx | 2 ++ .../server/routers/publicViewer/event.handler.ts | 14 ++++++++++++++ .../server/routers/publicViewer/event.schema.ts | 15 +++++++++++++++ .../routers/publicViewer/procedures/event.ts | 13 +++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 packages/trpc/server/routers/publicViewer/event.handler.ts create mode 100644 packages/trpc/server/routers/publicViewer/event.schema.ts create mode 100644 packages/trpc/server/routers/publicViewer/procedures/event.ts diff --git a/packages/trpc/server/routers/publicViewer/_router.tsx b/packages/trpc/server/routers/publicViewer/_router.tsx index 1a415643bf1667..b6aa0b3f744c6b 100644 --- a/packages/trpc/server/routers/publicViewer/_router.tsx +++ b/packages/trpc/server/routers/publicViewer/_router.tsx @@ -2,6 +2,7 @@ import publicProcedure from "../../procedures/publicProcedure"; import { importHandler, router } from "../../trpc"; import { ZUserEmailVerificationRequiredSchema } from "./checkIfUserEmailVerificationRequired.schema"; import { ZMarkHostAsNoShowInputSchema } from "./markHostAsNoShow.schema"; +import { event } from "./procedures/event"; import { session } from "./procedures/session"; import { ZSamlTenantProductInputSchema } from "./samlTenantProduct.schema"; import { ZStripeCheckoutSessionInputSchema } from "./stripeCheckoutSession.schema"; @@ -43,6 +44,7 @@ export const publicViewerRouter = router({ ); return handler(opts); }), + event, ssoConnections: publicProcedure.query(async () => { const handler = await importHandler( namespaced("ssoConnections"), diff --git a/packages/trpc/server/routers/publicViewer/event.handler.ts b/packages/trpc/server/routers/publicViewer/event.handler.ts new file mode 100644 index 00000000000000..1902468fec0107 --- /dev/null +++ b/packages/trpc/server/routers/publicViewer/event.handler.ts @@ -0,0 +1,14 @@ +import { EventRepository } from "@calcom/lib/server/repository/event"; + +import type { TEventInputSchema } from "./event.schema"; + +interface EventHandlerOptions { + input: TEventInputSchema; + userId?: number; +} + +export const eventHandler = async ({ input, userId }: EventHandlerOptions) => { + return await EventRepository.getPublicEvent(input, userId); +}; + +export default eventHandler; diff --git a/packages/trpc/server/routers/publicViewer/event.schema.ts b/packages/trpc/server/routers/publicViewer/event.schema.ts new file mode 100644 index 00000000000000..d10a5965cccbef --- /dev/null +++ b/packages/trpc/server/routers/publicViewer/event.schema.ts @@ -0,0 +1,15 @@ +import z from "zod"; + +export const ZEventInputSchema = z.object({ + username: z.string(), + eventSlug: z.string(), + isTeamEvent: z.boolean().optional(), + org: z.string().nullable(), + /** + * Informs that the event request has been sent from a page that was reached by a redirect from non-org link(i.e. app.cal.com/username redirected to acme.cal.com/username) + * Based on this decision like whether to allow unpublished organization's event to be served or not can be made. + */ + fromRedirectOfNonOrgLink: z.boolean().optional().default(false), +}); + +export type TEventInputSchema = z.infer; diff --git a/packages/trpc/server/routers/publicViewer/procedures/event.ts b/packages/trpc/server/routers/publicViewer/procedures/event.ts new file mode 100644 index 00000000000000..6f96bc68562255 --- /dev/null +++ b/packages/trpc/server/routers/publicViewer/procedures/event.ts @@ -0,0 +1,13 @@ +import { getUserSession } from "../../../middlewares/sessionMiddleware"; +import publicProcedure from "../../../procedures/publicProcedure"; +import { importHandler } from "../../../trpc"; +import { ZEventInputSchema } from "../event.schema"; + +const NAMESPACE = "publicViewer"; +const namespaced = (s: string) => `${NAMESPACE}.${s}`; + +export const event = publicProcedure.input(ZEventInputSchema).query(async (opts) => { + const { user } = await getUserSession(opts.ctx); + const handler = await importHandler(namespaced("event"), () => import("../event.handler")); + return handler({ input: opts.input, userId: user?.id }); +}); From ae08f171d5349a96e088330fafd35d1648915ff9 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:49:49 -0400 Subject: [PATCH 22/39] revert --- .../features/bookings/Booker/utils/event.ts | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index e0ceb544417d36..97dd1e48d34317 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -2,12 +2,50 @@ import { shallow } from "zustand/shallow"; import { useSchedule } from "@calcom/features/schedules"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; +import { trpc } from "@calcom/trpc/react"; import { useBookerTime } from "../components/hooks/useBookerTime"; import { useBookerStore } from "../store"; +export type useEventReturnType = ReturnType; export type useScheduleForEventReturnType = ReturnType; +/** + * Wrapper hook around the trpc query that fetches + * the event currently viewed in the booker. It will get + * the current event slug and username from the booker store. + * + * Using this hook means you only need to use one hook, instead + * of combining multiple conditional hooks. + */ +export const useEvent = (props?: { fromRedirectOfNonOrgLink?: boolean; disabled?: boolean }) => { + const [username, eventSlug, isTeamEvent, org] = useBookerStore( + (state) => [state.username, state.eventSlug, state.isTeamEvent, state.org], + shallow + ); + + const event = trpc.viewer.public.event.useQuery( + { + username: username ?? "", + eventSlug: eventSlug ?? "", + isTeamEvent, + org: org ?? null, + fromRedirectOfNonOrgLink: props?.fromRedirectOfNonOrgLink, + }, + { + refetchOnWindowFocus: false, + enabled: !props?.disabled && Boolean(username) && Boolean(eventSlug), + } + ); + + return { + data: event?.data, + isSuccess: event?.isSuccess, + isError: event?.isError, + isPending: event?.isPending, + }; +}; + /** * Gets schedule for the current event and current month. * Gets all values right away and not the store because it increases network timing, only for the first render. From bcd5171d0b59c9de9923912de82b2fd80b31bbf3 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:51:26 -0400 Subject: [PATCH 23/39] revert --- .../Booker/components/BookEventForm/BookingFields.tsx | 4 ++-- packages/features/bookings/types.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx index 86ef336f63c04c..313bee12877d8b 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookingFields.tsx @@ -5,9 +5,9 @@ import { getOrganizerInputLocationTypes } from "@calcom/app-store/locations"; import { useBookerStore } from "@calcom/features/bookings/Booker/store"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import getLocationOptionsForSelect from "@calcom/features/bookings/lib/getLocationOptionsForSelect"; -import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { FormBuilderField } from "@calcom/features/form-builder/FormBuilderField"; import { useLocale } from "@calcom/lib/hooks/useLocale"; +import type { RouterOutputs } from "@calcom/trpc/react"; import { SystemField } from "../../../lib/SystemField"; @@ -18,7 +18,7 @@ export const BookingFields = ({ isDynamicGroupBooking, bookingData, }: { - fields: NonNullable>>["bookingFields"]; + fields: NonNullable["bookingFields"]; locations: LocationObject[]; rescheduleUid?: string; bookingData?: GetBookingType | null; diff --git a/packages/features/bookings/types.ts b/packages/features/bookings/types.ts index 386176cf2c09b4..464b4545829953 100644 --- a/packages/features/bookings/types.ts +++ b/packages/features/bookings/types.ts @@ -1,13 +1,13 @@ import type { SchedulingType } from "@prisma/client"; import type { ErrorOption, FieldPath } from "react-hook-form"; -import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import type { BookingCreateBody } from "@calcom/prisma/zod/custom/booking"; +import type { RouterOutputs } from "@calcom/trpc/react"; import type { AppsStatus } from "@calcom/types/Calendar"; import type { DatePickerProps } from "../calendars/DatePicker"; -type PublicEvent = NonNullable>>; +export type PublicEvent = NonNullable; export type BookerEventQuery = { isSuccess: boolean; From 16c31ff15a5e2a8924ea2ebc9907c8fa1a56c9b0 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 02:54:22 -0400 Subject: [PATCH 24/39] fix --- packages/trpc/server/routers/publicViewer/event.handler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/trpc/server/routers/publicViewer/event.handler.ts b/packages/trpc/server/routers/publicViewer/event.handler.ts index 1902468fec0107..3983a657babfc2 100644 --- a/packages/trpc/server/routers/publicViewer/event.handler.ts +++ b/packages/trpc/server/routers/publicViewer/event.handler.ts @@ -1,4 +1,4 @@ -import { EventRepository } from "@calcom/lib/server/repository/event"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import type { TEventInputSchema } from "./event.schema"; @@ -8,7 +8,7 @@ interface EventHandlerOptions { } export const eventHandler = async ({ input, userId }: EventHandlerOptions) => { - return await EventRepository.getPublicEvent(input, userId); + return await EventTypeRepository.getPublicEvent(input, userId); }; export default eventHandler; From 629ba64c6de8650df41b96347863d9932623f15b Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 03:03:29 -0400 Subject: [PATCH 25/39] fix --- .../Booker/components/AvailableTimeSlots.tsx | 2 +- .../bookings/components/AvailableTimes.tsx | 18 ++++++++++-------- packages/features/embed/Embed.tsx | 11 +---------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx index a141d3ca2bb98a..f6b091d8412d0c 100644 --- a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx +++ b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx @@ -24,7 +24,7 @@ type AvailableTimeSlotsProps = { seatsPerTimeSlot?: number | null; showAvailableSeatsCount?: boolean | null; event: { - data?: Pick | null; + data?: Pick | null; }; customClassNames?: { availableTimeSlotsContainer?: string; diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 0182a96f7b19a6..285bfa7353ce8d 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -7,12 +7,12 @@ import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; import dayjs from "@calcom/dayjs"; import { OutOfOfficeInSlots } from "@calcom/features/bookings/Booker/components/OutOfOfficeInSlots"; import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; +import type { BookerEvent } from "@calcom/features/bookings/types"; import type { Slot } from "@calcom/features/schedules"; import { getPaymentAppData } from "@calcom/lib/getPaymentAppData"; import type { IOutOfOfficeData } from "@calcom/lib/getUserAvailability"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { localStorage } from "@calcom/lib/webstorage"; -import type { RouterOutputs } from "@calcom/trpc/react"; import classNames from "@calcom/ui/classNames"; import { Button } from "@calcom/ui/components/button"; import { Icon } from "@calcom/ui/components/icon"; @@ -60,7 +60,9 @@ type SlotItemProps = { onTimeSelect?: TOnTimeSelect; onTentativeTimeSelect?: TOnTentativeTimeSelect; showAvailableSeatsCount?: boolean | null; - eventData: Pick; + event: { + data?: Pick | null; + }; customClassNames?: string; confirmStepClassNames?: { confirmButton?: string; @@ -82,7 +84,7 @@ const SlotItem = ({ selectedSlots, onTimeSelect, showAvailableSeatsCount, - eventData, + event, customClassNames, loadingStates, renderConfirmNotVerifyEmailButtonCond, @@ -99,10 +101,10 @@ const SlotItem = ({ const { t } = useLocale(); const isPaidEvent = useMemo(() => { - if (!eventData?.price) return false; - const paymentAppData = getPaymentAppData(eventData); - return eventData?.price > 0 && !Number.isNaN(paymentAppData.price) && paymentAppData.price > 0; - }, [eventData]); + if (!event.data?.price) return false; + const paymentAppData = getPaymentAppData(event.data); + return event.data?.price > 0 && !Number.isNaN(paymentAppData.price) && paymentAppData.price > 0; + }, [event.data]); const overlayCalendarToggled = getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault"); @@ -127,7 +129,7 @@ const SlotItem = ({ const { isOverlapping, overlappingTimeEnd, overlappingTimeStart } = useCheckOverlapWithOverlay({ start: computedDateWithUsersTimezone, - selectedDuration: eventData?.length ?? 0, + selectedDuration: event.data?.length ?? 0, offset, }); diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index b6ea2545f568e3..0ead3ce431cd9e 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -390,16 +390,7 @@ const EmailEmbed = ({ handleSlotClick={handleSlotClick} slots={slots} showAvailableSeatsCount={eventType.seatsShowAvailabilityCount} - eventTypeData={ - eventTypeData - ? { - price: eventTypeData.price, - currency: eventTypeData.currency, - metadata: eventTypeData.metadata, - length: eventTypeData.length, - } - : undefined - } + event={eventData} /> ) : null} From 307eb9e33b4b66ead9c55cb172331ba02a1f52a5 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 03:03:33 -0400 Subject: [PATCH 26/39] fix --- packages/lib/getPaymentAppData.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/lib/getPaymentAppData.ts b/packages/lib/getPaymentAppData.ts index 08c451eb1298a3..113605b82c7f50 100644 --- a/packages/lib/getPaymentAppData.ts +++ b/packages/lib/getPaymentAppData.ts @@ -4,11 +4,14 @@ import { getEventTypeAppData } from "@calcom/app-store/_utils/getEventTypeAppDat import type { appDataSchemas } from "@calcom/app-store/apps.schemas.generated"; import type { appDataSchema, paymentOptionEnum } from "@calcom/app-store/stripepayment/zod"; import type { EventTypeAppsList } from "@calcom/app-store/utils"; +import type { BookerEvent } from "@calcom/features/bookings/types"; +import type { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils"; import { eventTypeMetaDataSchemaWithTypedApps } from "@calcom/prisma/zod-utils"; -import type { RouterOutputs } from "@calcom/trpc"; export function getPaymentAppData( - _eventType: Pick, + _eventType: Pick & { + metadata: z.infer; + }, forcedGet?: boolean ) { const eventType = { From 53d7a110ead07209615acf52c58c2bfd29005d0a Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 03:04:17 -0400 Subject: [PATCH 27/39] fix --- .../bookings/components/AvailableTimes.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 285bfa7353ce8d..0eee6a9e86ba48 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -61,7 +61,7 @@ type SlotItemProps = { onTentativeTimeSelect?: TOnTentativeTimeSelect; showAvailableSeatsCount?: boolean | null; event: { - data?: Pick | null; + data?: Pick | null; }; customClassNames?: string; confirmStepClassNames?: { @@ -100,11 +100,13 @@ const SlotItem = ({ }: SlotItemProps) => { const { t } = useLocale(); + const { data: eventData } = event; + const isPaidEvent = useMemo(() => { - if (!event.data?.price) return false; - const paymentAppData = getPaymentAppData(event.data); - return event.data?.price > 0 && !Number.isNaN(paymentAppData.price) && paymentAppData.price > 0; - }, [event.data]); + if (!eventData?.price) return false; + const paymentAppData = getPaymentAppData(eventData); + return eventData?.price > 0 && !Number.isNaN(paymentAppData.price) && paymentAppData.price > 0; + }, [eventData]); const overlayCalendarToggled = getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault"); @@ -129,7 +131,7 @@ const SlotItem = ({ const { isOverlapping, overlappingTimeEnd, overlappingTimeStart } = useCheckOverlapWithOverlay({ start: computedDateWithUsersTimezone, - selectedDuration: event.data?.length ?? 0, + selectedDuration: eventData?.length ?? 0, offset, }); From 1f482db688c77da63ca66342b6ced9efc80e98dd Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 03:17:26 -0400 Subject: [PATCH 28/39] fix --- .../bookings/Booker/components/AvailableTimeSlots.tsx | 8 +++----- packages/features/bookings/components/AvailableTimes.tsx | 4 ++-- packages/features/embed/Embed.tsx | 7 ++++--- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx index f6b091d8412d0c..2325f4990cf747 100644 --- a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx +++ b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx @@ -1,9 +1,9 @@ import { useCallback, useMemo, useRef } from "react"; import dayjs from "@calcom/dayjs"; -import { AvailableTimes, AvailableTimesSkeleton } from "@calcom/features/bookings"; import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; -import type { BookerEvent } from "@calcom/features/bookings/types"; +import { AvailableTimes, AvailableTimesSkeleton } from "@calcom/features/bookings/components/AvailableTimes"; +import type { SlotItemProps } from "@calcom/features/bookings/components/AvailableTimes"; import { useNonEmptyScheduleDays } from "@calcom/features/schedules"; import type { Slot } from "@calcom/features/schedules"; import { useSlotsForAvailableDates } from "@calcom/features/schedules/lib/use-schedule/useSlotsForDate"; @@ -23,9 +23,7 @@ type AvailableTimeSlotsProps = { isLoading: boolean; seatsPerTimeSlot?: number | null; showAvailableSeatsCount?: boolean | null; - event: { - data?: Pick | null; - }; + event: SlotItemProps["event"]; customClassNames?: { availableTimeSlotsContainer?: string; availableTimeSlotsTitle?: string; diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 0eee6a9e86ba48..d98f086a3f5e27 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -53,7 +53,7 @@ export type AvailableTimesProps = { unavailableTimeSlots?: string[]; } & Omit; -type SlotItemProps = { +export type SlotItemProps = { slot: Slot; seatsPerTimeSlot?: number | null; selectedSlots?: string[]; @@ -61,7 +61,7 @@ type SlotItemProps = { onTentativeTimeSelect?: TOnTentativeTimeSelect; showAvailableSeatsCount?: boolean | null; event: { - data?: Pick | null; + data?: Pick | null; }; customClassNames?: string; confirmStepClassNames?: { diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index 0ead3ce431cd9e..4aff5e2042be40 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -10,9 +10,10 @@ import { shallow } from "zustand/shallow"; import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; -import { AvailableTimes, AvailableTimesHeader } from "@calcom/features/bookings"; import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; import { useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; +import { AvailableTimes } from "@calcom/features/bookings/components/AvailableTimes"; +import { AvailableTimesHeader } from "@calcom/features/bookings/components/AvailableTimesHeader"; import DatePicker from "@calcom/features/calendars/DatePicker"; import { Dialog } from "@calcom/features/components/controlled-dialog"; import { TimezoneSelect } from "@calcom/features/components/timezone-select"; @@ -366,7 +367,7 @@ const EmailEmbed = ({ locale={i18n.language} browsingDate={month ? dayjs(month) : undefined} selected={dayjs(selectedDate)} - weekStart={weekdayToWeekIndex(eventTypeData?.users?.[0]?.weekStart)} + weekStart={weekdayToWeekIndex(eventTypeData?.users?.[0].weekStart)} eventSlug={eventType?.slug} /> @@ -442,7 +443,7 @@ const EmailEmbedPreview = ({ selectedDuration, userSettingsTimezone, }: { - eventType: EventType; + eventType: RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]; timezone?: string; emailContentRef: RefObject; username?: string; From fff5daabbbd23cb34f82cf956cb7bb2496d22ea4 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 03:18:08 -0400 Subject: [PATCH 29/39] fix --- packages/features/embed/Embed.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index 4aff5e2042be40..1a30cc388e3fcc 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -391,7 +391,7 @@ const EmailEmbed = ({ handleSlotClick={handleSlotClick} slots={slots} showAvailableSeatsCount={eventType.seatsShowAvailabilityCount} - event={eventData} + event={eventTypeData} /> ) : null} From 6390f1a7fd18558f40b3aff86cd2b0faa61d0406 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 5 Apr 2025 22:39:36 -0400 Subject: [PATCH 30/39] fix type check --- packages/lib/server/repository/eventType.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index 3c6dd78349f37c..e6e702fc16cde2 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -7,7 +7,7 @@ import { prisma, availabilityUserSelect } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { EventTypeMetaDataSchema, rrSegmentQueryValueSchema } from "@calcom/prisma/zod-utils"; -import type { TEventInputSchema } from "@calcom/trpc/server/routers/viewer/eventTypes/getPublicEvent.schema"; +import type { TEventInputSchema } from "@calcom/trpc/server/routers/publicViewer/event.schema"; import type { Ensure } from "@calcom/types/utils"; import { TRPCError } from "@trpc/server"; From 9c5f105ea6de6ed3e8aea9e7e620689d2dabd75d Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Wed, 9 Apr 2025 17:59:42 -0400 Subject: [PATCH 31/39] fix --- packages/features/bookings/Booker/Booker.tsx | 3 +- .../Booker/components/AvailableTimeSlots.tsx | 8 +++-- .../BookEventForm/BookFormAsModal.tsx | 35 ++++++------------- .../bookings/components/AvailableTimes.tsx | 4 +-- packages/features/embed/Embed.tsx | 20 +++++------ 5 files changed, 29 insertions(+), 41 deletions(-) diff --git a/packages/features/bookings/Booker/Booker.tsx b/packages/features/bookings/Booker/Booker.tsx index b8472097b6f0b9..173578c55168c2 100644 --- a/packages/features/bookings/Booker/Booker.tsx +++ b/packages/features/bookings/Booker/Booker.tsx @@ -569,8 +569,7 @@ const BookerComponent = ({ setSelectedTimeslot(null)} - visible={bookerState === "booking" && shouldShowFormInDialog} - eventDuration={event?.data?.length}> + visible={bookerState === "booking" && shouldShowFormInDialog}> {EventBooker} diff --git a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx index 2325f4990cf747..a141d3ca2bb98a 100644 --- a/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx +++ b/packages/features/bookings/Booker/components/AvailableTimeSlots.tsx @@ -1,9 +1,9 @@ import { useCallback, useMemo, useRef } from "react"; import dayjs from "@calcom/dayjs"; +import { AvailableTimes, AvailableTimesSkeleton } from "@calcom/features/bookings"; import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; -import { AvailableTimes, AvailableTimesSkeleton } from "@calcom/features/bookings/components/AvailableTimes"; -import type { SlotItemProps } from "@calcom/features/bookings/components/AvailableTimes"; +import type { BookerEvent } from "@calcom/features/bookings/types"; import { useNonEmptyScheduleDays } from "@calcom/features/schedules"; import type { Slot } from "@calcom/features/schedules"; import { useSlotsForAvailableDates } from "@calcom/features/schedules/lib/use-schedule/useSlotsForDate"; @@ -23,7 +23,9 @@ type AvailableTimeSlotsProps = { isLoading: boolean; seatsPerTimeSlot?: number | null; showAvailableSeatsCount?: boolean | null; - event: SlotItemProps["event"]; + event: { + data?: Pick | null; + }; customClassNames?: { availableTimeSlotsContainer?: string; availableTimeSlotsTitle?: string; diff --git a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx index 9a57f0e9f6ed05..dce506f198846f 100644 --- a/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx +++ b/packages/features/bookings/Booker/components/BookEventForm/BookFormAsModal.tsx @@ -11,18 +11,13 @@ import { DialogContent } from "@calcom/ui/components/dialog"; import { getDurationFormatted } from "../../../components/event-meta/Duration"; import { useBookerStore } from "../../store"; import { FromTime } from "../../utils/dates"; +import { useEvent } from "../../utils/event"; import { useBookerTime } from "../hooks/useBookerTime"; -const BookEventFormWrapper = ({ - children, - onCancel, - eventDuration, -}: { - onCancel: () => void; - children: ReactNode; - eventDuration?: number; -}) => { - return ; +const BookEventFormWrapper = ({ children, onCancel }: { onCancel: () => void; children: ReactNode }) => { + const { data } = useEvent(); + + return ; }; const PlatformBookEventFormWrapper = ({ @@ -36,21 +31,17 @@ const PlatformBookEventFormWrapper = ({ const { data } = useEventTypeById(eventId); return ( - + ); }; export const BookEventFormWrapperComponent = ({ child, - eventDuration, + eventLength, }: { onCancel: () => void; child: ReactNode; - eventDuration?: number; + eventLength?: number; }) => { const { i18n, t } = useLocale(); const selectedTimeslot = useBookerStore((state) => state.selectedTimeslot); @@ -71,9 +62,9 @@ export const BookEventFormWrapperComponent = ({ language={i18n.language} /> - {(selectedDuration || eventDuration) && ( + {(selectedDuration || eventLength) && ( - {getDurationFormatted(selectedDuration || eventDuration, t)} + {getDurationFormatted(selectedDuration || eventLength, t)} )} @@ -86,12 +77,10 @@ export const BookFormAsModal = ({ visible, onCancel, children, - eventDuration, }: { visible: boolean; onCancel: () => void; children: ReactNode; - eventDuration?: number; }) => { const isPlatform = useIsPlatform(); @@ -102,9 +91,7 @@ export const BookFormAsModal = ({ enableOverflow className="[&_.modalsticky]:border-t-subtle [&_.modalsticky]:bg-default max-h-[80vh] pb-0 [&_.modalsticky]:sticky [&_.modalsticky]:bottom-0 [&_.modalsticky]:left-0 [&_.modalsticky]:right-0 [&_.modalsticky]:-mx-8 [&_.modalsticky]:border-t [&_.modalsticky]:px-8 [&_.modalsticky]:py-4"> {!isPlatform ? ( - - {children} - + {children} ) : ( {children} )} diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index d98f086a3f5e27..0eee6a9e86ba48 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -53,7 +53,7 @@ export type AvailableTimesProps = { unavailableTimeSlots?: string[]; } & Omit; -export type SlotItemProps = { +type SlotItemProps = { slot: Slot; seatsPerTimeSlot?: number | null; selectedSlots?: string[]; @@ -61,7 +61,7 @@ export type SlotItemProps = { onTentativeTimeSelect?: TOnTentativeTimeSelect; showAvailableSeatsCount?: boolean | null; event: { - data?: Pick | null; + data?: Pick | null; }; customClassNames?: string; confirmStepClassNames?: { diff --git a/packages/features/embed/Embed.tsx b/packages/features/embed/Embed.tsx index 1a30cc388e3fcc..4c5a67f7cd41bf 100644 --- a/packages/features/embed/Embed.tsx +++ b/packages/features/embed/Embed.tsx @@ -10,10 +10,9 @@ import { shallow } from "zustand/shallow"; import type { Dayjs } from "@calcom/dayjs"; import dayjs from "@calcom/dayjs"; +import { AvailableTimes, AvailableTimesHeader } from "@calcom/features/bookings"; import { useBookerStore, useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; -import { useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; -import { AvailableTimes } from "@calcom/features/bookings/components/AvailableTimes"; -import { AvailableTimesHeader } from "@calcom/features/bookings/components/AvailableTimesHeader"; +import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import DatePicker from "@calcom/features/calendars/DatePicker"; import { Dialog } from "@calcom/features/components/controlled-dialog"; import { TimezoneSelect } from "@calcom/features/components/timezone-select"; @@ -45,6 +44,7 @@ import { useEmbedDialogCtx } from "./lib/hooks/useEmbedDialogCtx"; import { useEmbedParams } from "./lib/hooks/useEmbedParams"; import type { EmbedTabs, EmbedType, EmbedTypes, PreviewState } from "./types"; +type EventType = RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"] | undefined; type EmbedDialogProps = { types: EmbedTypes; tabs: EmbedTabs; @@ -223,7 +223,7 @@ const ChooseEmbedTypesDialogContent = ({ }; const EmailEmbed = ({ - eventTypeData, + eventType, username, orgSlug, isTeamEvent, @@ -231,7 +231,7 @@ const EmailEmbed = ({ setSelectedDuration, userSettingsTimezone, }: { - eventTypeData?: RouterOutputs["viewer"]["eventTypes"]["get"]; + eventType?: EventType; username: string; orgSlug?: string; isTeamEvent: boolean; @@ -240,7 +240,6 @@ const EmailEmbed = ({ userSettingsTimezone?: string; }) => { const { t, i18n } = useLocale(); - const eventType = eventTypeData?.eventType; const { timezoneFromBookerStore, timezoneFromTimePreferences } = useBookerTime(); const timezone = chooseTimezone({ timezoneFromBookerStore, @@ -272,6 +271,7 @@ const EmailEmbed = ({ ], shallow ); + const event = useEvent(); const schedule = useScheduleForEvent({ orgSlug, eventId: eventType?.id, @@ -367,7 +367,7 @@ const EmailEmbed = ({ locale={i18n.language} browsingDate={month ? dayjs(month) : undefined} selected={dayjs(selectedDate)} - weekStart={weekdayToWeekIndex(eventTypeData?.users?.[0].weekStart)} + weekStart={weekdayToWeekIndex(event?.data?.subsetOfUsers?.[0]?.weekStart)} eventSlug={eventType?.slug} /> @@ -391,7 +391,7 @@ const EmailEmbed = ({ handleSlotClick={handleSlotClick} slots={slots} showAvailableSeatsCount={eventType.seatsShowAvailabilityCount} - event={eventTypeData} + event={event} /> ) : null} @@ -443,7 +443,7 @@ const EmailEmbedPreview = ({ selectedDuration, userSettingsTimezone, }: { - eventType: RouterOutputs["viewer"]["eventTypes"]["get"]["eventType"]; + eventType: EventType; timezone?: string; emailContentRef: RefObject; username?: string; @@ -917,7 +917,7 @@ const EmbedTypeCodeAndPreviewDialogContent = ({

{embed.subtitle}

{eventTypeData?.eventType && embedType === "email" ? ( Date: Wed, 9 Apr 2025 19:01:32 -0400 Subject: [PATCH 32/39] fix --- apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx | 9 ++------- .../team/[slug]/[type]/getServerSideProps.ts | 6 +----- .../server/lib/[user]/[type]/getServerSideProps.ts | 13 ++----------- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index c40d2e37241e49..a9346092797b7f 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -19,11 +19,6 @@ export type PageProps = inferSSRProps & EmbedProps; async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); - if (!session?.user?.id) { - return { redirect: { permanent: false, destination: "/auth/login" } }; - } - const sessionUserId = session.user.id; - const { link, slug } = paramsSchema.parse(context.params); const { rescheduleUid, duration: queryDuration } = context.query; const { currentOrgDomain, isValidOrgDomain } = orgDomainConfig(context.req); @@ -111,7 +106,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { let booking: GetBookingType | null = null; if (rescheduleUid) { - booking = await getBookingForReschedule(`${rescheduleUid}`, sessionUserId); + booking = await getBookingForReschedule(`${rescheduleUid}`, session?.user?.id); } const isTeamEvent = !!hashedLink.eventType?.team?.id; @@ -126,7 +121,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - sessionUserId + session?.user?.id ); if (!eventData) { diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index 9e19b266edba6a..caea126b38a19a 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -16,10 +16,6 @@ const paramsSchema = z.object({ export const getServerSideProps = async (context: GetServerSidePropsContext) => { const session = await getServerSession({ req: context.req }); - if (!session?.user?.id) { - return { redirect: { permanent: false, destination: "/auth/login" } }; - } - const sessionUserId = session.user.id; const { slug: teamSlug, type: meetingSlug } = paramsSchema.parse(context.params); const { duration: queryDuration } = context.query; @@ -52,7 +48,7 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - sessionUserId + session?.user?.id ); if (!eventData || !org) { return { diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index 8c82a23bb21b5a..a218cf16356d0c 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -93,10 +93,6 @@ async function processSeatedEvent({ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); - if (!session?.user?.id) { - return { redirect: { permanent: false, destination: "/auth/login" } }; - } - const sessionUserId = session.user.id; const { user: usernames, type: slug } = paramsSchema.parse(context.params); const { rescheduleUid, bookingUid } = context.query; @@ -138,7 +134,7 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - sessionUserId + session?.user?.id ); if (!eventData) { @@ -181,11 +177,6 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { async function getUserPageProps(context: GetServerSidePropsContext) { const session = await getServerSession({ req: context.req }); - if (!session?.user?.id) { - return { redirect: { permanent: false, destination: "/auth/login" } }; - } - const sessionUserId = session.user.id; - const { user: usernames, type: slug } = paramsSchema.parse(context.params); const username = usernames[0]; const { rescheduleUid, bookingUid } = context.query; @@ -226,7 +217,7 @@ async function getUserPageProps(context: GetServerSidePropsContext) { org, fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", }, - sessionUserId + session?.user?.id ); if (!eventData) { From 7e7b1e187ae31d3425fe8d07e4416d06419ffc9b Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 02:22:59 -0400 Subject: [PATCH 33/39] finalize --- .../controllers/event-types.controller.ts | 14 +++++++------- .../queries/eventType/getPublicEvent/index.ts} | 0 .../getPublicEvent}/isCurrentlyAvailable.test.ts | 2 +- packages/lib/server/repository/eventType.ts | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) rename packages/{features/eventtypes/lib/getPublicEvent.ts => lib/server/queries/eventType/getPublicEvent/index.ts} (100%) rename packages/{features/eventtypes/lib => lib/server/queries/eventType/getPublicEvent}/isCurrentlyAvailable.test.ts (98%) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts index e08562a65f9c96..607baeb894a34e 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts @@ -38,6 +38,7 @@ import { } from "@nestjs/common"; import { ApiExcludeController as DocsExcludeController } from "@nestjs/swagger"; +import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; import { getPublicEvent, getEventTypesByViewer } from "@calcom/platform-libraries-0.0.2"; import { PrismaClient } from "@calcom/prisma"; @@ -112,16 +113,15 @@ export class EventTypesController_2024_04_15 { @Query() queryParams: GetPublicEventTypeQueryParams_2024_04_15 ): Promise { try { - const event = await getPublicEvent( - username.toLowerCase(), + const event = await EventTypeRepository.getPublicEvent({ + username: username.toLowerCase(), eventSlug, - queryParams.isTeamEvent, - queryParams.org || null, - this.prismaReadService.prisma as unknown as PrismaClient, + isTeamEvent: queryParams.isTeamEvent, + org: queryParams.org || null, // We should be fine allowing unpublished orgs events to be servable through platform because Platform access is behind license // If there is ever a need to restrict this, we can introduce a new query param `fromRedirectOfNonOrgLink` - true - ); + fromRedirectOfNonOrgLink: true, + }); return { data: event, status: SUCCESS_STATUS, diff --git a/packages/features/eventtypes/lib/getPublicEvent.ts b/packages/lib/server/queries/eventType/getPublicEvent/index.ts similarity index 100% rename from packages/features/eventtypes/lib/getPublicEvent.ts rename to packages/lib/server/queries/eventType/getPublicEvent/index.ts diff --git a/packages/features/eventtypes/lib/isCurrentlyAvailable.test.ts b/packages/lib/server/queries/eventType/getPublicEvent/isCurrentlyAvailable.test.ts similarity index 98% rename from packages/features/eventtypes/lib/isCurrentlyAvailable.test.ts rename to packages/lib/server/queries/eventType/getPublicEvent/isCurrentlyAvailable.test.ts index 77c6cec7283038..1dba1fa074a0c9 100644 --- a/packages/features/eventtypes/lib/isCurrentlyAvailable.test.ts +++ b/packages/lib/server/queries/eventType/getPublicEvent/isCurrentlyAvailable.test.ts @@ -1,7 +1,7 @@ import { PrismaClient } from "@prisma/client"; import { describe, it, expect, vi, beforeAll } from "vitest"; -import { isCurrentlyAvailable } from "./getPublicEvent"; +import { isCurrentlyAvailable } from "."; const prisma = new PrismaClient(); diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index e6e702fc16cde2..2ec75102fdaa2f 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -1,7 +1,6 @@ import type { EventType as PrismaEventType } from "@prisma/client"; import { Prisma } from "@prisma/client"; -import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import logger from "@calcom/lib/logger"; import { prisma, availabilityUserSelect } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; @@ -14,6 +13,7 @@ import { TRPCError } from "@trpc/server"; import { safeStringify } from "../../safeStringify"; import { eventTypeSelect } from "../eventTypeSelect"; +import { getPublicEvent } from "../queries/eventType/getPublicEvent"; import { LookupTarget, ProfileRepository } from "./profile"; import type { UserWithLegacySelectedCalendars } from "./user"; import { withSelectedCalendars } from "./user"; From 9b21957c6844d87bc012d2431a89e0837a440e32 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 02:26:59 -0400 Subject: [PATCH 34/39] finalize --- .../queries/eventType/getPublicEvent/index.ts | 31 +++++++++++++------ packages/lib/server/repository/eventType.ts | 16 ++++------ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/lib/server/queries/eventType/getPublicEvent/index.ts b/packages/lib/server/queries/eventType/getPublicEvent/index.ts index 79a88c61ee824e..dec266345529b0 100644 --- a/packages/lib/server/queries/eventType/getPublicEvent/index.ts +++ b/packages/lib/server/queries/eventType/getPublicEvent/index.ts @@ -215,16 +215,27 @@ function isAvailableInTimeSlot( } // TODO: Convert it to accept a single parameter with structured data -export const getPublicEvent = async ( - username: string, - eventSlug: string, - isTeamEvent: boolean | undefined, - org: string | null, - prisma: PrismaClient, - fromRedirectOfNonOrgLink: boolean, - currentUserId?: number, - fetchAllUsers = false -) => { +export type GetPublicEventProps = { + username: string; + eventSlug: string; + org: string | null; + prisma: PrismaClient; + fromRedirectOfNonOrgLink: boolean; + isTeamEvent?: boolean; + currentUserId?: number; + fetchAllUsers?: boolean; +}; + +export const getPublicEvent = async ({ + username, + eventSlug, + isTeamEvent, + org, + prisma, + fromRedirectOfNonOrgLink, + currentUserId, + fetchAllUsers = false, +}: GetPublicEventProps) => { const usernameList = getUsernameList(username); const orgQuery = org ? getSlugOrRequestedSlug(org) : null; // In case of dynamic group event, we fetch user's data and use the default event. diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index 2ec75102fdaa2f..f691eaa8ef7c68 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -6,7 +6,6 @@ import { prisma, availabilityUserSelect } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { EventTypeMetaDataSchema, rrSegmentQueryValueSchema } from "@calcom/prisma/zod-utils"; -import type { TEventInputSchema } from "@calcom/trpc/server/routers/publicViewer/event.schema"; import type { Ensure } from "@calcom/types/utils"; import { TRPCError } from "@trpc/server"; @@ -14,6 +13,7 @@ import { TRPCError } from "@trpc/server"; import { safeStringify } from "../../safeStringify"; import { eventTypeSelect } from "../eventTypeSelect"; import { getPublicEvent } from "../queries/eventType/getPublicEvent"; +import type { GetPublicEventProps } from "../queries/eventType/getPublicEvent"; import { LookupTarget, ProfileRepository } from "./profile"; import type { UserWithLegacySelectedCalendars } from "./user"; import { withSelectedCalendars } from "./user"; @@ -914,16 +914,12 @@ export class EventTypeRepository { return user.allSelectedCalendars.filter((calendar) => calendar.eventTypeId === eventTypeId); } - static async getPublicEvent(input: TEventInputSchema, userId?: number) { - const event = await getPublicEvent( - input.username, - input.eventSlug, - input.isTeamEvent, - input.org, + static async getPublicEvent(input: GetPublicEventProps, userId?: number) { + const event = await getPublicEvent({ + ...input, prisma, - input.fromRedirectOfNonOrgLink, - userId - ); + currentUserId: userId, + }); return event; } } From d2d3b30219c712c3cc4141b863e1ed2f1c5d1214 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 02:32:01 -0400 Subject: [PATCH 35/39] improve code --- .../d/[link]/[slug]/getServerSideProps.tsx | 18 +++++----- .../team/[slug]/[type]/getServerSideProps.ts | 18 +++++----- .../lib/[user]/[type]/getServerSideProps.ts | 34 ++++++++----------- packages/lib/server/repository/eventType.ts | 3 +- .../atoms/booker/BookerWebWrapper.tsx | 2 +- .../routers/publicViewer/event.handler.ts | 2 +- 6 files changed, 34 insertions(+), 43 deletions(-) diff --git a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx index a9346092797b7f..31be1384972b85 100644 --- a/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx +++ b/apps/web/lib/d/[link]/[slug]/getServerSideProps.tsx @@ -113,16 +113,14 @@ async function getUserPageProps(context: GetServerSidePropsContext) { // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const eventData = await EventTypeRepository.getPublicEvent( - { - username: name, - eventSlug: slug, - isTeamEvent, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }, - session?.user?.id - ); + const eventData = await EventTypeRepository.getPublicEvent({ + username: name, + eventSlug: slug, + isTeamEvent, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + currentUserId: session?.user?.id, + }); if (!eventData) { return notFound; diff --git a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts index caea126b38a19a..294d8e60d202fb 100644 --- a/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts +++ b/apps/web/lib/org/[orgSlug]/instant-meeting/team/[slug]/[type]/getServerSideProps.ts @@ -40,16 +40,14 @@ export const getServerSideProps = async (context: GetServerSidePropsContext) => const org = isValidOrgDomain ? currentOrgDomain : null; - const eventData = await EventTypeRepository.getPublicEvent( - { - username: teamSlug, - eventSlug: meetingSlug, - isTeamEvent: true, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }, - session?.user?.id - ); + const eventData = await EventTypeRepository.getPublicEvent({ + username: teamSlug, + eventSlug: meetingSlug, + isTeamEvent: true, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + currentUserId: session?.user?.id, + }); if (!eventData || !org) { return { notFound: true, diff --git a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts index a218cf16356d0c..4671dcdfdd2a12 100644 --- a/apps/web/server/lib/[user]/[type]/getServerSideProps.ts +++ b/apps/web/server/lib/[user]/[type]/getServerSideProps.ts @@ -6,8 +6,8 @@ import { getServerSession } from "@calcom/features/auth/lib/getServerSession"; import { getBookingForReschedule, getBookingForSeatedEvent } from "@calcom/features/bookings/lib/get-booking"; import type { GetBookingType } from "@calcom/features/bookings/lib/get-booking"; import { orgDomainConfig } from "@calcom/features/ee/organizations/lib/orgDomains"; -import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { getUsernameList } from "@calcom/lib/defaultEvents"; +import type { getPublicEvent } from "@calcom/lib/server/queries/eventType/getPublicEvent"; import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { UserRepository } from "@calcom/lib/server/repository/user"; import slugify from "@calcom/lib/slugify"; @@ -127,15 +127,13 @@ async function getDynamicGroupPageProps(context: GetServerSidePropsContext) { // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we c an show a 404 otherwise. - const eventData = await EventTypeRepository.getPublicEvent( - { - username: usernames.join("+"), - eventSlug: slug, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }, - session?.user?.id - ); + const eventData = await EventTypeRepository.getPublicEvent({ + username: usernames.join("+"), + eventSlug: slug, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + currentUserId: session?.user?.id, + }); if (!eventData) { return { @@ -210,15 +208,13 @@ async function getUserPageProps(context: GetServerSidePropsContext) { const org = isValidOrgDomain ? currentOrgDomain : null; // We use this to both prefetch the query on the server, // as well as to check if the event exist, so we can show a 404 otherwise. - const eventData = await EventTypeRepository.getPublicEvent( - { - username, - eventSlug: slug, - org, - fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", - }, - session?.user?.id - ); + const eventData = await EventTypeRepository.getPublicEvent({ + username, + eventSlug: slug, + org, + fromRedirectOfNonOrgLink: context.query.orgRedirection === "true", + currentUserId: session?.user?.id, + }); if (!eventData) { return { diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index f691eaa8ef7c68..35f12d3dc7879a 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -914,11 +914,10 @@ export class EventTypeRepository { return user.allSelectedCalendars.filter((calendar) => calendar.eventTypeId === eventTypeId); } - static async getPublicEvent(input: GetPublicEventProps, userId?: number) { + static async getPublicEvent(input: Omit) { const event = await getPublicEvent({ ...input, prisma, - currentUserId: userId, }); return event; } diff --git a/packages/platform/atoms/booker/BookerWebWrapper.tsx b/packages/platform/atoms/booker/BookerWebWrapper.tsx index db1304331cf41d..f9a5128d38bd3e 100644 --- a/packages/platform/atoms/booker/BookerWebWrapper.tsx +++ b/packages/platform/atoms/booker/BookerWebWrapper.tsx @@ -22,9 +22,9 @@ import { useBookerStore, useInitializeBookerStore } from "@calcom/features/booki import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import { getLastBookingResponse } from "@calcom/features/bookings/Booker/utils/lastBookingResponse"; import { useBrandColors } from "@calcom/features/bookings/Booker/utils/use-brand-colors"; -import type { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; import { DEFAULT_LIGHT_BRAND_COLOR, DEFAULT_DARK_BRAND_COLOR, WEBAPP_URL } from "@calcom/lib/constants"; import { useRouterQuery } from "@calcom/lib/hooks/useRouterQuery"; +import type { getPublicEvent } from "@calcom/lib/server/queries/eventType/getPublicEvent"; import { BookerLayouts } from "@calcom/prisma/zod-utils"; type BookerWebWrapperAtomProps = BookerProps & { diff --git a/packages/trpc/server/routers/publicViewer/event.handler.ts b/packages/trpc/server/routers/publicViewer/event.handler.ts index 3983a657babfc2..e8ab4127583a47 100644 --- a/packages/trpc/server/routers/publicViewer/event.handler.ts +++ b/packages/trpc/server/routers/publicViewer/event.handler.ts @@ -8,7 +8,7 @@ interface EventHandlerOptions { } export const eventHandler = async ({ input, userId }: EventHandlerOptions) => { - return await EventTypeRepository.getPublicEvent(input, userId); + return await EventTypeRepository.getPublicEvent({ ...input, currentUserId: userId }); }; export default eventHandler; From 412f4dd35cf9f7669b3a0d023d579c2281b69100 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 02:54:10 -0400 Subject: [PATCH 36/39] fix --- packages/platform/libraries/event-types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/platform/libraries/event-types.ts b/packages/platform/libraries/event-types.ts index 1e8864366972f2..ca20f897b2e99a 100644 --- a/packages/platform/libraries/event-types.ts +++ b/packages/platform/libraries/event-types.ts @@ -1,4 +1,4 @@ -import { getPublicEvent } from "@calcom/features/eventtypes/lib/getPublicEvent"; +import { getPublicEvent } from "@calcom/lib/server/queries/eventType/getPublicEvent"; export { getBulkUserEventTypes, getBulkTeamEventTypes } from "@calcom/lib/event-types/getBulkEventTypes"; From be8f919128ffb224b0924daab52dbd241675004c Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 19:46:29 -0400 Subject: [PATCH 37/39] fix --- .../controllers/event-types.controller.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts index 607baeb894a34e..1627e6428e1f13 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts @@ -38,7 +38,6 @@ import { } from "@nestjs/common"; import { ApiExcludeController as DocsExcludeController } from "@nestjs/swagger"; -import { EventTypeRepository } from "@calcom/lib/server/repository/eventType"; import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; import { getPublicEvent, getEventTypesByViewer } from "@calcom/platform-libraries-0.0.2"; import { PrismaClient } from "@calcom/prisma"; @@ -113,7 +112,7 @@ export class EventTypesController_2024_04_15 { @Query() queryParams: GetPublicEventTypeQueryParams_2024_04_15 ): Promise { try { - const event = await EventTypeRepository.getPublicEvent({ + const event = await getPublicEvent({ username: username.toLowerCase(), eventSlug, isTeamEvent: queryParams.isTeamEvent, From 3e0012e9edc5d4a716aa6d5822e66e8b75dc7edd Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 19:47:02 -0400 Subject: [PATCH 38/39] fix --- .../event-types_2024_04_15/controllers/event-types.controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts index 1627e6428e1f13..e313304bbb1e61 100644 --- a/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts +++ b/apps/api/v2/src/ee/event-types/event-types_2024_04_15/controllers/event-types.controller.ts @@ -40,7 +40,6 @@ import { ApiExcludeController as DocsExcludeController } from "@nestjs/swagger"; import { EVENT_TYPE_READ, EVENT_TYPE_WRITE, SUCCESS_STATUS } from "@calcom/platform-constants"; import { getPublicEvent, getEventTypesByViewer } from "@calcom/platform-libraries-0.0.2"; -import { PrismaClient } from "@calcom/prisma"; @Controller({ path: "/v2/event-types", From 644e0e5f9cd90a37c65565f3bdfc21ac3e913cd4 Mon Sep 17 00:00:00 2001 From: hbjORbj Date: Sat, 12 Apr 2025 20:17:17 -0400 Subject: [PATCH 39/39] fix --- packages/lib/server/repository/eventType.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/lib/server/repository/eventType.ts b/packages/lib/server/repository/eventType.ts index 35f12d3dc7879a..5369c673df5fb5 100644 --- a/packages/lib/server/repository/eventType.ts +++ b/packages/lib/server/repository/eventType.ts @@ -3,6 +3,7 @@ import { Prisma } from "@prisma/client"; import logger from "@calcom/lib/logger"; import { prisma, availabilityUserSelect } from "@calcom/prisma"; +import type { PrismaClient } from "@calcom/prisma"; import { MembershipRole } from "@calcom/prisma/enums"; import { credentialForCalendarServiceSelect } from "@calcom/prisma/selects/credential"; import { EventTypeMetaDataSchema, rrSegmentQueryValueSchema } from "@calcom/prisma/zod-utils"; @@ -914,10 +915,14 @@ export class EventTypeRepository { return user.allSelectedCalendars.filter((calendar) => calendar.eventTypeId === eventTypeId); } - static async getPublicEvent(input: Omit) { + static async getPublicEvent( + input: Omit & { + prisma?: PrismaClient; + } + ) { const event = await getPublicEvent({ ...input, - prisma, + prisma: input.prisma ?? prisma, }); return event; }