"use client"; import { Box, VStack, HStack, Text, Button, Spinner, Card, CardBody, CardHeader, Badge, Divider, Icon, Alert, AlertIcon, AlertTitle, AlertDescription, } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import { FaUsers, FaClock, FaCalendarAlt, FaPlus } from "react-icons/fa"; import { Meeting, CalendarEventResponse } from "../api"; import useApi from "../lib/useApi"; import { useRouter } from "next/navigation"; interface MeetingSelectionProps { roomName: string; isOwner: boolean; onMeetingSelect: (meeting: Meeting) => void; onCreateUnscheduled: () => void; } const formatDateTime = (date: string | Date) => { const d = new Date(date); return d.toLocaleString("en-US", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); }; const formatCountdown = (startTime: string | Date) => { const now = new Date(); const start = new Date(startTime); const diff = start.getTime() - now.getTime(); if (diff <= 0) return "Starting now"; const minutes = Math.floor(diff / 60000); const hours = Math.floor(minutes / 60); if (hours > 0) { return `Starts in ${hours}h ${minutes % 60}m`; } return `Starts in ${minutes} minutes`; }; export default function MeetingSelection({ roomName, isOwner, onMeetingSelect, onCreateUnscheduled, }: MeetingSelectionProps) { const [activeMeetings, setActiveMeetings] = useState([]); const [upcomingEvents, setUpcomingEvents] = useState( [], ); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const api = useApi(); const router = useRouter(); useEffect(() => { if (!api) return; const fetchMeetings = async () => { try { setLoading(true); // Fetch active meetings const active = await api.v1RoomsListActiveMeetings({ roomName }); setActiveMeetings(active); // Fetch upcoming calendar events (30 min ahead) const upcoming = await api.v1RoomsListUpcomingMeetings({ roomName, minutesAhead: 30, }); setUpcomingEvents(upcoming); setError(null); } catch (err) { console.error("Failed to fetch meetings:", err); setError("Failed to load meetings. Please try again."); } finally { setLoading(false); } }; fetchMeetings(); // Refresh every 30 seconds const interval = setInterval(fetchMeetings, 30000); return () => clearInterval(interval); }, [api, roomName]); const handleJoinMeeting = async (meetingId: string) => { if (!api) return; try { const meeting = await api.v1RoomsJoinMeeting({ roomName, meetingId, }); onMeetingSelect(meeting); } catch (err) { console.error("Failed to join meeting:", err); setError("Failed to join meeting. Please try again."); } }; const handleJoinUpcoming = (event: CalendarEventResponse) => { // Navigate to waiting page with event info router.push(`/room/${roomName}/wait?eventId=${event.id}`); }; if (loading) { return ( Loading meetings... ); } if (error) { return ( Error {error} ); } return ( Select a Meeting {/* Active Meetings */} {activeMeetings.length > 0 && ( <> Active Meetings {activeMeetings.map((meeting) => ( {meeting.calendar_metadata?.title || "Meeting"} {isOwner && meeting.calendar_metadata?.description && ( {meeting.calendar_metadata.description} )} {meeting.num_clients} participants Started {formatDateTime(meeting.start_date)} {isOwner && meeting.calendar_metadata?.attendees && ( {meeting.calendar_metadata.attendees .slice(0, 3) .map((attendee: any, idx: number) => ( {attendee.name || attendee.email} ))} {meeting.calendar_metadata.attendees.length > 3 && ( + {meeting.calendar_metadata.attendees.length - 3}{" "} more )} )} ))} )} {/* Upcoming Meetings */} {upcomingEvents.length > 0 && ( <> Upcoming Meetings {upcomingEvents.map((event) => ( {event.title || "Scheduled Meeting"} {formatCountdown(event.start_time)} {isOwner && event.description && ( {event.description} )} {formatDateTime(event.start_time)} -{" "} {formatDateTime(event.end_time)} {isOwner && event.attendees && ( {event.attendees .slice(0, 3) .map((attendee: any, idx: number) => ( {attendee.name || attendee.email} ))} {event.attendees.length > 3 && ( +{event.attendees.length - 3} more )} )} ))} )} {/* Create Unscheduled Meeting */} Start an Unscheduled Meeting Create a new meeting room that's not on the calendar ); }