create-exam-project
Version:
Create exam projects with React + Express + PostgreSQL in seconds
165 lines (153 loc) • 6.03 kB
JSX
import { useState } from 'react'
import { Link, useNavigate } from 'react-router-dom'
import { useForm } from 'react-hook-form'
import { useAuth } from '../contexts/AuthContext'
import { useConfig } from '../contexts/ConfigContext'
export default function Register() {
const { register: registerUser } = useAuth()
const { config } = useConfig()
const navigate = useNavigate()
const [isLoading, setIsLoading] = useState(false)
const { register, handleSubmit, formState: { errors } } = useForm()
const onSubmit = async (data) => {
setIsLoading(true)
const result = await registerUser(data)
setIsLoading(false)
if (result.success) {
// Проверяем роль и перенаправляем
if (result.user && result.user.role === 'admin') {
navigate('/admin/dashboard')
} else {
navigate('/dashboard')
}
}
}
return (
<div className="min-h-screen flex flex-col items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
<div className="max-w-md w-full space-y-8">
<div className="text-center">
<span className="text-5xl">{config.theme.logo}</span>
<h2 className="mt-6 text-3xl font-extrabold text-gray-900">
Регистрация в {config.title}
</h2>
<p className="mt-2 text-sm text-gray-600">
Создайте новую учетную запись
</p>
</div>
<form className="mt-8 space-y-6 card" onSubmit={handleSubmit(onSubmit)}>
<div className="space-y-4">
<div>
<label htmlFor="login" className="label">
Логин
</label>
<input
{...register('login', {
required: 'Введите логин',
minLength: { value: 4, message: 'Минимум 4 символа' },
pattern: { value: /^[а-яА-ЯёЁa-zA-Z0-9]+$/, message: 'Только буквы и цифры' }
})}
type="text"
className={`input ${errors.login ? 'input-error' : ''}`}
placeholder="Минимум 4 символа"
/>
{errors.login && (
<p className="mt-1 text-sm text-red-600">{errors.login.message}</p>
)}
</div>
<div>
<label htmlFor="password" className="label">
Пароль
</label>
<input
{...register('password', {
required: 'Введите пароль',
minLength: { value: 6, message: 'Минимум 6 символов' }
})}
type="password"
className={`input ${errors.password ? 'input-error' : ''}`}
placeholder="Минимум 6 символов"
/>
{errors.password && (
<p className="mt-1 text-sm text-red-600">{errors.password.message}</p>
)}
</div>
<div>
<label htmlFor="fullName" className="label">
ФИО
</label>
<input
{...register('fullName', {
required: 'Введите ФИО',
pattern: { value: /^[а-яА-ЯёЁ\s]+$/, message: 'Только русские буквы' }
})}
type="text"
className={`input ${errors.fullName ? 'input-error' : ''}`}
placeholder="Иванов Иван Иванович"
/>
{errors.fullName && (
<p className="mt-1 text-sm text-red-600">{errors.fullName.message}</p>
)}
</div>
<div>
<label htmlFor="phone" className="label">
Телефон
</label>
<input
{...register('phone', {
required: 'Введите телефон',
pattern: {
value: /^\+7\(\d{3}\)-\d{3}-\d{2}-\d{2}$/,
message: 'Формат: +7(XXX)-XXX-XX-XX'
}
})}
type="tel"
className={`input ${errors.phone ? 'input-error' : ''}`}
placeholder="+7(XXX)-XXX-XX-XX"
/>
{errors.phone && (
<p className="mt-1 text-sm text-red-600">{errors.phone.message}</p>
)}
</div>
<div>
<label htmlFor="email" className="label">
Email
</label>
<input
{...register('email', {
required: 'Введите email',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Неверный формат email'
}
})}
type="email"
className={`input ${errors.email ? 'input-error' : ''}`}
placeholder="example@mail.ru"
/>
{errors.email && (
<p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
)}
</div>
</div>
<div>
<button
type="submit"
disabled={isLoading}
className="w-full btn-primary"
>
{isLoading ? 'Регистрация...' : 'Зарегистрироваться'}
</button>
</div>
<div className="text-center">
<span className="text-sm text-gray-600">
Уже есть аккаунт?{' '}
<Link to="/login" className="font-medium text-primary-600 hover:text-primary-500">
Войти
</Link>
</span>
</div>
</form>
</div>
</div>
)
}