import React from 'react'; import { WEEKDAYS_SHORT, addDays, fromIso, monthEnd, todayIso, weekdayIndex } from '../../lib/format'; import { Avatar } from '../ui/controls'; import type { CalendarUser } from '../../lib/api'; import { holidaysOn, userColor, type CalendarIndex } from './calendarData'; /** * Zeitleiste: Personen in Zeilen, Tage des Monats in Spalten. Zeigt auf einen * Blick, wo sich Urlaube ueberschneiden. Breiter als das Handy - die Tabelle * scrollt seitlich, die Namensspalte bleibt stehen. */ export const Timeline: React.FC<{ month: string; index: CalendarIndex; users: CalendarUser[]; selected: string | null; onSelect: (day: string) => void; }> = ({ month, index, users, selected, onSelect }) => { const today = todayIso(); const days: string[] = []; for (let d = month; d <= monthEnd(month); d = addDays(d, 1)) days.push(d); return (
| Mitarbeiter | {days.map((day) => { const weekend = weekdayIndex(day) >= 5; const holidays = holidaysOn(index, day); return (onSelect(day)} className={`min-w-[28px] cursor-pointer border-b border-ink-200 px-0 py-1.5 text-center font-extrabold ${ day === selected ? 'bg-brand-100 text-brand-700' : holidays.length ? 'bg-amber-50 text-amber-700' : weekend ? 'bg-ink-50 text-ink-400' : 'text-ink-600' }`} > {WEEKDAYS_SHORT[weekdayIndex(day)].slice(0, 2)} {fromIso(day).getDate()} | ); })}
|---|---|
|
|
{days.map((day) => {
const entry = entries?.get(day);
const weekend = weekdayIndex(day) >= 5;
const vacation = entry?.kind === 'vacation';
// Aneinanderstossende Urlaubstage als ein Balken zeichnen.
const prev = entries?.get(addDays(day, -1))?.kind === 'vacation';
const next = entries?.get(addDays(day, 1))?.kind === 'vacation';
return (
onSelect(day)} className={`h-9 cursor-pointer border-b border-ink-100 px-0 py-1 ${ day === selected ? 'bg-brand-50' : entry?.kind === 'holiday' ? 'bg-amber-50' : weekend ? 'bg-ink-50/70' : '' }`} > {vacation && ( )} {entry?.kind === 'holiday' && } | ); })}