// Datum: Kalender-Widget (function () { const WEEKDAYS = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]; const MONTHS = [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember", ]; const monthLabel = document.getElementById("monthLabel"); const weekdayRow = document.getElementById("weekdayRow"); const dayGrid = document.getElementById("dayGrid"); const prevMonthBtn = document.getElementById("prevMonthBtn"); const nextMonthBtn = document.getElementById("nextMonthBtn"); const continueBtn = document.getElementById("continueBtn"); const today = new Date(); today.setHours(0, 0, 0, 0); let availableDatesMap = new Map(); let bookedDatesSet = new Set(); let viewYear = today.getFullYear(); let viewMonth = today.getMonth(); let selectedDate = null; let selectedDateType = "long"; WEEKDAYS.forEach((day) => { const span = document.createElement("span"); span.textContent = day; weekdayRow.appendChild(span); }); function toDateKey(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}`; } Promise.all([ fetch("appsettings.json?t=" + Date.now()).then((res) => res.json()), fetch("/api/booked-dates?t=" + Date.now(), { cache: "no-store" }) .then((res) => (res.ok ? res.json() : [])) .catch(() => []), ]) .then(([settings, bookedDates]) => { let localBooked = []; try { localBooked = JSON.parse(localStorage.getItem("bookedDates") || "[]"); } catch (e) {} const allBooked = [...(bookedDates || []), ...localBooked] .map((d) => (typeof d === "string" ? d.trim() : "")) .filter(Boolean); bookedDatesSet = new Set(allBooked); const datesList = settings.availableDates || []; datesList.forEach((item) => { let key = ""; let type = "long"; if (typeof item === "string") { key = item.trim(); } else if (item && item.date) { key = item.date.trim(); type = item.type || "long"; } if (key && !bookedDatesSet.has(key)) { availableDatesMap.set(key, { type }); } }); const upcoming = Array.from(availableDatesMap.keys()) .map((dateKey) => new Date(`${dateKey}T00:00:00`)) .filter((date) => date > today) .sort((a, b) => a - b); if (upcoming.length > 0) { viewYear = upcoming[0].getFullYear(); viewMonth = upcoming[0].getMonth(); } renderCalendar(); }) .catch(() => { dayGrid.textContent = "Verfügbare Termine konnten nicht geladen werden."; }); function renderCalendar() { monthLabel.textContent = `${MONTHS[viewMonth]} ${viewYear}`; dayGrid.innerHTML = ""; const firstOfMonth = new Date(viewYear, viewMonth, 1); // Montag = 0 ... Sonntag = 6 const leadingBlanks = (firstOfMonth.getDay() + 6) % 7; const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate(); for (let i = 0; i < leadingBlanks; i++) { const blank = document.createElement("span"); blank.className = "day-cell is-empty"; dayGrid.appendChild(blank); } for (let day = 1; day <= daysInMonth; day++) { const cellDate = new Date(viewYear, viewMonth, day); const key = toDateKey(cellDate); const button = document.createElement("button"); button.type = "button"; button.className = "day-cell"; button.textContent = String(day); const dateInfo = availableDatesMap.get(key); const isPastOrToday = cellDate <= today; const isAvailable = Boolean(dateInfo) && !isPastOrToday; const isToday = cellDate.getTime() === today.getTime(); const isSelected = selectedDate && cellDate.getTime() === selectedDate.getTime(); if (!isAvailable) { button.classList.add("is-disabled"); button.disabled = true; } if (isToday) { button.classList.add("is-today"); } if (isSelected) { button.classList.add("is-selected"); } button.addEventListener("click", () => { selectedDate = cellDate; selectedDateType = dateInfo ? dateInfo.type : "long"; renderCalendar(); updateContinueState(); }); dayGrid.appendChild(button); } const isCurrentMonth = viewYear === today.getFullYear() && viewMonth === today.getMonth(); prevMonthBtn.disabled = isCurrentMonth; } prevMonthBtn.addEventListener("click", () => { viewMonth -= 1; if (viewMonth < 0) { viewMonth = 11; viewYear -= 1; } renderCalendar(); }); nextMonthBtn.addEventListener("click", () => { viewMonth += 1; if (viewMonth > 11) { viewMonth = 0; viewYear += 1; } renderCalendar(); }); function updateContinueState() { continueBtn.disabled = !selectedDate; } continueBtn.addEventListener("click", () => { if (!selectedDate) { return; } localStorage.setItem("selectedDate", toDateKey(selectedDate)); localStorage.setItem("selectedDateType", selectedDateType); window.location.href = "activity.html"; }); })();