From 73f51920c5d871a703efe4921d92a708d720a070 Mon Sep 17 00:00:00 2001 From: Benny Joo Date: Sat, 31 Jan 2026 19:33:33 +0900 Subject: [PATCH] refactor: move Booker hooks from packages/features to apps/web/modules (#27343) * refactor: move Booker hooks from packages/features to apps/web/modules Migrate the following Booker hooks: - useOverlayCalendar - useSkipConfirmStep - useInitializeWeekStart - useIsQuickAvailabilityCheckFeatureEnabled - useDecoyBooking These hooks are only imported by apps/web files, making them safe to move without creating circular dependencies. Part of the tRPC-driven UI migration from packages/features to apps/web/modules. Co-Authored-By: benny@cal.com * fix: revert useIsQuickAvailabilityCheckFeatureEnabled move and fix import paths - Reverted useIsQuickAvailabilityCheckFeatureEnabled.ts back to packages/features since it's imported by useSlots.ts in packages/features (would create circular dependency) - Fixed import paths in useOverlayCalendar.ts to use @calcom/features paths - Fixed import paths in useSkipConfirmStep.ts to use @calcom/features paths - Updated Booker.tsx to import useIsQuickAvailabilityCheckFeatureEnabled from original location Co-Authored-By: benny@cal.com * fix: use @calcom/web alias for hook imports to fix vitest resolution Co-Authored-By: benny@cal.com * refactor * migrate more hooks * fix * mv types * fix * fix * fix * fix * revert: remove formatting-only changes to make PR easier to review Co-Authored-By: benny@cal.com * fix * fix * fix * revert: restore original import ordering in moved hooks Co-Authored-By: benny@cal.com * fix imports * fix * fix * wip * wip * wip * wip * wip * wip * fix: add isBrowser guard to useSlotsViewOnSmallScreen hook Address Cubic AI review feedback (confidence 9/10) by adding the isBrowser guard to the useSlotsViewOnSmallScreen hook to follow the file's client-only contract and avoid executing during SSR/prerendering. Co-Authored-By: unknown <> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../booking-successful/[uid]/page.tsx | 2 +- .../components/AvailableTimeSlots.tsx | 2 +- .../bookings/components/AvailableTimes.tsx | 4 +- .../BookEventForm/BookEventForm.tsx | 6 +- .../BookEventForm/BookFormAsModal.tsx | 2 +- .../bookings/components/Booker.test.tsx | 3 +- .../modules/bookings/components/Booker.tsx | 7 +- .../bookings/components/BookerWebWrapper.tsx | 14 +-- .../bookings/components/DatePicker.tsx | 2 +- .../modules/bookings/components/EventMeta.tsx | 2 +- .../modules/bookings/components/Header.tsx | 2 +- .../bookings/components/LargeCalendar.tsx | 4 +- .../OverlayCalendar/OverlayCalendar.tsx | 4 +- .../components/event-meta/Occurences.tsx | 2 +- .../modules/bookings}/hooks/useBookings.ts | 4 +- .../modules/bookings}/hooks/useCalendars.ts | 13 +-- .../bookings}/hooks/useDecoyBooking.ts | 0 .../bookings}/hooks/useInitializeWeekStart.ts | 11 +-- ...eIsQuickAvailabilityCheckFeatureEnabled.ts | 3 +- .../bookings}/hooks/useOverlayCalendar.ts | 13 ++- .../bookings}/hooks/useSkipConfirmStep.ts | 16 ++-- .../web/modules/bookings}/hooks/useSlots.ts | 7 +- .../modules/bookings}/hooks/useVerifyCode.ts | 0 .../modules/bookings}/hooks/useVerifyEmail.ts | 0 apps/web/modules/bookings/types.ts | 92 +++++++++++++++++++ .../components/LargeCalendar.tsx | 2 +- apps/web/modules/embed/components/Embed.tsx | 2 +- .../components/LargeCalendar.tsx | 2 +- .../embeds/embed-core/src/embed-iframe.ts | 2 +- .../src/embed-iframe/react-hooks.ts | 12 +++ .../hooks/useSlotsViewOnSmallScreen.ts | 13 --- .../hooks/useAvailableTimeSlots.ts | 2 +- .../{components => }/hooks/useBookerLayout.ts | 41 +++------ .../{components => }/hooks/useBookerTime.ts | 10 +- .../{components => }/hooks/useBookingForm.ts | 2 +- .../hooks/useInitialFormValues.test.ts | 2 +- .../hooks/useInitialFormValues.ts | 12 +-- .../{components => }/hooks/useLocalSet.tsx | 2 +- packages/features/bookings/Booker/types.ts | 87 ++---------------- .../features/bookings/Booker/utils/event.ts | 2 +- .../Booker/utils/isTimeslotAvailable.test.ts | 2 +- .../Booker/utils/isTimeslotAvailable.ts | 2 +- .../calendars/components/DatePicker.tsx | 2 +- .../atoms/booker/BookerPlatformWrapper.tsx | 6 +- .../EventTypeCalendarViewComponent.tsx | 4 +- .../hooks/bookings/useHandleBookEvent.ts | 4 +- 46 files changed, 214 insertions(+), 214 deletions(-) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useBookings.ts (98%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useCalendars.ts (88%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useDecoyBooking.ts (100%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useInitializeWeekStart.ts (70%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts (82%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useOverlayCalendar.ts (90%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useSkipConfirmStep.ts (87%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useSlots.ts (96%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useVerifyCode.ts (100%) rename {packages/features/bookings/Booker/components => apps/web/modules/bookings}/hooks/useVerifyEmail.ts (100%) delete mode 100644 packages/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen.ts rename packages/features/bookings/Booker/{components => }/hooks/useAvailableTimeSlots.ts (99%) rename packages/features/bookings/Booker/{components => }/hooks/useBookerLayout.ts (78%) rename packages/features/bookings/Booker/{components => }/hooks/useBookerTime.ts (77%) rename packages/features/bookings/Booker/{components => }/hooks/useBookingForm.ts (99%) rename packages/features/bookings/Booker/{components => }/hooks/useInitialFormValues.test.ts (99%) rename packages/features/bookings/Booker/{components => }/hooks/useInitialFormValues.ts (97%) rename packages/features/bookings/Booker/{components => }/hooks/useLocalSet.tsx (99%) diff --git a/apps/web/app/(booking-page-wrapper)/booking-successful/[uid]/page.tsx b/apps/web/app/(booking-page-wrapper)/booking-successful/[uid]/page.tsx index 881c585103..36d5e3a342 100644 --- a/apps/web/app/(booking-page-wrapper)/booking-successful/[uid]/page.tsx +++ b/apps/web/app/(booking-page-wrapper)/booking-successful/[uid]/page.tsx @@ -4,7 +4,7 @@ import { useParams } from "next/navigation"; import dayjs from "@calcom/dayjs"; import { DecoyBookingSuccessCard } from "~/bookings/components/DecoyBookingSuccessCard"; -import { useDecoyBooking } from "@calcom/features/bookings/Booker/components/hooks/useDecoyBooking"; +import { useDecoyBooking } from "~/bookings/hooks/useDecoyBooking"; export default function BookingSuccessful() { const params = useParams(); diff --git a/apps/web/modules/bookings/components/AvailableTimeSlots.tsx b/apps/web/modules/bookings/components/AvailableTimeSlots.tsx index 8bbb13b4cb..dec0b6c91d 100644 --- a/apps/web/modules/bookings/components/AvailableTimeSlots.tsx +++ b/apps/web/modules/bookings/components/AvailableTimeSlots.tsx @@ -6,7 +6,7 @@ import { AvailableTimesSkeleton, } from "@calcom/web/modules/bookings/components/AvailableTimes"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; +import type { IUseBookingLoadingStates } from "../hooks/useBookings"; import type { BookerEvent } from "@calcom/features/bookings/types"; import type { Slot } from "@calcom/features/schedules/lib/use-schedule/types"; import { useNonEmptyScheduleDays } from "@calcom/features/schedules/lib/use-schedule/useNonEmptyScheduleDays"; diff --git a/apps/web/modules/bookings/components/AvailableTimes.tsx b/apps/web/modules/bookings/components/AvailableTimes.tsx index 6fb16177db..87f5745385 100644 --- a/apps/web/modules/bookings/components/AvailableTimes.tsx +++ b/apps/web/modules/bookings/components/AvailableTimes.tsx @@ -9,7 +9,7 @@ import dayjs from "@calcom/dayjs"; import type { IOutOfOfficeData } from "@calcom/features/availability/lib/getUserAvailability"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; import { OutOfOfficeInSlots } from "./OutOfOfficeInSlots"; -import type { IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; +import type { IUseBookingLoadingStates } from "../hooks/useBookings"; import type { BookerEvent } from "@calcom/features/bookings/types"; import type { Slot } from "@calcom/features/schedules/lib/use-schedule/types"; import { useLocale } from "@calcom/lib/hooks/useLocale"; @@ -19,7 +19,7 @@ import { Button } from "@calcom/ui/components/button"; import { Icon } from "@calcom/ui/components/icon"; import { SkeletonText } from "@calcom/ui/components/skeleton"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param"; import { useCheckOverlapWithOverlay } from "@calcom/features/bookings/lib/useCheckOverlapWithOverlay"; import type { Slots } from "@calcom/features/bookings/types"; diff --git a/apps/web/modules/bookings/components/BookEventForm/BookEventForm.tsx b/apps/web/modules/bookings/components/BookEventForm/BookEventForm.tsx index 8a6c3b95df..82ecb7beed 100644 --- a/apps/web/modules/bookings/components/BookEventForm/BookEventForm.tsx +++ b/apps/web/modules/bookings/components/BookEventForm/BookEventForm.tsx @@ -18,9 +18,9 @@ import { EmptyScreen } from "@calcom/ui/components/empty-screen"; import { Form } from "@calcom/ui/components/form"; import { formatEventFromTime } from "@calcom/features/bookings/Booker/utils/dates"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; -import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; -import type { IUseBookingErrors, IUseBookingLoadingStates } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; +import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; +import type { IUseBookingErrors, IUseBookingLoadingStates } from "../../hooks/useBookings"; import { BookingFields } from "./BookingFields"; import { FormSkeleton } from "./Skeleton"; diff --git a/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx b/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx index 4c1c565de0..5758360a47 100644 --- a/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx +++ b/apps/web/modules/bookings/components/BookEventForm/BookFormAsModal.tsx @@ -12,7 +12,7 @@ import { DialogContent } from "@calcom/ui/components/dialog"; import { getDurationFormatted } from "../event-meta/Duration"; import { FromTime } from "@calcom/features/bookings/Booker/utils/dates"; import { useEvent } from "@calcom/features/bookings/Booker/utils/event"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; const BookEventFormWrapper = ({ children, onCancel }: { onCancel: () => void; children: ReactNode }) => { const { data } = useEvent(); diff --git a/apps/web/modules/bookings/components/Booker.test.tsx b/apps/web/modules/bookings/components/Booker.test.tsx index 956944c31e..478b2938c9 100644 --- a/apps/web/modules/bookings/components/Booker.test.tsx +++ b/apps/web/modules/bookings/components/Booker.test.tsx @@ -35,7 +35,8 @@ import "@calcom/dayjs/__mocks__"; import "@calcom/web/modules/auth/components/Turnstile"; import { render, screen } from "@calcom/features/bookings/Booker/__tests__/test-utils"; -import type { BookerProps, WrappedBookerProps } from "@calcom/features/bookings/Booker/types"; +import type { BookerProps } from "@calcom/features/bookings/Booker/types"; +import type { WrappedBookerProps } from "../types"; import { Booker } from "./Booker"; vi.mock("framer-motion", async (importOriginal) => { diff --git a/apps/web/modules/bookings/components/Booker.tsx b/apps/web/modules/bookings/components/Booker.tsx index 541d377766..4900c067c9 100644 --- a/apps/web/modules/bookings/components/Booker.tsx +++ b/apps/web/modules/bookings/components/Booker.tsx @@ -6,15 +6,16 @@ import { useEmbedUiConfig } from "@calcom/embed-core/embed-iframe"; import { updateEmbedBookerState } from "@calcom/embed-core/src/embed-iframe"; import TurnstileCaptcha from "@calcom/web/modules/auth/components/Turnstile"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useIsQuickAvailabilityCheckFeatureEnabled } from "@calcom/features/bookings/Booker/components/hooks/useIsQuickAvailabilityCheckFeatureEnabled"; -import useSkipConfirmStep from "@calcom/features/bookings/Booker/components/hooks/useSkipConfirmStep"; +import { useIsQuickAvailabilityCheckFeatureEnabled } from "../hooks/useIsQuickAvailabilityCheckFeatureEnabled"; +import { useSkipConfirmStep } from "@calcom/web/modules/bookings/hooks/useSkipConfirmStep"; import { fadeInLeft, getBookerSizeClassNames, useBookerResizeAnimation, } from "@calcom/features/bookings/Booker/config"; import framerFeatures from "@calcom/features/bookings/Booker/framer-features"; -import type { BookerProps, WrappedBookerProps } from "@calcom/features/bookings/Booker/types"; +import type { BookerProps } from "@calcom/features/bookings/Booker/types"; +import type { WrappedBookerProps } from "../types"; import { isBookingDryRun } from "@calcom/features/bookings/Booker/utils/isBookingDryRun"; import { isTimeSlotAvailable } from "@calcom/features/bookings/Booker/utils/isTimeslotAvailable"; import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param"; diff --git a/apps/web/modules/bookings/components/BookerWebWrapper.tsx b/apps/web/modules/bookings/components/BookerWebWrapper.tsx index 4562ec11f2..a7718987d5 100644 --- a/apps/web/modules/bookings/components/BookerWebWrapper.tsx +++ b/apps/web/modules/bookings/components/BookerWebWrapper.tsx @@ -8,13 +8,13 @@ import { useBookerStoreContext, useInitializeBookerStoreContext, } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useBookerLayout } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout"; -import { useBookingForm } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; -import { useBookings } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; -import { useCalendars } from "@calcom/features/bookings/Booker/components/hooks/useCalendars"; -import { useSlots } from "@calcom/features/bookings/Booker/components/hooks/useSlots"; -import { useVerifyCode } from "@calcom/features/bookings/Booker/components/hooks/useVerifyCode"; -import { useVerifyEmail } from "@calcom/features/bookings/Booker/components/hooks/useVerifyEmail"; +import { useBookerLayout } from "@calcom/features/bookings/Booker/hooks/useBookerLayout"; +import { useBookingForm } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; +import { useBookings } from "../hooks/useBookings"; +import { useCalendars } from "../hooks/useCalendars"; +import { useSlots } from "../hooks/useSlots"; +import { useVerifyCode } from "../hooks/useVerifyCode"; +import { useVerifyEmail } from "../hooks/useVerifyEmail"; import { useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; import { useEvent, useScheduleForEvent } from "@calcom/features/bookings/Booker/utils/event"; import { useBrandColors } from "@calcom/features/bookings/Booker/utils/use-brand-colors"; diff --git a/apps/web/modules/bookings/components/DatePicker.tsx b/apps/web/modules/bookings/components/DatePicker.tsx index 3b67e75348..8d49835b51 100644 --- a/apps/web/modules/bookings/components/DatePicker.tsx +++ b/apps/web/modules/bookings/components/DatePicker.tsx @@ -10,7 +10,7 @@ import { weekdayToWeekIndex } from "@calcom/lib/dayjs"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import type { User } from "@calcom/prisma/client"; import type { PeriodData } from "@calcom/types/Event"; -import { useSlotsViewOnSmallScreen } from "@calcom/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen"; +import { useSlotsViewOnSmallScreen } from "@calcom/embed-core/embed-iframe"; import type { Slots } from "@calcom/features/bookings/types"; diff --git a/apps/web/modules/bookings/components/EventMeta.tsx b/apps/web/modules/bookings/components/EventMeta.tsx index bc76016408..9fca96d38d 100644 --- a/apps/web/modules/bookings/components/EventMeta.tsx +++ b/apps/web/modules/bookings/components/EventMeta.tsx @@ -1,6 +1,6 @@ import { Timezone as PlatformTimezoneSelect } from "@calcom/atoms/timezone"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; import { fadeInUp } from "@calcom/features/bookings/Booker/config"; import type { Timezone } from "@calcom/features/bookings/Booker/types"; import { FromToTime } from "@calcom/features/bookings/Booker/utils/dates"; diff --git a/apps/web/modules/bookings/components/Header.tsx b/apps/web/modules/bookings/components/Header.tsx index 166c417900..e544fff1d5 100644 --- a/apps/web/modules/bookings/components/Header.tsx +++ b/apps/web/modules/bookings/components/Header.tsx @@ -5,7 +5,7 @@ import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; import dayjs from "@calcom/dayjs"; import { useIsEmbed } from "@calcom/embed-core/embed-iframe"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useInitializeWeekStart } from "@calcom/features/bookings/Booker/components/hooks/useInitializeWeekStart"; +import { useInitializeWeekStart } from "@calcom/web/modules/bookings/hooks/useInitializeWeekStart"; import { WEBAPP_URL } from "@calcom/lib/constants"; import { formatDateTime } from "@calcom/lib/dateTimeFormatter"; import { useLocale } from "@calcom/lib/hooks/useLocale"; diff --git a/apps/web/modules/bookings/components/LargeCalendar.tsx b/apps/web/modules/bookings/components/LargeCalendar.tsx index 0e2b07aa08..26ae9e9e3b 100644 --- a/apps/web/modules/bookings/components/LargeCalendar.tsx +++ b/apps/web/modules/bookings/components/LargeCalendar.tsx @@ -2,8 +2,8 @@ import { useMemo, useEffect } from "react"; import dayjs from "@calcom/dayjs"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/components/hooks/useAvailableTimeSlots"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/hooks/useAvailableTimeSlots"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; import type { BookerEvent } from "@calcom/features/bookings/types"; import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar"; import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events"; diff --git a/apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendar.tsx b/apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendar.tsx index 7fd9ed27dc..6f62658ad5 100644 --- a/apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendar.tsx +++ b/apps/web/modules/bookings/components/OverlayCalendar/OverlayCalendar.tsx @@ -1,6 +1,6 @@ import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; -import { useOverlayCalendar } from "@calcom/features/bookings/Booker/components/hooks/useOverlayCalendar"; -import type { WrappedBookerPropsMain } from "@calcom/features/bookings/Booker/types"; +import { useOverlayCalendar } from "@calcom/web/modules/bookings/hooks/useOverlayCalendar"; +import type { WrappedBookerPropsMain } from "../../types"; import { useEffect } from "react"; import { OverlayCalendarContinueModal } from "./OverlayCalendarContinueModal"; import { OverlayCalendarSettingsModal } from "./OverlayCalendarSettingsModal"; diff --git a/apps/web/modules/bookings/components/event-meta/Occurences.tsx b/apps/web/modules/bookings/components/event-meta/Occurences.tsx index fb0706cfee..0a2b771da6 100644 --- a/apps/web/modules/bookings/components/event-meta/Occurences.tsx +++ b/apps/web/modules/bookings/components/event-meta/Occurences.tsx @@ -11,7 +11,7 @@ import { Badge } from "@calcom/ui/components/badge"; import { Input } from "@calcom/ui/components/form"; import { Tooltip } from "@calcom/ui/components/tooltip"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; export const EventOccurences = ({ event }: { event: Pick }) => { const maxOccurences = event.recurringEvent?.count || null; diff --git a/packages/features/bookings/Booker/components/hooks/useBookings.ts b/apps/web/modules/bookings/hooks/useBookings.ts similarity index 98% rename from packages/features/bookings/Booker/components/hooks/useBookings.ts rename to apps/web/modules/bookings/hooks/useBookings.ts index 1f88fbc407..c87ba5949d 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookings.ts +++ b/apps/web/modules/bookings/hooks/useBookings.ts @@ -26,8 +26,8 @@ import { bookingMetadataSchema } from "@calcom/prisma/zod-utils"; import { trpc } from "@calcom/trpc/react"; import { showToast } from "@calcom/ui/components/toast"; -import { useBookingSuccessRedirect } from "../../../lib/bookingSuccessRedirect"; -import type { UseBookingFormReturnType } from "./useBookingForm"; +import { useBookingSuccessRedirect } from "@calcom/features/bookings/lib/bookingSuccessRedirect"; +import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; export interface IUseBookings { event: { diff --git a/packages/features/bookings/Booker/components/hooks/useCalendars.ts b/apps/web/modules/bookings/hooks/useCalendars.ts similarity index 88% rename from packages/features/bookings/Booker/components/hooks/useCalendars.ts rename to apps/web/modules/bookings/hooks/useCalendars.ts index 7f1e26119a..9bed978b3b 100644 --- a/packages/features/bookings/Booker/components/hooks/useCalendars.ts +++ b/apps/web/modules/bookings/hooks/useCalendars.ts @@ -1,12 +1,13 @@ -import { useTimePreferences } from "@calcom/features/bookings/lib"; -import { localStorage } from "@calcom/lib/webstorage"; -import { trpc } from "@calcom/trpc/react"; import { useSearchParams } from "next/navigation"; import { useEffect, useState } from "react"; import { shallow } from "zustand/shallow"; -import { useBookerStore } from "../../store"; -import type { ToggledConnectedCalendars } from "../../types"; -import { useOverlayCalendarStore } from "../OverlayCalendar/store"; + +import { useOverlayCalendarStore } from "@calcom/features/bookings/Booker/components/OverlayCalendar/store"; +import { useBookerStore } from "@calcom/features/bookings/Booker/store"; +import type { ToggledConnectedCalendars } from "@calcom/features/bookings/Booker/types"; +import { useTimePreferences } from "@calcom/features/bookings/lib"; +import { localStorage } from "@calcom/lib/webstorage"; +import { trpc } from "@calcom/trpc/react"; type UseCalendarsProps = { hasSession: boolean; diff --git a/packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts b/apps/web/modules/bookings/hooks/useDecoyBooking.ts similarity index 100% rename from packages/features/bookings/Booker/components/hooks/useDecoyBooking.ts rename to apps/web/modules/bookings/hooks/useDecoyBooking.ts diff --git a/packages/features/bookings/Booker/components/hooks/useInitializeWeekStart.ts b/apps/web/modules/bookings/hooks/useInitializeWeekStart.ts similarity index 70% rename from packages/features/bookings/Booker/components/hooks/useInitializeWeekStart.ts rename to apps/web/modules/bookings/hooks/useInitializeWeekStart.ts index d96b6f5d5f..6379ecc319 100644 --- a/packages/features/bookings/Booker/components/hooks/useInitializeWeekStart.ts +++ b/apps/web/modules/bookings/hooks/useInitializeWeekStart.ts @@ -1,19 +1,14 @@ import { useEffect } from "react"; import dayjs from "@calcom/dayjs"; +import { useSlotsViewOnSmallScreen } from "@calcom/embed-core/embed-iframe"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useSlotsViewOnSmallScreen } from "@calcom/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen"; -export const useInitializeWeekStart = ( - isPlatform: boolean, - isCalendarView: boolean -) => { +export const useInitializeWeekStart = (isPlatform: boolean, isCalendarView: boolean) => { const slotsViewOnSmallScreen = useSlotsViewOnSmallScreen(); const today = dayjs(); const weekStart = today.startOf("week").format("YYYY-MM-DD"); - const setSelectedDate = useBookerStoreContext( - (state) => state.setSelectedDate - ); + const setSelectedDate = useBookerStoreContext((state) => state.setSelectedDate); useEffect(() => { // don't auto-select date if slots view on small screen is enabled diff --git a/packages/features/bookings/Booker/components/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts b/apps/web/modules/bookings/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts similarity index 82% rename from packages/features/bookings/Booker/components/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts rename to apps/web/modules/bookings/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts index 7f52c9cf2f..2c25cb5cdc 100644 --- a/packages/features/bookings/Booker/components/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts +++ b/apps/web/modules/bookings/hooks/useIsQuickAvailabilityCheckFeatureEnabled.ts @@ -1,9 +1,8 @@ import { useEffect, useRef } from "react"; +import { isVisitorWithinPercentage } from "@calcom/features/bookings/Booker/utils/isFeatureEnabledForVisitor"; import { PUBLIC_QUICK_AVAILABILITY_ROLLOUT } from "@calcom/lib/constants"; -import { isVisitorWithinPercentage } from "../../utils/isFeatureEnabledForVisitor"; - export const useIsQuickAvailabilityCheckFeatureEnabled = () => { const isQuickAvailabilityCheckFeatureEnabledRef = useRef( isVisitorWithinPercentage({ percentage: PUBLIC_QUICK_AVAILABILITY_ROLLOUT }) diff --git a/packages/features/bookings/Booker/components/hooks/useOverlayCalendar.ts b/apps/web/modules/bookings/hooks/useOverlayCalendar.ts similarity index 90% rename from packages/features/bookings/Booker/components/hooks/useOverlayCalendar.ts rename to apps/web/modules/bookings/hooks/useOverlayCalendar.ts index 364f76eab1..e259660ce4 100644 --- a/packages/features/bookings/Booker/components/hooks/useOverlayCalendar.ts +++ b/apps/web/modules/bookings/hooks/useOverlayCalendar.ts @@ -1,10 +1,13 @@ -import dayjs from "@calcom/dayjs"; -import { useTimePreferences } from "@calcom/features/bookings/lib"; import { useEffect, useState } from "react"; import { shallow } from "zustand/shallow"; -import type { ToggledConnectedCalendars, WrappedBookerPropsMain } from "../../types"; -import { useOverlayCalendarStore } from "../OverlayCalendar/store"; -import { useLocalSet } from "./useLocalSet"; + +import dayjs from "@calcom/dayjs"; +import { useOverlayCalendarStore } from "@calcom/features/bookings/Booker/components/OverlayCalendar/store"; +import type { ToggledConnectedCalendars } from "@calcom/features/bookings/Booker/types"; +import { useTimePreferences } from "@calcom/features/bookings/lib"; + +import type { WrappedBookerPropsMain } from "../types"; +import { useLocalSet } from "@calcom/features/bookings/Booker/hooks/useLocalSet"; export const useOverlayCalendar = ({ connectedCalendars, diff --git a/packages/features/bookings/Booker/components/hooks/useSkipConfirmStep.ts b/apps/web/modules/bookings/hooks/useSkipConfirmStep.ts similarity index 87% rename from packages/features/bookings/Booker/components/hooks/useSkipConfirmStep.ts rename to apps/web/modules/bookings/hooks/useSkipConfirmStep.ts index 4535a903ed..a5abbd2fb6 100644 --- a/packages/features/bookings/Booker/components/hooks/useSkipConfirmStep.ts +++ b/apps/web/modules/bookings/hooks/useSkipConfirmStep.ts @@ -1,11 +1,13 @@ -import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; -import { useBookerStore } from "@calcom/features/bookings/Booker/store"; -import { getBookingResponsesSchemaWithOptionalChecks } from "@calcom/features/bookings/lib/getBookingResponsesSchema"; import { useEffect, useState } from "react"; -import type { BookerEvent } from "../../../types"; -import type { BookerState } from "../../types"; -const useSkipConfirmStep = ( +import { useBookerStore } from "@calcom/features/bookings/Booker/store"; +import type { BookerState } from "@calcom/features/bookings/Booker/types"; +import { getBookingResponsesSchemaWithOptionalChecks } from "@calcom/features/bookings/lib/getBookingResponsesSchema"; +import type { BookerEvent } from "@calcom/features/bookings/types"; + +import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; + +export const useSkipConfirmStep = ( bookingForm: UseBookingFormReturnType["bookingForm"], bookerState: BookerState, isInstantMeeting: boolean, @@ -45,5 +47,3 @@ const useSkipConfirmStep = ( return canSkip; }; - -export default useSkipConfirmStep; diff --git a/packages/features/bookings/Booker/components/hooks/useSlots.ts b/apps/web/modules/bookings/hooks/useSlots.ts similarity index 96% rename from packages/features/bookings/Booker/components/hooks/useSlots.ts rename to apps/web/modules/bookings/hooks/useSlots.ts index a246d8c856..b6ba21a52b 100644 --- a/packages/features/bookings/Booker/components/hooks/useSlots.ts +++ b/apps/web/modules/bookings/hooks/useSlots.ts @@ -12,12 +12,9 @@ import { } from "@calcom/lib/constants"; import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { trpc } from "@calcom/trpc/react"; -import type { TIsAvailableOutputSchema } from "@calcom/trpc/server/routers/viewer/slots/isAvailable.schema"; - +import type { QuickAvailabilityCheck } from "@calcom/features/bookings/Booker/types"; import { useIsQuickAvailabilityCheckFeatureEnabled } from "./useIsQuickAvailabilityCheckFeatureEnabled"; -export type QuickAvailabilityCheck = TIsAvailableOutputSchema["slots"][number]; - const useQuickAvailabilityChecks = ({ eventTypeId, eventDuration, @@ -51,7 +48,7 @@ const useQuickAvailabilityChecks = ({ { slots: slotsToCheck, // enabled flag can't be true if eventTypeId is nullish - + eventTypeId: eventTypeId!, }, { diff --git a/packages/features/bookings/Booker/components/hooks/useVerifyCode.ts b/apps/web/modules/bookings/hooks/useVerifyCode.ts similarity index 100% rename from packages/features/bookings/Booker/components/hooks/useVerifyCode.ts rename to apps/web/modules/bookings/hooks/useVerifyCode.ts diff --git a/packages/features/bookings/Booker/components/hooks/useVerifyEmail.ts b/apps/web/modules/bookings/hooks/useVerifyEmail.ts similarity index 100% rename from packages/features/bookings/Booker/components/hooks/useVerifyEmail.ts rename to apps/web/modules/bookings/hooks/useVerifyEmail.ts diff --git a/apps/web/modules/bookings/types.ts b/apps/web/modules/bookings/types.ts index 7e5be0e0ba..07ebe90537 100644 --- a/apps/web/modules/bookings/types.ts +++ b/apps/web/modules/bookings/types.ts @@ -1,7 +1,17 @@ import type { DataTableRow } from "@calcom/features/data-table/lib/separator"; import type { RouterOutputs } from "@calcom/trpc/react"; +import type { BookerEventQuery } from "@calcom/features/bookings/types"; +import type { useScheduleForEventReturnType } from "@calcom/features/bookings/Booker/utils/event"; +import type { ToggledConnectedCalendars, CustomClassNames } from "@calcom/features/bookings/Booker/types"; +import type { EventBusyDate } from "@calcom/types/Calendar"; import type { validStatuses } from "./lib/validStatuses"; +import type { UseBookerLayoutType } from "@calcom/features/bookings/Booker/hooks/useBookerLayout"; +import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; +import type { UseBookingsReturnType } from "./hooks/useBookings"; +import type { UseSlotsReturnType } from "./hooks/useSlots"; +import type { UseVerifyCodeReturnType } from "./hooks/useVerifyCode"; +import type { UseVerifyEmailReturnType } from "./hooks/useVerifyEmail"; export type BookingsGetOutput = RouterOutputs["viewer"]["bookings"]["get"]; @@ -26,3 +36,85 @@ export type BookingRowData = { export type RowData = DataTableRow; export type BookingListingStatus = (typeof validStatuses)[number]; + +export type { UseBookerLayoutType } from "@calcom/features/bookings/Booker/hooks/useBookerLayout"; +export type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; +export type { UseBookingsReturnType } from "./hooks/useBookings"; +export type { UseSlotsReturnType } from "./hooks/useSlots"; +export type { UseVerifyCodeReturnType } from "./hooks/useVerifyCode"; +export type { UseVerifyEmailReturnType } from "./hooks/useVerifyEmail"; + +export type WrappedBookerPropsMain = { + sessionUsername?: string | null; + rescheduleUid: string | null; + rescheduledBy: string | null; + bookingUid: string | null; + isRedirect: boolean; + fromUserNameRedirected: string; + hasSession: boolean; + onGoBackInstantMeeting: () => void; + onConnectNowInstantMeeting: () => void; + onOverlayClickNoCalendar: () => void; + onClickOverlayContinue: () => void; + onOverlaySwitchStateChange: (state: boolean) => void; + extraOptions: Record; + bookings: UseBookingsReturnType; + slots: UseSlotsReturnType; + calendars: { + overlayBusyDates?: EventBusyDate[]; + isOverlayCalendarEnabled: boolean; + connectedCalendars: { + calendars?: { + name?: string; + integrationTitle?: string; + externalId: string; + primary: boolean | null; + }[]; + credentialId: number; + delegationCredentialId?: string | null; + cacheUpdatedAt: null; + error?: { + message: string | null; + }; + primary?: { + email?: string; + }; + integration: { + slug: string; + name?: string | undefined; + title?: string; + logo: string; + }; + }[]; + loadingConnectedCalendar: boolean; + onToggleCalendar: (calendarsToLoad: Set) => void; + }; + bookerForm: UseBookingFormReturnType; + event: BookerEventQuery; + schedule: useScheduleForEventReturnType; + bookerLayout: UseBookerLayoutType; + verifyEmail: UseVerifyEmailReturnType; + customClassNames?: CustomClassNames; + isBookingDryRun?: boolean; + renderCaptcha?: boolean; + confirmButtonDisabled?: boolean; +}; + +export type WrappedBookerPropsForPlatform = WrappedBookerPropsMain & { + isPlatform: true; + verifyCode: undefined; + customClassNames?: CustomClassNames; + timeZones?: import("@calcom/features/bookings/Booker/types").Timezone[]; + roundRobinHideOrgAndTeam?: boolean; + hideOrgTeamAvatar?: boolean; +}; + +export type WrappedBookerPropsForWeb = WrappedBookerPropsMain & { + isPlatform: false; + verifyCode: UseVerifyCodeReturnType; + timeZones?: import("@calcom/features/bookings/Booker/types").Timezone[]; + roundRobinHideOrgAndTeam?: boolean; + hideOrgTeamAvatar?: boolean; +}; + +export type WrappedBookerProps = WrappedBookerPropsForPlatform | WrappedBookerPropsForWeb; diff --git a/apps/web/modules/calendar-view/components/LargeCalendar.tsx b/apps/web/modules/calendar-view/components/LargeCalendar.tsx index 664b555cd4..8616f20158 100644 --- a/apps/web/modules/calendar-view/components/LargeCalendar.tsx +++ b/apps/web/modules/calendar-view/components/LargeCalendar.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo } from "react"; import dayjs from "@calcom/dayjs"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; import type { BookerEvent } from "@calcom/features/bookings/types"; import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar"; import type { CalendarAvailableTimeslots } from "@calcom/features/calendars/weeklyview/types/state"; diff --git a/apps/web/modules/embed/components/Embed.tsx b/apps/web/modules/embed/components/Embed.tsx index 6054960a14..c0a02e8b83 100644 --- a/apps/web/modules/embed/components/Embed.tsx +++ b/apps/web/modules/embed/components/Embed.tsx @@ -53,7 +53,7 @@ import { Icon } from "@calcom/ui/components/icon"; import { HorizontalTabs } from "@calcom/ui/components/navigation"; import { showToast } from "@calcom/ui/components/toast"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; import { EmbedTabName, type tabs } from "./EmbedTabs"; import { buildCssVarsPerTheme } from "@calcom/features/embed/lib/buildCssVarsPerTheme"; import { EmbedTheme } from "@calcom/features/embed/lib/constants"; diff --git a/apps/web/modules/troubleshooter/components/LargeCalendar.tsx b/apps/web/modules/troubleshooter/components/LargeCalendar.tsx index ded1a09816..8e2253f701 100644 --- a/apps/web/modules/troubleshooter/components/LargeCalendar.tsx +++ b/apps/web/modules/troubleshooter/components/LargeCalendar.tsx @@ -1,5 +1,5 @@ import dayjs from "@calcom/dayjs"; -import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/components/hooks/useAvailableTimeSlots"; +import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/hooks/useAvailableTimeSlots"; import { useTimePreferences } from "@calcom/features/bookings/lib/timePreferences"; import { useSchedule } from "@calcom/features/schedules/lib/use-schedule/useSchedule"; import { useTroubleshooterStore } from "@calcom/features/troubleshooter/store"; diff --git a/packages/embeds/embed-core/src/embed-iframe.ts b/packages/embeds/embed-core/src/embed-iframe.ts index 43748ded6c..94d3675d18 100644 --- a/packages/embeds/embed-core/src/embed-iframe.ts +++ b/packages/embeds/embed-core/src/embed-iframe.ts @@ -33,7 +33,7 @@ import type { setNonStylesConfig, } from "./types"; import { useCompatSearchParams } from "./useCompatSearchParams"; -export { useBookerEmbedEvents } from "./embed-iframe/react-hooks"; +export { useBookerEmbedEvents, useSlotsViewOnSmallScreen } from "./embed-iframe/react-hooks"; // We don't import it from Booker/types because the types from this module are published to npm and we can't import packages that aren't published type BookerState = "loading" | "selecting_date" | "selecting_time" | "booking"; diff --git a/packages/embeds/embed-core/src/embed-iframe/react-hooks.ts b/packages/embeds/embed-core/src/embed-iframe/react-hooks.ts index 7c40c9d668..ff74182f0f 100644 --- a/packages/embeds/embed-core/src/embed-iframe/react-hooks.ts +++ b/packages/embeds/embed-core/src/embed-iframe/react-hooks.ts @@ -3,7 +3,9 @@ * All hooks defined in this file must be client side hooks and must not be executed in server side. * So, they should start with isBrowser check. */ +import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; import { sdkActionManager } from "../sdk-event"; +import { useEmbedUiConfig, useIsEmbed } from "../embed-iframe"; import { embedStore, getEventHasFired, setEventHasFired, getReloadInitiated, setReloadInitiated } from "./lib/embedStore"; import { isBrowser, isPrerendering } from "./lib/utils"; @@ -114,3 +116,13 @@ export const useBookerEmbedEvents = ({ } }; +export const useSlotsViewOnSmallScreen = () => { + const isEmbed = useIsEmbed(); + const isMobile = useMediaQuery("(max-width: 768px)"); + + const embedUiConfig = useEmbedUiConfig(); + + if (!isBrowser || !isEmbed || !isMobile) return false; + + return embedUiConfig.useSlotsViewOnSmallScreen ?? false; +}; diff --git a/packages/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen.ts b/packages/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen.ts deleted file mode 100644 index dbfea3b1bb..0000000000 --- a/packages/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useIsEmbed, useEmbedUiConfig } from "@calcom/embed-core/embed-iframe"; -import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; - -export const useSlotsViewOnSmallScreen = () => { - const isEmbed = useIsEmbed(); - const isMobile = useMediaQuery("(max-width: 768px)"); - - const embedUiConfig = useEmbedUiConfig(); - - if (!isEmbed || !isMobile) return false; - - return embedUiConfig.useSlotsViewOnSmallScreen ?? false; -}; diff --git a/packages/features/bookings/Booker/components/hooks/useAvailableTimeSlots.ts b/packages/features/bookings/Booker/hooks/useAvailableTimeSlots.ts similarity index 99% rename from packages/features/bookings/Booker/components/hooks/useAvailableTimeSlots.ts rename to packages/features/bookings/Booker/hooks/useAvailableTimeSlots.ts index b88856c06b..4df8f84562 100644 --- a/packages/features/bookings/Booker/components/hooks/useAvailableTimeSlots.ts +++ b/packages/features/bookings/Booker/hooks/useAvailableTimeSlots.ts @@ -27,4 +27,4 @@ export const useAvailableTimeSlots = ({ schedule, eventDuration }: UseAvailableT return availableTimeslots; }, [schedule, eventDuration]); -}; +}; \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useBookerLayout.ts b/packages/features/bookings/Booker/hooks/useBookerLayout.ts similarity index 78% rename from packages/features/bookings/Booker/components/hooks/useBookerLayout.ts rename to packages/features/bookings/Booker/hooks/useBookerLayout.ts index 3740dde433..ec5d345cd2 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookerLayout.ts +++ b/packages/features/bookings/Booker/hooks/useBookerLayout.ts @@ -5,45 +5,32 @@ import { useEmbedType, useEmbedUiConfig, useIsEmbed, + useSlotsViewOnSmallScreen, } from "@calcom/embed-core/embed-iframe"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; +import { extraDaysConfig } from "@calcom/features/bookings/Booker/config"; +import type { BookerLayout } from "@calcom/features/bookings/Booker/types"; +import { validateLayout } from "@calcom/features/bookings/Booker/utils/layout"; +import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param"; import type { BookerEvent } from "@calcom/features/bookings/types"; import useMediaQuery from "@calcom/lib/hooks/useMediaQuery"; import type { BookerLayouts } from "@calcom/prisma/zod-utils"; import { defaultBookerLayoutSettings } from "@calcom/prisma/zod-utils"; -import { useSlotsViewOnSmallScreen } from "@calcom/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen"; - -import { extraDaysConfig } from "../../config"; -import type { BookerLayout } from "../../types"; -import { validateLayout } from "../../utils/layout"; -import { getQueryParam } from "../../utils/query-param"; export type UseBookerLayoutType = ReturnType; export const useBookerLayout = ( - profileBookerLayouts: - | BookerEvent["profile"]["bookerLayouts"] - | undefined - | null + profileBookerLayouts: BookerEvent["profile"]["bookerLayouts"] | undefined | null ) => { - const [_layout, setLayout] = useBookerStoreContext( - (state) => [state.layout, state.setLayout], - shallow - ); + const [_layout, setLayout] = useBookerStoreContext((state) => [state.layout, state.setLayout], shallow); const isEmbed = useIsEmbed(); const isMobile = useMediaQuery("(max-width: 768px)"); const isTablet = useMediaQuery("(max-width: 1024px)"); const embedUiConfig = useEmbedUiConfig(); // In Embed we give preference to embed configuration for the layout.If that's not set, we use the App configuration for the event layout // But if it's mobile view, there is only one layout supported which is 'mobile' - const layout = isEmbed - ? isMobile - ? "mobile" - : validateLayout(embedUiConfig.layout) || _layout - : _layout; - const extraDays = isTablet - ? extraDaysConfig[layout].tablet - : extraDaysConfig[layout].desktop; + const layout = isEmbed ? (isMobile ? "mobile" : validateLayout(embedUiConfig.layout) || _layout) : _layout; + const extraDays = isTablet ? extraDaysConfig[layout].tablet : extraDaysConfig[layout].desktop; const embedType = useEmbedType(); // Floating Button and Element Click both are modal and thus have dark background const hasDarkBackground = isEmbed && embedType !== "inline"; @@ -72,9 +59,7 @@ export const useBookerLayout = ( bookerLayouts?.enabledLayouts?.length && layout !== _layout ) { - const validLayout = bookerLayouts.enabledLayouts.find( - (userLayout) => userLayout === layout - ); + const validLayout = bookerLayouts.enabledLayouts.find((userLayout) => userLayout === layout); if (validLayout) setLayout(validLayout); } }, [bookerLayouts, setLayout, _layout, isEmbed, isMobile]); @@ -99,8 +84,8 @@ export const useBookerLayout = ( const hideEventTypeDetails = isEmbed ? embedUiConfig.hideEventTypeDetails : typeof hideEventTypeDetailsParam === "string" - ? hideEventTypeDetailsParam === "true" - : false; + ? hideEventTypeDetailsParam === "true" + : false; const slotsViewOnSmallScreen = useSlotsViewOnSmallScreen(); @@ -118,4 +103,4 @@ export const useBookerLayout = ( slotsViewOnSmallScreen, bookerLayouts, }; -}; +}; \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useBookerTime.ts b/packages/features/bookings/Booker/hooks/useBookerTime.ts similarity index 77% rename from packages/features/bookings/Booker/components/hooks/useBookerTime.ts rename to packages/features/bookings/Booker/hooks/useBookerTime.ts index 1faf164dd2..2b34d8614d 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookerTime.ts +++ b/packages/features/bookings/Booker/hooks/useBookerTime.ts @@ -1,9 +1,7 @@ -import { shallow } from "zustand/shallow"; - import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; - -import { useTimePreferences } from "../../../lib/timePreferences"; -import { getBookerTimezone } from "../../utils/getBookerTimezone"; +import { getBookerTimezone } from "@calcom/features/bookings/Booker/utils/getBookerTimezone"; +import { useTimePreferences } from "@calcom/features/bookings/lib/timePreferences"; +import { shallow } from "zustand/shallow"; export const useBookerTime = () => { const [timezoneFromBookerStore] = useBookerStoreContext((state) => [state.timezone], shallow); @@ -19,4 +17,4 @@ export const useBookerTime = () => { timezoneFromBookerStore, timezoneFromTimePreferences, }; -}; +}; \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useBookingForm.ts b/packages/features/bookings/Booker/hooks/useBookingForm.ts similarity index 99% rename from packages/features/bookings/Booker/components/hooks/useBookingForm.ts rename to packages/features/bookings/Booker/hooks/useBookingForm.ts index 44a7c24d38..2d2dd92691 100644 --- a/packages/features/bookings/Booker/components/hooks/useBookingForm.ts +++ b/packages/features/bookings/Booker/hooks/useBookingForm.ts @@ -127,4 +127,4 @@ export const useBookingForm = ({ formErrors: errors, errors, }; -}; +}; \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useInitialFormValues.test.ts b/packages/features/bookings/Booker/hooks/useInitialFormValues.test.ts similarity index 99% rename from packages/features/bookings/Booker/components/hooks/useInitialFormValues.test.ts rename to packages/features/bookings/Booker/hooks/useInitialFormValues.test.ts index f358cd603a..6834f94fb0 100644 --- a/packages/features/bookings/Booker/components/hooks/useInitialFormValues.test.ts +++ b/packages/features/bookings/Booker/hooks/useInitialFormValues.test.ts @@ -291,4 +291,4 @@ describe("useInitialFormValues - Autofill Disable Feature", () => { expect(result.current.values.responses?.phone).toBeUndefined(); }); }); -}); +}); \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useInitialFormValues.ts b/packages/features/bookings/Booker/hooks/useInitialFormValues.ts similarity index 97% rename from packages/features/bookings/Booker/components/hooks/useInitialFormValues.ts rename to packages/features/bookings/Booker/hooks/useInitialFormValues.ts index 661eafc743..98d5217576 100644 --- a/packages/features/bookings/Booker/components/hooks/useInitialFormValues.ts +++ b/packages/features/bookings/Booker/hooks/useInitialFormValues.ts @@ -85,7 +85,7 @@ export function useInitialFormValues({ eventType?.owner?.profile?.organization?.organizationSettings?.disableAutofillOnBookingPage ?? false; useEffect(() => { - (async function () { + (async () => { if (Object.keys(formValues).length) { setInitialValuesState({ values: formValues, @@ -118,11 +118,11 @@ export function useInitialFormValues({ const defaultUserValues = (() => { const rescheduledEmail = rescheduleUid && bookingData && bookingData.attendees.length > 0 - ? bookingData.attendees[0].email ?? "" + ? (bookingData.attendees[0].email ?? "") : ""; const rescheduledName = rescheduleUid && bookingData && bookingData.attendees.length > 0 - ? bookingData.attendees[0].name ?? "" + ? (bookingData.attendees[0].name ?? "") : ""; if (isAutofillDisabledByOrg) { @@ -133,8 +133,8 @@ export function useInitialFormValues({ } return { - email: rescheduledEmail || (parsedQuery["email"] ? parsedQuery["email"] : email ?? ""), - name: rescheduledName || (parsedQuery["name"] ? parsedQuery["name"] : name ?? username ?? ""), + email: rescheduledEmail || (parsedQuery["email"] ? parsedQuery["email"] : (email ?? "")), + name: rescheduledName || (parsedQuery["name"] ? parsedQuery["name"] : (name ?? username ?? "")), }; })(); @@ -212,4 +212,4 @@ export function useInitialFormValues({ ]); return initialValuesState; -} +} \ No newline at end of file diff --git a/packages/features/bookings/Booker/components/hooks/useLocalSet.tsx b/packages/features/bookings/Booker/hooks/useLocalSet.tsx similarity index 99% rename from packages/features/bookings/Booker/components/hooks/useLocalSet.tsx rename to packages/features/bookings/Booker/hooks/useLocalSet.tsx index 67a8609c8c..7709f7bcad 100644 --- a/packages/features/bookings/Booker/components/hooks/useLocalSet.tsx +++ b/packages/features/bookings/Booker/hooks/useLocalSet.tsx @@ -68,4 +68,4 @@ export function useLocalSet(key: string, initialValue: }; return { set, addValue, removeById, toggleValue, hasItem, clearSet }; -} +} \ No newline at end of file diff --git a/packages/features/bookings/Booker/types.ts b/packages/features/bookings/Booker/types.ts index 23016cec89..60ed3c984a 100644 --- a/packages/features/bookings/Booker/types.ts +++ b/packages/features/bookings/Booker/types.ts @@ -1,13 +1,8 @@ -import type { UseBookerLayoutType } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout"; -import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; -import type { UseBookingsReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookings"; -import type { UseSlotsReturnType } from "@calcom/features/bookings/Booker/components/hooks/useSlots"; -import type { UseVerifyCodeReturnType } from "@calcom/features/bookings/Booker/components/hooks/useVerifyCode"; -import type { UseVerifyEmailReturnType } from "@calcom/features/bookings/Booker/components/hooks/useVerifyEmail"; import type { useScheduleForEventReturnType } from "@calcom/features/bookings/Booker/utils/event"; import type { BookerEventQuery } from "@calcom/features/bookings/types"; import type { IntlSupportedTimeZones } from "@calcom/lib/timeZones"; import type { EventBusyDate } from "@calcom/types/Calendar"; +import type { TIsAvailableOutputSchema } from "@calcom/trpc/server/routers/viewer/slots/isAvailable.schema"; import type React from "react"; import type { GetBookingType } from "../lib/get-booking"; @@ -110,79 +105,6 @@ export type ToggledConnectedCalendars = { externalId: string; }; -export type WrappedBookerPropsMain = { - sessionUsername?: string | null; - rescheduleUid: string | null; - rescheduledBy: string | null; - bookingUid: string | null; - isRedirect: boolean; - fromUserNameRedirected: string; - hasSession: boolean; - onGoBackInstantMeeting: () => void; - onConnectNowInstantMeeting: () => void; - onOverlayClickNoCalendar: () => void; - onClickOverlayContinue: () => void; - onOverlaySwitchStateChange: (state: boolean) => void; - extraOptions: Record; - bookings: UseBookingsReturnType; - slots: UseSlotsReturnType; - calendars: { - overlayBusyDates?: EventBusyDate[]; - isOverlayCalendarEnabled: boolean; - connectedCalendars: { - calendars?: { - name?: string; - integrationTitle?: string; - externalId: string; - primary: boolean | null; - }[]; - credentialId: number; - delegationCredentialId?: string | null; - cacheUpdatedAt: null; - error?: { - message: string | null; - }; - primary?: { - email?: string; - }; - integration: { - slug: string; - name?: string | undefined; - title?: string; - logo: string; - }; - }[]; - loadingConnectedCalendar: boolean; - onToggleCalendar: (calendarsToLoad: Set) => void; - }; - bookerForm: UseBookingFormReturnType; - event: BookerEventQuery; - schedule: useScheduleForEventReturnType; - bookerLayout: UseBookerLayoutType; - verifyEmail: UseVerifyEmailReturnType; - customClassNames?: CustomClassNames; - isBookingDryRun?: boolean; - renderCaptcha?: boolean; - confirmButtonDisabled?: boolean; -}; - -export type WrappedBookerPropsForPlatform = WrappedBookerPropsMain & { - isPlatform: true; - verifyCode: undefined; - customClassNames?: CustomClassNames; - timeZones?: Timezone[]; - roundRobinHideOrgAndTeam?: boolean; - hideOrgTeamAvatar?: boolean; -}; -export type WrappedBookerPropsForWeb = WrappedBookerPropsMain & { - isPlatform: false; - verifyCode: UseVerifyCodeReturnType; - timeZones?: Timezone[]; - roundRobinHideOrgAndTeam?: boolean; - hideOrgTeamAvatar?: boolean; -}; - -export type WrappedBookerProps = WrappedBookerPropsForPlatform | WrappedBookerPropsForWeb; export type VIEW_TYPE = "MONTH_VIEW" | "WEEK_VIEW" | "COLUMN_VIEW"; export type BookerState = "loading" | "selecting_date" | "selecting_time" | "booking"; @@ -221,3 +143,10 @@ export type DatePickerClassNames = { datePickerDatesActive?: string; datePickerToggle?: string; }; + +export type QuickAvailabilityCheck = { + status: "available" | "reserved" | "minBookNoticeViolation" | "slotInPast"; + utcStartIso: string; + utcEndIso: string; + realStatus?: "available" | "reserved" | "minBookNoticeViolation" | "slotInPast" | undefined; +}; diff --git a/packages/features/bookings/Booker/utils/event.ts b/packages/features/bookings/Booker/utils/event.ts index e4b1b988c5..a9dc76c176 100644 --- a/packages/features/bookings/Booker/utils/event.ts +++ b/packages/features/bookings/Booker/utils/event.ts @@ -5,7 +5,7 @@ import { useSchedule } from "@calcom/features/schedules/lib/use-schedule/useSche import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams"; import { trpc } from "@calcom/trpc/react"; -import { useBookerTime } from "../components/hooks/useBookerTime"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; export type useEventReturnType = ReturnType; export type useScheduleForEventReturnType = ReturnType; diff --git a/packages/features/bookings/Booker/utils/isTimeslotAvailable.test.ts b/packages/features/bookings/Booker/utils/isTimeslotAvailable.test.ts index 4d68f981de..5bbc1a2c19 100644 --- a/packages/features/bookings/Booker/utils/isTimeslotAvailable.test.ts +++ b/packages/features/bookings/Booker/utils/isTimeslotAvailable.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import type { QuickAvailabilityCheck } from "../components/hooks/useSlots"; +import type { QuickAvailabilityCheck } from "../types"; import { isTimeSlotAvailable } from "./isTimeslotAvailable"; describe("isTimeSlotAvailable", () => { diff --git a/packages/features/bookings/Booker/utils/isTimeslotAvailable.ts b/packages/features/bookings/Booker/utils/isTimeslotAvailable.ts index 0b8b8ceb05..8c239a8ca0 100644 --- a/packages/features/bookings/Booker/utils/isTimeslotAvailable.ts +++ b/packages/features/bookings/Booker/utils/isTimeslotAvailable.ts @@ -1,6 +1,6 @@ import dayjs from "@calcom/dayjs"; -import type { QuickAvailabilityCheck } from "../components/hooks/useSlots"; +import type { QuickAvailabilityCheck } from "../types"; import { isSlotEquivalent, isValidISOFormat } from "./isSlotEquivalent"; type Maybe = T | undefined; diff --git a/packages/features/calendars/components/DatePicker.tsx b/packages/features/calendars/components/DatePicker.tsx index 95d7776a86..efea5d8551 100644 --- a/packages/features/calendars/components/DatePicker.tsx +++ b/packages/features/calendars/components/DatePicker.tsx @@ -17,7 +17,7 @@ import { SkeletonText } from "@calcom/ui/components/skeleton"; import { Tooltip } from "@calcom/ui/components/tooltip"; import NoAvailabilityDialog from "./NoAvailabilityDialog"; -import { useSlotsViewOnSmallScreen } from "@calcom/features/bookings/Booker/components/hooks/useSlotsViewOnSmallScreen"; +import { useSlotsViewOnSmallScreen } from "@calcom/embed-core/embed-iframe"; export type DatePickerProps = { /** which day of the week to render the calendar. Usually Sunday (=0) or Monday (=1) - default: Sunday */ diff --git a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx index 5cde5eab09..5cef210ebf 100644 --- a/packages/platform/atoms/booker/BookerPlatformWrapper.tsx +++ b/packages/platform/atoms/booker/BookerPlatformWrapper.tsx @@ -7,9 +7,9 @@ import { useBookerStoreContext, useInitializeBookerStoreContext, } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useBookerLayout } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout"; -import { useBookingForm } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; -import { useLocalSet } from "@calcom/features/bookings/Booker/components/hooks/useLocalSet"; +import { useBookerLayout } from "@calcom/features/bookings/Booker/hooks/useBookerLayout"; +import { useBookingForm } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; +import { useLocalSet } from "@calcom/features/bookings/Booker/hooks/useLocalSet"; import { useInitializeBookerStore } from "@calcom/features/bookings/Booker/store"; import { useTimePreferences } from "@calcom/features/bookings/lib"; import type { ConnectedDestinationCalendars } from "@calcom/features/calendars/lib/getConnectedDestinationCalendars"; diff --git a/packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx b/packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx index 816ef0b367..ee4756cf83 100644 --- a/packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx +++ b/packages/platform/atoms/calendar-view/EventTypeCalendarViewComponent.tsx @@ -7,8 +7,8 @@ import { } from "@calcom/features/bookings/Booker/BookerStoreProvider"; import { Header } from "@calcom/web/modules/bookings/components/Header"; import { BookerSection } from "@calcom/web/modules/bookings/components/Section"; -import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/components/hooks/useAvailableTimeSlots"; -import { useBookerLayout } from "@calcom/features/bookings/Booker/components/hooks/useBookerLayout"; +import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/hooks/useAvailableTimeSlots"; +import { useBookerLayout } from "@calcom/features/bookings/Booker/hooks/useBookerLayout"; import { useTimePreferences } from "@calcom/features/bookings/lib"; import { LargeCalendar } from "@calcom/web/modules/calendar-view/components/LargeCalendar"; import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents"; diff --git a/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts b/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts index f9d6adb60a..0d8dd70535 100644 --- a/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts +++ b/packages/platform/atoms/hooks/bookings/useHandleBookEvent.ts @@ -2,8 +2,8 @@ import { useSearchParams } from "next/navigation"; import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform"; import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider"; -import { useBookerTime } from "@calcom/features/bookings/Booker/components/hooks/useBookerTime"; -import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/components/hooks/useBookingForm"; +import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime"; +import type { UseBookingFormReturnType } from "@calcom/features/bookings/Booker/hooks/useBookingForm"; import { mapBookingToMutationInput, mapRecurringBookingToMutationInput } from "@calcom/features/bookings/lib"; import type { BookingCreateBody } from "@calcom/features/bookings/lib/bookingCreateBodySchema"; import type { BookerEvent } from "@calcom/features/bookings/types";