"use client"; import { useState, useEffect } from "react"; import Link from "next/link"; import { Card, CardHeader, CardContent } from "./Card"; import Badge from "./Badge"; import Button from "./Button"; import { formatDate } from "@/lib/utils"; import { format, startOfMonth, endOfMonth, startOfWeek, endOfWeek, addDays, isSameMonth, isSameDay, addMonths, subMonths, parseISO, isAfter, isBefore, startOfDay, addWeeks } from "date-fns"; import { pl } from "date-fns/locale"; const statusColors = { registered: "bg-blue-100 text-blue-800", approved: "bg-green-100 text-green-800", pending: "bg-yellow-100 text-yellow-800", in_progress: "bg-orange-100 text-orange-800", fulfilled: "bg-gray-100 text-gray-800", cancelled: "bg-red-100 text-red-800", }; const statusTranslations = { registered: "Zarejestrowany", approved: "Zatwierdzony", pending: "Oczekujący", in_progress: "W trakcie", fulfilled: "Zakończony", cancelled: "Wycofany", }; export default function ProjectCalendarWidget({ projects = [], compact = false, showUpcoming = true, maxUpcoming = 5 }) { const [currentDate, setCurrentDate] = useState(new Date()); const [viewMode, setViewMode] = useState(compact ? 'upcoming' : 'mini-calendar'); // Filter projects that have finish dates and are not fulfilled const activeProjects = projects.filter(p => p.finish_date && p.project_status !== 'fulfilled' ); const getProjectsForDate = (date) => { return activeProjects.filter(project => { if (!project.finish_date) return false; try { const projectDate = parseISO(project.finish_date); return isSameDay(projectDate, date); } catch (error) { return false; } }); }; const getUpcomingProjects = () => { const today = startOfDay(new Date()); const nextMonth = addWeeks(today, 4); return activeProjects .filter(project => { if (!project.finish_date) return false; try { const projectDate = parseISO(project.finish_date); return isAfter(projectDate, today) && isBefore(projectDate, nextMonth); } catch (error) { return false; } }) .sort((a, b) => { const dateA = parseISO(a.finish_date); const dateB = parseISO(b.finish_date); return dateA - dateB; }) .slice(0, maxUpcoming); }; const getOverdueProjects = () => { const today = startOfDay(new Date()); return activeProjects .filter(project => { if (!project.finish_date) return false; try { const projectDate = parseISO(project.finish_date); return isBefore(projectDate, today); } catch (error) { return false; } }) .sort((a, b) => { const dateA = parseISO(a.finish_date); const dateB = parseISO(b.finish_date); return dateB - dateA; // Most recently overdue first }) .slice(0, maxUpcoming); }; const renderMiniCalendar = () => { const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); const calendarStart = startOfWeek(monthStart, { weekStartsOn: 1 }); const calendarEnd = endOfWeek(monthEnd, { weekStartsOn: 1 }); const days = []; let day = calendarStart; while (day <= calendarEnd) { days.push(day); day = addDays(day, 1); } const weekdays = ['P', 'W', 'Ś', 'C', 'P', 'S', 'N']; return (
{/* Calendar Header */}

{format(currentDate, 'LLLL yyyy', { locale: pl })}

{/* Weekday Headers */}
{weekdays.map(weekday => (
{weekday}
))}
{/* Calendar Grid */}
{days.map((day, index) => { const dayProjects = getProjectsForDate(day); const isCurrentMonth = isSameMonth(day, currentDate); const isToday = isSameDay(day, new Date()); const hasProjects = dayProjects.length > 0; return (
p.project_name).join(', ')}` : ''} > {format(day, 'd')} {hasProjects && isCurrentMonth && (
)}
); })}
); }; const renderUpcomingList = () => { const upcomingProjects = getUpcomingProjects(); const overdueProjects = getOverdueProjects(); return (
{/* Overdue Projects */} {overdueProjects.length > 0 && (

Przeterminowane ({overdueProjects.length})

{overdueProjects.map(project => (
{project.project_name}
{formatDate(project.finish_date)}
))}
)} {/* Upcoming Projects */} {upcomingProjects.length > 0 && (

Nadchodzące ({upcomingProjects.length})

{upcomingProjects.map(project => { const daysUntilDeadline = Math.ceil((parseISO(project.finish_date) - new Date()) / (1000 * 60 * 60 * 24)); return (
{project.project_name}
{formatDate(project.finish_date)} • za {daysUntilDeadline} dni
); })}
)} {upcomingProjects.length === 0 && overdueProjects.length === 0 && (
Brak nadchodzących terminów
)}
); }; if (activeProjects.length === 0) { return (

Kalendarz projektów

Brak aktywnych projektów z terminami
); } return (

Kalendarz projektów

{!compact && (
)}
{viewMode === 'mini-calendar' ? renderMiniCalendar() : renderUpcomingList()}
); }