Files
cats/client/src/pages/RegisterPage.tsx

78 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, FormEvent } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { useAuth } from '@/hooks/useAuth';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
export default function RegisterPage() {
const { user, register } = useAuth();
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [confirm, setConfirm] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
if (user) return <Navigate to="/feed" replace />;
const handleSubmit = async (e: FormEvent) => {
e.preventDefault();
setError('');
if (password !== confirm) { setError('Пароли не совпадают'); return; }
setLoading(true);
try { await register(username, password); }
catch (err: any) { setError(err.response?.data?.error || 'Ошибка регистрации'); }
finally { setLoading(false); }
};
return (
<div className="flex min-h-screen items-center justify-center p-5" style={{ background: 'linear-gradient(135deg, #fafaf9 0%, #f0f0ef 100%)' }}>
<div className="w-full max-w-sm animate-rise">
<div className="text-center mb-10">
<div className="mx-auto mb-5 flex h-16 w-16 items-center justify-center rounded-xl shadow-sm"
style={{ background: 'linear-gradient(135deg, #2563eb, #7c3aed)' }}>
<svg className="h-8 w-8 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.5}>
<path d="M12 2C7.58 2 4 5.58 4 10c0 3.78 2.58 7.02 6 8.12V20h4v-1.88c3.42-1.1 6-4.34 6-8.12 0-4.42-3.58-8-8-8z" />
<circle cx="12" cy="10" r="3" />
</svg>
</div>
<h1 className="text-2xl font-bold text-gradient">Catstagram</h1>
<p className="text-sm text-[var(--fg-secondary)] mt-1.5">Присоединяйтесь к сообществу</p>
</div>
<form onSubmit={handleSubmit} className="space-y-4">
<Input value={username} onChange={(e) => setUsername(e.target.value)}
placeholder="Имя пользователя" minLength={3} required autoFocus
className="h-12 text-sm rounded-xl bg-white border focus-ring" />
<Input type="password" value={password} onChange={(e) => setPassword(e.target.value)}
placeholder="Пароль (мин. 4 символа)" minLength={4} required
className="h-12 text-sm rounded-xl bg-white border focus-ring" />
<Input type="password" value={confirm} onChange={(e) => setConfirm(e.target.value)}
placeholder="Подтвердите пароль" required
className="h-12 text-sm rounded-xl bg-white border focus-ring" />
{error && (
<div className="flex items-center gap-2 px-4 py-3 rounded-xl bg-[var(--danger-light)] text-[var(--danger)] text-xs font-medium animate-rise">
<span></span><span>{error}</span>
</div>
)}
<Button type="submit" disabled={loading}
className="w-full h-12 rounded-xl text-sm font-semibold transition-all active:scale-[0.98]"
style={{ background: 'linear-gradient(135deg, #2563eb, #7c3aed)' }}>
{loading ? (
<span className="flex items-center gap-2">
<span className="h-4 w-4 rounded-full border-2 border-white/30 border-t-white animate-spin" />
Создание...
</span>
) : 'Создать аккаунт'}
</Button>
</form>
<p className="mt-8 text-center text-sm text-[var(--fg-secondary)]">
Уже есть аккаунт?{' '}
<Link to="/login" className="font-semibold text-[var(--primary)] hover:opacity-80 transition-opacity">Войти</Link>
</p>
</div>
</div>
);
}