/** * Calendar Widget - displays upcoming events */ import { useState, useEffect } from "react"; import { Calendar as CalendarIcon, Clock, MapPin } from "lucide-react"; import type { WidgetProps } from "@mosaic/shared"; interface Event { id: string; title: string; startTime: string; endTime?: string; location?: string; allDay: boolean; } export function CalendarWidget({ id: _id, config: _config }: WidgetProps): React.JSX.Element { const [events, setEvents] = useState([]); const [isLoading, setIsLoading] = useState(true); // Mock data for now - will fetch from API later useEffect(() => { setIsLoading(true); const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const tomorrow = new Date(today); tomorrow.setDate(tomorrow.getDate() + 1); setTimeout(() => { setEvents([ { id: "1", title: "Team Standup", startTime: new Date(today.setHours(9, 0, 0, 0)).toISOString(), endTime: new Date(today.setHours(9, 30, 0, 0)).toISOString(), location: "Zoom", allDay: false, }, { id: "2", title: "Project Review", startTime: new Date(today.setHours(14, 0, 0, 0)).toISOString(), endTime: new Date(today.setHours(15, 0, 0, 0)).toISOString(), location: "Conference Room A", allDay: false, }, { id: "3", title: "Sprint Planning", startTime: new Date(tomorrow.setHours(10, 0, 0, 0)).toISOString(), endTime: new Date(tomorrow.setHours(12, 0, 0, 0)).toISOString(), allDay: false, }, ]); setIsLoading(false); }, 500); }, []); const formatTime = (dateString: string): string => { const date = new Date(dateString); return date.toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", hour12: true, }); }; const formatDay = (dateString: string): string => { const date = new Date(dateString); const today = new Date(); const tomorrow = new Date(today); tomorrow.setDate(tomorrow.getDate() + 1); if (date.toDateString() === today.toDateString()) { return "Today"; } else if (date.toDateString() === tomorrow.toDateString()) { return "Tomorrow"; } return date.toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" }); }; const getUpcomingEvents = (): Event[] => { const now = new Date(); return events .filter((e) => new Date(e.startTime) > now) .sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime()) .slice(0, 5); }; if (isLoading) { return (
Loading events...
); } const upcomingEvents = getUpcomingEvents(); return (
{/* Header */}
Upcoming Events
{/* Event list */}
{upcomingEvents.length === 0 ? (
No upcoming events
) : ( upcomingEvents.map((event) => (
{event.title}
{!event.allDay && (
{formatTime(event.startTime)} {event.endTime && ` - ${formatTime(event.endTime)}`}
)} {event.location && (
{event.location}
)}
{formatDay(event.startTime)}
)) )}
); }