"use client"; import { Button } from "@mdxui/primitives"; import { cn } from "@mdxui/primitives/lib/utils"; import { addDays, addMonths, addWeeks, endOfMonth, endOfWeek, format, isSameDay, isSameMonth, startOfDay, startOfMonth, startOfWeek, } from "date-fns"; import { ChevronLeft, ChevronRight } from "lucide-react"; import * as React from "react"; import type { CalendarProps, CalendarView } from "./types"; export function Calendar({ view = "month", date = new Date(), events = [], onViewChange, onDateChange, onEventClick, onSlotClick, className, }: CalendarProps) { const [currentDate, setCurrentDate] = React.useState(date); const [currentView, setCurrentView] = React.useState(view); React.useEffect(() => { setCurrentDate(date); }, [date]); React.useEffect(() => { setCurrentView(view); }, [view]); const handlePrevious = () => { const newDate = currentView === "month" ? addMonths(currentDate, -1) : currentView === "week" ? addWeeks(currentDate, -1) : addDays(currentDate, -1); setCurrentDate(newDate); onDateChange?.(newDate); }; const handleNext = () => { const newDate = currentView === "month" ? addMonths(currentDate, 1) : currentView === "week" ? addWeeks(currentDate, 1) : addDays(currentDate, 1); setCurrentDate(newDate); onDateChange?.(newDate); }; const handleToday = () => { const today = new Date(); setCurrentDate(today); onDateChange?.(today); }; const handleViewChange = (newView: CalendarView) => { setCurrentView(newView); onViewChange?.(newView); }; const getEventsForDay = (day: Date) => { return events.filter((event) => { const eventStart = startOfDay(event.start); const eventEnd = startOfDay(event.end); const checkDay = startOfDay(day); return checkDay >= eventStart && checkDay <= eventEnd; }); }; const renderMonthView = () => { const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); const startDate = startOfWeek(monthStart); const endDate = endOfWeek(monthEnd); const rows = []; let days = []; let day = startDate; while (day <= endDate) { for (let i = 0; i < 7; i++) { const dayEvents = getEventsForDay(day); const isCurrentMonth = isSameMonth(day, monthStart); const isToday = isSameDay(day, new Date()); const dayKey = day.toString(); const currentDay = day; days.push( ))} {dayEvents.length > 3 && (
+{dayEvents.length - 3} more
)} , ); day = addDays(day, 1); } rows.push(
{days}
, ); days = []; } return (
{["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].map((day) => (
{day}
))}
{rows}
); }; const renderWeekView = () => { const weekStart = startOfWeek(currentDate); const days = Array.from({ length: 7 }, (_, i) => addDays(weekStart, i)); const hours = Array.from({ length: 24 }, (_, i) => i); return (
{days.map((day) => (
{format(day, "EEE")}
{format(day, "d")}
))}
{hours.map((hour) => (
{format(new Date().setHours(hour, 0), "ha")}
{days.map((day) => { const slotDate = new Date(day); slotDate.setHours(hour, 0, 0, 0); return (
); }; const renderDayView = () => { const hours = Array.from({ length: 24 }, (_, i) => i); const dayEvents = getEventsForDay(currentDate); return (
{format(currentDate, "EEEE")}
{format(currentDate, "d")}
{hours.map((hour) => { const slotDate = new Date(currentDate); slotDate.setHours(hour, 0, 0, 0); return (
{format(new Date().setHours(hour, 0), "ha")}
))}
); })}
); }; return (

{currentView === "month" && format(currentDate, "MMMM yyyy")} {currentView === "week" && `Week of ${format(startOfWeek(currentDate), "MMM d, yyyy")}`} {currentView === "day" && format(currentDate, "MMMM d, yyyy")}

{currentView === "month" && renderMonthView()} {currentView === "week" && renderWeekView()} {currentView === "day" && renderDayView()}
); }