import { zodResolver } from "@hookform/resolvers/zod"; import { AppCategories } from "@prisma/client"; import { useRouter } from "next/router"; import { useState, useReducer, FC } from "react"; import { Controller, useForm } from "react-hook-form"; import { z } from "zod"; import AppCategoryNavigation from "@calcom/app-store/_components/AppCategoryNavigation"; import { appKeysSchemas } from "@calcom/app-store/apps.keys-schemas.generated"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { RouterOutputs, trpc } from "@calcom/trpc/react"; import { Button, ConfirmationDialogContent, Dialog, DialogClose, DialogContent, DialogFooter, Dropdown, DropdownItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, EmptyScreen, Form, List, showToast, SkeletonButton, SkeletonContainer, SkeletonText, TextField, } from "@calcom/ui"; import { FiAlertCircle, FiEdit, FiMoreHorizontal, FiCheckCircle, FiXCircle, } from "@calcom/ui/components/icon"; import AppListCard from "../../../apps/web/components/AppListCard"; type App = RouterOutputs["viewer"]["appsRouter"]["listLocal"][number]; const IntegrationContainer = ({ app, category, handleModelOpen, }: { app: App; category: string; handleModelOpen: (data: EditModalState) => void; }) => { const { t } = useLocale(); const utils = trpc.useContext(); const [disableDialog, setDisableDialog] = useState(false); const showKeyModal = () => { if (app.keys) { handleModelOpen({ dirName: app.dirName, keys: app.keys, slug: app.slug, type: app.type, isOpen: "editKeys", }); } }; const enableAppMutation = trpc.viewer.appsRouter.toggle.useMutation({ onSuccess: (enabled) => { utils.viewer.appsRouter.listLocal.invalidate({ category }); setDisableDialog(false); showToast( enabled ? t("app_is_enabled", { appName: app.name }) : t("app_is_disabled", { appName: app.name }), "success" ); if (enabled) { showKeyModal(); } }, onError: (error) => { showToast(error.message, "error"); }, }); return (
  • ); }; const querySchema = z.object({ category: z .nativeEnum({ ...AppCategories, conferencing: "conferencing" }) .optional() .default(AppCategories.calendar), }); const AdminAppsList = ({ baseURL, className, useQueryParam = false, }: { baseURL: string; className?: string; useQueryParam?: boolean; }) => { const router = useRouter(); return (
    { e.preventDefault(); router.replace("/"); }}>
    ); }; const EditKeysModal: FC<{ dirName: string; slug: string; type: string; isOpen: boolean; keys: App["keys"]; handleModelClose: () => void; }> = (props) => { const { t } = useLocale(); const { dirName, slug, type, isOpen, keys, handleModelClose } = props; const appKeySchema = appKeysSchemas[dirName as keyof typeof appKeysSchemas]; const formMethods = useForm({ resolver: zodResolver(appKeySchema), }); const saveKeysMutation = trpc.viewer.appsRouter.saveKeys.useMutation({ onSuccess: () => { showToast(t("keys_have_been_saved"), "success"); handleModelClose(); }, onError: (error) => { showToast(error.message, "error"); }, }); return ( {!!keys && typeof keys === "object" && (
    saveKeysMutation.mutate({ slug, type, keys: values, dirName, }) } className="px-4 pb-4"> {Object.keys(keys).map((key) => ( ( { formMethods.setValue(key, e?.target.value); }} /> )} /> ))} )}
    ); }; interface EditModalState extends Pick { isOpen: "none" | "editKeys" | "disableKeys"; dirName: string; type: string; slug: string; } const AdminAppsListContainer = () => { const { t } = useLocale(); const router = useRouter(); const { category } = querySchema.parse(router.query); const { data: apps, isLoading } = trpc.viewer.appsRouter.listLocal.useQuery( { category }, { enabled: router.isReady } ); const [modalState, setModalState] = useReducer( (data: EditModalState, partialData: Partial) => ({ ...data, ...partialData }), { keys: null, isOpen: "none", dirName: "", type: "", slug: "", } ); const handleModelClose = () => setModalState({ keys: null, isOpen: "none", dirName: "", slug: "", type: "" }); const handleModelOpen = (data: EditModalState) => setModalState({ ...data }); if (isLoading) return ; if (!apps) { return ( ); } return ( <> {apps.map((app) => ( ))} ); }; export default AdminAppsList; const SkeletonLoader = () => { return (
    ); };