"use client"; import { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import toast, { Toaster } from "react-hot-toast"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { Mail, Lock, Eye, EyeOff, ArrowLeft, LogIn, CheckCircle, Loader2, Home, Shield, Phone, KeyRound, } from "lucide-react"; import { loginWithEmail, loginWithPhone, sendEmailOTP, sendPhoneOTP, verifyEmail, verifyPhone, isEmail, isPhoneNumber, getOwnerByUserId, getCustomerByUserId, } from "../utils/api"; import AuthService from "../services/AuthService"; export default function LoginPage() { const router = useRouter(); // Step: 'login' | 'otp' const [step, setStep] = useState("login"); const [loginMethod, setLoginMethod] = useState("email"); // 'email' | 'phone' const [showPassword, setShowPassword] = useState(false); const [isLoading, setIsLoading] = useState(false); const [isSuccess, setIsSuccess] = useState(false); const [formData, setFormData] = useState({ credential: "", password: "", rememberMe: false, }); const [otpCode, setOtpCode] = useState(""); const [otpError, setOtpError] = useState(""); const [errors, setErrors] = useState({}); const validateForm = () => { const newErrors = {}; if (!formData.credential) { newErrors.credential = loginMethod === "email" ? "البريد الإلكتروني مطلوب" : "رقم الهاتف مطلوب"; // } else if (loginMethod === 'email' && !isEmail(formData.credential)) { // newErrors.credential = 'البريد الإلكتروني غير صالح'; // } else if (loginMethod === 'phone' && !isPhoneNumber(formData.credential)) { newErrors.credential = "رقم الهاتف غير صالح"; } if (!formData.password) { newErrors.password = "كلمة المرور مطلوبة"; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleLogin = async (e) => { e.preventDefault(); if (!validateForm()) return; setIsLoading(true); setErrors({}); try { const loginFn = loginMethod === "email" ? loginWithEmail : loginWithPhone; console.log( "[Login] Attempting login via", loginMethod, ":", formData.credential, ); const result = await loginFn(formData.credential, formData.password); console.log("[Login] Response status:", result.status); if (result.status === 200) { const token = typeof result.data === "string" ? result.data : result.data?.token || result.data?.accessToken; AuthService.addToken(token); console.log("[Login] Token stored"); // Fetch user profile to get full name const authUser = AuthService.getUser(); if (authUser?.id) { try { const isOwner = AuthService.isOwner(); const fetchFn = isOwner ? getOwnerByUserId : getCustomerByUserId; const profile = await fetchFn(authUser.id); if (profile) { AuthService.cacheUser({ name: profile.fullName || profile.name || `${profile.firstName || ""} ${profile.lastName || ""}`.trim(), email: profile.email || authUser.email, phone: profile.phone || profile.phoneNumber || authUser.phone, }); console.log("[Login] User profile cached"); } } catch (err) { console.warn("[Login] Failed to fetch profile:", err); } } const userRole = AuthService.isAdmin() ? "admin" : AuthService.isOwner() ? "owner" : "customer"; console.log("[Login] User role:", userRole); setIsSuccess(true); toast.success("تم تسجيل الدخول بنجاح!", { style: { background: "#dcfce7", color: "#166534" }, }); setTimeout(() => { if (userRole === "admin") { router.push("/admin"); } else { router.push("/"); } }, 1500); } else if (result.status === 206) { console.log("[Login] 206 — OTP required"); const tempToken = typeof result.data === "string" ? result.data : result.data?.token || result.data?.accessToken; if (tempToken) { AuthService.addToken(tempToken); console.log("[Login] Temp token stored for OTP"); } toast("يرجى إدخال رمز التحقق", { icon: "🔐", style: { background: "#fef3c7", color: "#92400e" }, }); // Send OTP try { if (loginMethod === "email") { await sendEmailOTP(); } else { await sendPhoneOTP(); } console.log("[Login] OTP sent successfully"); } catch (otpErr) { console.warn("[Login] OTP send failed, proceeding anyway:", otpErr); } setStep("otp"); } else { // Other error console.error("[Login] Unexpected status:", result.status, result.data); toast.error( result.data?.message || result.data || "بيانات الدخول غير صحيحة", { style: { background: "#fee2e2", color: "#991b1b" }, }, ); } } catch (err) { console.error("[Login] Error:", err); toast.error(err.message || "حدث خطأ في الاتصال", { style: { background: "#fee2e2", color: "#991b1b" }, }); } finally { setIsLoading(false); } }; const handleVerifyOTP = async (e) => { e.preventDefault(); if (!otpCode || otpCode.length < 4) { setOtpError("يرجى إدخال رمز التحقق"); return; } setIsLoading(true); setOtpError(""); try { const verifyFn = loginMethod === "email" ? verifyEmail : verifyPhone; console.log("[OTP] Verifying code:", otpCode); const result = await verifyFn(otpCode); console.log("[OTP] Verify response status:", result.status); if (result.ok) { const finalToken = typeof result.data === "string" ? result.data : result.data?.token || result.data?.accessToken; if (finalToken && typeof finalToken === "string") { AuthService.addToken(finalToken); console.log("[OTP] Final token stored"); } setIsSuccess(true); toast.success("تم التحقق بنجاح!", { style: { background: "#dcfce7", color: "#166534" }, }); setTimeout(() => { console.log("[OTP] Redirecting to home"); router.push("/"); }, 1500); } else { console.error("[OTP] Verification failed:", result.data); setOtpError(result.data?.message || "رمز التحقق غير صحيح"); } } catch (err) { console.error("[OTP] Error:", err); setOtpError(err.message || "حدث خطأ في التحقق"); } finally { setIsLoading(false); } }; const resendOTP = async () => { try { console.log("[OTP] Resending OTP via", loginMethod); if (loginMethod === "email") { await sendEmailOTP(); } else { await sendPhoneOTP(); } toast.success("تم إرسال رمز التحقق مجدداً", { style: { background: "#dcfce7", color: "#166534" }, }); } catch (err) { console.error("[OTP] Resend failed:", err); toast.error("فشل إرسال الرمز"); } }; // Auto-detect login method from input const handleCredentialChange = (value) => { setFormData({ ...formData, credential: value }); if (errors.credential) setErrors({ ...errors, credential: null }); // Auto-switch method // if (isEmail(value)) { // setLoginMethod('email'); // } else if (isPhoneNumber(value)) { // setLoginMethod('phone'); // } }; const particles = Array.from({ length: 20 }, (_, i) => ({ id: i, x: Math.random() * 100, y: Math.random() * 100, size: Math.random() * 3 + 1, duration: Math.random() * 15 + 10, delay: Math.random() * 5, })); const containerVariants = { hidden: { opacity: 0 }, visible: { opacity: 1, transition: { staggerChildren: 0.1, delayChildren: 0.2 }, }, }; const itemVariants = { hidden: { y: 20, opacity: 0 }, visible: { y: 0, opacity: 1, transition: { type: "spring", stiffness: 100 }, }, }; return (
{step === "otp" ? "أدخل رمز التحقق" : "مرحباً بعودتك!"}
تم إرسال رمز التحقق إلى{" "} {formData.credential}