initial
This commit is contained in:
115
frontend/src/pages/RegisterPage.tsx
Normal file
115
frontend/src/pages/RegisterPage.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
import { useState } from 'react'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { z } from 'zod'
|
||||
import { useAuthStore } from '@/store/auth'
|
||||
import { Button, Input, Card, CardHeader, CardTitle, CardContent } from '@/components/ui'
|
||||
|
||||
const registerSchema = z.object({
|
||||
login: z
|
||||
.string()
|
||||
.min(3, 'Логин должен быть не менее 3 символов')
|
||||
.max(50, 'Логин должен быть не более 50 символов')
|
||||
.regex(/^[a-zA-Z0-9_]+$/, 'Логин может содержать только буквы, цифры и подчёркивания'),
|
||||
nickname: z
|
||||
.string()
|
||||
.min(2, 'Никнейм должен быть не менее 2 символов')
|
||||
.max(50, 'Никнейм должен быть не более 50 символов'),
|
||||
password: z.string().min(6, 'Пароль должен быть не менее 6 символов'),
|
||||
confirmPassword: z.string(),
|
||||
}).refine((data) => data.password === data.confirmPassword, {
|
||||
message: 'Пароли не совпадают',
|
||||
path: ['confirmPassword'],
|
||||
})
|
||||
|
||||
type RegisterForm = z.infer<typeof registerSchema>
|
||||
|
||||
export function RegisterPage() {
|
||||
const navigate = useNavigate()
|
||||
const { register: registerUser, isLoading, error, clearError } = useAuthStore()
|
||||
const [submitError, setSubmitError] = useState<string | null>(null)
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors },
|
||||
} = useForm<RegisterForm>({
|
||||
resolver: zodResolver(registerSchema),
|
||||
})
|
||||
|
||||
const onSubmit = async (data: RegisterForm) => {
|
||||
setSubmitError(null)
|
||||
clearError()
|
||||
try {
|
||||
await registerUser({
|
||||
login: data.login,
|
||||
password: data.password,
|
||||
nickname: data.nickname,
|
||||
})
|
||||
navigate('/marathons')
|
||||
} catch {
|
||||
setSubmitError(error || 'Ошибка регистрации')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="max-w-md mx-auto">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-center">Регистрация</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
||||
{(submitError || error) && (
|
||||
<div className="p-3 bg-red-500/20 border border-red-500 rounded-lg text-red-500 text-sm">
|
||||
{submitError || error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Input
|
||||
label="Логин"
|
||||
placeholder="Придумайте логин"
|
||||
error={errors.login?.message}
|
||||
{...register('login')}
|
||||
/>
|
||||
|
||||
<Input
|
||||
label="Никнейм"
|
||||
placeholder="Придумайте никнейм"
|
||||
error={errors.nickname?.message}
|
||||
{...register('nickname')}
|
||||
/>
|
||||
|
||||
<Input
|
||||
label="Пароль"
|
||||
type="password"
|
||||
placeholder="Придумайте пароль"
|
||||
error={errors.password?.message}
|
||||
{...register('password')}
|
||||
/>
|
||||
|
||||
<Input
|
||||
label="Подтвердите пароль"
|
||||
type="password"
|
||||
placeholder="Повторите пароль"
|
||||
error={errors.confirmPassword?.message}
|
||||
{...register('confirmPassword')}
|
||||
/>
|
||||
|
||||
<Button type="submit" className="w-full" isLoading={isLoading}>
|
||||
Зарегистрироваться
|
||||
</Button>
|
||||
|
||||
<p className="text-center text-gray-400 text-sm">
|
||||
Уже есть аккаунт?{' '}
|
||||
<Link to="/login" className="link">
|
||||
Войти
|
||||
</Link>
|
||||
</p>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user