import { authClient } from '@documenso/auth/client'; import { useAnalytics } from '@documenso/lib/client-only/hooks/use-analytics'; import { AppError } from '@documenso/lib/errors/app-error'; import { ZNameSchema } from '@documenso/lib/types/name'; import { env } from '@documenso/lib/utils/env'; import { zEmail } from '@documenso/lib/utils/zod'; import { ZPasswordSchema } from '@documenso/trpc/server/auth-router/schema'; import { Button } from '@documenso/ui/primitives/button'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form'; import { Input } from '@documenso/ui/primitives/input'; import { PasswordInput } from '@documenso/ui/primitives/password-input'; import { useToast } from '@documenso/ui/primitives/use-toast'; import { zodResolver } from '@hookform/resolvers/zod'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import type { TurnstileInstance } from '@marsidev/react-turnstile'; import { Turnstile } from '@marsidev/react-turnstile'; import { useRef } from 'react'; import { useForm } from 'react-hook-form'; import { useNavigate } from 'react-router'; import { z } from 'zod'; import { SIGNUP_ERROR_MESSAGES } from '~/components/forms/signup'; export type ClaimAccountProps = { defaultName: string; defaultEmail: string; trigger?: React.ReactNode; }; export const ZClaimAccountFormSchema = z .object({ name: ZNameSchema, email: zEmail().min(1), password: ZPasswordSchema, }) .refine( (data) => { const { name, email, password } = data; return !password.includes(name) && !password.includes(email.split('@')[0]); }, { message: msg`Password should not be common or based on personal information`.id, path: ['password'], }, ); export type TClaimAccountFormSchema = z.infer; export const ClaimAccount = ({ defaultName, defaultEmail }: ClaimAccountProps) => { const { _ } = useLingui(); const { toast } = useToast(); const analytics = useAnalytics(); const navigate = useNavigate(); const turnstileSiteKey = env('NEXT_PUBLIC_TURNSTILE_SITE_KEY'); const turnstileRef = useRef(null); const form = useForm({ values: { name: defaultName ?? '', email: defaultEmail, password: '', }, resolver: zodResolver(ZClaimAccountFormSchema), }); const onFormSubmit = async ({ name, email, password }: TClaimAccountFormSchema) => { try { let token: string | undefined; if (turnstileSiteKey) { token = await turnstileRef.current?.getResponsePromise(3000).catch((_err) => undefined); if (!token) { toast({ title: _(msg`Human verification required`), description: _(msg`Please complete the CAPTCHA challenge before signing in.`), variant: 'destructive', }); return; } } await authClient.emailPassword.signUp({ name, email, password, captchaToken: token ?? undefined, }); await navigate(`/unverified-account`); toast({ title: _(msg`Registration Successful`), description: _( msg`You have successfully registered. Please verify your account by clicking on the link you received in the email.`, ), duration: 5000, }); analytics.capture('App: User Claim Account', { email, timestamp: new Date().toISOString(), }); } catch (err) { const error = AppError.parseError(err); const errorMessage = SIGNUP_ERROR_MESSAGES[error.code] ?? SIGNUP_ERROR_MESSAGES.INVALID_REQUEST; toast({ title: _(msg`An error occurred`), description: _(errorMessage), variant: 'destructive', }); turnstileRef.current?.reset(); } }; return (
( Name )} /> ( Email address )} /> ( Set a password )} /> {turnstileSiteKey && (
)}
); };