3a84756872
Co-authored-by: lethemanh <lethemanh@lethemanhs-MacBook-Pro.local>
269 lines
7.9 KiB
TypeScript
269 lines
7.9 KiB
TypeScript
import { AppDispatch } from "@/app/store";
|
|
import { User } from "@/components/Attendees/PeopleSearch";
|
|
import { formatLocalDateTime } from "@/components/Event/utils/dateTimeFormatters";
|
|
import { Calendar } from "@/features/Calendars/CalendarTypes";
|
|
import {
|
|
getEventAsync,
|
|
putEventAsync,
|
|
updateEventInstanceAsync,
|
|
updateSeriesAsync,
|
|
} from "@/features/Calendars/services";
|
|
import { getEvent } from "@/features/Events/EventApi";
|
|
import { CalendarEvent } from "@/features/Events/EventsTypes";
|
|
import { updateAttendeesAfterTimeChange } from "@/features/Events/updateEventHelpers/updateAttendeesAfterTimeChange";
|
|
import {
|
|
AttendeeOptions,
|
|
createAttendee,
|
|
} from "@/features/User/models/attendee.mapper";
|
|
import { getDeltaInMilliseconds } from "@/utils/dateUtils";
|
|
import {
|
|
CalendarApi,
|
|
DateSelectArg,
|
|
EventClickArg,
|
|
EventDropArg,
|
|
} from "@fullcalendar/core";
|
|
import { EventResizeDoneArg } from "@fullcalendar/interaction";
|
|
|
|
export interface EventHandlersProps {
|
|
setSelectedRange: (range: DateSelectArg | null) => void;
|
|
setAnchorEl: (el: HTMLElement | null) => void;
|
|
calendarRef: React.RefObject<CalendarApi | null>;
|
|
dispatch: AppDispatch;
|
|
setOpenEventDisplay: (open: boolean) => void;
|
|
setEventDisplayedId: (id: string) => void;
|
|
setEventDisplayedCalId: (id: string) => void;
|
|
setEventDisplayedTemp: (temp: boolean) => void;
|
|
calendars: Record<string, Calendar>;
|
|
setSelectedEvent: (event: CalendarEvent) => void;
|
|
setAfterChoiceFunc: (
|
|
func: ((type: "solo" | "all" | undefined) => void) | undefined
|
|
) => void;
|
|
setOpenEditModePopup: (open: string) => void;
|
|
tempUsers: User[];
|
|
setTempEvent: (event: CalendarEvent) => void;
|
|
timezone: string;
|
|
}
|
|
|
|
export const createEventHandlers = (props: EventHandlersProps) => {
|
|
const {
|
|
setSelectedRange,
|
|
setAnchorEl,
|
|
calendarRef,
|
|
dispatch,
|
|
setOpenEventDisplay,
|
|
setEventDisplayedId,
|
|
setEventDisplayedCalId,
|
|
setEventDisplayedTemp,
|
|
calendars,
|
|
setSelectedEvent,
|
|
setAfterChoiceFunc,
|
|
setOpenEditModePopup,
|
|
tempUsers,
|
|
setTempEvent,
|
|
timezone,
|
|
} = props;
|
|
|
|
const handleDateSelect = (selectInfo: DateSelectArg) => {
|
|
setSelectedRange(selectInfo);
|
|
if (tempUsers) {
|
|
const newEvent: CalendarEvent = {
|
|
start: selectInfo?.start
|
|
? formatLocalDateTime(selectInfo?.start, timezone)
|
|
: "",
|
|
end: selectInfo?.end
|
|
? formatLocalDateTime(selectInfo?.end, timezone)
|
|
: "",
|
|
attendee: tempUsers.map((user) => {
|
|
const attendeeOption: AttendeeOptions = {
|
|
cal_address: user.email,
|
|
cn: user.displayName,
|
|
rsvp: "TRUE",
|
|
};
|
|
|
|
if (user.objectType === "resource") {
|
|
attendeeOption.cutype = "RESOURCE";
|
|
}
|
|
return createAttendee(attendeeOption);
|
|
}),
|
|
} as CalendarEvent;
|
|
|
|
setTempEvent(newEvent);
|
|
}
|
|
setAnchorEl(document.body);
|
|
};
|
|
|
|
const handleClosePopover = () => {
|
|
calendarRef.current?.unselect();
|
|
setAnchorEl(null);
|
|
setSelectedRange(null);
|
|
};
|
|
|
|
const handleCloseEventDisplay = () => {
|
|
setOpenEventDisplay(false);
|
|
};
|
|
|
|
const handleEventClick = (info: EventClickArg) => {
|
|
info.jsEvent.preventDefault();
|
|
|
|
if (info.event.url) {
|
|
window.open(info.event.url);
|
|
} else {
|
|
setOpenEventDisplay(true);
|
|
if (
|
|
calendars[info.event.extendedProps.calId] &&
|
|
calendars[info.event.extendedProps.calId].events[
|
|
info.event.extendedProps.uid
|
|
]
|
|
) {
|
|
dispatch(
|
|
getEventAsync(
|
|
calendars[info.event.extendedProps.calId].events[
|
|
info.event.extendedProps.uid
|
|
]
|
|
)
|
|
);
|
|
}
|
|
|
|
setEventDisplayedId(info.event.extendedProps.uid);
|
|
setEventDisplayedCalId(info.event.extendedProps.calId);
|
|
setEventDisplayedTemp(info.event._def.extendedProps.temp);
|
|
}
|
|
};
|
|
|
|
const handleEventAllow = () => {
|
|
return true;
|
|
};
|
|
|
|
const handleEventDrop = async (arg: EventDropArg) => {
|
|
if (!arg.event || !arg.event._def || !arg.event._def.extendedProps) {
|
|
return;
|
|
}
|
|
|
|
const event =
|
|
calendars[arg.event._def.extendedProps.calId].events[
|
|
arg.event._def.extendedProps.uid
|
|
];
|
|
const calendar = calendars[arg.event._def.extendedProps.calId];
|
|
|
|
const isRecurring = event.uid.includes("/");
|
|
const totalDeltaMs = getDeltaInMilliseconds(arg.delta);
|
|
|
|
const originalStart = new Date(event.start);
|
|
const computedNewStart = new Date(originalStart.getTime() + totalDeltaMs);
|
|
const originalEnd = new Date(event.end ?? "");
|
|
const computedNewEnd = new Date(originalEnd.getTime() + totalDeltaMs);
|
|
const newEvent = updateAttendeesAfterTimeChange(
|
|
{
|
|
...event,
|
|
start: computedNewStart.toISOString(),
|
|
end: computedNewEnd.toISOString(),
|
|
sequence: (event.sequence ?? 1) + 1,
|
|
} as CalendarEvent,
|
|
true
|
|
);
|
|
if (isRecurring) {
|
|
setSelectedEvent(event);
|
|
setOpenEditModePopup("edit");
|
|
setAfterChoiceFunc(
|
|
() => async (typeOfAction: "solo" | "all" | undefined) => {
|
|
if (typeOfAction === "solo") {
|
|
await dispatch(
|
|
updateEventInstanceAsync({ cal: calendar, event: newEvent })
|
|
);
|
|
} else if (typeOfAction === "all") {
|
|
const master = await getEvent(newEvent, true);
|
|
await dispatch(
|
|
updateSeriesAsync({
|
|
cal: calendar,
|
|
event: {
|
|
...master,
|
|
start: computedNewStart.toISOString(),
|
|
end: computedNewEnd.toISOString(),
|
|
sequence: (master.sequence ?? 1) + 1,
|
|
},
|
|
})
|
|
);
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
await dispatch(
|
|
putEventAsync({ cal: calendars[newEvent.calId], newEvent })
|
|
);
|
|
}
|
|
};
|
|
|
|
const handleEventResize = async (arg: EventResizeDoneArg) => {
|
|
if (!arg.event || !arg.event._def || !arg.event._def.extendedProps) {
|
|
return;
|
|
}
|
|
|
|
const event =
|
|
calendars[arg.event._def.extendedProps.calId].events[
|
|
arg.event._def.extendedProps.uid
|
|
];
|
|
const calendar = calendars[arg.event._def.extendedProps.calId];
|
|
|
|
const isRecurring = event.uid.includes("/");
|
|
|
|
const originalStart = new Date(event.start);
|
|
const computedNewStart = new Date(
|
|
originalStart.getTime() + getDeltaInMilliseconds(arg.startDelta)
|
|
);
|
|
const originalEnd = new Date(event.end ?? "");
|
|
const computedNewEnd = new Date(
|
|
originalEnd.getTime() + getDeltaInMilliseconds(arg.endDelta)
|
|
);
|
|
const newEvent = updateAttendeesAfterTimeChange(
|
|
{
|
|
...event,
|
|
start: computedNewStart.toISOString(),
|
|
end: computedNewEnd.toISOString(),
|
|
sequence: (event.sequence ?? 1) + 1,
|
|
} as CalendarEvent,
|
|
true
|
|
);
|
|
if (isRecurring) {
|
|
setSelectedEvent(event);
|
|
setOpenEditModePopup("edit");
|
|
setAfterChoiceFunc(
|
|
() => async (typeOfAction: "solo" | "all" | undefined) => {
|
|
if (typeOfAction === "solo") {
|
|
await dispatch(
|
|
updateEventInstanceAsync({ cal: calendar, event: newEvent })
|
|
);
|
|
} else if (typeOfAction === "all") {
|
|
const master = await getEvent(newEvent, true);
|
|
|
|
await dispatch(
|
|
updateSeriesAsync({
|
|
cal: calendar,
|
|
event: {
|
|
...master,
|
|
start: computedNewStart.toISOString(),
|
|
end: computedNewEnd.toISOString(),
|
|
sequence: (master.sequence ?? 1) + 1,
|
|
},
|
|
})
|
|
);
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
await dispatch(
|
|
putEventAsync({ cal: calendars[newEvent.calId], newEvent })
|
|
);
|
|
}
|
|
};
|
|
|
|
return {
|
|
handleDateSelect,
|
|
handleClosePopover,
|
|
handleCloseEventDisplay,
|
|
handleEventClick,
|
|
handleEventAllow,
|
|
handleEventDrop,
|
|
handleEventResize,
|
|
};
|
|
};
|