Files
Calendarr/frontend/js/views/agenda.js

95 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { isPast } from '../utils.js';
const DOW = ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'];
const MON = ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'];
export function renderAgenda(container, currentDate, events, onEventClick) {
if (!events.length) {
container.innerHTML = `<div class="agenda-view"><div class="agenda-empty">Keine Termine im angezeigten Zeitraum</div></div>`;
return;
}
// Group events by date
const groups = {};
events.forEach(ev => {
const d = new Date(ev.start);
const key = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
if (!groups[key]) groups[key] = [];
groups[key].push(ev);
});
// Sort groups
const sortedKeys = Object.keys(groups).sort();
const html = sortedKeys.map(key => {
const date = new Date(key + 'T00:00:00');
const isToday = isTodayDate(date);
const todayCls = isToday ? 'today' : '';
const evHtml = groups[key]
.sort((a, b) => {
if (a.allDay && !b.allDay) return -1;
if (!a.allDay && b.allDay) return 1;
return new Date(a.start) - new Date(b.start);
})
.map(ev => {
const color = ev.color || ev.calendarColor || '#4285f4';
const pastCls = isPast(ev) ? 'past' : '';
let timeStr = 'Ganztägig';
if (!ev.allDay) {
const s = new Date(ev.start);
const e = new Date(ev.end);
timeStr = `${fmtTime(s)} ${fmtTime(e)}`;
}
const locHtml = ev.location
? `<span class="agenda-ev-meta"> · ${escHtml(ev.location)}</span>`
: '';
return `<div class="agenda-event ${pastCls}" data-id="${ev.id}" data-url="${escAttr(ev.url)}">
<div class="agenda-ev-color" style="background:${color}"></div>
<div class="agenda-ev-info">
<div class="agenda-ev-title">${escHtml(ev.title)}</div>
<div class="agenda-ev-meta">${timeStr}${locHtml}</div>
</div>
</div>`;
}).join('');
return `<div class="agenda-day">
<div class="agenda-date ${todayCls}">
<div class="agenda-date-num">${date.getDate()}</div>
<div class="agenda-date-label">
<span class="wd">${DOW[date.getDay()]}</span>
<span class="mo">${MON[date.getMonth()]} ${date.getFullYear()}</span>
</div>
</div>
${evHtml}
</div>`;
}).join('');
container.innerHTML = `<div class="agenda-view">${html}</div>`;
container.querySelectorAll('.agenda-event').forEach(el => {
el.addEventListener('click', () => {
const ev = events.find(ev => ev.id === el.dataset.id && ev.url === el.dataset.url);
if (ev) onEventClick(ev, el);
});
});
}
function isTodayDate(d) {
const now = new Date();
return d.getFullYear() === now.getFullYear() &&
d.getMonth() === now.getMonth() &&
d.getDate() === now.getDate();
}
function fmtTime(d) {
return d.toLocaleTimeString('de', { hour: '2-digit', minute: '2-digit' });
}
function escHtml(s) {
return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
function escAttr(s) {
return String(s).replace(/"/g,'&quot;').replace(/'/g,'&#39;');
}