import { useAppDispatch, useAppSelector } from "@/app/hooks"; import { getCalendars } from "@/features/Calendars/CalendarApi"; import { Calendar } from "@/features/Calendars/CalendarTypes"; import { addSharedCalendarAsync } from "@/features/Calendars/services"; import { CalendarData } from "@/features/Calendars/types/CalendarData"; import { renameDefault } from "@/utils/renameDefault"; import { Avatar, Box, Button, IconButton, TextField, Typography, useTheme, } from "@linagora/twake-mui"; import CloseIcon from "@mui/icons-material/Close"; import { useState } from "react"; import { useI18n } from "twake-i18n"; import { PeopleSearch, User } from "../Attendees/PeopleSearch"; import { ResponsiveDialog } from "../Dialog"; import { stringAvatar } from "../Event/utils/eventUtils"; import { ColorPicker } from "./CalendarColorPicker"; import { defaultColors, getAccessiblePair } from "./utils/calendarColorsUtils"; interface CalendarWithOwner { cal: CalendarData; owner: User; } function CalendarItem({ cal, onRemove, onColorChange, }: { cal: CalendarWithOwner; onRemove: () => void; onColorChange: (color: Record) => void; }) { const theme = useTheme(); const { t } = useI18n(); return ( {renameDefault( cal.cal["dav:name"], cal.owner.displayName, t, false )} {cal.owner.email} ); } function SelectedCalendarsList({ calendars, selectedCal, onRemove, onColorChange, }: { calendars: Record; selectedCal: CalendarWithOwner[]; onRemove: (cal: CalendarWithOwner) => void; onColorChange: ( cal: CalendarWithOwner, color: Record ) => void; }) { const { t } = useI18n(); if (selectedCal.length === 0) return null; const groupedByOwner = selectedCal.reduce< Record< string, { owner: User; visibleCals: CalendarWithOwner[]; alreadyExisting: boolean; } > >((acc, cal) => { const exists = Object.values(calendars).some( (existing: Calendar) => existing.id === cal.cal?._links?.self?.href ?.replace("/calendars/", "") .replace(".json", "") ); if (!acc[cal.owner.email]) { acc[cal.owner.email] = { owner: cal.owner, visibleCals: [], alreadyExisting: false, }; } if (exists) { acc[cal.owner.email].alreadyExisting = true; } else { acc[cal.owner.email].visibleCals.push(cal); } return acc; }, {}); return ( {t("common.name")} {Object.values(groupedByOwner).map( ({ owner, visibleCals, alreadyExisting }) => ( {visibleCals.length > 0 ? ( visibleCals.map((cal) => cal.cal ? ( onRemove(cal)} onColorChange={(color) => onColorChange(cal, color)} /> ) : ( {t("calendar.noPublicCalendarsFor", { name: owner.displayName, })} ) ) ) : alreadyExisting ? ( {t("calendar.noMoreCalendarsFor", { name: owner.displayName })} ) : null} ) )} ); } export default function CalendarSearch({ open, onClose, }: { open: boolean; onClose: ( result?: string[] | Record, reason?: "backdropClick" | "escapeKeyDown" ) => void; }) { const dispatch = useAppDispatch(); const theme = useTheme(); const openpaasId = useAppSelector((state) => state.user.userData?.openpaasId) ?? ""; const calendars = useAppSelector((state) => state.calendars.list); const [selectedCal, setSelectedCalendars] = useState([]); const [selectedUsers, setSelectedUsers] = useState([]); const handleSave = async () => { if (selectedCal.length > 0) { const idList = await Promise.all( selectedCal.map(async (cal) => { const calId = crypto.randomUUID(); const exists = Object.values(calendars).some( (existing: Calendar) => existing.id === cal.cal?._links?.self?.href ?.replace("/calendars/", "") .replace(".json", "") ); if (!exists && cal.cal) { await dispatch( addSharedCalendarAsync({ userId: openpaasId, calId, cal: { ...cal, color: cal.cal["apple:color"] ? { light: cal.cal["apple:color"], dark: getAccessiblePair(cal.cal["apple:color"], theme), } : defaultColors[0], }, }) ); return cal.cal._links.self?.href ?.replace("/calendars/", "") .replace(".json", ""); } return null; }) ); onClose(idList.filter(Boolean) as string[]); setSelectedCalendars([]); setSelectedUsers([]); } }; const { t } = useI18n(); return ( { onClose({}, "backdropClick"); setSelectedCalendars([]); setSelectedUsers([]); }} title={t("calendar.browseOtherCalendars")} actions={ <> } > } onChange={async (_event: React.SyntheticEvent, value: User[]) => { setSelectedUsers(value); const cals = await Promise.all( value.map(async (user: User) => { if (user?.openpaasId) { const cals = await getCalendars( user.openpaasId, "sharedPublic=true&" ); return cals._embedded?.["dav:calendar"] ? cals._embedded["dav:calendar"].map((cal) => ({ cal, owner: user, })) : { cal: undefined, owner: user }; } return null; }) ); setSelectedCalendars( cals.flat().filter(Boolean) as CalendarWithOwner[] ); }} /> { if (!cal.cal?._links?.self?.href) return; setSelectedCalendars((prev) => prev.filter( (c) => c.cal?._links?.self?.href !== cal.cal._links.self?.href ) ); if ( !selectedCal.find( (c) => cal.owner.email === c.owner.email && c.cal?._links?.self?.href !== cal.cal._links.self?.href ) ) { setSelectedUsers((prev) => prev.filter((u) => u.email !== cal.owner.email) ); } }} onColorChange={(cal, color) => setSelectedCalendars((prev) => prev.map((prevcal) => prevcal.owner.email === cal.owner.email && prevcal.cal._links.self?.href === cal.cal._links.self?.href ? { ...prevcal, cal: { ...prevcal.cal, "apple:color": color.light, }, } : prevcal ) ) } /> ); }