initialer commit, Grundcode
This commit is contained in:
94
frontend/js/views/agenda.js
Normal file
94
frontend/js/views/agenda.js
Normal file
@@ -0,0 +1,94 @@
|
||||
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,'&').replace(/</g,'<').replace(/>/g,'>');
|
||||
}
|
||||
function escAttr(s) {
|
||||
return String(s).replace(/"/g,'"').replace(/'/g,''');
|
||||
}
|
||||
Reference in New Issue
Block a user