refactor recurring event modification (#173)

This commit is contained in:
Camille Moussu
2025-10-07 18:16:00 +02:00
committed by GitHub
parent 3f8f3eff23
commit c86db8fa49
15 changed files with 1924 additions and 176 deletions
+21
View File
@@ -33,6 +33,7 @@ import {
} from "./utils/calendarUtils";
import { useCalendarEventHandlers } from "./hooks/useCalendarEventHandlers";
import { useCalendarViewHandlers } from "./hooks/useCalendarViewHandlers";
import { EditModeDialog } from "../Event/EditModeDialog";
interface CalendarAppProps {
calendarRef: React.RefObject<CalendarApi | null>;
@@ -166,6 +167,14 @@ export default function CalendarApp({
const [eventDisplayedId, setEventDisplayedId] = useState("");
const [eventDisplayedTemp, setEventDisplayedTemp] = useState(false);
const [eventDisplayedCalId, setEventDisplayedCalId] = useState("");
const [openEditModePopup, setOpenEditModePopup] = useState<string | null>(
null
);
const [, setTypeOfAction] = useState<"solo" | "all" | undefined>(undefined);
const [afterChoiceFunc, setAfterChoiceFunc] = useState<Function>();
const [selectedEvent, setSelectedEvent] = useState<CalendarEvent>(
{} as CalendarEvent
);
const [selectedRange, setSelectedRange] = useState<DateSelectArg | null>(
null
);
@@ -188,6 +197,9 @@ export default function CalendarApp({
setEventDisplayedCalId,
setEventDisplayedTemp,
calendars,
setSelectedEvent,
setAfterChoiceFunc,
setOpenEditModePopup,
});
// View handlers
@@ -422,6 +434,15 @@ export default function CalendarApp({
calendarRef={calendarRef}
event={tempEvent}
/>
<EditModeDialog
type={openEditModePopup}
setOpen={setOpenEditModePopup}
event={selectedEvent}
eventAction={(type: "solo" | "all" | undefined) => {
setTypeOfAction(type);
afterChoiceFunc && afterChoiceFunc(type);
}}
/>
{openEventDisplay && eventDisplayedId && eventDisplayedCalId && (
<EventPreviewModal
eventId={eventDisplayedId}
@@ -5,11 +5,14 @@ import { Calendars } from "../../../features/Calendars/CalendarTypes";
import { getDeltaInMilliseconds } from "../../../utils/dateUtils";
import {
getCalendarDetailAsync,
getEventAsync,
putEventAsync,
updateEventInstanceAsync,
updateEventLocal,
updateSeriesAsync,
} from "../../../features/Calendars/CalendarSlice";
import { formatDateToYYYYMMDDTHHMMSS } from "../../../utils/dateUtils";
import { getEvent } from "../../../features/Events/EventApi";
import { refreshCalendars } from "../../Event/utils/eventUtils";
export interface EventHandlersProps {
setSelectedRange: (range: DateSelectArg | null) => void;
@@ -24,6 +27,9 @@ export interface EventHandlersProps {
setEventDisplayedCalId: (id: string) => void;
setEventDisplayedTemp: (temp: boolean) => void;
calendars: Record<string, Calendars>;
setSelectedEvent: (event: CalendarEvent) => void;
setAfterChoiceFunc: (func: Function) => void;
setOpenEditModePopup: (open: string) => void;
}
export const createEventHandlers = (props: EventHandlersProps) => {
@@ -40,6 +46,9 @@ export const createEventHandlers = (props: EventHandlersProps) => {
setEventDisplayedCalId,
setEventDisplayedTemp,
calendars,
setSelectedEvent,
setAfterChoiceFunc,
setOpenEditModePopup,
} = props;
const handleDateSelect = (selectInfo: DateSelectArg) => {
@@ -113,12 +122,6 @@ export const createEventHandlers = (props: EventHandlersProps) => {
};
const handleEventAllow = (dropInfo: any, draggedEvent: any) => {
if (
draggedEvent?.extendedProps.uid &&
draggedEvent.extendedProps.uid.split("/")[1]
) {
return false;
}
return true;
};
@@ -131,7 +134,9 @@ export const createEventHandlers = (props: EventHandlersProps) => {
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);
@@ -143,8 +148,43 @@ export const createEventHandlers = (props: EventHandlersProps) => {
start: computedNewStart.toISOString(),
end: computedNewEnd.toISOString(),
} as CalendarEvent;
dispatch(updateEventLocal({ calId: newEvent.calId, event: newEvent }));
dispatch(putEventAsync({ cal: calendars[newEvent.calId], newEvent }));
if (isRecurring) {
setSelectedEvent(event);
setOpenEditModePopup("edit");
setAfterChoiceFunc(
() => async (typeOfAction: "solo" | "all" | undefined) => {
if (typeOfAction === "solo") {
dispatch(
updateEventInstanceAsync({ cal: calendar, event: newEvent })
);
dispatch(
updateEventLocal({ calId: newEvent.calId, 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(),
},
})
);
await refreshCalendars(
dispatch,
Object.values(calendars),
calendarRange
);
}
}
);
} else {
dispatch(updateEventLocal({ calId: newEvent.calId, event: newEvent }));
dispatch(putEventAsync({ cal: calendars[newEvent.calId], newEvent }));
}
};
const handleEventResize = (arg: any) => {
@@ -156,9 +196,10 @@ export const createEventHandlers = (props: EventHandlersProps) => {
calendars[arg.event._def.extendedProps.calId].events[
arg.event._def.extendedProps.uid
];
if (event.uid.split("/")[1]) {
dispatch(getEventAsync(event));
}
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)
@@ -173,7 +214,42 @@ export const createEventHandlers = (props: EventHandlersProps) => {
end: computedNewEnd.toISOString(),
} as CalendarEvent;
dispatch(putEventAsync({ cal: calendars[newEvent.calId], newEvent }));
if (isRecurring) {
setSelectedEvent(event);
setOpenEditModePopup("edit");
setAfterChoiceFunc(
() => async (typeOfAction: "solo" | "all" | undefined) => {
if (typeOfAction === "solo") {
dispatch(
updateEventInstanceAsync({ cal: calendar, event: newEvent })
);
dispatch(
updateEventLocal({ calId: newEvent.calId, 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(),
},
})
);
await refreshCalendars(
dispatch,
Object.values(calendars),
calendarRange
);
}
}
);
} else {
dispatch(putEventAsync({ cal: calendars[newEvent.calId], newEvent }));
}
};
return {
@@ -37,6 +37,9 @@ export const useCalendarEventHandlers = (props: EventHandlersProps) => {
handleEventDrop: useCallback(eventHandlers.handleEventDrop, [
props.calendars,
props.dispatch,
props.setSelectedEvent,
props.setOpenEditModePopup,
props.setAfterChoiceFunc,
]),
handleEventResize: useCallback(eventHandlers.handleEventResize, [
props.calendars,