Files
calendar/packages/features/bookings/Booker/utils/event.ts
T
sean-brydonGitHubrajiv@cal.com <sahalrajiv6900@gmail.com>Rajiv SahalRyukemeisterDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>Benny Joo
4c01f171ae fix: multiple widgets for Booker atom (#22925)
* fix manage test error

* fix manage test error

* update useBookerContext

* wrap store provider around booker

* replace useStore with useBookerStoreContext

* replace useBookerStore with useBookerStoreContext

* add initializer function for booker store provider

* update props

* fixup: pass more props

* export StoreInitializeType type

* replace useBookerStore with useBookerStoreContext

* fixup: dont wrap BookerStoreProvider around booker directly

* wrap BookerStoreProvider around booker web wrapper and fix local storage import

* fix: wrap test components with BookerStoreProvider to fix failing unit tests

- Create reusable test utility in test-utils.tsx with comprehensive mock store
- Update Booker.test.tsx to use context-based testing approach
- Fix DatePicker tests in both bookings and calendars packages
- Simulate auto-advance behavior for month navigation tests
- All 14 previously failing tests now pass

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* add changesets

* fix: complete migration from useBookerStore to useBookerStoreContext

- Updated all remaining files to use useBookerStoreContext instead of useBookerStore
- Fixed BookingFields.test.tsx by wrapping test component with BookerStoreProvider
- Ensures all Booker components work within the new context-based store pattern
- Resolves failing unit tests in CI by completing the store migration

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* fix: add missing useBookerStoreContext import in BookerWebWrapper.tsx

- Fixes TypeScript errors in CI where useBookerStoreContext was used but not imported
- Completes the migration from useBookerStore to useBookerStoreContext pattern
- All tests pass locally after this fix

Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com>

* Revert "fix: add missing useBookerStoreContext import in BookerWebWrapper.tsx"

This reverts commit 12947ca63f46c42e5aee74c78176ef230e2bf2cf.

* Revert "fix: complete migration from useBookerStore to useBookerStoreContext"

This reverts commit 87d837f2d30e4f9259d2be786049d21856f4eef0.

* fixup: useBookerStoreContext and useInitializeBookerStoreContext for booker web wrapper

* fixup: failing E2E tests

* fixup: email embed breaking

* fixup: troubleshooter crashing

* replace useBookerstore with useBookerStoreContext

---------

Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
Co-authored-by: Ryukemeister <sahalrajiv6900@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Benny Joo <sldisek783@gmail.com>
2025-08-14 17:57:59 +05:30

127 lines
3.7 KiB
TypeScript

import { shallow } from "zustand/shallow";
import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider";
import { useSchedule } from "@calcom/features/schedules/lib/use-schedule/useSchedule";
import { useCompatSearchParams } from "@calcom/lib/hooks/useCompatSearchParams";
import { trpc } from "@calcom/trpc/react";
import { useBookerTime } from "../components/hooks/useBookerTime";
export type useEventReturnType = ReturnType<typeof useEvent>;
export type useScheduleForEventReturnType = ReturnType<typeof useScheduleForEvent>;
/**
* 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] = useBookerStoreContext(
(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.
* We can read from the store if we want to get the latest values.
*
* Using this hook means you only need to use one hook, instead
* of combining multiple conditional hooks.
*
* The prefetchNextMonth argument can be used to prefetch two months at once,
* useful when the user is viewing dates near the end of the month,
* this way the multi day view will show data of both months.
*/
export const useScheduleForEvent = ({
prefetchNextMonth,
username,
eventSlug,
eventId,
month,
duration,
monthCount,
dayCount,
selectedDate,
orgSlug,
teamMemberEmail,
isTeamEvent,
useApiV2 = true,
}: {
prefetchNextMonth?: boolean;
username?: string | null;
eventSlug?: string | null;
eventId?: number | null;
month?: string | null;
duration?: number | null;
monthCount?: number;
dayCount?: number | null;
selectedDate?: string | null;
orgSlug?: string;
teamMemberEmail?: string | null;
fromRedirectOfNonOrgLink?: boolean;
isTeamEvent?: boolean;
useApiV2?: boolean;
} = {}) => {
const { timezone } = useBookerTime();
const [usernameFromStore, eventSlugFromStore, monthFromStore, durationFromStore] = useBookerStoreContext(
(state) => [state.username, state.eventSlug, state.month, state.selectedDuration],
shallow
);
const searchParams = useCompatSearchParams();
const rescheduleUid = searchParams?.get("rescheduleUid");
const schedule = useSchedule({
username: usernameFromStore ?? username,
eventSlug: eventSlugFromStore ?? eventSlug,
eventId,
timezone,
selectedDate,
prefetchNextMonth,
monthCount,
dayCount,
rescheduleUid,
month: monthFromStore ?? month,
duration: durationFromStore ?? duration,
isTeamEvent,
orgSlug,
teamMemberEmail,
useApiV2: useApiV2,
});
return {
data: schedule?.data,
isPending: schedule?.isPending,
isError: schedule?.isError,
isSuccess: schedule?.isSuccess,
isLoading: schedule?.isLoading,
invalidate: schedule?.invalidate,
};
};