CoffeeJoo_Panel_kafeDar/app/(auth)/login/page.js

200 lines
5.9 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.

"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { useDispatch } from "react-redux";
import { setProfile } from "@/redux/slices/profileSlice";
import { showToast } from "@/redux/slices/toastSlice";
import Link from "next/link";
export default function LoginPage() {
const router = useRouter();
const dispatch = useDispatch();
const [formData, setFormData] = useState({
email: "",
password: "",
});
const [errors, setErrors] = useState({});
const [isLoading, setIsLoading] = useState(false);
const validateForm = () => {
const newErrors = {};
if (!formData.email.trim()) {
newErrors.email = "ایمیل الزامی است";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
newErrors.email = "ایمیل معتبر نیست";
}
if (!formData.password.trim()) {
newErrors.password = "رمز عبور الزامی است";
} else if (formData.password.length < 6) {
newErrors.password = "رمز عبور باید حداقل 6 کاراکتر باشد";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prev) => ({
...prev,
[name]: value,
}));
if (errors[name]) {
setErrors((prev) => ({
...prev,
[name]: "",
}));
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!validateForm()) {
return;
}
setIsLoading(true);
try {
// فراخوانی API (توکن خودکار در HTTP-only cookie ذخیره می‌شود)
const response = await fetch("/api/auth/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: formData.email,
password: formData.password,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || "خطا در ورود");
}
const data = await response.json();
// ذخیره user info در Redux (فقط برای UI)
dispatch(
setProfile(
data.user || { email: formData.email }
)
);
dispatch(
showToast({
message: "خوش آمدید! شما با موفقیت وارد شدید",
type: "success",
})
);
// Redirect به صفحه اصلی
// (middleware خودکار بررسی توکن را انجام می‌دهد)
router.push("/");
} catch (error) {
dispatch(
showToast({
message: error.message || "خطایی در حین ورود رخ داد",
type: "error",
})
);
setErrors((prev) => ({
...prev,
submit: error.message,
}));
} finally {
setIsLoading(false);
}
};
return (
<div className="min-h-screen flex items-center justify-center bg-linear-to-br from-blue-50 to-indigo-100 px-4">
<div className="w-full max-w-md bg-white rounded-lg shadow-lg p-8">
<h1 className="text-3xl font-bold text-center text-gray-800 mb-2">
خوش آمدید
</h1>
<p className="text-center text-gray-600 mb-6">
لطفاً وارد حساب خود شوید
</p>
{errors.submit && (
<div className="mb-4 p-3 bg-red-50 border border-red-200 rounded-lg text-red-700 text-sm">
{errors.submit}
</div>
)}
<form onSubmit={handleSubmit} className="space-y-5">
{/* Email Field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
ایمیل
</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="ایمیل خود را وارد کنید"
className={`w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 transition ${
errors.email ? "border-red-500" : "border-gray-300"
}`}
disabled={isLoading}
/>
{errors.email && (
<p className="mt-1 text-red-600 text-xs">{errors.email}</p>
)}
</div>
{/* Password Field */}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
رمز عبور
</label>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="رمز عبور خود را وارد کنید"
className={`w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 transition ${
errors.password ? "border-red-500" : "border-gray-300"
}`}
disabled={isLoading}
/>
{errors.password && (
<p className="mt-1 text-red-600 text-xs">{errors.password}</p>
)}
</div>
{/* Submit Button */}
<button
type="submit"
disabled={isLoading}
className="w-full bg-indigo-600 text-white font-semibold py-2 rounded-lg hover:bg-indigo-700 transition disabled:bg-gray-400 disabled:cursor-not-allowed"
>
{isLoading ? "درحال ورود..." : "ورود"}
</button>
</form>
{/* Register Link */}
<div className="mt-6 text-center text-gray-600">
حساب کاربری ندارید؟{" "}
<Link
href="/register"
className="text-indigo-600 font-semibold hover:underline"
>
ثبتنام کنید
</Link>
</div>
</div>
</div>
);
}