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 { marathonsApi } from '@/api' import { NeonButton, Input, GlassCard } from '@/components/ui' import { Gamepad2, LogIn, AlertCircle, Trophy, Users, Zap, Target, Shield, ArrowLeft } from 'lucide-react' const loginSchema = z.object({ login: z.string().min(3, 'Логин должен быть не менее 3 символов'), password: z.string().min(6, 'Пароль должен быть не менее 6 символов'), }) type LoginForm = z.infer export function LoginPage() { const navigate = useNavigate() const { login, verify2FA, cancel2FA, pending2FA, isLoading, error, clearError, consumePendingInviteCode } = useAuthStore() const [submitError, setSubmitError] = useState(null) const [twoFACode, setTwoFACode] = useState('') const { register, handleSubmit, formState: { errors }, } = useForm({ resolver: zodResolver(loginSchema), }) const onSubmit = async (data: LoginForm) => { setSubmitError(null) clearError() try { const result = await login(data) // If 2FA required, don't navigate if (result.requires2FA) { return } // Check for pending invite code const pendingCode = consumePendingInviteCode() if (pendingCode) { try { const marathon = await marathonsApi.join(pendingCode) navigate(`/marathons/${marathon.id}`) return } catch { // If join fails (already member, etc), just go to marathons } } navigate('/marathons') } catch { // Error is already set in store by login function // Ban case is handled separately via banInfo state } } const handle2FASubmit = async (e: React.FormEvent) => { e.preventDefault() setSubmitError(null) clearError() try { await verify2FA(twoFACode) navigate('/marathons') } catch { setSubmitError(error || 'Неверный код') } } const handleCancel2FA = () => { cancel2FA() setTwoFACode('') setSubmitError(null) } const features = [ { icon: , text: 'Соревнуйтесь с друзьями' }, { icon: , text: 'Выполняйте челленджи' }, { icon: , text: 'Зарабатывайте очки' }, { icon: , text: 'Создавайте марафоны' }, ] return (
{/* Background effects */}
{/* Bento Grid */}
{/* Branding Block (left) */} {/* Background decoration */}
{/* Logo */}
{/* Title */}

Game Marathon

Платформа для игровых соревнований

{/* Features */}
{features.map((feature, index) => (
{feature.icon}
{feature.text}
))}
{/* Form Block (right) */} {pending2FA ? ( // 2FA Form <> {/* Header */}

Двухфакторная аутентификация

Введите код из Telegram

{/* 2FA Form */}
{(submitError || error) && (
{submitError || error}
)} setTwoFACode(e.target.value.replace(/\D/g, '').slice(0, 6))} maxLength={6} className="text-center text-2xl tracking-widest font-mono" autoFocus /> } > Подтвердить
{/* Back button */}
) : ( // Regular Login Form <> {/* Header */}

Добро пожаловать!

Войдите, чтобы продолжить

{/* Form */}
{(submitError || error) && (
{submitError || error}
)} } > Войти
{/* Footer */}

Нет аккаунта?{' '} Зарегистрироваться

)}
{/* Decorative elements */}
) }