"use client"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { authClient } from "@/lib/auth/client"; import { ErrorContext } from "better-auth/react"; import { Check, Eye, EyeOff, Loader2, RefreshCw, X } from "lucide-react"; import { useRouter } from "next/navigation"; import { useState } from "react"; import { toast } from "sonner"; export function SignUpForm( { captchaToken, setShowSignIn }: { captchaToken: string | null, setShowSignIn: (show: boolean) => void } ) { const router = useRouter(); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [confirmPassword, setConfirmPassword] = useState(""); const [isUsernameAvailable, setIsUsernameAvailable] = useState(null); const [loading, setLoading] = useState(false); const [isValidatingUsername, setIsValidatingUsername] = useState(false); const [showPassword, setShowPassword] = useState(false); const handleSignUp = async (e: React.FormEvent) => { e.preventDefault(); if (password !== confirmPassword) { toast.error("Passwords do not match"); return; } if (password.length > 30) { toast.error("Password must be less than 30 characters"); return; } await authClient.signUp.email( { email: `${username}.user@sipher.space`, name: username, username, password, fetchOptions: { headers: { "x-captcha-response": captchaToken ?? "", }, }, }, { onRequest: () => { setLoading(true); }, onSuccess: async () => { setLoading(false); toast.success("Account created successfully, now log in to continue!"); setShowSignIn(true); router.push("/"); }, onError: (ctx: ErrorContext) => { setLoading(false); toast.error(ctx.error.message); }, } ); }; const generatePassword = () => { const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+"; let newPassword = ""; for (let i = 0; i < 16; i++) { newPassword += chars.charAt(Math.floor(Math.random() * chars.length)); } setPassword(newPassword); setConfirmPassword(newPassword); navigator.clipboard.writeText(newPassword); toast.success("Password generated and copied to clipboard"); }; return (
{ const val = e.target.value; setUsername(val); if (val) { setIsValidatingUsername(true); // @ts-ignore const isValid = await authClient.isUsernameAvailable({ username: val }); setIsUsernameAvailable(!!isValid); setIsValidatingUsername(false); } else { setIsUsernameAvailable(null); } }} className={`bg-background/50 focus:bg-background transition-colors pr-10 ${isUsernameAvailable === false ? "border-red-500 focus-visible:ring-red-500" : isUsernameAvailable === true ? "border-green-500 focus-visible:ring-green-500" : "" }`} />
{isValidatingUsername ? ( ) : isUsernameAvailable === true ? ( ) : isUsernameAvailable === false ? ( ) : null}
{isUsernameAvailable === false && (

Username is already taken

)}
setPassword(e.target.value)} className={`bg-background/50 focus:bg-background transition-colors pr-24 ${password.length >= 8 && password.length <= 30 ? "border-green-500 focus-visible:ring-green-500" : password.length > 30 ? "border-red-500 focus-visible:ring-red-500" : "" }`} />
{password.length > 30 ? ( ) : password.length >= 8 && ( )}
{password.length > 30 && (

Password must be less than 30 characters

)}
setConfirmPassword(e.target.value)} className={`bg-background/50 focus:bg-background transition-colors pr-10 ${confirmPassword && password === confirmPassword && password.length <= 30 ? "border-green-500 focus-visible:ring-green-500" : (confirmPassword && password !== confirmPassword) || (confirmPassword && password.length > 30) ? "border-red-500 focus-visible:ring-red-500" : "" }`} />
{confirmPassword && password === confirmPassword && password.length <= 30 ? ( ) : confirmPassword && (password !== confirmPassword || password.length > 30) ? ( ) : null}
{confirmPassword && password !== confirmPassword && (

Passwords do not match

)}
); }