Files
ruby-sea-battle/frontend/src/components/AuthModal.jsx
T

104 lines
3.5 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
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 } from 'react'
import { useAuth } from '../auth'
export default function AuthModal({ onClose }) {
const { login, register } = useAuth()
const [mode, setMode] = useState('login') // 'login' | 'register'
const [nickname, setNickname] = useState('')
const [password, setPassword] = useState('')
const [avatar, setAvatar] = useState(null)
const [avatarPreview, setAvatarPreview] = useState(null)
const [error, setError] = useState(null)
const [submitting, setSubmitting] = useState(false)
const handleAvatarChange = (e) => {
const file = e.target.files?.[0] || null
setAvatar(file)
setAvatarPreview(file ? URL.createObjectURL(file) : null)
}
const handleSubmit = async (e) => {
e.preventDefault()
setError(null)
setSubmitting(true)
try {
if (mode === 'login') {
await login(nickname.trim(), password)
} else {
await register(nickname.trim(), password, avatar)
}
onClose()
} catch (err) {
setError(err.message)
} finally {
setSubmitting(false)
}
}
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal" onClick={(e) => e.stopPropagation()}>
<button className="modal-close" onClick={onClose} aria-label="Закрыть">
×
</button>
<h2 className="modal-title">{mode === 'login' ? 'Вход' : 'Регистрация'}</h2>
<form onSubmit={handleSubmit} className="auth-form">
<label className="field">
<span>Имя</span>
<input
type="text"
value={nickname}
onChange={(e) => setNickname(e.target.value)}
minLength={mode === 'register' ? 3 : undefined}
maxLength={mode === 'register' ? 24 : undefined}
required
autoFocus
/>
</label>
<label className="field">
<span>Пароль</span>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
minLength={mode === 'register' ? 6 : undefined}
required
/>
</label>
{mode === 'register' && (
<label className="field avatar-field">
<span>Аватарка (необязательно)</span>
<div className="avatar-picker">
{avatarPreview ? (
<img src={avatarPreview} alt="Аватар" className="avatar-preview" />
) : (
<div className="avatar-preview avatar-placeholder">?</div>
)}
<input type="file" accept="image/png,image/jpeg,image/gif,image/webp" onChange={handleAvatarChange} />
</div>
</label>
)}
{error && <div className="form-error">{error}</div>}
<button type="submit" className="btn btn-primary" disabled={submitting}>
{submitting ? 'Подождите…' : mode === 'login' ? 'Войти' : 'Зарегистрироваться'}
</button>
</form>
<button
className="link-button"
onClick={() => {
setMode(mode === 'login' ? 'register' : 'login')
setError(null)
}}
>
{mode === 'login' ? 'Нет аккаунта? Зарегистрироваться' : 'Уже есть аккаунт? Войти'}
</button>
</div>
</div>
)
}