import React from 'react'; import { MONTHS, addDays, formatDuration, fromIso, mondayOf, todayIso, weekdayIndex } from '../../lib/format'; import { useGrow } from '../../lib/hooks'; import { BudgetBar, Card } from '../ui/controls'; import type { TimeEntry } from '../../types'; /** Jahresansicht: Monatskacheln mit Soll/Ist und eine Heatmap aller Tage. */ export const YearView: React.FC<{ year: string; entries: TimeEntry[]; weeklyTarget: number; onOpenMonth: (month: string) => void }> = ({ year, entries, weeklyTarget, onOpenMonth, }) => { const today = todayIso(); const perDay = new Map(); for (const e of entries) perDay.set(e.entry_date, (perDay.get(e.entry_date) || 0) + e.minutes); const grown = useGrow(year); const months = MONTHS.map((name, i) => { const key = `${year}-${String(i + 1).padStart(2, '0')}`; const list = entries.filter((e) => e.entry_date.startsWith(key)); const minutes = list.reduce((s, e) => s + e.minutes, 0); const billable = list.filter((e) => e.billable).reduce((s, e) => s + e.minutes, 0); let workdays = 0; for (let d = `${key}-01`; d.startsWith(key); d = addDays(d, 1)) { if (d > today) break; if (weekdayIndex(d) < 5) workdays++; } const target = (weeklyTarget / 5) * workdays * 60; return { key, name, minutes, billable, target }; }); const max = Math.max(1, ...months.map((m) => m.minutes)); // Heatmap: Wochen als Spalten, Mo-So als Zeilen. const first = mondayOf(`${year}-01-01`); const weeks: string[][] = []; for (let d = first; d <= `${year}-12-31`; d = addDays(d, 7)) { weeks.push(Array.from({ length: 7 }, (_, i) => addDays(d, i))); } const level = (minutes: number) => (minutes === 0 ? 0 : minutes < 180 ? 1 : minutes < 360 ? 2 : minutes < 480 ? 3 : 4); const LEVELS = ['var(--color-ink-100)', 'var(--color-brand-200)', 'var(--color-brand-300)', 'var(--color-brand-500)', 'var(--color-brand-700)']; return (

Buchungsdichte {year}

{weeks.map((week, w) => (
{week.map((date) => { const minutes = perDay.get(date) || 0; const out = !date.startsWith(year); return ( ); })}
))}
weniger {LEVELS.map((c) => ( ))} mehr
{months.map((m, i) => ( ))}
); };