"use client"; import React, { useState, useEffect, useRef } from "react"; import { motion, AnimatePresence } from "motion/react"; import { X, User, Building2, Heart, ShieldCheck, Phone, Key, LogIn, ArrowRight, RefreshCw, Lock } from "lucide-react"; import { useUserStore, UserRole } from "../lib/store/userStore"; import { authService } from "../lib/services/authService"; import { toast } from "sonner"; import { toPersian } from "../lib/utils"; interface AuthModalProps { isOpen: boolean; onClose: () => void; } export default function AuthModal({ isOpen, onClose }: AuthModalProps) { const { setRole, setLoggedIn, fetchProfile } = useUserStore(); const [view, setView] = useState<"login" | "register" | "otp-phone" | "otp" | "forgot-password" | "forgot-otp" | "reset-password">("login"); const [phoneNumber, setPhoneNumber] = useState(""); const [password, setPassword] = useState(""); const [newPassword, setNewPassword] = useState(""); const [email, setEmail] = useState(""); const [firstName, setFirstName] = useState(""); const [lastName, setLastName] = useState(""); const [otpCode, setOtpCode] = useState(""); const [isLoading, setIsLoading] = useState(false); const [countdown, setCountdown] = useState(0); const otpInputRef = useRef(null); useEffect(() => { if (view === "otp") { const timer = setTimeout(() => { otpInputRef.current?.focus(); }, 100); return () => clearTimeout(timer); } }, [view]); // Reset modal state on open/close useEffect(() => { if (!isOpen) { setView("login"); setPhoneNumber(""); setPassword(""); setNewPassword(""); setEmail(""); setFirstName(""); setLastName(""); setOtpCode(""); setIsLoading(false); setCountdown(0); } }, [isOpen]); // Cooldown countdown timer useEffect(() => { if (countdown > 0) { const timer = setTimeout(() => setCountdown(countdown - 1), 1000); return () => clearTimeout(timer); } }, [countdown]); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); if (!phoneNumber || !password) return toast.error("شماره موبایل و رمز عبور الزامی است"); setIsLoading(true); try { const res = await authService.login(phoneNumber, password); if (res.success) { await fetchProfile(); toast.success("با موفقیت وارد شدید"); onClose(); } } catch (err: any) { toast.error(err.message || "خطا در ورود"); } finally { setIsLoading(false); } }; const handleRegister = async (e: React.FormEvent) => { e.preventDefault(); if (!firstName || !lastName || !phoneNumber || !password) { return toast.error("لطفاً فیلدهای الزامی را پر کنید"); } setIsLoading(true); try { const res = await authService.register({ firstName, lastName, mobile: phoneNumber, email, password }); if (res.success) { await fetchProfile(); toast.success("ثبت‌نام با موفقیت انجام شد"); onClose(); } } catch (err: any) { toast.error(err.message || "خطا در ثبت‌نام"); } finally { setIsLoading(false); } }; const handleSendOtp = async (e: React.FormEvent) => { e.preventDefault(); const cleanPhone = phoneNumber.trim(); if (!/^09\d{9}$/.test(cleanPhone)) { toast.error("شماره موبایل نامعتبر است"); return; } setIsLoading(true); try { const res = await authService.sendOtp(cleanPhone); if ((res as any).code) { toast.info(`کد تایید (تست): ${(res as any).code}`, { duration: 10000 }); } else { toast.success("کد تایید پیامک شد"); } setView("otp"); setCountdown(120); } catch (err: any) { toast.error(err.message || "خطا در ارسال کد تایید"); } finally { setIsLoading(false); } }; const handleVerifyOtp = async (e: React.FormEvent) => { e.preventDefault(); const cleanCode = otpCode.trim(); if (cleanCode.length !== 5) { toast.error("کد باید ۵ رقم باشد"); return; } setIsLoading(true); try { const response = await authService.verifyOtp(phoneNumber.trim(), cleanCode); if (response.success) { await fetchProfile(); toast.success("ورود موفقیت‌آمیز بود"); onClose(); } } catch (err: any) { toast.error(err.message || "کد تایید نامعتبر است"); } finally { setIsLoading(false); } }; const handleResendOtp = async () => { if (countdown > 0) return; setIsLoading(true); try { await authService.sendOtp(phoneNumber.trim()); toast.success("کد تایید جدید ارسال شد"); setCountdown(120); } catch (err: any) { toast.error(err.message || "خطا در ارسال مجدد کد"); } finally { setIsLoading(false); } }; const handleForgotSendOtp = async (e: React.FormEvent) => { e.preventDefault(); const cleanPhone = phoneNumber.trim(); if (!/^09\d{9}$/.test(cleanPhone)) { toast.error("شماره موبایل نامعتبر است"); return; } setIsLoading(true); try { const res = await authService.sendOtp(cleanPhone); if ((res as any).code) { toast.info(`کد تایید (تست): ${(res as any).code}`, { duration: 10000 }); } else { toast.success("کد بازیابی رمز پیامک شد"); } setView("forgot-otp"); setCountdown(120); } catch (err: any) { toast.error(err.message || "خطا در ارسال کد"); } finally { setIsLoading(false); } }; const handleForgotVerifyOtp = async (e: React.FormEvent) => { e.preventDefault(); if (otpCode.trim().length !== 5) { toast.error("کد باید ۵ رقم باشد"); return; } setIsLoading(true); try { // Verify OTP - if success, allow password reset await authService.verifyOtp(phoneNumber.trim(), otpCode.trim()); setView("reset-password"); } catch (err: any) { toast.error(err.message || "کد تایید نامعتبر است"); } finally { setIsLoading(false); } }; const handleResetPassword = async (e: React.FormEvent) => { e.preventDefault(); if (newPassword.length < 6) { toast.error("رمز جدید باید حداقل ۶ کاراکتر باشد"); return; } setIsLoading(true); try { // Use authService to update password after OTP verification await authService.updateProfile({ password: newPassword } as any); toast.success("رمز عبور با موفقیت تغییر یافت"); setView("login"); } catch (err: any) { toast.error(err.message || "خطا در تغییر رمز"); } finally { setIsLoading(false); } }; return ( {isOpen && ( <> {/* Backdrop */} {/* Modal content */} {/* Top highlight bar */}
{/* Close Button */} {/* Title Header */}

ورود به دنیای کانینا

{view === "otp" ? `کد تایید ارسال شده به شماره ${toPersian(phoneNumber)} را وارد کنید` : "برای دسترسی به پرونده سلامت و سفارشات وارد شوید"}

{/* Content Panel */} {view === "login" && (
setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-left tracking-widest" />
setPassword(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left" />
)} {view === "register" && (
setFirstName(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-sm" />
setLastName(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-sm" />
setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left tracking-widest text-sm" />
setEmail(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left text-sm" />
setPassword(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-2 px-3 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left text-sm" />
)} {view === "otp-phone" && (
setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-lg text-left tracking-widest" />
)} {view === "otp" && (
setOtpCode(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pr-12 pl-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-2xl text-center tracking-[0.5em]" />
{countdown > 0 ? ( ارسال مجدد کد پس از {toPersian(countdown)} ثانیه ) : ( )}
)} {/* Forgot Password - Enter Phone */} {view === "forgot-password" && (

برای بازیابی رمز عبور، کد تایید به شمارهتان ارسال می‌شود

setPhoneNumber(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-bold text-left tracking-widest" />
)} {/* Forgot Password - Enter OTP */} {view === "forgot-otp" && (

کد ارسال شده به {toPersian(phoneNumber)} را وارد کنید

setOtpCode(e.target.value.replace(/[^0-9]/g, ''))} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-2xl py-4 pl-4 pr-4 focus:ring-2 focus:ring-canina-blue/20 outline-none font-black text-2xl text-center tracking-[0.5em]" />
{countdown > 0 ? (

ارسال مجدد پس از {toPersian(countdown)} ثانیه

) : ( )}
)} {/* Reset Password */} {view === "reset-password" && (

هویت تایید شد. رمز جدید خود را وارد کنید

setNewPassword(e.target.value)} disabled={isLoading} className="w-full bg-medical-gray-50 border border-medical-gray-200 rounded-xl py-3 px-4 focus:ring-2 focus:ring-canina-blue/20 outline-none text-left" />
)}
)} ); }