"use client"; import React, { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { z } from "zod"; import { toast } from "sonner"; import { authClient } from "@/lib/auth/client"; import { cn } from "@/lib/utils"; import { Eye, EyeOff, Loader2, AlertCircle } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; const registerSchema = z .object({ name: z.string().min(2, "Name must be at least 2 characters"), email: z.string().email("Please enter a valid email address"), password: z.string().min(8, "Password must be at least 8 characters"), confirm: z.string(), }) .refine((d) => d.password === d.confirm, { message: "Passwords do not match", path: ["confirm"], }); type RegisterFormValues = z.infer; type FieldErrors = Partial>; function CubeIcon({ className }: { className?: string }) { return ( ); } interface FormFieldProps { id: string; label: string; type?: string; value: string; onChange: (value: string) => void; error?: string; placeholder?: string; autoComplete?: string; disabled?: boolean; children?: React.ReactNode; } function FormField({ id, label, type = "text", value, onChange, error, placeholder, autoComplete, disabled, children, }: FormFieldProps) { return (
onChange((e.target as HTMLInputElement).value)} placeholder={placeholder} autoComplete={autoComplete} disabled={disabled} aria-invalid={!!error} aria-describedby={error ? `${id}-error` : undefined} className={cn( "h-9 bg-zinc-900/60 border-zinc-800 text-zinc-100 placeholder:text-zinc-600 focus-visible:border-emerald-500/50 focus-visible:ring-emerald-500/20", children && "pr-10", error && "border-red-500/50 focus-visible:border-red-500/50 focus-visible:ring-red-500/20", )} /> {children}
{error && ( )}
); } export default function RegisterPage() { const router = useRouter(); const [name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [confirm, setConfirm] = useState(""); const [showPassword, setShowPassword] = useState(false); const [showConfirm, setShowConfirm] = useState(false); const [fieldErrors, setFieldErrors] = useState({}); const [globalError, setGlobalError] = useState(null); const [isPending, startTransition] = useTransition(); function validate(): RegisterFormValues | null { const result = registerSchema.safeParse({ name, email, password, confirm }); if (!result.success) { const errors: FieldErrors = {}; for (const issue of result.error.issues) { const field = issue.path[0] as keyof RegisterFormValues; if (!errors[field]) errors[field] = issue.message; } setFieldErrors(errors); return null; } setFieldErrors({}); return result.data; } async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setGlobalError(null); const values = validate(); if (!values) return; startTransition(async () => { try { const { error } = await authClient.signUp.email({ name: values.name, email: values.email, password: values.password, }); if (error) { const msg = error.code?.toLowerCase().includes("user_already_exists") ? "An account with this email already exists." : (error.message ?? "Registration failed. Please try again."); setGlobalError(msg); return; } toast.success("Account created — welcome to CubeAdmin!"); router.push("/dashboard"); router.refresh(); } catch { setGlobalError("An unexpected error occurred. Please try again."); } }); } return (
{/* Background grid */}