diff --git a/frontend/css/app.css b/frontend/css/app.css index c51fda2..8f16b98 100644 --- a/frontend/css/app.css +++ b/frontend/css/app.css @@ -551,11 +551,17 @@ a { color: var(--primary); text-decoration: none; } color: #fff; font-weight: 700; } .mini-day.selected:not(.today) { background: var(--primary-dim); color: var(--primary); font-weight: 600; } -.mini-day.has-events::after { - content: ''; position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%); - width: 4px; height: 4px; border-radius: 50%; background: var(--primary); +/* One dot per calendar with an event that day, in that calendar's colour. */ +.mini-dots { + position: absolute; bottom: 1px; left: 0; right: 0; + display: flex; justify-content: center; align-items: center; gap: 2px; + line-height: 0; pointer-events: none; } -.mini-day.today.has-events::after { background: #fff; } +.mini-dots i { + width: 4px; height: 4px; border-radius: 50%; flex: none; +} +/* Today's cell is a filled circle — ring the dots so they stay readable on it. */ +.mini-day.today .mini-dots i { box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9); } /* ── Calendar List ──────────────────────────────────────── */ .cal-list { padding: 8px 0; } diff --git a/frontend/js/calendar.js b/frontend/js/calendar.js index 711774b..e0eaa9d 100644 --- a/frontend/js/calendar.js +++ b/frontend/js/calendar.js @@ -559,6 +559,8 @@ function updateViewButtons() { } // ── Mini Calendar ───────────────────────────────────────── +const MINI_MAX_DOTS = 4; + function renderMiniCal() { const d = state.currentDate; const miniD = new Date(d.getFullYear(), d.getMonth(), 1); @@ -576,10 +578,14 @@ function renderMiniCal() { const DOW_LABELS = weekStartDay === 'sunday' ? DOW_SUNDAY : DOW_MONDAY; miniDowEls.forEach((el, i) => { el.textContent = DOW_LABELS[i]; }); - // Build event date set — mark every day an event spans, not just its start - // day, so multi-day events (Urlaub/Ferien) show a dot across the whole range. - const eventDates = new Set(); - state.events.forEach(ev => { + // Build per-day colour sets — one dot per calendar that has at least one event + // that day, in that calendar's colour. Every day an event spans is marked, not + // just its start day, so multi-day events (Urlaub/Ferien) mark the whole range. + const dayColors = new Map(); // 'y-m-d' → Set of colours + const colorRank = new Map(); // colour → first-seen index, for a stable dot order + filterEvents(state.events).forEach(ev => { + const color = ev.color || ev.calendarColor || '#4285f4'; + if (!colorRank.has(color)) colorRank.set(color, colorRank.size); const s = new Date(ev.start); let end = new Date(ev.end || ev.start); // All-day events store an exclusive end → step back to the last real day. @@ -588,7 +594,10 @@ function renderMiniCal() { const last = new Date(end.getFullYear(), end.getMonth(), end.getDate()); let guard = 0; while (cur <= last && guard++ < 400) { - eventDates.add(`${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`); + const key = `${cur.getFullYear()}-${cur.getMonth()}-${cur.getDate()}`; + let set = dayColors.get(key); + if (!set) { set = new Set(); dayColors.set(key, set); } + set.add(color); cur.setDate(cur.getDate() + 1); } }); @@ -604,7 +613,8 @@ function renderMiniCal() { const isOther = day.getMonth() !== miniD.getMonth(); const isToday_ = isToday(day); const isSelected = isSameDay(day, state.currentDate); - const hasEvs = eventDates.has(`${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`); + const colors = dayColors.get(`${day.getFullYear()}-${day.getMonth()}-${day.getDate()}`); + const hasEvs = !!colors; const cls = [ 'mini-day', isOther ? 'other-month' : '', @@ -612,7 +622,14 @@ function renderMiniCal() { isSelected && !isToday_ ? 'selected' : '', hasEvs ? 'has-events' : '', ].filter(Boolean).join(' '); - return `