Files
workavia-calendar-front/src/components/Calendar/handlers/mouseHandlers.ts
T
lenhanphung 1228f0a50e Update calendar hover and slot label opacity logic
- Update hover effect to highlight 30-minute time slots instead of 1-hour slots
- Reset slot label opacity to full visibility when viewing other weeks/days
2025-10-02 14:19:05 +07:00

106 lines
3.2 KiB
TypeScript

export interface MouseHandlersProps {
calendarEl: HTMLElement;
}
export const createMouseHandlers = (props: MouseHandlersProps) => {
const { calendarEl } = props;
const handleMouseMove = (e: MouseEvent) => {
const timegridEl = calendarEl.querySelector(".fc-timegrid-body");
if (!timegridEl) return;
const allDayTable = calendarEl.querySelector(".fc-scrollgrid-sync-table");
if (allDayTable) {
const allDayRect = allDayTable.getBoundingClientRect();
if (e.clientY >= allDayRect.top && e.clientY <= allDayRect.bottom) {
timegridEl
.querySelectorAll(".hour-highlight")
.forEach((el: Element) => el.remove());
return;
}
}
const target = e.target as HTMLElement;
if (target && target.closest(".fc-timegrid-slot-label")) {
timegridEl
.querySelectorAll(".hour-highlight")
.forEach((el: Element) => el.remove());
return;
}
const dayColumns = timegridEl.querySelectorAll(".fc-timegrid-col");
if (dayColumns.length === 0) return;
timegridEl
.querySelectorAll(".hour-highlight")
.forEach((el: Element) => el.remove());
let targetColumn: Element | null = null;
for (const column of dayColumns) {
const rect = column.getBoundingClientRect();
if (e.clientX >= rect.left && e.clientX <= rect.right) {
targetColumn = column;
break;
}
}
if (targetColumn) {
const rect = targetColumn.getBoundingClientRect();
const relativeY = e.clientY - rect.top;
const slotHeight = rect.height / 48;
const slotIndex = Math.floor(relativeY / slotHeight);
if (relativeY >= 0 && relativeY <= rect.height) {
const highlight = document.createElement("div");
highlight.className = "hour-highlight";
highlight.style.top = `${slotIndex * slotHeight}px`;
highlight.style.height = `${slotHeight}px`;
(targetColumn as HTMLElement).style.position = "relative";
targetColumn.appendChild(highlight);
}
}
};
const handleMouseLeave = () => {
const timegridEl = calendarEl.querySelector(".fc-timegrid-body");
if (timegridEl) {
timegridEl
.querySelectorAll(".hour-highlight")
.forEach((el: Element) => el.remove());
}
};
const addMouseEventListeners = () => {
calendarEl.addEventListener("mousemove", handleMouseMove);
calendarEl.addEventListener("mouseleave", handleMouseLeave);
(calendarEl as any).__calendarMouseMoveHandler = handleMouseMove;
(calendarEl as any).__calendarMouseLeaveHandler = handleMouseLeave;
};
const removeMouseEventListeners = () => {
if ((calendarEl as any).__calendarMouseMoveHandler) {
calendarEl.removeEventListener(
"mousemove",
(calendarEl as any).__calendarMouseMoveHandler
);
delete (calendarEl as any).__calendarMouseMoveHandler;
}
if ((calendarEl as any).__calendarMouseLeaveHandler) {
calendarEl.removeEventListener(
"mouseleave",
(calendarEl as any).__calendarMouseLeaveHandler
);
delete (calendarEl as any).__calendarMouseLeaveHandler;
}
};
return {
handleMouseMove,
handleMouseLeave,
addMouseEventListeners,
removeMouseEventListeners,
};
};