Files
echoes-of-the-ash/pwa/src/components/Login.tsx
2026-02-23 15:42:21 +01:00

118 lines
3.2 KiB
TypeScript

import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useAuth } from '../hooks/useAuth'
import { GameButton } from './common/GameButton'
import './Login.css'
function Login() {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('')
const [loading, setLoading] = useState(false)
const { login } = useAuth()
const navigate = useNavigate()
const { t } = useTranslation()
const validateEmail = (email: string) => {
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return re.test(email)
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError('')
// Validation
if (!validateEmail(email)) {
setError(t('auth.errors.invalidEmail'))
return
}
if (password.length < 6) {
setError(t('auth.errors.passwordLength'))
return
}
setLoading(true)
try {
await login(email, password)
// Navigate to character selection after successful login
navigate('/characters')
} catch (err: any) {
setError(err.response?.data?.detail || t('auth.errors.loginFailed'))
} finally {
setLoading(false)
}
}
return (
<div className="login-container">
<div className="login-card game-panel">
<h1 className="auth-title">{t('auth.loginTitle')}</h1>
<p className="login-subtitle">{t('auth.loginSubtitle')}</p>
<form onSubmit={handleSubmit} className="auth-form">
<div className="form-group">
<label htmlFor="email">{t('auth.email')}</label>
<input
type="email"
id="email"
className="game-input"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder={t('auth.emailPlaceholder')}
required
disabled={loading}
autoComplete="email"
/>
</div>
<div className="form-group">
<label htmlFor="password">{t('auth.password')}</label>
<input
type="password"
id="password"
className="game-input"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder={t('auth.passwordPlaceholderLogin')}
required
disabled={loading}
autoComplete="current-password"
/>
</div>
{error && <div className="error-message">{error}</div>}
<GameButton
variant="primary"
size="lg"
className="auth-submit"
disabled={loading}
onClick={() => { }} // Form will handle it via submit
>
{loading ? t('auth.loggingIn') : t('auth.login')}
</GameButton>
</form>
<div className="login-toggle">
<GameButton
variant="secondary"
size="sm"
onClick={() => navigate('/register')}
disabled={loading}
>
{t('auth.registerLink')}
</GameButton>
</div>
</div>
</div>
)
}
export default Login