From 322840a010efcd3046211fb92c5f19584c74def7 Mon Sep 17 00:00:00 2001 From: Kevin Wu Date: Sun, 8 Dec 2024 12:20:05 -0800 Subject: [PATCH] feat: event wrapper --- .../src/components/Calendar/CalendarRoot.tsx | 6 ++- .../calendar-course-event-wrapper.tsx | 46 +++++++++++++++++++ .../Calendar/calendar-event-popover.tsx | 4 +- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 apps/antalmanac/src/components/Calendar/calendar-course-event-wrapper.tsx diff --git a/apps/antalmanac/src/components/Calendar/CalendarRoot.tsx b/apps/antalmanac/src/components/Calendar/CalendarRoot.tsx index 381bb7241..3c6b64c06 100644 --- a/apps/antalmanac/src/components/Calendar/CalendarRoot.tsx +++ b/apps/antalmanac/src/components/Calendar/CalendarRoot.tsx @@ -11,6 +11,7 @@ import { CalendarToolbar } from './CalendarToolbar'; import { CalendarEvent, CourseEvent } from './CourseCalendarEvent'; import { CalendarCourseEvent } from '$components/Calendar/calendar-course-event'; +import { CalendarCourseEventWrapper } from '$components/Calendar/calendar-course-event-wrapper'; import { CalendarEventPopover } from '$components/Calendar/calendar-event-popover'; import { getDefaultFinalsStartDate, getFinalsStartDateForTerm } from '$lib/termData'; import AppStore from '$stores/AppStore'; @@ -19,7 +20,10 @@ import { useTimeFormatStore } from '$stores/SettingsStore'; const localizer = momentLocalizer(moment); const views = [Views.WEEK, Views.WORK_WEEK]; -const components = { event: CalendarCourseEvent }; +const components = { + event: CalendarCourseEvent, + eventWrapper: CalendarCourseEventWrapper, +}; const max = new Date(2018, 0, 1, 23); export const ScheduleCalendar = memo(() => { diff --git a/apps/antalmanac/src/components/Calendar/calendar-course-event-wrapper.tsx b/apps/antalmanac/src/components/Calendar/calendar-course-event-wrapper.tsx new file mode 100644 index 000000000..3f9951602 --- /dev/null +++ b/apps/antalmanac/src/components/Calendar/calendar-course-event-wrapper.tsx @@ -0,0 +1,46 @@ +import { Box } from '@mui/material'; +import { useCallback, useEffect, useRef } from 'react'; +import { EventWrapperProps } from 'react-big-calendar'; +import { shallow } from 'zustand/shallow'; + +import type { CalendarEvent } from '$components/Calendar/CourseCalendarEvent'; +import { useSelectedEventStore } from '$stores/SelectedEventStore'; + +interface CalendarCourseEventWrapperProps extends EventWrapperProps { + children?: React.ReactNode; +} + +/** + * CalendarCourseEventWrapper allows us to override the default onClick event behavior which problamtically rerenders the entire calendar + */ +export const CalendarCourseEventWrapper = ({ children, ...props }: CalendarCourseEventWrapperProps) => { + const ref = useRef(null); + + const setSelectedEvent = useSelectedEventStore((state) => state.setSelectedEvent, shallow); + + const handleClick = useCallback( + (e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + + setSelectedEvent(e, props.event); + }, + [props.event, setSelectedEvent] + ); + + useEffect(() => { + const node = ref.current; + if (!node) { + return; + } + + const rbcEvent = node.querySelector('.rbc-event') as HTMLDivElement; + if (!rbcEvent) { + return; + } + + rbcEvent.onclick = (e) => handleClick(e as unknown as React.MouseEvent); // the native onclick requires a little type hacking + }, [handleClick]); + + return {children}; +}; diff --git a/apps/antalmanac/src/components/Calendar/calendar-event-popover.tsx b/apps/antalmanac/src/components/Calendar/calendar-event-popover.tsx index 3c72727be..788578aea 100644 --- a/apps/antalmanac/src/components/Calendar/calendar-event-popover.tsx +++ b/apps/antalmanac/src/components/Calendar/calendar-event-popover.tsx @@ -40,8 +40,8 @@ export function CalendarEventPopover() { open={Boolean(anchorEl) && !!selectedEvent} onClose={handleClosePopover} anchorOrigin={{ - vertical: 'bottom', - horizontal: 'left', + vertical: 'top', + horizontal: 'right', }} transformOrigin={{ vertical: 'top',