mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
* chore: decouple ui dialog from AppRouter and Atoms * fix type e2e test * fix: import dialog from @calcom/ui/components/dialog * fix: remove log * fix unit test * fix * fix and move data-override-list test to features package --------- Co-authored-by: hbjORbj <[email protected]>
148 lines
6.2 KiB
TypeScript
148 lines
6.2 KiB
TypeScript
import Link from "next/link";
|
|
import { Fragment } from "react";
|
|
|
|
import { useIsPlatform } from "@calcom/atoms/hooks/useIsPlatform";
|
|
import { Dialog } from "@calcom/features/components/controlled-dialog";
|
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
|
import classNames from "@calcom/ui/classNames";
|
|
import { Alert } from "@calcom/ui/components/alert";
|
|
import { DialogContent, DialogClose } from "@calcom/ui/components/dialog";
|
|
import { EmptyScreen } from "@calcom/ui/components/empty-screen";
|
|
import { Switch } from "@calcom/ui/components/form";
|
|
import { ListItem, ListItemText, ListItemTitle } from "@calcom/ui/components/list";
|
|
import { SkeletonContainer } from "@calcom/ui/components/skeleton";
|
|
import { SkeletonText } from "@calcom/ui/components/skeleton";
|
|
|
|
import type { UseCalendarsReturnType } from "../hooks/useCalendars";
|
|
|
|
interface IOverlayCalendarSettingsModalProps {
|
|
open?: boolean;
|
|
onClose?: (state: boolean) => void;
|
|
onClickNoCalendar?: () => void;
|
|
isLoading: boolean;
|
|
connectedCalendars: UseCalendarsReturnType["connectedCalendars"];
|
|
onToggleConnectedCalendar: (externalCalendarId: string, credentialId: number) => void;
|
|
checkIsCalendarToggled: (externalCalendarId: string, credentialId: number) => boolean;
|
|
}
|
|
|
|
const SkeletonLoader = () => {
|
|
return (
|
|
<SkeletonContainer>
|
|
<div className="border-subtle mt-3 space-y-4 rounded-xl border px-4 py-4 ">
|
|
<SkeletonText className="h-4 w-full" />
|
|
<SkeletonText className="h-4 w-full" />
|
|
<SkeletonText className="h-4 w-full" />
|
|
<SkeletonText className="h-4 w-full" />
|
|
</div>
|
|
</SkeletonContainer>
|
|
);
|
|
};
|
|
|
|
export function OverlayCalendarSettingsModal({
|
|
connectedCalendars,
|
|
isLoading,
|
|
open,
|
|
onClose,
|
|
onClickNoCalendar,
|
|
onToggleConnectedCalendar,
|
|
checkIsCalendarToggled,
|
|
}: IOverlayCalendarSettingsModalProps) {
|
|
const { t } = useLocale();
|
|
const isPlatform = useIsPlatform();
|
|
|
|
return (
|
|
<>
|
|
<Dialog open={open} onOpenChange={onClose}>
|
|
<DialogContent
|
|
enableOverflow
|
|
type="creation"
|
|
title="Calendar Settings"
|
|
className="pb-4"
|
|
description={t("view_overlay_calendar_events")}>
|
|
<div className="no-scrollbar max-h-full overflow-y-scroll ">
|
|
{isLoading ? (
|
|
<SkeletonLoader />
|
|
) : (
|
|
<>
|
|
{connectedCalendars.length === 0 ? (
|
|
<EmptyScreen
|
|
Icon="calendar"
|
|
headline={t("no_calendar_installed")}
|
|
description={t("no_calendar_installed_description")}
|
|
buttonText={t("add_a_calendar")}
|
|
buttonOnClick={onClickNoCalendar}
|
|
/>
|
|
) : (
|
|
<>
|
|
{connectedCalendars.map((item) => (
|
|
<Fragment key={item.credentialId}>
|
|
{item.error && !item.calendars && (
|
|
<Alert severity="error" title={item.error.message} />
|
|
)}
|
|
{item?.error === undefined && item.calendars && (
|
|
<ListItem className="flex-col rounded-md">
|
|
<div className="flex w-full flex-1 items-center space-x-3 pb-4 rtl:space-x-reverse">
|
|
{
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
item.integration.logo && (
|
|
<img
|
|
className={classNames(
|
|
"h-10 w-10",
|
|
item.integration.logo.includes("-dark") && "dark:invert"
|
|
)}
|
|
src={
|
|
isPlatform
|
|
? `https://app.cal.com${item.integration.logo}`
|
|
: item.integration.logo
|
|
}
|
|
alt={`${item.integration.title} logo`}
|
|
/>
|
|
)
|
|
}
|
|
<div className="flex-grow truncate pl-2">
|
|
<ListItemTitle component="h3" className="space-x-2 rtl:space-x-reverse">
|
|
<Link href={`/apps/${item.integration.slug}`}>
|
|
{item.integration.name || item.integration.title}
|
|
</Link>
|
|
</ListItemTitle>
|
|
<ListItemText component="p">{item.primary.email}</ListItemText>
|
|
</div>
|
|
</div>
|
|
<div className="border-subtle w-full border-t pt-4">
|
|
<ul className="space-y-4">
|
|
{item.calendars.map((cal, index) => {
|
|
const id = cal.integrationTitle ?? `calendar-switch-${index}`;
|
|
return (
|
|
<li className="flex gap-3" key={id}>
|
|
<Switch
|
|
id={id}
|
|
checked={checkIsCalendarToggled(cal.externalId, item.credentialId)}
|
|
onCheckedChange={() => {
|
|
onToggleConnectedCalendar(cal.externalId, item.credentialId);
|
|
}}
|
|
/>
|
|
<label htmlFor={id}>{cal.name}</label>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
</div>
|
|
</ListItem>
|
|
)}
|
|
</Fragment>
|
|
))}
|
|
</>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
|
|
<div className="mt-4 flex gap-2 self-end">
|
|
<DialogClose>{t("done")}</DialogClose>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</>
|
|
);
|
|
}
|