Create basic (ugly) event detail popup

This commit is contained in:
Antoine Bartuccio 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();
}
});
}
}

View File

@ -11,53 +11,49 @@
--fc-button-hover-bg-color: #15608F;
--fc-today-bg-color: rgba(26, 120, 179, 0.1);
--fc-border-color: #DDDDDD;
--sc-main-background-color: #f9fafb;
--sc-main-padding: 5px;
--sc-main-border: 0px solid #DDDDDD;
--sc-main-border-radius: 0px;
--sc-body-font-family: Roboto;
--sc-title-font-family: Roboto;
--sc-body-font-size: 16px;
--sc-title-font-size: 28px;
--sc-body-font-weight: 400;
--sc-title-font-weight: 500;
--sc-title-font-color: #111111;
--sc-base-body-font-color: #222222;
--sc-title-font-style: normal;
--sc-body-font-style: normal;
--sc-event-dot-color: #1a78b3;
--sc-button-border: 1px solid #ffffff;
--sc-button-border-radius: 4px;
--sc-button-icons-size: 22px;
--sc-grid-event-white-space: nowrap;
--sc-block-event-background-color-hovered: rgb(245, 245, 245);
--sc-block-event-border: 1px solid rgba(255, 255, 255, 0);
--sc-block-event-border-radius: 2.5px;
--sc-dot-event-background-color: rgba(255, 255, 255, 0);
--sc-dot-event-background-color-hovered: rgb(245, 245, 245);
--sc-dot-event-text-color: #222222;
--sc-dot-event-border: 1px solid rgba(255, 255, 255, 0);
--sc-dot-event-border-radius: 2.5px;
--sc-grid-day-header-background-color: rgba(255, 255, 255, 0);
--sc-list-day-header-background-color: rgba(208, 208, 208, 0.3);
--sc-inner-calendar-background-color: rgba(255, 255, 255, 0);
--sc-past-day-background-color: rgba(255, 255, 255, 0);
--sc-future-day-background-color: rgba(255, 255, 255, 0);
--sc-disabled-day-background-color: rgba(208, 208, 208, 0.3);
--sc-event-overlay-background-color: white;
--sc-event-overlay-padding: 20px;
--sc-event-overlay-border: 1px solid #EEEEEE;
--sc-event-overlay-border-radius: 4px;
--sc-event-overlay-primary-icon-color: #1a78b3;
--sc-event-overlay-secondary-icon-color: black;
--sc-event-overlay-box-shadow: 0px 6px 20px 4px rgb(0 0 0 / 16%);
--sc-event-overlay-max-width: 600px;
--event-details-background-color: white;
--event-details-padding: 20px;
--event-details-border: 1px solid #EEEEEE;
--event-details-border-radius: 4px;
--event-details-box-shadow: 0px 6px 20px 4px rgb(0 0 0 / 16%);
--event-details-max-width: 600px;
}
ics-calendar {
border: none;
box-shadow: none;
#event-details {
z-index: 10;
max-width: 1151px;
position: absolute;
.event-details-container {
display: flex;
color: black;
flex-direction: column;
min-width: 200px;
max-width: var(--event-details-max-width);
padding: var(--event-details-padding);
border: var(--event-details-border);
border-radius: var(--event-details-border-radius);
background-color: var(--event-details-background-color);
box-shadow: var(--event-details-box-shadow);
}
.event-details-row {
display: flex;
flex-direction: row;
align-items: start;
}
.event-details-title {
background-color: var(--event-details-background-color);
margin-top: 0px;
margin-bottom: 4px;
}
}
a.fc-col-header-cell-cushion,
a.fc-col-header-cell-cushion:hover {
color: black;
@ -69,7 +65,7 @@ ics-calendar {
}
td {
overflow: visible; // Show events on multiple days
overflow-x: visible; // Show events on multiple days
}
//Reset from style.scss