CampFireCritics/src/pages/RegisterPage.jsx
2025-09-05 16:12:32 +03:00

226 lines
8.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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 { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom";
import { useAuth } from "../contexts/AuthContext";
function RegisterPage() {
const [login, setLogin] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
const { user, userProfile, loading: authLoading, register, isInitialized } = useAuth();
const navigate = useNavigate();
useEffect(() => {
if (!authLoading && isInitialized) {
if (user && userProfile) {
navigate("/");
}
}
}, [user, userProfile, authLoading, isInitialized, navigate]);
const handleSubmit = async (e) => {
e.preventDefault();
if (!login || !password || !confirmPassword) {
setError("Заполни обязательные поля");
return;
}
if (password !== confirmPassword) {
setError("Хмм, пароли не совпадают...");
return;
}
if (password.length < 6) {
setError("Коротковато...");
return;
}
if (!/^[a-zA-Z0-9_]+$/.test(login)) {
setError("Логин может содержать только латинские буквы, цифры и знак подчеркивания");
return;
}
if (login.length < 3 || login.length > 20) {
setError("Логин должен быть от 3 до 20 символов");
return;
}
try {
setError("");
setLoading(true);
await register(login, password, email || null);
} catch (err) {
if (err.response && err.response.data) {
const errorData = err.response.data;
if (errorData.login && errorData.login.code === 'validation_not_unique') {
setError("Этот логин уже занят");
} else if (errorData.email && errorData.email.code === 'validation_not_unique') {
setError("Пользователь с таким email уже существует");
} else {
setError(err.message || "Произошла ошибка при регистрации");
}
} else {
setError(err.message || "Произошла ошибка при регистрации");
}
} finally {
setLoading(false);
}
};
if (authLoading || !isInitialized) {
return (
<div className="min-h-screen bg-campfire-dark pt-20 flex justify-center items-center">
<div className="animate-spin rounded-full h-16 w-16 border-t-2 border-b-2 border-campfire-amber"></div>
</div>
);
}
return (
<div className="pt-20 min-h-screen flex items-center justify-center bg-campfire-dark text-campfire-light">
<div className="container-custom max-w-md py-12">
<div className="bg-campfire-charcoal rounded-lg shadow-lg p-8 border border-campfire-ash/20">
<div className="text-center mb-8">
<h1 className="text-3xl font-bold text-campfire-light mb-2">
Присоединиться к CampFire мнеие
</h1>
<p className="text-campfire-ash">
Создай свою учетную запись CampFire, чтобы оценивать и рецензировать
все что движется.
</p>
</div>
{error && (
<div className="bg-status-error/20 text-status-error p-4 rounded-md mb-6 border border-status-error/30">
{error}
</div>
)}
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="login" className="block text-sm font-medium text-campfire-light mb-1">
Логин *
</label>
<input
type="text"
id="login"
value={login}
onChange={(e) => setLogin(e.target.value)}
className="input w-full px-3 py-2 bg-campfire-dark text-campfire-light border border-campfire-ash/30 rounded-md focus:outline-none focus:ring-campfire-amber focus:border-campfire-amber transition-colors"
placeholder="Введите логин"
required
autoComplete="username"
/>
<p className="text-xs text-campfire-ash mt-1">
От 3 до 20 символов, только латинские буквы, цифры и _
</p>
<p className="text-xs text-campfire-ash mt-1">
Логин чувствителен к регистру букв
</p>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-campfire-light mb-1">
Email (необязательно)
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="input w-full px-3 py-2 bg-campfire-dark text-campfire-light border border-campfire-ash/30 rounded-md focus:outline-none focus:ring-campfire-amber focus:border-campfire-amber transition-colors"
placeholder="your@campfiregg.ru"
autoComplete="email"
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-campfire-light mb-1">
Пароль *
</label>
<input
type="password"
id="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="input w-full px-3 py-2 bg-campfire-dark text-campfire-light border border-campfire-ash/30 rounded-md focus:outline-none focus:ring-campfire-amber focus:border-campfire-amber transition-colors"
placeholder="••••••••"
required
autoComplete="new-password"
/>
<p className="text-xs text-campfire-ash mt-1">
Не меньше 6 знаков
</p>
</div>
<div>
<label htmlFor="confirm-password" className="block text-sm font-medium text-campfire-light mb-1">
Повторите пароль *
</label>
<input
type="password"
id="confirm-password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="input w-full px-3 py-2 bg-campfire-dark text-campfire-light border border-campfire-ash/30 rounded-md focus:outline-none focus:ring-campfire-amber focus:border-campfire-amber transition-colors"
placeholder="••••••••"
required
autoComplete="new-password"
/>
</div>
<button
type="submit"
disabled={loading}
className={`btn-primary w-full ${loading ? "opacity-80 cursor-not-allowed" : ""} transition-colors duration-200`}
>
{loading ? (
<span className="inline-flex items-center">
<svg
className="animate-spin -ml-1 mr-2 h-4 w-4 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
Запечатываем...
</span>
) : (
"Создать"
)}
</button>
</form>
<div className="mt-6 text-center text-sm text-campfire-ash">
Уже в строю?{" "}
<Link
to="/auth/login"
className="text-campfire-amber hover:text-campfire-ember font-medium transition-colors"
>
Войти
</Link>
</div>
</div>
</div>
</div>
);
}
export default RegisterPage;