Calendar: drop month grid, show schedule-webhook event list directly; date format dd.mm.yyyy
This commit is contained in:
+1
-59
@@ -1479,65 +1479,7 @@ TELEGRAM BANNER
|
||||
font-weight: 700;
|
||||
color: #1c1e21;
|
||||
}
|
||||
.calendar-nav {
|
||||
background: #f0f2f5;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1;
|
||||
color: #1c1e21;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
.calendar-nav:hover { background: #e4e6eb; }
|
||||
.calendar-weekdays {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
text-align: center;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
color: #65676b;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
.calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
gap: 2px;
|
||||
}
|
||||
.calendar-day {
|
||||
aspect-ratio: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 8px;
|
||||
font-size: 0.85rem;
|
||||
color: #1c1e21;
|
||||
position: relative;
|
||||
}
|
||||
.calendar-day.empty { visibility: hidden; }
|
||||
.calendar-day.today {
|
||||
background: #e7f3ff;
|
||||
color: #1877f2;
|
||||
font-weight: 700;
|
||||
}
|
||||
.calendar-day.has-event { font-weight: 700; }
|
||||
.calendar-dots {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
}
|
||||
.calendar-dots i {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
background: #1877f2;
|
||||
display: inline-block;
|
||||
}
|
||||
.calendar-events { margin-top: 12px; border-top: 1px solid #e4e6eb; padding-top: 10px; }
|
||||
.calendar-events { border-top: 1px solid #e4e6eb; padding-top: 10px; }
|
||||
.calendar-events-hint { color: #65676b; font-size: 0.85rem; text-align: center; margin: 0; }
|
||||
.calendar-event-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
|
||||
.calendar-event-list li {
|
||||
|
||||
+3
-10
@@ -428,18 +428,11 @@
|
||||
</div>
|
||||
<div class="calendar-card">
|
||||
<div class="calendar-header">
|
||||
<button type="button" class="calendar-nav" id="calendar-prev" aria-label="Monat zurück">‹</button>
|
||||
<div class="calendar-title" id="calendar-title">
|
||||
<span class="hide-de">Kalender</span>
|
||||
<span class="hide-en">Calendar</span>
|
||||
<div class="calendar-title">
|
||||
<span class="hide-de">Termine</span>
|
||||
<span class="hide-en">Upcoming Dates</span>
|
||||
</div>
|
||||
<button type="button" class="calendar-nav" id="calendar-next" aria-label="Monat vor">›</button>
|
||||
</div>
|
||||
<div class="calendar-weekdays">
|
||||
<span class="hide-de">Mo</span><span class="hide-de">Di</span><span class="hide-de">Mi</span><span class="hide-de">Do</span><span class="hide-de">Fr</span><span class="hide-de">Sa</span><span class="hide-de">So</span>
|
||||
<span class="hide-en">Mo</span><span class="hide-en">Tu</span><span class="hide-en">We</span><span class="hide-en">Th</span><span class="hide-en">Fr</span><span class="hide-en">Sa</span><span class="hide-en">Su</span>
|
||||
</div>
|
||||
<div class="calendar-grid" id="calendar-grid"></div>
|
||||
<div class="calendar-events" id="calendar-events">
|
||||
<p class="calendar-events-hint">
|
||||
<span class="hide-de">Termine werden geladen...</span>
|
||||
|
||||
+12
-81
@@ -1000,103 +1000,34 @@ function renderDates(events) {
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CALENDAR (next to newsletter) — month view from schedule webhook
|
||||
// CALENDAR (next to newsletter) — plain event list from schedule webhook
|
||||
// ========================================
|
||||
const MONTH_NAMES_DE = ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'];
|
||||
const MONTH_NAMES_EN = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
||||
|
||||
let calendarDate = new Date();
|
||||
|
||||
function isoDay(d) {
|
||||
return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') + '-' + String(d.getDate()).padStart(2, '0');
|
||||
}
|
||||
|
||||
function eventsByDay() {
|
||||
const map = {};
|
||||
scheduleData.forEach(ev => {
|
||||
if (!ev || !ev.start) return;
|
||||
const key = isoDay(new Date(ev.start));
|
||||
(map[key] = map[key] || []).push(ev);
|
||||
});
|
||||
return map;
|
||||
}
|
||||
function pad2(n) { return String(n).padStart(2, '0'); }
|
||||
|
||||
function initCalendar() {
|
||||
const prev = document.getElementById('calendar-prev');
|
||||
const next = document.getElementById('calendar-next');
|
||||
if (!prev || !next) return;
|
||||
prev.addEventListener('click', () => {
|
||||
calendarDate = new Date(calendarDate.getFullYear(), calendarDate.getMonth() - 1, 1);
|
||||
renderCalendar();
|
||||
});
|
||||
next.addEventListener('click', () => {
|
||||
calendarDate = new Date(calendarDate.getFullYear(), calendarDate.getMonth() + 1, 1);
|
||||
renderCalendar();
|
||||
});
|
||||
renderCalendar();
|
||||
}
|
||||
|
||||
function renderCalendar() {
|
||||
const grid = document.getElementById('calendar-grid');
|
||||
const title = document.getElementById('calendar-title');
|
||||
if (!grid || !title) return;
|
||||
|
||||
const lang = isDE() ? MONTH_NAMES_DE : MONTH_NAMES_EN;
|
||||
const year = calendarDate.getFullYear();
|
||||
const month = calendarDate.getMonth();
|
||||
title.innerHTML = '<span>' + escapeHtml(lang[month]) + ' ' + year + '</span>';
|
||||
|
||||
const firstDay = new Date(year, month, 1);
|
||||
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
||||
// Monday as first weekday: JS getDay() -> 0=Sun..6=Sat
|
||||
let startOffset = (firstDay.getDay() + 6) % 7;
|
||||
|
||||
const todayKey = isoDay(new Date());
|
||||
const eventMap = eventsByDay();
|
||||
|
||||
let html = '';
|
||||
for (let i = 0; i < startOffset; i++) {
|
||||
html += '<div class="calendar-day empty"></div>';
|
||||
}
|
||||
for (let day = 1; day <= daysInMonth; day++) {
|
||||
const key = isoDay(new Date(year, month, day));
|
||||
const dayEvents = eventMap[key] || [];
|
||||
const classes = ['calendar-day'];
|
||||
if (key === todayKey) classes.push('today');
|
||||
if (dayEvents.length > 0) classes.push('has-event');
|
||||
let cell = '<div class="' + classes.join(' ') + '"' +
|
||||
(dayEvents.length ? ' title="' + escapeHtml(dayEvents.map(e => e.headline || 'Event').join(', ')) + '"' : '') + '>';
|
||||
cell += '<span class="calendar-day-number">' + day + '</span>';
|
||||
if (dayEvents.length > 0) {
|
||||
cell += '<span class="calendar-dots">' + '<i></i>'.repeat(Math.min(dayEvents.length, 3)) + '</span>';
|
||||
}
|
||||
cell += '</div>';
|
||||
html += cell;
|
||||
}
|
||||
grid.innerHTML = html;
|
||||
|
||||
// Event list below: upcoming events from this month (or hint)
|
||||
const eventsEl = document.getElementById('calendar-events');
|
||||
if (!eventsEl) return;
|
||||
const monthEvents = scheduleData
|
||||
.filter(ev => {
|
||||
const d = new Date(ev.start);
|
||||
return d.getFullYear() === year && d.getMonth() === month;
|
||||
})
|
||||
.sort((a, b) => new Date(a.start) - new Date(b.start));
|
||||
|
||||
if (monthEvents.length === 0) {
|
||||
if (scheduleData.length === 0) {
|
||||
eventsEl.innerHTML = '<p class="calendar-events-hint">' +
|
||||
(isDE() ? 'Keine Termine in diesem Monat.' : 'No events this month.') + '</p>';
|
||||
(isDE() ? 'Keine Termine geplant.' : 'No events scheduled.') + '</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const sorted = [...scheduleData].sort((a, b) => new Date(a.start) - new Date(b.start));
|
||||
let list = '<ul class="calendar-event-list">';
|
||||
monthEvents.forEach(ev => {
|
||||
sorted.forEach(ev => {
|
||||
if (!ev || !ev.start) return;
|
||||
const sd = new Date(ev.start);
|
||||
const ed = ev.end ? new Date(ev.end) : null;
|
||||
const timeStr = String(sd.getHours()).padStart(2, '0') + ':' + String(sd.getMinutes()).padStart(2, '0') +
|
||||
(ed ? '–' + String(ed.getHours()).padStart(2, '0') + ':' + String(ed.getMinutes()).padStart(2, '0') : '');
|
||||
list += '<li><span class="calendar-event-date">' + String(sd.getDate()).padStart(2, '0') + '. ' + escapeHtml(lang[month].slice(0, 2)) + '</span>' +
|
||||
const dateStr = pad2(sd.getDate()) + '.' + pad2(sd.getMonth() + 1) + '.' + sd.getFullYear();
|
||||
const timeStr = pad2(sd.getHours()) + ':' + pad2(sd.getMinutes()) +
|
||||
(ed ? '–' + pad2(ed.getHours()) + ':' + pad2(ed.getMinutes()) : '');
|
||||
list += '<li><span class="calendar-event-date">' + dateStr + '</span>' +
|
||||
'<span class="calendar-event-headline">' + escapeHtml(ev.headline || 'Event') + '</span>' +
|
||||
'<span class="calendar-event-time">' + timeStr + '</span></li>';
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user