import { useEffect, useState } from "react"; import { deleteEventAsync } from "../Calendars/CalendarSlice"; import { useAppDispatch, useAppSelector } from "../../app/hooks"; import { Popover, Button, Box, Typography, ButtonGroup, Card, CardContent, Divider, IconButton, Avatar, Badge, } from "@mui/material"; import EditIcon from "@mui/icons-material/Edit"; import DeleteIcon from "@mui/icons-material/Delete"; import CloseIcon from "@mui/icons-material/Close"; import CalendarTodayIcon from "@mui/icons-material/CalendarToday"; import LocationOnIcon from "@mui/icons-material/LocationOn"; import VideocamIcon from "@mui/icons-material/Videocam"; import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline"; import CircleIcon from "@mui/icons-material/Circle"; import CancelIcon from "@mui/icons-material/Cancel"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import { userAttendee } from "../User/userDataTypes"; function EventDisplayModal({ eventId, calId, anchorEl, open, onClose, }: { eventId: string; calId: string; anchorEl: HTMLElement | null; open: boolean; onClose: (event: {}, reason: "backdropClick" | "escapeKeyDown") => void; }) { const dispatch = useAppDispatch(); const calendar = useAppSelector((state) => state.calendars.list[calId]); const event = useAppSelector( (state) => state.calendars.list[calId]?.events[eventId] ); const user = useAppSelector((state) => state.user); const [showAllAttendees, setShowAllAttendees] = useState(false); useEffect(() => { if (!event || !calendar) { onClose({}, "backdropClick"); } }, [event, calendar, onClose]); if (!event || !calendar) return null; const attendeeDisplayLimit = 3; const attendees = event.attendee?.filter( (a) => a.cal_address !== event.organizer?.cal_address ) || []; const visibleAttendees = showAllAttendees ? attendees : attendees.slice(0, attendeeDisplayLimit); const currentUserAttendee = event.attendee?.find( (person) => person.cal_address === user.userData.email ); const organizer = event.attendee?.find( (a) => a.cal_address === event.organizer?.cal_address ); return ( {/* Top-right buttons */} {calendar.id.split("/")[0] === user.userData.openpaasId && ( { onClose({}, "backdropClick"); dispatch(deleteEventAsync({ calId, eventId })); }} > )} onClose({}, "backdropClick")}> {event.title && ( {event.title} )} {/* Time info*/} {formatDate(event.start)} {event.end && ` – ${new Date(event.end).toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit", })}`} {/* Location */} {event.location && ( } text={event.location} /> )} {/* Video */} {event.x_openpass_videoconference && ( } text="Video conference available" /> )} {/* Attendees */} {event.attendee?.length > 0 && ( Attendees: {organizer && renderAttendeeBadge(organizer, "org", true)} {visibleAttendees.map((a, idx) => renderAttendeeBadge(a, idx.toString()) )} {attendees.length > attendeeDisplayLimit && ( setShowAllAttendees(!showAllAttendees)} > {showAllAttendees ? "Show less" : `Show more (${ attendees.length - attendeeDisplayLimit } more)`} )} )} {/* Error */} {event.error && ( } text={event.error} error /> )} {/* Calendar color dot */} {calendar.name} {/* RSVP */} {currentUserAttendee && ( Will you attend? )} {/* Description */} {event.description && ( {event.description} )} ); } function InfoRow({ icon, text, error = false, }: { icon: React.ReactNode; text: string; error?: boolean; }) { return ( {icon} {text} ); } function renderAttendeeBadge( a: userAttendee, key: string, isOrganizer?: boolean ) { const statusIcon = a.partstat === "ACCEPTED" ? ( ) : a.partstat === "DECLINED" ? ( ) : null; return ( {statusIcon} ) } > {a.cn || a.cal_address} {isOrganizer && ( Organizer )} ); } function formatDate(date: Date) { return new Date(date).toLocaleString(undefined, { weekday: "long", month: "long", day: "numeric", hour: "2-digit", minute: "2-digit", }); } export function stringToColor(string: string) { let hash = 0; for (let i = 0; i < string.length; i++) { hash = string.charCodeAt(i) + ((hash << 5) - hash); } let color = "#"; for (let i = 0; i < 3; i++) { const value = (hash >> (i * 8)) & 0xff; color += `00${value.toString(16)}`.slice(-2); } return color; } function stringAvatar(name: string) { return { sx: { width: 24, height: 24, fontSize: 18, bgcolor: stringToColor(name) }, children: name[0], }; } export default EventDisplayModal;