Files
workavia-calendar-front/src/components/Calendar/handlers/viewHandlers.ts
T
Camille Moussu cfb2b59584 [DELEGATION] Edit attendance and events, delete event for someone (#553)
* [#523] added way to manage attendance for delegated calendars

* [DELEGATION] #523 & #524 changed eventURL calculation for delegated events to have the rigth one

* [#524] added drag and drop authorisation to delegated event

* [#524] added tests

* [#524] support for the permission access

* [#524] no edit when delegated event is not public
2026-02-19 09:50:29 +01:00

165 lines
4.6 KiB
TypeScript

import { EventErrorHandler } from "@/components/Error/EventErrorHandler";
import { EventChip } from "@/components/Event/EventChip/EventChip";
import { Calendar } from "@/features/Calendars/CalendarTypes";
import { userAttendee } from "@/features/User/models/attendee";
import {
CalendarApi,
DayHeaderMountArg,
EventContentArg,
EventMountArg,
NowIndicatorContentArg,
ViewMountArg,
} from "@fullcalendar/core";
import React from "react";
import { createMouseHandlers } from "./mouseHandlers";
export interface ViewHandlersProps {
calendarRef: React.RefObject<CalendarApi | null>;
setSelectedDate: (date: Date) => void;
setSelectedMiniDate: (date: Date) => void;
onViewChange?: (view: string) => void;
calendars: Record<string, Calendar>;
tempcalendars: Record<string, Calendar>;
errorHandler: EventErrorHandler;
}
export const createViewHandlers = (props: ViewHandlersProps) => {
const {
calendarRef,
setSelectedDate,
setSelectedMiniDate,
onViewChange,
calendars,
tempcalendars,
errorHandler,
} = props;
const handleNowIndicatorContent = (arg: NowIndicatorContentArg) => {
if (arg.isAxis) {
return React.createElement(
"div",
{ style: { display: "flex", alignItems: "center" } },
React.createElement(
"div",
{ className: "now-time-label" },
new Date().toLocaleTimeString(undefined, {
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: arg.view.dateEnv.timeZone,
})
)
);
}
};
const handleDayHeaderDidMount = (arg: DayHeaderMountArg) => {
if (arg.view.type === "timeGridWeek") {
const headerEl = arg.el;
const handleDayHeaderClick = () => {
calendarRef.current?.changeView("timeGridDay", arg.date);
setSelectedDate(new Date(arg.date));
setSelectedMiniDate(new Date(arg.date));
if (onViewChange) {
onViewChange("timeGridDay");
}
};
headerEl.addEventListener("click", handleDayHeaderClick);
headerEl.__dayHeaderClickHandler = handleDayHeaderClick;
}
};
const handleDayHeaderWillUnmount = (arg: DayHeaderMountArg) => {
const headerEl = arg.el;
if (headerEl.__dayHeaderClickHandler) {
headerEl.removeEventListener("click", headerEl.__dayHeaderClickHandler);
delete headerEl.__dayHeaderClickHandler;
}
};
const handleViewDidMount = (arg: ViewMountArg) => {
if (arg.view.type === "timeGridWeek" || arg.view.type === "timeGridDay") {
const calendarEl = document.querySelector(".fc") as HTMLElement;
if (calendarEl) {
const mouseHandlers = createMouseHandlers({ calendarEl });
mouseHandlers.addMouseEventListeners();
}
}
};
const handleViewWillUnmount = (arg: ViewMountArg) => {
if (arg.el.__timeInterval) {
clearInterval(arg.el.__timeInterval);
delete arg.el.__timeInterval;
}
if (arg.el.__timeObserver) {
arg.el.__timeObserver.disconnect();
delete arg.el.__timeObserver;
}
const calendarEl = document.querySelector(".fc") as HTMLElement;
if (calendarEl) {
const mouseHandlers = createMouseHandlers({ calendarEl });
mouseHandlers.removeMouseEventListeners();
}
};
const handleEventContent = (arg: EventContentArg) => {
return React.createElement(EventChip, {
arg,
calendars,
tempcalendars,
errorHandler,
});
};
const handleEventDidMount = (arg: EventMountArg) => {
const attendees = arg.event._def.extendedProps.attendee || [];
if (!calendars[arg.event._def.extendedProps.calId]) return;
const ownerEmails = new Set(
calendars[arg.event._def.extendedProps.calId].owner?.emails?.map(
(email) => email.toLowerCase()
)
);
const showSpecialDisplay = attendees.filter((att: userAttendee) =>
ownerEmails.has(att.cal_address.toLowerCase())
);
if (!showSpecialDisplay[0]) return;
arg.el.classList.remove(
"declined-event",
"tentative-event",
"needs-action-event"
);
switch (showSpecialDisplay[0].partstat) {
case "DECLINED":
arg.el.classList.add("declined-event");
break;
case "TENTATIVE":
arg.el.classList.add("tentative-event");
break;
case "NEEDS-ACTION":
arg.el.classList.add("needs-action-event");
break;
default:
break;
}
};
return {
handleNowIndicatorContent,
handleDayHeaderDidMount,
handleDayHeaderWillUnmount,
handleViewDidMount,
handleViewWillUnmount,
handleEventContent,
handleEventDidMount,
};
};