"use client"; import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { InputOTP, InputOTPGroup, InputOTPSlot, } from "@/components/ui/input-otp"; import { Heart, Eye, EyeOff, X, Loader2, CheckCircle2 } from "lucide-react"; import Link from "next/link"; import Image from "next/image"; import { useRouter, useSearchParams } from "next/navigation"; import { useAppTheme } from "@/components/ThemeProvider"; import { useAuth } from "@/hooks/useAuth"; import { registerSchema, verifyOtpSchema, type RegisterInput, type VerifyOtpInput } from "@/lib/schema/auth"; import { toast } from "sonner"; export default function Signup() { const { theme } = useAppTheme(); const isDark = theme === "dark"; const [showPassword, setShowPassword] = useState(false); const [showPassword2, setShowPassword2] = useState(false); const [step, setStep] = useState<"register" | "verify">("register"); const [registeredEmail, setRegisteredEmail] = useState(""); const [formData, setFormData] = useState({ first_name: "", last_name: "", email: "", phone_number: "", password: "", password2: "", }); const [otpData, setOtpData] = useState({ email: "", otp: "", }); const [errors, setErrors] = useState>>({}); const router = useRouter(); const searchParams = useSearchParams(); const { register, verifyOtp, isAuthenticated, registerMutation, verifyOtpMutation, resendOtpMutation } = useAuth(); // Redirect if already authenticated useEffect(() => { if (isAuthenticated) { const redirect = searchParams.get("redirect") || "/admin/dashboard"; router.push(redirect); } }, [isAuthenticated, router, searchParams]); const handleRegister = async (e: React.FormEvent) => { e.preventDefault(); setErrors({}); // Validate form const validation = registerSchema.safeParse(formData); if (!validation.success) { const fieldErrors: Partial> = {}; validation.error.issues.forEach((err) => { if (err.path[0]) { fieldErrors[err.path[0] as keyof RegisterInput] = err.message; } }); setErrors(fieldErrors); return; } try { const result = await register(formData); // If registration is successful, redirect to login page with verify parameter toast.success("Registration successful! Please check your email for OTP verification."); // Redirect to login page with verify step router.push(`/login?verify=true&email=${encodeURIComponent(formData.email)}`); } catch (error) { const errorMessage = error instanceof Error ? error.message : "Registration failed. Please try again."; // If OTP sending failed, don't show OTP verification - just show error if (errorMessage.toLowerCase().includes("failed to send") || errorMessage.toLowerCase().includes("failed to send otp")) { toast.error("Registration failed: OTP could not be sent. Please try again later or contact support."); setErrors({}); return; } toast.error(errorMessage); // Don't set field errors for server errors, only show toast setErrors({}); } }; const handleVerifyOtp = async (e: React.FormEvent) => { e.preventDefault(); setErrors({}); // Validate OTP const validation = verifyOtpSchema.safeParse(otpData); if (!validation.success) { const fieldErrors: Partial> = {}; validation.error.issues.forEach((err) => { if (err.path[0]) { fieldErrors[err.path[0] as keyof VerifyOtpInput] = err.message; } }); setErrors(fieldErrors); return; } try { const result = await verifyOtp(otpData); // If verification is successful (no error thrown), show success and redirect toast.success("Email verified successfully! Redirecting to login..."); // Redirect to login page after OTP verification with email pre-filled setTimeout(() => { router.push(`/login?email=${encodeURIComponent(otpData.email)}`); }, 1500); } catch (error) { const errorMessage = error instanceof Error ? error.message : "OTP verification failed. Please try again."; toast.error(errorMessage); // Don't set field errors for server errors, only show toast setErrors({}); } }; const handleResendOtp = async () => { try { await resendOtpMutation.mutateAsync({ email: registeredEmail, context: "registration" }); toast.success("OTP resent successfully! Please check your email."); } catch (error) { const errorMessage = error instanceof Error ? error.message : "Failed to resend OTP. Please try again."; toast.error(errorMessage); } }; const handleChange = (field: keyof RegisterInput, value: string) => { setFormData((prev) => ({ ...prev, [field]: value })); // Clear error when user starts typing if (errors[field]) { setErrors((prev) => ({ ...prev, [field]: undefined })); } }; const handleOtpChange = (field: keyof VerifyOtpInput, value: string) => { setOtpData((prev) => ({ ...prev, [field]: value })); // Clear error when user starts typing if (errors[field]) { setErrors((prev) => ({ ...prev, [field]: undefined })); } }; return (
{/* Background Image */}
Therapy and counseling session with African American clients {/* Overlay for better readability */}
{/* Branding - Top Left */}
Attune Heart Therapy
{/* Centered White Card - Signup Form */}
{/* Header with Close Button */}
{/* Heading */}

{step === "register" ? "Create an account" : "Verify your email"}

{/* Login Prompt */} {step === "register" && (

Already have an account?{" "} Log in

)} {step === "verify" && (

We've sent a verification code to {registeredEmail}

)}
{/* Close Button */}
{step === "register" ? ( /* Registration Form */
{/* First Name Field */}
handleChange("first_name", e.target.value)} className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'} ${errors.first_name ? 'border-red-500' : ''}`} required /> {errors.first_name && (

{errors.first_name}

)}
{/* Last Name Field */}
handleChange("last_name", e.target.value)} className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'} ${errors.last_name ? 'border-red-500' : ''}`} required /> {errors.last_name && (

{errors.last_name}

)}
{/* Email Field */}
handleChange("email", e.target.value)} className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'} ${errors.email ? 'border-red-500' : ''}`} required />
{/* Phone Field */}
handleChange("phone_number", e.target.value)} className={`h-11 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'}`} />
{/* Password Field */}
handleChange("password", e.target.value)} className={`h-11 pr-12 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'} ${errors.password ? 'border-red-500' : ''}`} required />
{errors.password && (

{errors.password}

)}
{/* Confirm Password Field */}
handleChange("password2", e.target.value)} className={`h-11 pr-12 ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'} ${errors.password2 ? 'border-red-500' : ''}`} required />
{errors.password2 && (

{errors.password2}

)}
{/* Submit Button */}
) : ( /* OTP Verification Form */

Check your email

We've sent a 6-digit verification code to your email address.

{/* OTP Field */}
handleOtpChange("otp", value)} aria-invalid={!!errors.otp} >
{/* Resend OTP */}
{/* Submit Button */} {/* Back to registration */}
)}
); }