'use client'; import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; export default function LoginPage() { const router = useRouter(); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [error, setError] = useState(''); const [loading, setLoading] = useState(false); // Проверяем авторизацию при загрузке useEffect(() => { async function checkAuth() { try { const response = await fetch('/api/auth/me', { credentials: 'same-origin' }); if (response.ok) { router.push('/dashboard'); } } catch (err) { // Не авторизован, остаёмся на странице входа } } checkAuth(); }, [router]); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); setLoading(true); setError(''); try { const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ email, password }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || 'Ошибка входа'); } // CSRF токен теперь в cookie с SameSite защитой // Next.js автоматически отправит его с последующими запросами router.push('/dashboard'); } catch (err: unknown) { setError(err instanceof Error ? err.message : 'Неизвестная ошибка'); setLoading(false); } } return (

Uno Click

Войдите для продолжения

{error &&
{error}
}
setEmail(e.target.value)} required placeholder="test.user@uno-click.local" style={styles.input} />
setPassword(e.target.value)} required placeholder="test123" style={styles.input} />
); } const styles: Record = { container: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', background: '#f5f5f5', }, card: { background: 'white', padding: '40px', borderRadius: '8px', boxShadow: '0 2px 10px rgba(0,0,0,0.1)', width: '100%', maxWidth: '400px', }, title: { fontSize: '24px', fontWeight: 600, marginBottom: '8px', color: '#333', }, subtitle: { color: '#666', marginBottom: '32px', fontSize: '14px', }, formGroup: { marginBottom: '20px', }, label: { display: 'block', marginBottom: '6px', fontSize: '14px', color: '#333', fontWeight: 500, }, input: { width: '100%', padding: '12px 14px', border: '1px solid #ddd', borderRadius: '6px', fontSize: '14px', transition: 'border-color 0.2s', }, button: { width: '100%', padding: '12px', background: '#007bff', color: 'white', border: 'none', borderRadius: '6px', fontSize: '14px', fontWeight: 500, cursor: 'pointer', transition: 'background 0.2s', }, buttonDisabled: { background: '#ccc', cursor: 'not-allowed', }, error: { background: '#fee', color: '#c00', padding: '12px', borderRadius: '6px', marginBottom: '20px', fontSize: '14px', }, };