import type { App_RoutingForms_Form } from "@prisma/client"; import Link from "next/link"; import { useEffect, useState } from "react"; import type { UseFormReturn } from "react-hook-form"; import { Controller, useForm } from "react-hook-form"; import { ShellMain } from "@calcom/features/shell/Shell"; import useApp from "@calcom/lib/hooks/useApp"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import { trpc } from "@calcom/trpc/react"; import type { AppGetServerSidePropsContext, AppPrisma, AppSsrInit, AppUser, } from "@calcom/types/AppGetServerSideProps"; import { Alert, Badge, Button, ButtonGroup, Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, DropdownMenuSeparator, Form, Meta, SettingsToggle, showToast, TextAreaField, TextField, Tooltip, VerticalDivider, } from "@calcom/ui"; import { ExternalLink, Link as LinkIcon, Download, Code, Trash } from "@calcom/ui/components/icon"; import { RoutingPages } from "../lib/RoutingPages"; import { getSerializableForm } from "../lib/getSerializableForm"; import { processRoute } from "../lib/processRoute"; import type { Response, Route, SerializableForm } from "../types/types"; import { FormAction, FormActionsDropdown, FormActionsProvider } from "./FormActions"; import FormInputFields from "./FormInputFields"; import RoutingNavBar from "./RoutingNavBar"; type RoutingForm = SerializableForm; export type RoutingFormWithResponseCount = RoutingForm & { _count: { responses: number; }; }; const Actions = ({ form, mutation, }: { form: RoutingFormWithResponseCount; mutation: { isLoading: boolean; }; }) => { const { t } = useLocale(); const { data: typeformApp } = useApp("typeform"); return (
{typeformApp?.isInstalled ? ( {t("Copy Typeform Redirect Url")} ) : null}
{t("preview")} {t("copy_link_to_form")} {t("download_responses")} {t("embed")} {typeformApp ? ( {t("Copy Typeform Redirect Url")} ) : null} {t("delete")}
); }; type SingleFormComponentProps = { form: RoutingFormWithResponseCount; appUrl: string; Page: React.FC<{ form: RoutingFormWithResponseCount; appUrl: string; hookForm: UseFormReturn; }>; }; function SingleForm({ form, appUrl, Page }: SingleFormComponentProps) { const utils = trpc.useContext(); const { t } = useLocale(); const [isTestPreviewOpen, setIsTestPreviewOpen] = useState(false); const [response, setResponse] = useState({}); const [decidedAction, setDecidedAction] = useState(null); function testRouting() { const action = processRoute({ form, response }); setDecidedAction(action); } const hookForm = useForm({ defaultValues: form, }); useEffect(() => { hookForm.reset(form); }, [form, hookForm]); const mutation = trpc.viewer.appRoutingForms.formMutation.useMutation({ onSuccess() { showToast("Form updated successfully.", "success"); }, onError(e) { if (e.message) { showToast(e.message, "error"); return; } showToast(`Something went wrong`, "error"); }, onSettled() { utils.viewer.appRoutingForms.formQuery.invalidate({ id: form.id }); }, }); const connectedForms = form.connectedForms; return ( <>
{ // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore mutation.mutate({ ...data, }); }}> }>
{ return ( onChange(val)} /> ); }} />
{form.routers.length ? (
Routers

{t("modifications_in_fields_warning")}

{form.routers.map((router) => { return (
{router.name}
); })}
) : null} {connectedForms?.length ? (
{t("connected_forms")}

{t("form_modifications_warning")}

{connectedForms.map((router) => { return (
{router.name}
); })}
) : null}
{!form._count?.responses && ( <> )}
{ e.preventDefault(); testRouting(); }}>
{form && }
{decidedAction && (
{t("route_to")}:
{RoutingPages.map((page) => { if (page.value !== decidedAction.type) return null; return (
{page.label}
); })} :{" "} {decidedAction.type === "customPageMessage" ? ( {decidedAction.value} ) : decidedAction.type === "externalRedirectUrl" ? ( {decidedAction.value} ) : ( {decidedAction.value} )}
)}
{ setIsTestPreviewOpen(false); setDecidedAction(null); setResponse({}); }}> {t("close")}
); } export default function SingleFormWrapper({ form: _form, ...props }: SingleFormComponentProps) { const { data: form, isLoading } = trpc.viewer.appRoutingForms.formQuery.useQuery( { id: _form.id }, { initialData: _form, trpc: {}, } ); const { t } = useLocale(); if (isLoading) { // It shouldn't be possible because we are passing the data from SSR to it as initialData. So, no need for skeleton here return null; } if (!form) { throw new Error(t("something_went_wrong")); } return ; } export const getServerSidePropsForSingleFormView = async function getServerSidePropsForSingleFormView( context: AppGetServerSidePropsContext, prisma: AppPrisma, user: AppUser, ssrInit: AppSsrInit ) { const ssr = await ssrInit(context); if (!user) { return { redirect: { permanent: false, destination: "/auth/login", }, }; } const { params } = context; if (!params) { return { notFound: true, }; } const formId = params.appPages[0]; if (!formId || params.appPages.length > 1) { return { notFound: true, }; } const isFormEditAllowed = (await import("../lib/isFormEditAllowed")).isFormEditAllowed; if (!(await isFormEditAllowed({ userId: user.id, formId }))) { return { notFound: true, }; } const form = await prisma.app_RoutingForms_Form.findUnique({ where: { id: formId, }, include: { _count: { select: { responses: true, }, }, }, }); if (!form) { return { notFound: true, }; } return { props: { trpcState: ssr.dehydrate(), form: await getSerializableForm(form), }, }; };