refactor: remove circular dependencies from CalendarView atom (#27850)
* fix: decouple large calendar from features * fix: move calendar to features since this is the better approach * chore: move OOO slots to features * feat: add DefaultOutOfOfficeSlot fallback for calendar OOO rendering Co-Authored-By: rajiv@cal.com <sahalrajiv6900@gmail.com> * chore: cleanup unused LargeCalendar component --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
rajiv@cal.com
Devin AI
parent
9603831def
commit
38b43f75ba
+1
-1
@@ -3,7 +3,7 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
|
||||
import type { CalendarComponentProps, Hours } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import dayjs from "@calcom/dayjs";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
|
||||
import { useGetTheme } from "@calcom/lib/hooks/useTheme";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import { useBanners } from "@calcom/web/modules/shell/banners/useBanners";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useBookingDetailsSheetStore } from "../store/bookingDetailsSheetStore";
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { useMemo, useEffect } from "react";
|
||||
import { useEffect, useMemo } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider";
|
||||
import { useOverlayCalendarStore } from "@calcom/features/bookings/Booker/components/OverlayCalendar/store";
|
||||
import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/hooks/useAvailableTimeSlots";
|
||||
import { useBookerTime } from "@calcom/features/bookings/Booker/hooks/useBookerTime";
|
||||
import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param";
|
||||
import type { BookerEvent } from "@calcom/features/bookings/types";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import type { CalendarEvent } from "@calcom/features/calendars/weeklyview/types/events";
|
||||
import { localStorage } from "@calcom/lib/webstorage";
|
||||
|
||||
import type { useScheduleForEventReturnType } from "@calcom/web/modules/schedules/hooks/useEvent";
|
||||
import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param";
|
||||
import { useOverlayCalendarStore } from "@calcom/features/bookings/Booker/components/OverlayCalendar/store";
|
||||
|
||||
import { OutOfOfficeInSlots } from "./OutOfOfficeInSlots";
|
||||
|
||||
export const LargeCalendar = ({
|
||||
extraDays,
|
||||
@@ -78,6 +80,7 @@ export const LargeCalendar = ({
|
||||
hoverEventDuration={eventDuration}
|
||||
hideHeader
|
||||
timezone={timezone}
|
||||
renderOutOfOffice={(props) => <OutOfOfficeInSlots {...props} />}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { usePathname } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import type { CalendarComponentProps, Hours } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import { weekdayDates } from "@calcom/features/calendars/weeklyview/utils";
|
||||
import { CURRENT_TIMEZONE } from "@calcom/lib/timezoneConstants";
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useAvailableTimeSlots } from "@calcom/features/bookings/Booker/hooks/useAvailableTimeSlots";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib/timePreferences";
|
||||
import { useSchedule } from "~/schedules/hooks/useSchedule";
|
||||
import { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import { useTroubleshooterStore } from "@calcom/features/troubleshooter/store";
|
||||
import { BookingStatus } from "@calcom/prisma/enums";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
import { Calendar } from "@calcom/web/modules/calendars/weeklyview/components/Calendar";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { useSchedule } from "~/schedules/hooks/useSchedule";
|
||||
|
||||
import { OutOfOfficeInSlots } from "../../bookings/components/OutOfOfficeInSlots";
|
||||
|
||||
export const LargeCalendar = ({ extraDays }: { extraDays: number }) => {
|
||||
const { timezone } = useTimePreferences();
|
||||
@@ -125,6 +129,7 @@ export const LargeCalendar = ({ extraDays }: { extraDays: number }) => {
|
||||
hoverEventDuration={30}
|
||||
hideHeader
|
||||
timezone={timezone}
|
||||
renderOutOfOffice={(props) => <OutOfOfficeInSlots {...props} />}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
+2
@@ -39,6 +39,7 @@ function CalendarInner(props: CalendarComponentProps) {
|
||||
const borderColor = useCalendarStore((state) => state.borderColor ?? "default");
|
||||
const scrollToCurrentTime = useCalendarStore((state) => state.scrollToCurrentTime ?? true);
|
||||
const updateCurrentTimeOnFocus = useCalendarStore((state) => state.updateCurrentTimeOnFocus ?? false);
|
||||
const renderOutOfOffice = useCalendarStore((state) => state.renderOutOfOffice);
|
||||
|
||||
const days = useMemo(() => getDaysBetweenDates(startDate, endDate), [startDate, endDate]);
|
||||
|
||||
@@ -148,6 +149,7 @@ function CalendarInner(props: CalendarComponentProps) {
|
||||
day={days[i]}
|
||||
startHour={startHour}
|
||||
availableSlots={availableTimeslots}
|
||||
renderOutOfOffice={renderOutOfOffice}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
+3
-5
@@ -1,11 +1,9 @@
|
||||
import React from "react";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import type { BorderColor } from "@calcom/features/calendars/weeklyview/types/common";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import type React from "react";
|
||||
|
||||
type Props = {
|
||||
showBorder: boolean;
|
||||
@@ -0,0 +1,67 @@
|
||||
import type { OutOfOfficeRenderProps } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import ServerTrans from "@calcom/lib/components/ServerTrans";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
export function DefaultOutOfOfficeSlot(props: OutOfOfficeRenderProps) {
|
||||
const { t } = useLocale();
|
||||
const {
|
||||
fromUser,
|
||||
toUser,
|
||||
emoji = "\u{1F3DD}\uFE0F",
|
||||
reason,
|
||||
borderDashed = true,
|
||||
className,
|
||||
notes,
|
||||
showNotePublicly,
|
||||
} = props;
|
||||
|
||||
const isHoliday = !fromUser && reason;
|
||||
|
||||
if (!isHoliday && !fromUser) return null;
|
||||
|
||||
return (
|
||||
<div className={classNames("relative h-full pb-5", className)}>
|
||||
<div
|
||||
className={classNames(
|
||||
"flex h-full flex-col items-center justify-start rounded-md border bg-white px-4 py-4 font-normal dark:bg-transparent",
|
||||
borderDashed && "border-dashed"
|
||||
)}>
|
||||
<div className="bg-emphasis flex h-14 w-14 flex-col items-center justify-center rounded-full">
|
||||
<span className="m-auto text-center text-lg">{emoji}</span>
|
||||
</div>
|
||||
<div className="stack-y-2 max-h-[300px] w-full overflow-y-auto text-center">
|
||||
{isHoliday ? (
|
||||
<>
|
||||
<p className="mt-2 text-base font-bold">{reason}</p>
|
||||
<p className="text-subtle text-center text-sm">{t("holiday_no_availability")}</p>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<p className="mt-2 text-base font-bold">
|
||||
{t("ooo_user_is_ooo", { displayName: fromUser?.displayName })}
|
||||
</p>
|
||||
|
||||
{notes && showNotePublicly && (
|
||||
<p className="text-subtle mt-2 max-h-[120px] overflow-y-auto break-words px-2 text-center text-sm italic">
|
||||
{notes}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{fromUser?.displayName && toUser?.displayName && (
|
||||
<p className="text-center text-sm">
|
||||
<ServerTrans
|
||||
t={t}
|
||||
i18nKey="ooo_slots_returning"
|
||||
values={{ displayName: toUser.displayName }}
|
||||
components={[<strong key="username">username</strong>]}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+2
-4
@@ -1,9 +1,7 @@
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import { useMemo } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import { BlockedTimeCell } from "./BlockedTimeCell";
|
||||
|
||||
type Props = {
|
||||
+29
-19
@@ -1,16 +1,18 @@
|
||||
import { useMemo } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import type { Dayjs } from "@calcom/dayjs";
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import { OutOfOfficeInSlots } from "@calcom/web/modules/bookings/components/OutOfOfficeInSlots";
|
||||
import { DefaultOutOfOfficeSlot } from "@calcom/features/calendars/weeklyview/components/DefaultOutOfOfficeSlot";
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import type { CalendarAvailableTimeslots } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import type {
|
||||
CalendarAvailableTimeslots,
|
||||
OutOfOfficeRenderProps,
|
||||
} from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import type { GridCellToDateProps } from "@calcom/features/calendars/weeklyview/utils";
|
||||
import { gridCellToDateTime } from "@calcom/features/calendars/weeklyview/utils";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import type { ReactNode } from "react";
|
||||
import { useMemo } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
type EmptyCellProps = GridCellToDateProps & {
|
||||
isDisabled?: boolean;
|
||||
@@ -37,9 +39,16 @@ type AvailableCellProps = {
|
||||
availableSlots: CalendarAvailableTimeslots;
|
||||
day: GridCellToDateProps["day"];
|
||||
startHour: GridCellToDateProps["startHour"];
|
||||
renderOutOfOffice?: (props: OutOfOfficeRenderProps) => ReactNode;
|
||||
};
|
||||
|
||||
export function AvailableCellsForDay({ timezone, availableSlots, day, startHour }: AvailableCellProps) {
|
||||
export function AvailableCellsForDay({
|
||||
timezone,
|
||||
availableSlots,
|
||||
day,
|
||||
startHour,
|
||||
renderOutOfOffice,
|
||||
}: AvailableCellProps) {
|
||||
const date = dayjs(day);
|
||||
const dateFormatted = date.format("YYYY-MM-DD");
|
||||
const slotsForToday = availableSlots && availableSlots[dateFormatted];
|
||||
@@ -98,22 +107,23 @@ export function AvailableCellsForDay({ timezone, availableSlots, day, startHour
|
||||
|
||||
if (slots.startEndTimeDuration) {
|
||||
const { firstSlot, startEndTimeDuration } = slots;
|
||||
const renderOOO = renderOutOfOffice ?? ((p: OutOfOfficeRenderProps) => <DefaultOutOfOfficeSlot {...p} />);
|
||||
return (
|
||||
<CustomCell
|
||||
timeSlot={dayjs(firstSlot?.start).tz(slots.timezone)}
|
||||
topOffsetMinutes={slots.slots[0]?.topOffsetMinutes}
|
||||
startEndTimeDuration={startEndTimeDuration}>
|
||||
<OutOfOfficeInSlots
|
||||
fromUser={firstSlot?.fromUser}
|
||||
toUser={firstSlot?.toUser}
|
||||
reason={firstSlot?.reason}
|
||||
emoji={firstSlot?.emoji}
|
||||
notes={firstSlot?.notes}
|
||||
showNotePublicly={firstSlot?.showNotePublicly}
|
||||
borderDashed={false}
|
||||
date={dateFormatted}
|
||||
className="pb-0"
|
||||
/>
|
||||
{renderOOO({
|
||||
fromUser: firstSlot?.fromUser,
|
||||
toUser: firstSlot?.toUser,
|
||||
reason: firstSlot?.reason,
|
||||
emoji: firstSlot?.emoji,
|
||||
notes: firstSlot?.notes,
|
||||
showNotePublicly: firstSlot?.showNotePublicly,
|
||||
borderDashed: false,
|
||||
date: dateFormatted,
|
||||
className: "pb-0",
|
||||
})}
|
||||
</CustomCell>
|
||||
);
|
||||
}
|
||||
+3
-5
@@ -1,11 +1,9 @@
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import { calculateEventLayouts, createLayoutMap } from "@calcom/features/calendars/weeklyview/utils/overlap";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { shallow } from "zustand/shallow";
|
||||
import { Event } from "./Event";
|
||||
|
||||
type Props = {
|
||||
+1
-2
@@ -1,9 +1,8 @@
|
||||
import dayjs from "@calcom/dayjs";
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
import { Button } from "@calcom/ui/components/button";
|
||||
import { ButtonGroup } from "@calcom/ui/components/buttonGroup";
|
||||
|
||||
import { useCalendarStore } from "@calcom/features/calendars/weeklyview/state/store";
|
||||
|
||||
export function SchedulerHeading() {
|
||||
const { startDate, endDate, handleDateChange } = useCalendarStore((state) => ({
|
||||
startDate: dayjs(state.startDate),
|
||||
+2
-4
@@ -1,10 +1,8 @@
|
||||
import { useId } from "react";
|
||||
|
||||
import type dayjs from "@calcom/dayjs";
|
||||
import { useTimePreferences } from "@calcom/features/bookings/lib";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import type { BorderColor } from "@calcom/features/calendars/weeklyview/types/common";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
import { useId } from "react";
|
||||
|
||||
export const HorizontalLines = ({
|
||||
hours,
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
import type dayjs from "@calcom/dayjs";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
import type { BorderColor } from "@calcom/features/calendars/weeklyview/types/common";
|
||||
import classNames from "@calcom/ui/classNames";
|
||||
|
||||
export const VerticalLines = ({ days, borderColor }: { days: dayjs.Dayjs[]; borderColor: BorderColor }) => {
|
||||
const isRTL = () => {
|
||||
@@ -1,8 +1,23 @@
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
import type { IFromUser, IToUser } from "@calcom/features/availability/lib/getUserAvailability";
|
||||
import type { TimeRange } from "@calcom/types/schedule";
|
||||
|
||||
import type { BorderColor } from "./common";
|
||||
import type { CalendarEvent } from "./events";
|
||||
|
||||
export type OutOfOfficeRenderProps = {
|
||||
date: string;
|
||||
fromUser?: IFromUser;
|
||||
toUser?: IToUser;
|
||||
emoji?: string;
|
||||
reason?: string;
|
||||
notes?: string | null;
|
||||
showNotePublicly?: boolean;
|
||||
borderDashed?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export type View = "month" | "week" | "day";
|
||||
export type Hours =
|
||||
| 0
|
||||
@@ -162,6 +177,11 @@ export type CalendarState = {
|
||||
* @default false
|
||||
*/
|
||||
updateCurrentTimeOnFocus?: boolean;
|
||||
/**
|
||||
* Render function for out-of-office slots.
|
||||
* Web consumers pass OutOfOfficeInSlots, atoms/platform can pass their own or null.
|
||||
*/
|
||||
renderOutOfOffice?: (props: OutOfOfficeRenderProps) => ReactNode;
|
||||
};
|
||||
|
||||
export type CalendarComponentProps = CalendarPublicActions & CalendarState & { isPending?: boolean };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Header } from "@calcom/features/bookings/components/Header";
|
||||
import { BookerSection } from "@calcom/features/bookings/components/Section";
|
||||
import { LargeCalendar } from "@calcom/web/modules/calendar-view/components/LargeCalendar";
|
||||
import { LargeCalendar } from "./components/LargeCalendar";
|
||||
import { bookerLayoutOptions } from "@calcom/prisma/zod-utils";
|
||||
|
||||
import { AtomsWrapper } from "../src/components/atoms-wrapper";
|
||||
|
||||
@@ -10,7 +10,7 @@ import { BookerSection } from "@calcom/features/bookings/components/Section";
|
||||
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 { LargeCalendar } from "./components/LargeCalendar";
|
||||
import { getUsernameList } from "@calcom/features/eventtypes/lib/defaultEvents";
|
||||
import { useTimesForSchedule } from "@calcom/features/schedules/hooks/useTimesForSchedule";
|
||||
|
||||
|
||||
+4
-4
@@ -4,14 +4,14 @@ import dayjs from "@calcom/dayjs";
|
||||
import { useBookerStoreContext } from "@calcom/features/bookings/Booker/BookerStoreProvider";
|
||||
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 { Calendar } from "@calcom/features/calendars/weeklyview/components/Calendar";
|
||||
import type { CalendarAvailableTimeslots } from "@calcom/features/calendars/weeklyview/types/state";
|
||||
import { localStorage } from "@calcom/lib/webstorage";
|
||||
import type { BookingStatus } from "@calcom/prisma/enums";
|
||||
|
||||
import { useBookings } from "@calcom/atoms/hooks/bookings/useBookings";
|
||||
import { useCalendarsBusyTimes } from "@calcom/atoms/hooks/useCalendarsBusyTimes";
|
||||
import { useConnectedCalendars } from "@calcom/atoms/hooks/useConnectedCalendars";
|
||||
import { useBookings } from "../../hooks/bookings/useBookings";
|
||||
import { useCalendarsBusyTimes } from "../../hooks/useCalendarsBusyTimes";
|
||||
import { useConnectedCalendars } from "../../hooks/useConnectedCalendars";
|
||||
import { getQueryParam } from "@calcom/features/bookings/Booker/utils/query-param";
|
||||
|
||||
export const LargeCalendar = ({
|
||||
Reference in New Issue
Block a user