diff --git a/packages/features/bookings/Booker/components/LargeCalendar.tsx b/packages/features/bookings/Booker/components/LargeCalendar.tsx index 8d71521eb4c2bd..10439c6ee05ff6 100644 --- a/packages/features/bookings/Booker/components/LargeCalendar.tsx +++ b/packages/features/bookings/Booker/components/LargeCalendar.tsx @@ -39,12 +39,17 @@ export const LargeCalendar = ({ if (!schedule) return availableTimeslots; if (!schedule.slots) return availableTimeslots; + // Get the user's timezone + const userTimezone = dayjs.tz.guess(); + for (const day in schedule.slots) { availableTimeslots[day] = schedule.slots[day].map((slot) => { const { time, ...rest } = slot; + // Convert UTC time to user's timezone + const slotTime = dayjs.utc(time).tz(userTimezone); return { - start: dayjs(time).toDate(), - end: dayjs(time).add(eventDuration, "minutes").toDate(), + start: slotTime.toDate(), + end: slotTime.add(eventDuration, "minutes").toDate(), ...rest, }; }); diff --git a/packages/features/bookings/components/AvailableTimes.tsx b/packages/features/bookings/components/AvailableTimes.tsx index 0eee6a9e86ba48..488671458d4190 100644 --- a/packages/features/bookings/components/AvailableTimes.tsx +++ b/packages/features/bookings/components/AvailableTimes.tsx @@ -115,6 +115,8 @@ const SlotItem = ({ const bookingData = useBookerStore((state) => state.bookingData); const layout = useBookerStore((state) => state.layout); const hasTimeSlots = !!seatsPerTimeSlot; + + // Convert UTC time to user's timezone const computedDateWithUsersTimezone = dayjs.utc(slot.time).tz(timezone); const bookingFull = !!(hasTimeSlots && slot.attendees && slot.attendees >= seatsPerTimeSlot); @@ -122,17 +124,12 @@ const SlotItem = ({ const isNearlyFull = slot.attendees && seatsPerTimeSlot && slot.attendees / seatsPerTimeSlot >= 0.83; const colorClass = isNearlyFull ? "bg-rose-600" : isHalfFull ? "bg-yellow-500" : "bg-emerald-400"; - const nowDate = dayjs(); - const usersTimezoneDate = nowDate.tz(timezone); - - const offset = (usersTimezoneDate.utcOffset() - nowDate.utcOffset()) / 60; - const selectedTimeslot = useBookerStore((state) => state.selectedTimeslot); const { isOverlapping, overlappingTimeEnd, overlappingTimeStart } = useCheckOverlapWithOverlay({ start: computedDateWithUsersTimezone, selectedDuration: eventData?.length ?? 0, - offset, + offset: 0, // We don't need manual offset since we're using proper timezone conversion }); const onButtonClick = () => { diff --git a/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx b/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx index ba994ee7f7fa26..72c1a4f79a9077 100644 --- a/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx +++ b/packages/features/bookings/lib/useCheckOverlapWithOverlay.tsx @@ -28,11 +28,14 @@ export function useCheckOverlapWithOverlay({ overlayBusyDates.some((busyDate) => { const busyDateStart = dayjs(busyDate.start); const busyDateEnd = dayjs(busyDate.end); - const selectedEndTime = dayjs(start.add(offset, "hours")).add(selectedDuration ?? 0, "minute"); + + // Use the offset parameter if provided, otherwise use 0 + const adjustedStart = offset !== 0 ? start.add(offset, "hours") : start; + const selectedEndTime = adjustedStart.add(selectedDuration ?? 0, "minute"); const isOverlapping = (selectedEndTime.isSame(busyDateStart) || selectedEndTime.isAfter(busyDateStart)) && - start.add(offset, "hours") < busyDateEnd && + adjustedStart < busyDateEnd && selectedEndTime > busyDateStart; overlappingTimeStart = isOverlapping ? getCurrentTime(busyDateStart.toDate()) : null; diff --git a/packages/features/bookings/tsconfig.json b/packages/features/bookings/tsconfig.json new file mode 100644 index 00000000000000..203b50aa517e0c --- /dev/null +++ b/packages/features/bookings/tsconfig.json @@ -0,0 +1,24 @@ +{ + "extends": "@calcom/tsconfig/react-library.json", + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./*"], + "@calcom/*": ["../../../packages/*"] + }, + "resolveJsonModule": true, + "esModuleInterop": true, + "jsx": "react-jsx", + "types": ["react", "node"], + "typeRoots": ["../../../node_modules/@types", "../../../packages/types"] + }, + "include": [ + ".", + "../../../packages/types/next-auth.d.ts", + "../../../packages/types/tanstack-table.d.ts", + "../../../packages/types/next.d.ts", + "../../../packages/types/Calendar.d.ts", + "../../../packages/types/schedule.d.ts" + ], + "exclude": ["dist", "build", "node_modules", "**/*.test.*", "**/__mocks__/*", "**/__tests__/*"] +}