import { signIn } from "next-auth/react"; import { useRouter } from "next/router"; import type { Dispatch, SetStateAction } from "react"; import { useState } from "react"; import useDigitInput from "react-digit-input"; import { Controller, useForm } from "react-hook-form"; import { subdomainSuffix } from "@calcom/features/ee/organizations/lib/orgDomains"; import { useLocale } from "@calcom/lib/hooks/useLocale"; import slugify from "@calcom/lib/slugify"; import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry"; import { trpc } from "@calcom/trpc/react"; import { Button, Form, TextField, Alert, Dialog, DialogClose, DialogContent, DialogFooter, DialogHeader, Label, Input, } from "@calcom/ui"; import { ArrowRight, Info } from "@calcom/ui/components/icon"; function extractDomainFromEmail(email: string) { let out = ""; try { const match = email.match(/^(?:.*?:\/\/)?.*?(?[\w\-]*(?:\.\w{2,}|\.\w{2,}\.\w{2}))(?:[\/?#:]|$)/); out = (match && match.groups?.root) ?? ""; } catch (ignore) {} return out.split(".")[0]; } export const VerifyCodeDialog = ({ isOpenDialog, setIsOpenDialog, email, onSuccess, }: { isOpenDialog: boolean; setIsOpenDialog: Dispatch>; email: string; onSuccess: (isVerified: boolean) => void; }) => { const { t } = useLocale(); // Not using the mutation isLoading flag because after verifying we submit the underlying org creation form const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(""); const [value, onChange] = useState(""); const digits = useDigitInput({ acceptedCharacters: /^[0-9]$/, length: 6, value, onChange, }); const verifyCodeMutation = trpc.viewer.organizations.verifyCode.useMutation({ onSuccess: (data) => { setIsLoading(false); onSuccess(data); }, onError: (err) => { setIsLoading(false); if (err.message === "invalid_code") { setError(t("code_provided_invalid")); } }, }); const digitClassName = "h-12 w-12 !text-xl text-center"; return ( { onChange(""); setError(""); setIsOpenDialog(open); }}>
{error && (

{error}

)}
); }; export const CreateANewOrganizationForm = () => { const { t, i18n } = useLocale(); const router = useRouter(); const telemetry = useTelemetry(); const [serverErrorMessage, setServerErrorMessage] = useState(null); const [showVerifyCode, setShowVerifyCode] = useState(false); const { slug } = router.query; const newOrganizationFormMethods = useForm<{ name: string; slug: string; adminEmail: string; adminUsername: string; }>({ defaultValues: { slug: `${slug ?? ""}`, }, }); const watchAdminEmail = newOrganizationFormMethods.watch("adminEmail"); const createOrganizationMutation = trpc.viewer.organizations.create.useMutation({ onSuccess: async (data) => { if (data.checked) { setShowVerifyCode(true); } else if (data.user) { telemetry.event(telemetryEventTypes.org_created); await signIn("credentials", { redirect: false, callbackUrl: "/", email: data.user.email, password: data.user.password, }); router.push(`/settings/organizations/${data.user.organizationId}/set-password`); } }, onError: (err) => { if (err.message === "admin_email_taken") { newOrganizationFormMethods.setError("adminEmail", { type: "custom", message: t("email_already_used"), }); } else if (err.message === "organization_url_taken") { newOrganizationFormMethods.setError("slug", { type: "custom", message: t("url_taken") }); } else { setServerErrorMessage(err.message); } }, }); return ( <>
{ if (!createOrganizationMutation.isLoading) { setServerErrorMessage(null); createOrganizationMutation.mutate(v); } }}>
{serverErrorMessage && (
)} (
{ const domain = extractDomainFromEmail(e?.target.value); newOrganizationFormMethods.setValue("adminEmail", e?.target.value); newOrganizationFormMethods.setValue("adminUsername", e?.target.value.split("@")[0]); if (newOrganizationFormMethods.getValues("slug") === "") { newOrganizationFormMethods.setValue("slug", domain); } newOrganizationFormMethods.setValue( "name", domain.charAt(0).toUpperCase() + domain.slice(1) ); }} autoComplete="off" />
)} />
( <> { newOrganizationFormMethods.setValue("name", e?.target.value); if (newOrganizationFormMethods.formState.touchedFields["slug"] === undefined) { newOrganizationFormMethods.setValue("slug", slugify(e?.target.value)); } }} autoComplete="off" /> )} />
( { newOrganizationFormMethods.setValue("slug", slugify(e?.target.value), { shouldTouch: true, }); newOrganizationFormMethods.clearErrors("slug"); }} /> )} />
{ if (isVerified) { createOrganizationMutation.mutate({ ...newOrganizationFormMethods.getValues(), language: i18n.language, check: false, }); } }} /> ); };