import { DateTime } from "luxon"; import { buildEventQueryParams, getQuery, pushQuery } from "../../dist/router/router"; import { Calendar } from "@fullcalendar/core"; import dayGridPlugin from "@fullcalendar/daygrid"; import timeGridPlugin from "@fullcalendar/timegrid"; import listPlugin from "@fullcalendar/list"; import luxon2Plugin from "@fullcalendar/luxon2"; import { getUserLanguage } from "../../localisation/language"; import { getStatusInfoByBookingStatus } from "../../models/offer"; const state = { offers: {} }; "dayGridMonth"; "timeGridWeek"; "timeGridDay"; "listWeek"; export const availableCalendarViews: Array = [ { keyEdoobox: "month", keyFullCalendar: "dayGridMonth" }, { keyEdoobox: "agendaWeek", keyFullCalendar: "timeGridWeek" }, { keyEdoobox: "agendaDay", keyFullCalendar: "timeGridDay" }, { keyEdoobox: "listMonth", keyFullCalendar: "listWeek" }, ]; export const calendarViewMap: object = { v1: availableCalendarViews[0].keyFullCalendar, v2: availableCalendarViews[1].keyFullCalendar, v3: availableCalendarViews[2].keyFullCalendar, v4: availableCalendarViews[3].keyFullCalendar }; export default function ($) { var calendarElement = document.getElementById('calendar'); var calendar = new Calendar(calendarElement, { allDaySlot: false, aspectRatio: 1.75, expandRows: true, plugins: [ dayGridPlugin, timeGridPlugin, listPlugin, luxon2Plugin ], buttonText: { today: tg('N88771')/*Heute*/, month: tg('N33644')/*Monat*/, week: tg('N17274')/*Woche*/, day: tg('N6351')/*Tag*/, list: tg('N91117')/*Liste*/ }, dayMaxEventRows: 4, headerToolbar: { start: 'prev,next today', center: 'title', end: getActiveCalendarViewsSetByAdmin().map((view: CalendarView) => view.keyFullCalendar).join(",") }, editable: false, eventTimeFormat: 'HH:mm', firstDay: 1, initialDate: getInitialCalendarDate(), initialView: getInitialCalendarView(), locale: getUserLanguage(), moreLinkText: tg('N39246')/*Weitere*/, navLinks: true, scrollTime : $('#calendar').data('scrolltime'), slotDuration: $('#calendar').data('slottime'), minTime: $('#calendar').data('mintime'), maxTime: $('#calendar').data('maxtime'), slotLabelFormat: { hour: "2-digit", hour12: false, minute: "2-digit" }, themeSystem: 'bootstrap3', weekends: !! +calendarElement.dataset.weekend ? true : false, allDayDidMount: updateCalendarUrlQueries, dayCellDidMount: updateCalendarUrlQueries, events: fetchEvents, eventDidMount: function (info) { var element = info.el; var offerId = info.event.extendedProps.offerid; var offer = state.offers[offerId]; var { iconName, offerStatusText, secondButtonStatus, secondButtonText } = getStatusInfoByBookingStatus(offer.booking_status); var statusTemplate = $(''); $(element).find('.fc-daygrid-event-dot').replaceWith(statusTemplate); $(element).addClass('edevents_' + offerId); $(element).addClass('edevents'); element.title = info.event.title; $(".edevents").popover({ placement: 'top', trigger: "click", container: ".edoobox-plugin", content: function () { var content = '
×'; //Wurde ein Bild übermittelt? if (offer.image) { content += '
'; content += '
'; content += '
'; content += '
'; } else { content += '
'; } content += '
'; //Gibt es eine Beschreibung? if (offer.shortdescription.length > 4) { content += '
' + '
' + offer.shortdescription + '
'; } content += '
'; if (DateTime.fromISO(offer.start_date).toFormat('LLLL d, yyyy') == DateTime.fromISO(offer.end_date).toFormat('LLLL d, yyyy')) { content += '
' + DateTime.fromISO(offer.start_date).toFormat('LLLL d, yyyy t') + ' – ' + DateTime.fromISO(offer.end_date).toFormat('HH:mm') + '
'; } else { content += '
' + DateTime.fromISO(offer.start_date).toFormat('LLLL d, yyyy t') + ' – ' + DateTime.fromISO(offer.end_date).toFormat('LLLL d, yyyy t') + '
'; } content += '
' + '
' + offerStatusText + '
' + '
'; content += '
' + tg('N3238')/*Details*/ + ''; if (secondButtonText) { content += '' + secondButtonText + '
'; } content += '
'; return content; }, html: true }); $(".edevents").on('click', function () { $(".edevents").not(this).popover('hide'); }); $(".edevents").on("shown.bs.popover", function (e) { $(".close").on("click", function (e) { $(".edoobox-plugin .popover").remove(); }); }); }, viewDidMount: updateCalendarUrlQueries }); calendar.render(); } export function dateIsValid(date: Date): boolean { return date instanceof Date && ! isNaN(date.getTime()); } export function getInitialCalendarView(): string { return calendarViewMap[getQuery('edview')] || getFullCalendarViewKeySetByAdmin() || availableCalendarViews[0].keyFullCalendar; } export function getInitialCalendarDate(): Date { const dateFromShortcode: Date | undefined = getStartDateFromShortcode(); const date: Date = dateFromShortcode || new Date(getQuery("edstart") || Date.now()); return dateIsValid(date) ? date : new Date; } export function getQueryParamFromView(view: string): string { return Object.keys(calendarViewMap).find(key => calendarViewMap[key] === view); } export function getStartDateFromShortcode(): Date | undefined { const eventsUrl = calendarElement("#calendar")?.dataset?.events; const shortcodeDateAsString = new URLSearchParams(eventsUrl).get("edstart")?.split("?")[0]; const shortcodeDate = new Date(shortcodeDateAsString); return dateIsValid(shortcodeDate) ? new Date(shortcodeDate) : undefined; } export function fetchEvents(info) { const formatDate = (date) => { const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; }; const startFormatted = formatDate(new Date(info.start)); const endFormatted = formatDate(new Date(info.end)); const params = new URLSearchParams(); params.append('start', startFormatted); params.append('end', endFormatted); return fetch(calendarElement().dataset.events, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString() }) .then(response => response.json()) .then(json => { state.offers = { ...(state.offers || {}), ...(json.offers || {}) }; return Object.values(json.rsl)?.map(value => ({ id: value.id, classNames: [value.id], title: json.offers[value['offerid']].name, start: value.start, end: value.end, borderColor: value.color, allDay: false, offerid: value['offerid'] })); }); } export function updateCalendarUrlQueries(view): void { const date: string = DateTime.fromJSDate(view.view.currentStart).toFormat("yyyy-LL-dd"); const viewQueryParam: string = getQueryParamFromView(view.view.type); pushQuery("edstart", date); pushQuery("edview", viewQueryParam); document.querySelectorAll(".popover").forEach(element => element.remove()); } function calendarElement(id: string = "#calendar"): HTMLElement | undefined { return document.querySelector(id); } function getActiveCalendarViewsSetByAdmin(): Array { const availableViews: string = calendarElement()?.dataset?.views; return availableCalendarViews.filter(view => availableViews.includes(view.keyEdoobox)); } function getFullCalendarViewKeySetByAdmin(): string { const edooboxViewKeySetByAdmin: string = calendarElement()?.dataset?.defaultview || ""; return availableCalendarViews.find(view => view.keyEdoobox === edooboxViewKeySetByAdmin)?.keyFullCalendar || ""; }