"use client"; import { zodResolver } from "@hookform/resolvers/zod"; import { authClient } from "@repo/auth/client"; import { config } from "@repo/config"; import { useAuthErrorMessages } from "@saas/auth/hooks/errors-messages"; import { OrganizationInvitationAlert } from "@saas/organizations/components/OrganizationInvitationAlert"; import { useFormErrors } from "@shared/hooks/form-errors"; import { Alert, AlertDescription, AlertTitle } from "@ui/components/alert"; import { Button } from "@ui/components/button"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@ui/components/form"; import { Input } from "@ui/components/input"; import { AlertTriangleIcon, ArrowRightIcon, EyeIcon, EyeOffIcon, MailboxIcon, } from "lucide-react"; import { useTranslations } from "next-intl"; import Link from "next/link"; import { useRouter, useSearchParams } from "next/navigation"; import { useState } from "react"; import type { SubmitHandler } from "react-hook-form"; import { useForm } from "react-hook-form"; import { withQuery } from "ufo"; import { z } from "zod"; import { type OAuthProvider, oAuthProviders, } from "../constants/oauth-providers"; import { SocialSigninButton } from "./SocialSigninButton"; const formSchema = z.object({ email: z.string().email(), password: z.string().min(1), name: z.string().min(1), }); type FormValues = z.infer; export function SignupForm({ prefillEmail }: { prefillEmail?: string }) { const t = useTranslations(); const router = useRouter(); const { zodErrorMap } = useFormErrors(); const { getAuthErrorMessage } = useAuthErrorMessages(); const searchParams = useSearchParams(); const [showPassword, setShowPassword] = useState(false); const invitationId = searchParams.get("invitationId"); const email = searchParams.get("email"); const redirectTo = searchParams.get("redirectTo"); const form = useForm({ resolver: zodResolver(formSchema, { errorMap: zodErrorMap, }), values: { name: "", email: prefillEmail ?? email ?? "", password: "", }, }); const invitationOnlyMode = !config.auth.enableSignup && invitationId; const redirectPath = invitationId ? `/app/organization-invitation/${invitationId}` : (redirectTo ?? config.auth.redirectAfterSignIn); const onSubmit: SubmitHandler = async ({ email, password, name, }) => { try { const { error } = await authClient.signUp.email({ email, password, name, callbackURL: redirectPath, }); if (error) { throw error; } if (invitationOnlyMode) { const { error } = await authClient.organization.acceptInvitation({ invitationId, }); if (error) { throw error; } router.push(config.auth.redirectAfterSignIn); } } catch (e) { form.setError("root", { message: getAuthErrorMessage( e && typeof e === "object" && "code" in e ? (e.code as string) : undefined, ), }); } }; return (

{t("auth.signup.title")}

{t("auth.signup.message")}

{form.formState.isSubmitSuccessful && !invitationOnlyMode ? ( {t("auth.signup.hints.verifyEmail")} ) : ( <> {invitationId && ( )}
{form.formState.isSubmitted && form.formState.errors.root && ( {form.formState.errors.root.message} )} ( {t("auth.signup.name")} )} /> ( {t("auth.signup.email")} )} /> ( {t("auth.signup.password")}
)} /> {config.auth.enableSignup && config.auth.enableSocialLogin && ( <>

{t("auth.login.continueWith")}

{Object.keys(oAuthProviders).map( (providerId) => ( ), )}
)} )}
{t("auth.signup.alreadyHaveAccount")}{" "} {t("auth.signup.signIn")}
); }