"use client"; import { useState } from "react"; import { Button } from "@/components/ui/button"; import { useAppTheme } from "@/components/ThemeProvider"; import { Input } from "@/components/ui/input"; import { InputOTP, InputOTPGroup, InputOTPSlot, } from "@/components/ui/input-otp"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Eye, EyeOff, Loader2, X, CheckCircle2 } from "lucide-react"; import { useAuth } from "@/hooks/useAuth"; import { forgotPasswordSchema, verifyPasswordResetOtpSchema, resetPasswordSchema, type ForgotPasswordInput, type VerifyPasswordResetOtpInput, type ResetPasswordInput } from "@/lib/schema/auth"; import { toast } from "sonner"; interface ForgotPasswordDialogProps { open: boolean; onOpenChange: (open: boolean) => void; onSuccess?: () => void; } type Step = "request" | "verify" | "reset"; export function ForgotPasswordDialog({ open, onOpenChange, onSuccess }: ForgotPasswordDialogProps) { const { theme } = useAppTheme(); const isDark = theme === "dark"; const { forgotPasswordMutation, verifyPasswordResetOtpMutation, resetPasswordMutation, resendOtpMutation } = useAuth(); const [step, setStep] = useState("request"); const [email, setEmail] = useState(""); const [otpData, setOtpData] = useState({ email: "", otp: "", }); const [resetData, setResetData] = useState({ email: "", otp: "", new_password: "", confirm_password: "", }); const [showPassword, setShowPassword] = useState(false); const [showPassword2, setShowPassword2] = useState(false); const handleRequestOtp = async (e: React.FormEvent) => { e.preventDefault(); const validation = forgotPasswordSchema.safeParse({ email }); if (!validation.success) { const firstError = validation.error.issues[0]; toast.error(firstError.message); return; } try { await forgotPasswordMutation.mutateAsync({ email }); setOtpData({ email, otp: "" }); setResetData({ email, otp: "", new_password: "", confirm_password: "" }); setStep("verify"); toast.success("Password reset OTP sent! Please check your email."); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Failed to send OTP. Please try again."; toast.error(errorMessage); } }; const handleVerifyOtp = async (e: React.FormEvent) => { e.preventDefault(); const emailToVerify = email || otpData.email; if (!emailToVerify) { toast.error("Email is required"); return; } const validation = verifyPasswordResetOtpSchema.safeParse({ email: emailToVerify, otp: otpData.otp, }); if (!validation.success) { const firstError = validation.error.issues[0]; toast.error(firstError.message); return; } try { await verifyPasswordResetOtpMutation.mutateAsync({ email: emailToVerify, otp: otpData.otp, }); setResetData({ email: emailToVerify, otp: otpData.otp, new_password: "", confirm_password: "" }); setStep("reset"); toast.success("OTP verified! Please set your new password."); } catch (err) { const errorMessage = err instanceof Error ? err.message : "OTP verification failed. Please try again."; toast.error(errorMessage); } }; const handleResetPassword = async (e: React.FormEvent) => { e.preventDefault(); const validation = resetPasswordSchema.safeParse(resetData); if (!validation.success) { const firstError = validation.error.issues[0]; toast.error(firstError.message); return; } try { await resetPasswordMutation.mutateAsync(resetData); toast.success("Password reset successful! Please log in with your new password."); handleDialogChange(false); if (onSuccess) { onSuccess(); } } catch (err) { const errorMessage = err instanceof Error ? err.message : "Password reset failed. Please try again."; toast.error(errorMessage); } }; const handleResendOtp = async () => { const emailToResend = email || otpData.email; if (!emailToResend) { toast.error("Email is required"); return; } try { await resendOtpMutation.mutateAsync({ email: emailToResend, context: "password_reset" }); toast.success("OTP resent successfully! Please check your email."); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Failed to resend OTP"; toast.error(errorMessage); } }; const handleOtpChange = (field: keyof VerifyPasswordResetOtpInput, value: string) => { setOtpData((prev) => ({ ...prev, [field]: value })); }; // Reset step when dialog closes const handleDialogChange = (isOpen: boolean) => { if (!isOpen) { setStep("request"); setEmail(""); setOtpData({ email: "", otp: "" }); setResetData({ email: "", otp: "", new_password: "", confirm_password: "" }); } onOpenChange(isOpen); }; return ( {/* Header with Close Button - Fixed */}
{step === "request" && "Reset Password"} {step === "verify" && "Verify OTP"} {step === "reset" && "Set New Password"} {step === "request" && "Enter your email to receive a password reset code"} {step === "verify" && "Enter the verification code sent to your email"} {step === "reset" && "Enter your new password"} {/* Close Button */}
{/* Scrollable Content */}
{/* Request OTP Form */} {step === "request" && (
setEmail(e.target.value)} className={`h-11 sm:h-12 text-sm sm:text-base ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'}`} required />
)} {/* Verify OTP Form */} {step === "verify" && (

Check your email

We've sent a 6-digit verification code to {email || otpData.email || "your email address"}.

{/* Email Field (if not set) */} {!email && (
handleOtpChange("email", e.target.value)} className={`h-11 sm:h-12 text-sm sm:text-base ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'}`} required />
)} {/* OTP Field */}
handleOtpChange("otp", value)} >
{/* Resend OTP */}
{/* Submit Button */} {/* Back to request */}
)} {/* Reset Password Form */} {step === "reset" && (
{/* New Password Field */}
setResetData({ ...resetData, new_password: e.target.value })} className={`h-11 sm:h-12 pr-12 text-sm sm:text-base ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'}`} required />
{/* Confirm Password Field */}
setResetData({ ...resetData, confirm_password: e.target.value })} className={`h-11 sm:h-12 pr-12 text-sm sm:text-base ${isDark ? 'bg-gray-700 border-gray-600 text-white placeholder:text-gray-400' : 'bg-white border-gray-300 text-gray-900'}`} required />
{/* Submit Button */} {/* Back to verify */}
)}
); }