import React, { Fragment, useState } from "react"; import { useMutation } from "react-query"; import Select from "react-select"; import { QueryCell } from "@lib/QueryCell"; import { useLocale } from "@lib/hooks/useLocale"; import showToast from "@lib/notification"; import { trpc } from "@lib/trpc"; import { List } from "@components/List"; import { ShellSubHeading } from "@components/Shell"; import { Alert } from "@components/ui/Alert"; import Button from "@components/ui/Button"; import Switch from "@components/ui/Switch"; import ConnectIntegration from "./ConnectIntegrations"; import DisconnectIntegration from "./DisconnectIntegration"; import IntegrationListItem from "./IntegrationListItem"; import SubHeadingTitleWithConnections from "./SubHeadingTitleWithConnections"; type Props = { onChanged: () => unknown | Promise; }; function CalendarSwitch(props: { type: string; externalId: string; title: string; defaultSelected: boolean; }) { const utils = trpc.useContext(); const mutation = useMutation< unknown, unknown, { isOn: boolean; } >( async ({ isOn }) => { const body = { integration: props.type, externalId: props.externalId, }; if (isOn) { const res = await fetch("/api/availability/calendar", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!res.ok) { throw new Error("Something went wrong"); } } else { const res = await fetch("/api/availability/calendar", { method: "DELETE", headers: { "Content-Type": "application/json", }, body: JSON.stringify(body), }); if (!res.ok) { throw new Error("Something went wrong"); } } }, { async onSettled() { await utils.invalidateQueries(["viewer.integrations"]); }, onError() { showToast(`Something went wrong when toggling "${props.title}""`, "error"); }, } ); return (
{ mutation.mutate({ isOn }); }} />
); } function ConnectedCalendarsList(props: Props) { const { t } = useLocale(); const query = trpc.useQuery(["viewer.connectedCalendars"], { suspense: true }); return ( null} success={({ data }) => { if (!data.connectedCalendars.length) { return null; } return ( {data.connectedCalendars.map((item) => ( {item.calendars ? ( ( )} onOpenChange={props.onChanged} /> }>
    {item.calendars.map((cal) => ( ))}
) : ( ( )} onOpenChange={() => props.onChanged()} /> } /> )}
))}
); }} /> ); } function PrimaryCalendarSelector() { const { t } = useLocale(); const query = trpc.useQuery(["viewer.connectedCalendars"], { suspense: true, }); const [selectedOption, setSelectedOption] = useState(() => { const selected = query.data?.connectedCalendars .map((connected) => connected.calendars ?? []) .flat() .find((cal) => cal.externalId === query.data.destinationCalendar?.externalId); if (!selected) { return null; } return { value: `${selected.integration}:${selected.externalId}`, label: selected.name, }; }); const mutation = trpc.useMutation("viewer.setUserDestinationCalendar"); if (!query.data?.connectedCalendars.length) { return null; } const options = query.data.connectedCalendars.map((selectedCalendar) => ({ key: selectedCalendar.credentialId, label: `${selectedCalendar.integration.title} (${selectedCalendar.primary?.name})`, options: (selectedCalendar.calendars ?? []).map((cal) => ({ label: cal.name || "", value: `${cal.integration}:${cal.externalId}`, })), })) ?? []; return (
{/* There's no easy way to customize the displayed value for a Select, so we fake it. */}