feat: frontend to handle multiple calendars for connect atoms (#16527)
* handle multiple calendars in connect atoms * resolve merge conflicts * fixup * frontend for multiple calendars * fixup * remove comment * add missing props * add prop for multi calendar view * add multi calendar support * fixup
This commit is contained in:
1 parent
26a1c749f7
commit
1d203dc566
6 files changed
+113
-14
No files matched your search
@@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import type { FC } from "react";
|
||||
|
||||
import type { CALENDARS } from "@calcom/platform-constants";
|
||||
@@ -8,6 +9,7 @@ import { Button } from "@calcom/ui";
|
||||
import type { OnCheckErrorType, UseCheckProps } from "../hooks/connect/useCheck";
|
||||
import { useCheck } from "../hooks/connect/useCheck";
|
||||
import { useConnect } from "../hooks/connect/useConnect";
|
||||
import { useConnectedCalendars } from "../hooks/useConnectedCalendars";
|
||||
import { AtomsWrapper } from "../src/components/atoms-wrapper";
|
||||
import { cn } from "../src/lib/utils";
|
||||
|
||||
@@ -19,6 +21,10 @@ export type OAuthConnectProps = {
|
||||
onCheckError?: OnCheckErrorType;
|
||||
redir?: string;
|
||||
initialData: UseCheckProps["initialData"];
|
||||
isMultiCalendar?: boolean;
|
||||
tooltip?: ReactNode;
|
||||
tooltipSide?: "top" | "bottom" | "left" | "right";
|
||||
isClickable?: boolean;
|
||||
};
|
||||
|
||||
export const OAuthConnect: FC<
|
||||
@@ -34,9 +40,12 @@ export const OAuthConnect: FC<
|
||||
calendar,
|
||||
redir,
|
||||
initialData,
|
||||
isMultiCalendar = false,
|
||||
tooltip,
|
||||
tooltipSide = "bottom",
|
||||
isClickable,
|
||||
}) => {
|
||||
const { connect } = useConnect(calendar, redir);
|
||||
|
||||
const { allowConnect, checked } = useCheck({
|
||||
onCheckError,
|
||||
calendar: calendar,
|
||||
@@ -54,6 +63,24 @@ export const OAuthConnect: FC<
|
||||
displayedLabel = alreadyConnectedLabel;
|
||||
}
|
||||
|
||||
if (isMultiCalendar) {
|
||||
return (
|
||||
<AtomsWrapper>
|
||||
<Button
|
||||
StartIcon="calendar-days"
|
||||
color="primary"
|
||||
disabled={isClickable ? false : isChecking}
|
||||
tooltip={tooltip ? tooltip : <ConnectedCalendarsTooltip />}
|
||||
tooltipSide={tooltipSide}
|
||||
tooltipOffset={10}
|
||||
className={cn("", !isDisabled && "cursor-pointer", className)}
|
||||
onClick={() => connect()}>
|
||||
{displayedLabel}
|
||||
</Button>
|
||||
</AtomsWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<AtomsWrapper>
|
||||
<Button
|
||||
@@ -62,10 +89,10 @@ export const OAuthConnect: FC<
|
||||
disabled={isDisabled}
|
||||
className={cn(
|
||||
"",
|
||||
className,
|
||||
isChecking && "animate-pulse",
|
||||
isDisabled && "cursor-not-allowed",
|
||||
!isDisabled && "cursor-pointer"
|
||||
!isDisabled && "cursor-pointer",
|
||||
className
|
||||
)}
|
||||
onClick={() => connect()}>
|
||||
{displayedLabel}
|
||||
@@ -73,3 +100,27 @@ export const OAuthConnect: FC<
|
||||
</AtomsWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const ConnectedCalendarsTooltip = () => {
|
||||
const { data: connectedCalendars, isLoading: isConnectedCalendarsLoading } = useConnectedCalendars({});
|
||||
|
||||
if (isConnectedCalendarsLoading)
|
||||
return (
|
||||
<div className="bg-subtle flex flex-col rounded-md border border-gray-300 px-4 py-2">Loading...</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="bg-subtle flex flex-col rounded-md border border-gray-300">
|
||||
{connectedCalendars?.connectedCalendars.map((calendar, index, arr) => {
|
||||
return (
|
||||
<>
|
||||
<div key={calendar.primary?.externalId} className="bg-transparent px-4 py-2 text-black">
|
||||
{calendar.primary?.name} - {calendar.primary?.email}
|
||||
</div>
|
||||
{arr.length - 1 !== index && <hr className="w-[90%] self-center" />}
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -21,6 +21,7 @@ import { useSaveCalendarCredentials } from "../../hooks/connect/useConnect";
|
||||
import { AtomsWrapper } from "../../src/components/atoms-wrapper";
|
||||
import { useToast } from "../../src/components/ui/use-toast";
|
||||
import { cn } from "../../src/lib/utils";
|
||||
import { ConnectedCalendarsTooltip } from "../OAuthConnect";
|
||||
import type { OAuthConnectProps } from "../OAuthConnect";
|
||||
|
||||
export const AppleConnect: FC<Partial<Omit<OAuthConnectProps, "redir">>> = ({
|
||||
@@ -29,6 +30,10 @@ export const AppleConnect: FC<Partial<Omit<OAuthConnectProps, "redir">>> = ({
|
||||
loadingLabel,
|
||||
className,
|
||||
initialData,
|
||||
isMultiCalendar = false,
|
||||
tooltip,
|
||||
tooltipSide = "bottom",
|
||||
isClickable,
|
||||
}) => {
|
||||
const { t } = useLocale();
|
||||
const form = useForm({
|
||||
@@ -77,14 +82,36 @@ export const AppleConnect: FC<Partial<Omit<OAuthConnectProps, "redir">>> = ({
|
||||
<AtomsWrapper>
|
||||
<Dialog open={isDialogOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
StartIcon="calendar-days"
|
||||
color="primary"
|
||||
disabled={isDisabled}
|
||||
className={cn("", className, isDisabled && "cursor-not-allowed", !isDisabled && "cursor-pointer")}
|
||||
onClick={() => setIsDialogOpen(true)}>
|
||||
{displayedLabel}
|
||||
</Button>
|
||||
<>
|
||||
{isMultiCalendar && (
|
||||
<Button
|
||||
StartIcon="calendar-days"
|
||||
color="primary"
|
||||
disabled={isClickable ? false : isChecking}
|
||||
tooltip={tooltip ? tooltip : <ConnectedCalendarsTooltip />}
|
||||
tooltipSide={tooltipSide}
|
||||
tooltipOffset={10}
|
||||
className={cn("", !isDisabled && "cursor-pointer", className)}
|
||||
onClick={() => setIsDialogOpen(true)}>
|
||||
{displayedLabel}
|
||||
</Button>
|
||||
)}
|
||||
{!isMultiCalendar && (
|
||||
<Button
|
||||
StartIcon="calendar-days"
|
||||
color="primary"
|
||||
disabled={isDisabled}
|
||||
className={cn(
|
||||
"",
|
||||
isDisabled && "cursor-not-allowed",
|
||||
!isDisabled && "cursor-pointer",
|
||||
className
|
||||
)}
|
||||
onClick={() => setIsDialogOpen(true)}>
|
||||
{displayedLabel}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
|
||||
@@ -16,6 +16,10 @@ export const GcalConnect: FC<Partial<OAuthConnectProps>> = ({
|
||||
onCheckError,
|
||||
redir,
|
||||
initialData,
|
||||
isMultiCalendar = false,
|
||||
tooltipSide,
|
||||
tooltip,
|
||||
isClickable,
|
||||
}) => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
@@ -28,6 +32,10 @@ export const GcalConnect: FC<Partial<OAuthConnectProps>> = ({
|
||||
onCheckError={onCheckError}
|
||||
redir={redir}
|
||||
initialData={initialData}
|
||||
isMultiCalendar={isMultiCalendar}
|
||||
tooltipSide={tooltipSide}
|
||||
tooltip={tooltip}
|
||||
isClickable={isClickable}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -16,6 +16,10 @@ export const OutlookConnect: FC<Partial<OAuthConnectProps>> = ({
|
||||
onCheckError,
|
||||
redir,
|
||||
initialData,
|
||||
isMultiCalendar = false,
|
||||
tooltipSide,
|
||||
tooltip,
|
||||
isClickable,
|
||||
}) => {
|
||||
const { t } = useLocale();
|
||||
return (
|
||||
@@ -28,6 +32,10 @@ export const OutlookConnect: FC<Partial<OAuthConnectProps>> = ({
|
||||
onCheckError={onCheckError}
|
||||
redir={redir}
|
||||
initialData={initialData}
|
||||
isMultiCalendar={isMultiCalendar}
|
||||
tooltipSide={tooltipSide}
|
||||
tooltip={tooltip}
|
||||
isClickable={isClickable}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -25,17 +25,21 @@ export default function Home(props: { calUsername: string; calEmail: string }) {
|
||||
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
|
||||
/>
|
||||
<Connect.OutlookCalendar
|
||||
isMultiCalendar={true}
|
||||
redir="http://localhost:4321/calendars"
|
||||
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
|
||||
/>
|
||||
<Connect.AppleCalendar className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700" />
|
||||
<Connect.AppleCalendar
|
||||
isMultiCalendar={true}
|
||||
className="h-[40px] bg-gradient-to-r from-[#8A2387] via-[#E94057] to-[#F27121] text-center text-base font-semibold text-transparent text-white hover:bg-orange-700"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden lg:block">
|
||||
<img
|
||||
width="76%"
|
||||
height="76%"
|
||||
className=" rounded-lg shadow-2xl"
|
||||
className="rounded-lg shadow-2xl"
|
||||
alt="cover image"
|
||||
src="https://images.unsplash.com/photo-1506784365847-bbad939e9335?q=80&w=2668&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
|
||||
/>
|
||||
|
||||
@@ -32,7 +32,8 @@ export function Tooltip({
|
||||
"calcom-tooltip",
|
||||
side === "top" && "-mt-7",
|
||||
side === "right" && "ml-2",
|
||||
"bg-inverted text-inverted relative z-50 rounded-md px-2 py-1 text-xs font-semibold shadow-lg",
|
||||
"relative z-50 rounded-md text-xs font-semibold shadow-lg",
|
||||
!isPlatform && "bg-inverted text-inverted px-2 py-1",
|
||||
props.className && `${props.className}`
|
||||
)}
|
||||
side={side}
|
||||
|
||||
Reference in new issue
Block a user