cal.pub0.org/packages/features/bookings/Booker/components/LargeCalendar.tsx

86 lines
3.2 KiB
TypeScript

import { useMemo, useEffect } from "react";
import dayjs from "@calcom/dayjs";
import { Calendar } from "@calcom/features/calendars/weeklyview";
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
import type { CalendarAvailableTimeslots } from "@calcom/features/calendars/weeklyview/types/state";
import { useBookerStore } from "../store";
import { useEvent, useScheduleForEvent } from "../utils/event";
import { getQueryParam } from "../utils/query-param";
import { useOverlayCalendarStore } from "./OverlayCalendar/store";
export const LargeCalendar = ({ extraDays }: { extraDays: number }) => {
const selectedDate = useBookerStore((state) => state.selectedDate);
const date = selectedDate || dayjs().format("YYYY-MM-DD");
const setSelectedTimeslot = useBookerStore((state) => state.setSelectedTimeslot);
const selectedEventDuration = useBookerStore((state) => state.selectedDuration);
const overlayEvents = useOverlayCalendarStore((state) => state.overlayBusyDates);
const schedule = useScheduleForEvent({
prefetchNextMonth: !!extraDays && dayjs(date).month() !== dayjs(date).add(extraDays, "day").month(),
});
const displayOverlay =
getQueryParam("overlayCalendar") === "true" || localStorage.getItem("overlayCalendarSwitchDefault");
const event = useEvent();
const eventDuration = selectedEventDuration || event?.data?.length || 30;
const availableSlots = useMemo(() => {
const availableTimeslots: CalendarAvailableTimeslots = {};
if (!schedule.data) return availableTimeslots;
if (!schedule.data.slots) return availableTimeslots;
for (const day in schedule.data.slots) {
availableTimeslots[day] = schedule.data.slots[day].map((slot) => ({
start: dayjs(slot.time).toDate(),
end: dayjs(slot.time).add(eventDuration, "minutes").toDate(),
}));
}
return availableTimeslots;
}, [schedule, eventDuration]);
const startDate = selectedDate ? dayjs(selectedDate).toDate() : dayjs().toDate();
const endDate = dayjs(startDate)
.add(extraDays - 1, "day")
.toDate();
// 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(() => {
if (!overlayEvents || !displayOverlay) return [];
return overlayEvents.map((event, id) => {
return {
id,
start: dayjs(event.start).toDate(),
end: dayjs(event.end).toDate(),
title: "Busy",
options: {
status: "ACCEPTED",
},
} as CalendarEvent;
});
}, [overlayEvents, displayOverlay]);
return (
<div className="h-full [--calendar-dates-sticky-offset:66px]">
<Calendar
isLoading={schedule.isLoading}
availableTimeslots={availableSlots}
startHour={0}
endHour={23}
events={overlayEventsForDate}
startDate={startDate}
endDate={endDate}
onEmptyCellClick={(date) => setSelectedTimeslot(date.toISOString())}
gridCellsPerHour={60 / eventDuration}
hoverEventDuration={eventDuration}
hideHeader
/>
</div>
);
};