Create basic (ugly) event detail popup

This commit is contained in:
2024-12-31 12:15:17 +01:00
parent 48f6d134bf
commit eac2709e86
2 changed files with 117 additions and 43 deletions

View File

@ -1,6 +1,6 @@
import { makeUrl } from "#core:utils/api";
import { inheritHtmlElement, registerComponent } from "#core:utils/web-components";
import { Calendar } from "@fullcalendar/core";
import { Calendar, type EventClickArg } from "@fullcalendar/core";
import enLocale from "@fullcalendar/core/locales/en-gb";
import frLocale from "@fullcalendar/core/locales/fr";
import dayGridPlugin from "@fullcalendar/daygrid";
@ -46,6 +46,71 @@ export class IcsCalendar extends inheritHtmlElement("div") {
};
}
formatDate(date: Date) {
return new Intl.DateTimeFormat(this.locale, {
dateStyle: "medium",
timeStyle: "short",
}).format(date);
}
createEventDetailPopup(event: EventClickArg) {
// Delete previous popup
const oldPopup = document.getElementById("event-details");
if (oldPopup !== null) {
oldPopup.remove();
}
// Create new popup
const popup = document.createElement("div");
const popupContainer = document.createElement("div");
const popupFirstRow = document.createElement("div");
const popupSecondRow = document.createElement("div");
const popupTitleTimeIcon = document.createElement("i");
const popupTitleTime = document.createElement("div");
const popupTitle = document.createElement("h4");
const popupTime = document.createElement("span");
popup.setAttribute("id", "event-details");
popupContainer.setAttribute("class", "event-details-container");
popupFirstRow.setAttribute("class", "event-details-row");
popupSecondRow.setAttribute("class", "event-details-row");
popupTitleTimeIcon.setAttribute("class", "fa-solid fa-calendar-days fa-xl");
popupTitle.setAttribute("class", "event-details-title");
popupTitle.textContent = event.event.title;
popupTime.setAttribute("class", "event-details-time");
popupTime.textContent = `${this.formatDate(event.event.start)} - ${this.formatDate(event.event.end)}`;
popupTitleTime.appendChild(popupTitle);
popupTitleTime.appendChild(popupTime);
popupFirstRow.appendChild(popupTitleTimeIcon);
popupSecondRow.appendChild(popupTitleTime);
popupContainer.appendChild(popupFirstRow);
popupContainer.appendChild(popupSecondRow);
popup.appendChild(popupContainer);
// We can't just add the element relative to the one we want to appear under
// Otherwise, it either gets clipped by the boundaries of the calendar or resize cells
// Here, we create a popup outside the calendar that follows the clicked element
this.node.appendChild(popup);
const follow = (node: HTMLElement) => {
const rect = node.getBoundingClientRect();
popup.setAttribute(
"style",
`top: calc(${rect.top + window.scrollY}px + ${rect.height}px); left: ${rect.left + window.scrollX}px;`,
);
};
follow(event.el);
window.addEventListener("resize", () => {
follow(event.el);
});
}
async connectedCallback() {
super.connectedCallback();
this.calendar = new Calendar(this.node, {
@ -69,7 +134,20 @@ export class IcsCalendar extends inheritHtmlElement("div") {
this.calendar.changeView(this.currentView());
this.calendar.setOption("headerToolbar", this.currentToolbar());
},
eventClick: (event) => {
// Avoid our popup to be deleted because we clicked outside of it
event.jsEvent.stopPropagation();
this.createEventDetailPopup(event);
},
});
this.calendar.render();
window.addEventListener("click", (event: MouseEvent) => {
// Auto close popups when clicking outside of it
const popup = document.getElementById("event-details");
if (popup !== null && !popup.contains(event.target as Node)) {
popup.remove();
}
});
}
}