Files
HellreigN/frontend/src/pages/register.page.tsx
T
nikitaa_ts 96f82b4162
ci-front / build (push) Successful in 2m1s
feat: create register
2026-04-04 05:57:34 +03:00

390 lines
14 KiB
TypeScript
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 React, { useState, useEffect } from "react";
import { useNavigate, Link } from "react-router-dom";
import { FiUser, FiLock, FiUserPlus } from "react-icons/fi";
import { useAuthStore } from "@/modules/auth/store/useAuthStore";
export const RegisterPage: React.FC = () => {
const navigate = useNavigate();
const { register, isLoading, error, clearError } = useAuthStore();
const [formData, setFormData] = useState({
login: "",
password: "",
confirmPassword: "",
firstName: "",
lastName: "",
});
const [passwordError, setPasswordError] = useState<string | null>(null);
const [successMessage, setSuccessMessage] = useState<string | null>(null);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (formData.password !== formData.confirmPassword) {
setPasswordError("Пароли не совпадают");
return;
}
setPasswordError(null);
try {
await register({
login: formData.login,
password: formData.password,
firstName: formData.firstName,
lastName: formData.lastName,
});
setSuccessMessage("Аккаунт успешно создан! Теперь вы можете войти.");
setFormData({
login: "",
password: "",
confirmPassword: "",
firstName: "",
lastName: "",
});
setTimeout(() => {
navigate("/auth");
}, 2000);
} catch (err) {
// Error is handled by store
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value,
});
if (error) clearError();
if (passwordError) setPasswordError(null);
};
const inputStyles = `
w-full pl-10 pr-3 py-2.5 rounded-lg border focus:outline-none focus:ring-2 transition-all
`;
const simpleInputStyles = `
w-full px-3 py-2.5 rounded-lg border focus:outline-none focus:ring-2 transition-all
`;
return (
<div
className="min-h-screen flex items-center justify-center p-4"
style={{ backgroundColor: "var(--bg-primary)" }}
>
<div className="w-full max-w-md">
{/* Card */}
<div
className="rounded-2xl shadow-2xl p-8 border"
style={{
backgroundColor: "var(--card-bg)",
borderColor: "var(--border)",
boxShadow: "0 20px 60px var(--shadow-color)",
}}
>
{/* Header */}
<div className="text-center mb-8">
<div
className="w-16 h-16 mx-auto mb-4 rounded-full flex items-center justify-center"
style={{ backgroundColor: "var(--bg-secondary)" }}
>
<FiUserPlus
className="w-8 h-8"
style={{ color: "var(--accent)" }}
/>
</div>
<h1
className="text-3xl font-bold mb-2"
style={{ color: "var(--text-primary)" }}
>
Создать аккаунт
</h1>
<p style={{ color: "var(--text-secondary)" }}>
Зарегистрируйтесь, чтобы начать
</p>
</div>
{/* Error Message */}
{error && (
<div
className="mb-6 p-4 rounded-lg border text-sm"
style={{
backgroundColor: "var(--error-bg)",
borderColor: "var(--error-border)",
color: "var(--error-text)",
}}
>
{error}
</div>
)}
{/* Success Message */}
{successMessage && (
<div
className="mb-6 p-4 rounded-lg border text-sm"
style={{
backgroundColor: "var(--success-bg)",
borderColor: "var(--success-border)",
color: "var(--success-text)",
}}
>
{successMessage}
</div>
)}
{/* Form */}
<form onSubmit={handleSubmit} className="space-y-4">
{/* Name Fields */}
<div className="grid grid-cols-2 gap-4">
<div>
<label
className="block text-sm font-medium mb-2"
style={{ color: "var(--text-secondary)" }}
>
Имя
</label>
<input
type="text"
name="firstName"
value={formData.firstName}
onChange={handleChange}
required
className={simpleInputStyles}
style={{
backgroundColor: "var(--input-bg)",
borderColor: "var(--border)",
color: "var(--text-primary)",
}}
onFocus={(e) => {
e.currentTarget.style.borderColor = "var(--border-focus)";
e.currentTarget.style.boxShadow = `0 0 0 3px ${e.currentTarget.style.borderColor}20`;
}}
onBlur={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.boxShadow = "none";
}}
placeholder="Иван"
/>
</div>
<div>
<label
className="block text-sm font-medium mb-2"
style={{ color: "var(--text-secondary)" }}
>
Фамилия
</label>
<input
type="text"
name="lastName"
value={formData.lastName}
onChange={handleChange}
required
className={simpleInputStyles}
style={{
backgroundColor: "var(--input-bg)",
borderColor: "var(--border)",
color: "var(--text-primary)",
}}
onFocus={(e) => {
e.currentTarget.style.borderColor = "var(--border-focus)";
e.currentTarget.style.boxShadow = `0 0 0 3px ${e.currentTarget.style.borderColor}20`;
}}
onBlur={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.boxShadow = "none";
}}
placeholder="Иванов"
/>
</div>
</div>
{/* Login */}
<div>
<label
className="block text-sm font-medium mb-2"
style={{ color: "var(--text-secondary)" }}
>
Логин
</label>
<div className="relative">
<FiUser
className="absolute left-3 top-1/2 transform -translate-y-1/2"
style={{ color: "var(--text-muted)" }}
/>
<input
type="text"
name="login"
value={formData.login}
onChange={handleChange}
required
className={inputStyles}
style={{
backgroundColor: "var(--input-bg)",
borderColor: "var(--border)",
color: "var(--text-primary)",
}}
onFocus={(e) => {
e.currentTarget.style.borderColor = "var(--border-focus)";
e.currentTarget.style.boxShadow = `0 0 0 3px ${e.currentTarget.style.borderColor}20`;
}}
onBlur={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.boxShadow = "none";
}}
placeholder="Придумайте логин"
/>
</div>
</div>
{/* Password */}
<div>
<label
className="block text-sm font-medium mb-2"
style={{ color: "var(--text-secondary)" }}
>
Пароль
</label>
<div className="relative">
<FiLock
className="absolute left-3 top-1/2 transform -translate-y-1/2"
style={{ color: "var(--text-muted)" }}
/>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
required
className={inputStyles}
style={{
backgroundColor: "var(--input-bg)",
borderColor: "var(--border)",
color: "var(--text-primary)",
}}
onFocus={(e) => {
e.currentTarget.style.borderColor = "var(--border-focus)";
e.currentTarget.style.boxShadow = `0 0 0 3px ${e.currentTarget.style.borderColor}20`;
}}
onBlur={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.boxShadow = "none";
}}
placeholder="Придумайте пароль"
/>
</div>
</div>
{/* Confirm Password */}
<div>
<label
className="block text-sm font-medium mb-2"
style={{ color: "var(--text-secondary)" }}
>
Подтвердите пароль
</label>
<div className="relative">
<FiLock
className="absolute left-3 top-1/2 transform -translate-y-1/2"
style={{ color: "var(--text-muted)" }}
/>
<input
type="password"
name="confirmPassword"
value={formData.confirmPassword}
onChange={handleChange}
required
className={inputStyles}
style={{
backgroundColor: "var(--input-bg)",
borderColor: "var(--border)",
color: "var(--text-primary)",
}}
onFocus={(e) => {
e.currentTarget.style.borderColor = "var(--border-focus)";
e.currentTarget.style.boxShadow = `0 0 0 3px ${e.currentTarget.style.borderColor}20`;
}}
onBlur={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.boxShadow = "none";
}}
placeholder="Повторите пароль"
/>
</div>
{passwordError && (
<p
className="mt-2 text-sm flex items-center gap-1"
style={{ color: "var(--error-text)" }}
>
<svg
className="w-4 h-4"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z"
clipRule="evenodd"
/>
</svg>
{passwordError}
</p>
)}
</div>
<button
type="submit"
disabled={isLoading}
className="w-full flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed font-medium"
style={{
backgroundColor: "var(--button-primary)",
color: "var(--button-primary-text)",
}}
onMouseEnter={(e) => {
if (!isLoading) {
e.currentTarget.style.backgroundColor =
"var(--button-primary-hover)";
}
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = "var(--button-primary)";
}}
>
{isLoading ? (
<>
<div className="w-5 h-5 border-2 border-current border-t-transparent rounded-full animate-spin" />
Регистрация...
</>
) : (
<>
<FiUserPlus />
Зарегистрироваться
</>
)}
</button>
</form>
{/* Footer */}
<div className="mt-6 text-center">
<p className="text-sm" style={{ color: "var(--text-secondary)" }}>
Уже есть аккаунт?{" "}
<Link
to="/auth"
className="font-medium hover:underline transition-colors"
style={{ color: "var(--link)" }}
onMouseEnter={(e) => {
e.currentTarget.style.color = "var(--link-hover)";
}}
onMouseLeave={(e) => {
e.currentTarget.style.color = "var(--link)";
}}
>
Войти
</Link>
</p>
</div>
</div>
</div>
</div>
);
};