258 lines
8.0 KiB
JavaScript
258 lines
8.0 KiB
JavaScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { useDispatch } from "react-redux";
|
||
import { useRouter } from "next/navigation";
|
||
import { setToken } from "@/redux/slices/authSlice";
|
||
import { setProfile } from "@/redux/slices/profileSlice";
|
||
import { showToast } from "@/redux/slices/toastSlice";
|
||
import authService from "@/services/auth";
|
||
import Link from "next/link";
|
||
|
||
export default function RegisterPage() {
|
||
const dispatch = useDispatch();
|
||
const router = useRouter();
|
||
|
||
const [formData, setFormData] = useState({
|
||
name: "",
|
||
email: "",
|
||
password: "",
|
||
confirmPassword: "",
|
||
});
|
||
|
||
const [errors, setErrors] = useState({});
|
||
const [isLoading, setIsLoading] = useState(false);
|
||
|
||
const validateForm = () => {
|
||
const newErrors = {};
|
||
|
||
if (!formData.name.trim()) {
|
||
newErrors.name = "نام الزامی است";
|
||
} else if (formData.name.trim().length < 3) {
|
||
newErrors.name = "نام باید حداقل 3 کاراکتر باشد";
|
||
}
|
||
|
||
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 کاراکتر باشد";
|
||
}
|
||
|
||
if (!formData.confirmPassword.trim()) {
|
||
newErrors.confirmPassword = "تأیید رمز عبور الزامی است";
|
||
} else if (formData.password !== formData.confirmPassword) {
|
||
newErrors.confirmPassword = "رمز عبور و تأیید آن یکسان نیستند";
|
||
}
|
||
|
||
setErrors(newErrors);
|
||
return Object.keys(newErrors).length === 0;
|
||
};
|
||
|
||
const handleChange = (e) => {
|
||
const { name, value } = e.target;
|
||
setFormData((prev) => ({
|
||
...prev,
|
||
[name]: value,
|
||
}));
|
||
// پاک کردن error هنگام تایپ
|
||
if (errors[name]) {
|
||
setErrors((prev) => ({
|
||
...prev,
|
||
[name]: "",
|
||
}));
|
||
}
|
||
};
|
||
|
||
const handleSubmit = async (e) => {
|
||
e.preventDefault();
|
||
|
||
if (!validateForm()) {
|
||
return;
|
||
}
|
||
|
||
setIsLoading(true);
|
||
|
||
try {
|
||
const response = await fetch("/api/auth/register", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
name: formData.name,
|
||
email: formData.email,
|
||
password: formData.password,
|
||
}),
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.message || "خطا در ثبتنام");
|
||
}
|
||
|
||
const data = await response.json();
|
||
|
||
dispatch(
|
||
setProfile(
|
||
data.user || { name: formData.name, email: formData.email }
|
||
)
|
||
);
|
||
|
||
dispatch(
|
||
showToast({
|
||
message: "ثبتنام شما موفق بود! خوش آمدید",
|
||
type: "success",
|
||
})
|
||
);
|
||
|
||
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-green-50 to-teal-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">
|
||
{/* Name Field */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
نام
|
||
</label>
|
||
<input
|
||
type="text"
|
||
name="name"
|
||
value={formData.name}
|
||
onChange={handleChange}
|
||
placeholder="نام خود را وارد کنید"
|
||
className={`w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 transition ${
|
||
errors.name ? "border-red-500" : "border-gray-300"
|
||
}`}
|
||
disabled={isLoading}
|
||
/>
|
||
{errors.name && (
|
||
<p className="mt-1 text-red-600 text-xs">{errors.name}</p>
|
||
)}
|
||
</div>
|
||
|
||
{/* 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-teal-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-teal-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>
|
||
|
||
{/* Confirm Password Field */}
|
||
<div>
|
||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||
تأیید رمز عبور
|
||
</label>
|
||
<input
|
||
type="password"
|
||
name="confirmPassword"
|
||
value={formData.confirmPassword}
|
||
onChange={handleChange}
|
||
placeholder="رمز عبور را دوباره وارد کنید"
|
||
className={`w-full px-4 py-2 border rounded-lg focus:outline-none focus:ring-2 focus:ring-teal-500 transition ${
|
||
errors.confirmPassword ? "border-red-500" : "border-gray-300"
|
||
}`}
|
||
disabled={isLoading}
|
||
/>
|
||
{errors.confirmPassword && (
|
||
<p className="mt-1 text-red-600 text-xs">
|
||
{errors.confirmPassword}
|
||
</p>
|
||
)}
|
||
</div>
|
||
|
||
{/* Submit Button */}
|
||
<button
|
||
type="submit"
|
||
disabled={isLoading}
|
||
className="w-full bg-teal-600 text-white font-semibold py-2 rounded-lg hover:bg-teal-700 transition disabled:bg-gray-400 disabled:cursor-not-allowed"
|
||
>
|
||
{isLoading ? "درحال ثبتنام..." : "ثبتنام"}
|
||
</button>
|
||
</form>
|
||
|
||
{/* Login Link */}
|
||
<div className="mt-6 text-center text-gray-600">
|
||
قبلاً حساب دارید؟{" "}
|
||
<Link
|
||
href="/login"
|
||
className="text-teal-600 font-semibold hover:underline"
|
||
>
|
||
وارد شوید
|
||
</Link>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
} |