CoffeeJoo_Panel_kafeDar/src/pages/Login/Login.jsx

198 lines
10 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useDispatch } from "react-redux";
import { FiLock } from "react-icons/fi";
import { FaRegUser } from "react-icons/fa6";
// Assets
import Loginpic from "../../../src/assets/image/loginpic.jpg";
import LogoDM from "../../assets/icons/LogoDM.svg";
// Redux
import { setToken } from "../../redux/slices/authSlice";
import { setProfile } from "../../redux/slices/profileSlice";
// Services
import authService from "../../services/auth";
export default function Login() {
const navigate = useNavigate();
const dispatch = useDispatch();
// State Management
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
// Handle Login
const handleLogin = async (e) => {
e.preventDefault();
setError("");
setLoading(true);
try {
const res = await authService.login({ userName, password });
if (res.data.success && res.data.data?.tokens?.accessToken) {
dispatch(setToken(res.data.data.tokens.accessToken));
dispatch(setProfile(res.data.data.admin));
console.log("✅ Login successful:", res.data.data.admin);
navigate("/dashboard");
} else {
setError("اطلاعات دریافتی معتبر نیست");
}
} catch (error) {
console.error("❌ Login error:", error);
const errorMessage =
error.response?.data?.message ||
(error.request ? "خطا در برقراری ارتباط با سرور" : "خطای نامشخص رخ داده است");
setError(errorMessage);
} finally {
setLoading(false);
}
};
return (
<div className="relative min-h-screen" dir="rtl">
{/* Header */}
<header className="fixed top-0 left-0 right-0 bg-white z-10 shadow-sm">
<div className="flex items-center justify-between px-6 md:px-8 lg:px-12 py-4">
{/* Left Section */}
<div className="flex items-center gap-4">
<img src={LogoDM} alt="Logo" className="h-10 w-10 md:h-12 md:w-12" />
<div className="relative">
<select className="appearance-none px-4 md:px-6 py-2 pr-4 pl-10 bg-white border-2 border-gray-300 rounded-xl text-sm focus:outline-none focus:border-button1 transition-colors cursor-pointer">
<option>شهر</option>
<option>تهران</option>
<option>اصفهان</option>
<option>شیراز</option>
<option>مشهد</option>
</select>
<svg className="absolute left-4 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-500 pointer-events-none" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
{/* Center Links (Hidden on Mobile) */}
<nav className="hidden md:flex items-center gap-8 font-bold text-primary">
<a href="#" className="hover:text-button1 transition-colors text-sm">خانه</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">دسته بندی</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">تماس با ما</a>
<a href="#" className="hover:text-button1 transition-colors text-sm">درباره ما</a>
</nav>
{/* Right Section */}
<button className="px-6 md:px-10 py-2 bg-button1 text-white rounded-full text-sm md:text-base font-medium hover:bg-[#5f494f] transition-colors">
ثبت نام
</button>
</div>
</header>
{/* Main Content */}
<div className="flex min-h-screen pt-20">
{/* Left Side - Login Form */}
<div
style={{
backgroundImage: isMobile ? `url(${Loginpic})` : 'none',
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundAttachment: 'fixed'
}}
className="w-full md:w-1/2 flex items-start justify-center md:justify-start md:bg-background px-4 md:px-12 lg:px-24 py-8 md:py-16 relative">
{/* Dark Overlay */}
<div className="absolute inset-0 bg-black/10 backdrop-blur-[1px] md:bg-transparent"></div>
<div className="w-full max-w-md relative z-10">
{/* Breadcrumb */}
<div className="flex items-center gap-2 text-xs md:text-sm text-gray-500 mb-8">
<span>ورود</span>
<span className="font-bold text-lg">&gt;</span>
<span>خانه</span>
</div>
{/* Header */}
<div className="mb-8">
<h1 className="text-2xl md:text-3xl font-bold mb-2 text-white md:text-primary">ورود ادمین</h1>
<p className="text-sm md:text-base md:text-gray-700 text-white/80">دسترسی ویژه برای مدیریت و گزارشها</p>
</div>
{/* Login Form */}
<form onSubmit={handleLogin} className="space-y-6">
{/* Error Message */}
{error && (
<div className="bg-red-50 border-2 border-red-300 text-red-700 px-4 py-3 rounded-xl text-sm">
{error}
</div>
)}
{/* Username Field */}
<div className="relative">
<label className="md:absolute -top-2.5 right-4 text-background md:text-primary md:bg-background z-50 px-1 text-sm">نام کاربری</label>
<div className="relative mt-2">
<input
type="text"
value={userName}
onChange={(e) => setUserName(e.target.value)}
placeholder="userName"
className="w-full pl-12 pr-4 py-3 border-2 bg-background border-gray-300 rounded-xl focus:outline-none focus:border-button1 transition-colors text-sm"
dir="ltr"
required
/>
<FaRegUser className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
</div>
</div>
{/* Password Field */}
<div className="relative">
<label className="md:absolute -top-2.5 right-4 z-50 md:bg-background md:text-primary px-1 text-sm text-background">رمز عبور</label>
<div className="relative mt-2">
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="password"
className="w-full pl-12 pr-4 py-3 border-2 bg-background border-gray-300 rounded-xl focus:outline-none focus:border-button1 transition-colors text-sm"
dir="ltr"
required
/>
<FiLock className="absolute left-4 top-1/2 -translate-y-1/2 text-gray-400 w-5 h-5" />
</div>
</div>
{/* Forgot Password */}
<div className="text-right">
<a href="#" className="text-sm text-background hover:text-button1 transition-colors">
فراموشی رمز عبور؟
</a>
</div>
{/* Submit Button */}
<button
type="submit"
disabled={loading || !userName || !password}
className="w-full bg-button1 text-white py-3 rounded-full font-bold text-sm md:text-base hover:bg-[#5f494f] transition-all duration-300 shadow-lg hover:shadow-xl disabled:bg-gray-400 disabled:cursor-not-allowed"
>
{loading ? "در حال ورود..." : "ورود"}
</button>
</form>
</div>
</div>
{/* Right Side - Image (Hidden on Mobile) */}
<div className="hidden md:block w-1/2 h-[calc(100vh-5rem)] relative overflow-hidden">
<img src={Loginpic} alt="Coffee workspace" className="w-full h-full object-cover " />
</div>
</div>
</div>
);
}