From c289fac0085095373f55a2d494b26468696570cd Mon Sep 17 00:00:00 2001 From: Eunjae Lee Date: Mon, 20 Oct 2025 15:59:59 +0200 Subject: [PATCH] refactor: make timezone a required prop in Calendar component (#24567) * refactor: make timezone a required prop in Calendar component - Remove useBookerTime hook from Calendar.tsx - Add timezone as required prop in CalendarState type - Update all parent components to pass timezone prop: - packages/features/bookings/Booker/components/LargeCalendar.tsx - packages/features/calendar-view/LargeCalendar.tsx - packages/features/troubleshooter/components/LargeCalendar.tsx - All parent components now use useTimePreferences hook to get timezone Co-Authored-By: eunjae@cal.com * use right implementation * remove a line * use user's timezone instead of booker timezone * get timezone from calendar store --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../features/bookings/Booker/components/LargeCalendar.tsx | 4 +++- packages/features/calendar-view/LargeCalendar.tsx | 3 +++ .../features/calendars/weeklyview/components/Calendar.tsx | 3 +-- packages/features/calendars/weeklyview/state/store.ts | 6 ++++-- packages/features/calendars/weeklyview/types/state.ts | 4 ++++ .../features/troubleshooter/components/LargeCalendar.tsx | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/features/bookings/Booker/components/LargeCalendar.tsx b/packages/features/bookings/Booker/components/LargeCalendar.tsx index 839b5a6fdc..d1accdc72a 100644 --- a/packages/features/bookings/Booker/components/LargeCalendar.tsx +++ b/packages/features/bookings/Booker/components/LargeCalendar.tsx @@ -3,6 +3,7 @@ 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 type { BookerEvent } from "@calcom/features/bookings/types"; import { Calendar } from "@calcom/features/calendars/weeklyview"; import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events"; @@ -31,6 +32,7 @@ export const LargeCalendar = ({ const overlayEvents = useOverlayCalendarStore((state) => state.overlayBusyDates); const displayOverlay = getQueryParam("overlayCalendar") === "true" || localStorage?.getItem("overlayCalendarSwitchDefault"); + const { timezone } = useBookerTime(); const eventDuration = selectedEventDuration || event?.data?.length || 30; @@ -43,7 +45,6 @@ export const LargeCalendar = ({ // HACK: force rerender when overlay events change // Sine we dont use react router here we need to force rerender (ATOM SUPPORT) - // eslint-disable-next-line @typescript-eslint/no-empty-function useEffect(() => {}, [displayOverlay]); const overlayEventsForDate = useMemo(() => { @@ -75,6 +76,7 @@ export const LargeCalendar = ({ gridCellsPerHour={60 / eventDuration} hoverEventDuration={eventDuration} hideHeader + timezone={timezone} /> ); diff --git a/packages/features/calendar-view/LargeCalendar.tsx b/packages/features/calendar-view/LargeCalendar.tsx index 0884424e9d..53b8acf257 100644 --- a/packages/features/calendar-view/LargeCalendar.tsx +++ b/packages/features/calendar-view/LargeCalendar.tsx @@ -3,6 +3,7 @@ import { useEffect, useMemo } 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 type { BookerEvent } from "@calcom/features/bookings/types"; import { Calendar } from "@calcom/features/calendars/weeklyview"; import { localStorage } from "@calcom/lib/webstorage"; @@ -29,6 +30,7 @@ export const LargeCalendar = ({ const selectedEventDuration = useBookerStoreContext((state) => state.selectedDuration); const displayOverlay = getQueryParam("overlayCalendar") === "true" || localStorage?.getItem("overlayCalendarSwitchDefault"); + const { timezone } = useBookerTime(); const eventDuration = selectedEventDuration || event?.data?.length || 30; @@ -85,6 +87,7 @@ export const LargeCalendar = ({ gridCellsPerHour={60 / eventDuration} hoverEventDuration={eventDuration} hideHeader + timezone={timezone} /> ); diff --git a/packages/features/calendars/weeklyview/components/Calendar.tsx b/packages/features/calendars/weeklyview/components/Calendar.tsx index 878a82a0db..ef8844f0dd 100644 --- a/packages/features/calendars/weeklyview/components/Calendar.tsx +++ b/packages/features/calendars/weeklyview/components/Calendar.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useRef } from "react"; import classNames from "@calcom/ui/classNames"; -import { useBookerTime } from "../../../bookings/Booker/components/hooks/useBookerTime"; import { useCalendarStore } from "../state/store"; import "../styles/styles.css"; import type { CalendarComponentProps } from "../types/state"; @@ -23,7 +22,6 @@ export function Calendar(props: CalendarComponentProps) { const containerOffset = useRef(null); const schedulerGrid = useRef(null); const initialState = useCalendarStore((state) => state.initState); - const { timezone } = useBookerTime(); const startDate = useCalendarStore((state) => state.startDate); const endDate = useCalendarStore((state) => state.endDate); @@ -32,6 +30,7 @@ export function Calendar(props: CalendarComponentProps) { const usersCellsStopsPerHour = useCalendarStore((state) => state.gridCellsPerHour || 4); const availableTimeslots = useCalendarStore((state) => state.availableTimeslots); const hideHeader = useCalendarStore((state) => state.hideHeader); + const timezone = useCalendarStore((state) => state.timezone); const days = useMemo(() => getDaysBetweenDates(startDate, endDate), [startDate, endDate]); diff --git a/packages/features/calendars/weeklyview/state/store.ts b/packages/features/calendars/weeklyview/state/store.ts index af1b52358d..c3c0e92a8d 100644 --- a/packages/features/calendars/weeklyview/state/store.ts +++ b/packages/features/calendars/weeklyview/state/store.ts @@ -1,6 +1,7 @@ import { create } from "zustand"; import dayjs from "@calcom/dayjs"; +import { CURRENT_TIMEZONE } from "@calcom/lib/timezoneConstants"; import type { CalendarComponentProps, @@ -18,6 +19,7 @@ const defaultState: CalendarComponentProps = { startHour: 0, endHour: 23, gridCellsPerHour: 4, + timezone: CURRENT_TIMEZONE, }; export const useCalendarStore = create((set) => ({ @@ -62,7 +64,7 @@ export const useCalendarStore = create((set) => ({ } // We call this callback if we have it -> Allows you to change your state outside of the component - state.onDateChange && state.onDateChange(newStartDate, newEndDate); + state.onDateChange?.(newStartDate, newEndDate); return { startDate: newStartDate, endDate: newEndDate, @@ -70,7 +72,7 @@ export const useCalendarStore = create((set) => ({ } const newStartDate = dayjs(startDate).subtract(1, state.view).toDate(); const newEndDate = dayjs(endDate).subtract(1, state.view).toDate(); - state.onDateChange && state.onDateChange(newStartDate, newEndDate); + state.onDateChange?.(newStartDate, newEndDate); return { startDate: newStartDate, endDate: newEndDate, diff --git a/packages/features/calendars/weeklyview/types/state.ts b/packages/features/calendars/weeklyview/types/state.ts index f16b4597bf..a9fc46301b 100644 --- a/packages/features/calendars/weeklyview/types/state.ts +++ b/packages/features/calendars/weeklyview/types/state.ts @@ -127,6 +127,10 @@ export type CalendarState = { * Optional boolean to hide the main header. Default the header will be visible. */ hideHeader?: boolean; + /** + * Timezone to use for displaying times in the calendar + */ + timezone: string; }; export type CalendarComponentProps = CalendarPublicActions & CalendarState & { isPending?: boolean }; diff --git a/packages/features/troubleshooter/components/LargeCalendar.tsx b/packages/features/troubleshooter/components/LargeCalendar.tsx index 28ba9f2935..6ffd5ea060 100644 --- a/packages/features/troubleshooter/components/LargeCalendar.tsx +++ b/packages/features/troubleshooter/components/LargeCalendar.tsx @@ -122,6 +122,7 @@ export const LargeCalendar = ({ extraDays }: { extraDays: number }) => { gridCellsPerHour={60 / (event?.duration || 15)} hoverEventDuration={30} hideHeader + timezone={timezone} /> );