import { useMemo, useState } from 'preact/hooks'; import { animated, useSpring } from '@react-spring/web'; import { getStatusLabel } from '../../stores/taskStore'; const WEEKDAY_LABELS = ['Po', 'Ut', 'Sr', 'Če', 'Pe', 'Su', 'Ne']; const MONTH_NAMES = [ 'Siječanj', 'Veljača', 'Ožujak', 'Travanj', 'Svibanj', 'Lipanj', 'Srpanj', 'Kolovoz', 'Rujan', 'Listopad', 'Studeni', 'Prosinac', ]; const PANEL_WIDTH = 300; function toIsoDateKey(dateStr) { if (!dateStr) return null; const d = new Date(dateStr); if (Number.isNaN(d.getTime())) return null; return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`; } function formatDayLabel(year, month, day) { return `${String(day).padStart(2, '0')}.${String(month + 1).padStart(2, '0')}.${year}`; } export default function TaskCalendarWidget({ tasks = [], onTaskClick }) { const [open, setOpen] = useState(false); const [viewYear, setViewYear] = useState(() => new Date().getFullYear()); const [viewMonth, setViewMonth] = useState(() => new Date().getMonth()); const [selectedDay, setSelectedDay] = useState(null); const panelSpring = useSpring({ left: open ? 0 : -PANEL_WIDTH, config: { tension: 260, friction: 28 }, }); const buttonSpring = useSpring({ left: open ? PANEL_WIDTH : 0, config: { tension: 260, friction: 28 }, }); // Map: "YYYY-MM-DD" -> task[] const tasksByDate = useMemo(() => { const map = {}; for (const task of tasks) { const key = toIsoDateKey(task.scheduled_date); if (!key) continue; if (!map[key]) map[key] = []; map[key].push(task); } return map; }, [tasks]); // Calendar grid cells for current month const calendarDays = useMemo(() => { const firstDay = new Date(viewYear, viewMonth, 1); let startDow = firstDay.getDay(); // 0=Sun startDow = (startDow + 6) % 7; // shift to Mon=0 const daysInMonth = new Date(viewYear, viewMonth + 1, 0).getDate(); const cells = []; for (let i = 0; i < startDow; i++) cells.push(null); for (let d = 1; d <= daysInMonth; d++) cells.push(d); return cells; }, [viewYear, viewMonth]); const selectedDayKey = selectedDay ? `${viewYear}-${String(viewMonth + 1).padStart(2, '0')}-${String(selectedDay).padStart(2, '0')}` : null; const selectedDayTasks = selectedDayKey ? (tasksByDate[selectedDayKey] ?? []) : []; const today = new Date(); function prevMonth() { setSelectedDay(null); if (viewMonth === 0) { setViewYear((y) => y - 1); setViewMonth(11); } else setViewMonth((m) => m - 1); } function nextMonth() { setSelectedDay(null); if (viewMonth === 11) { setViewYear((y) => y + 1); setViewMonth(0); } else setViewMonth((m) => m + 1); } function handleDayClick(day) { setSelectedDay((prev) => (prev === day ? null : day)); } function handleTaskClick(task) { onTaskClick?.(task); setOpen(false); } const totalScheduled = Object.values(tasksByDate).flat().length; return ( <> {/* Backdrop */} {open && (
{formatDayLabel(viewYear, viewMonth, selectedDay)}
{selectedDayTasks.length === 0 ? (Nema zadataka za odabrani datum.
) : (Odaberite datum u kalendaru za prikaz zadataka.
{totalScheduled > 0 && ({totalScheduled} zadatak/a s planiranim datumom.
)} {totalScheduled === 0 && (Nijedan zadatak nema postavljen planirani datum.
)} > )}