// src/components/AuthModal.jsx import { useState, useEffect } from "react"; import { useTranslation } from 'react-i18next'; import CloseIcon from "./icons/CloseIcon"; import { useAuthContext } from "../context/AuthContext"; import { login as apiLogin, register as apiRegister } from "../api/apiClient"; /** * AuthModal — модальное окно входа и регистрации прямо на странице ленты. * Открывается когда неавторизованный пользователь пытается создать объявление. */ export default function AuthModal({ onClose }) { const { t } = useTranslation(); const [mode, setMode] = useState("login"); // "login" | "register" const { login: saveAuth } = useAuthContext(); useEffect(() => { const prev = document.body.style.overflow; document.body.style.overflow = "hidden"; return () => { document.body.style.overflow = prev; }; }, []); return (
e.target === e.currentTarget && onClose()}>
{mode === "login" ? t('auth.loginModalTitle') : t('auth.registerModalTitle')}
{mode === "login" ? setMode("register")} /> : setMode("login")} /> }
); } // ─── Login form (inline modal) ────────────────────────────────────────────── function LoginFormInline({ saveAuth, onClose, onSwitch }) { const { t } = useTranslation(); const [login, setLogin] = useState(""); const [password, setPassword] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const handleSubmit = async (e) => { e.preventDefault(); if (!login || !password) { setError(t('auth.enterLoginPassword')); return; } setLoading(true); setError(""); try { const { token, refreshToken, user } = await apiLogin( login, password, t('auth.invalidCredentials') ); saveAuth(user, token, refreshToken); onClose(); } catch (err) { setError(err.message); } finally { setLoading(false); } }; return (
{ setLogin(e.target.value); setError(""); }} autoComplete="off" />
{ setPassword(e.target.value); setError(""); }} />
{error &&

{error}

}

{t('auth.noAccount')}{" "}

); } // ─── Register form (inline modal) ────────────────────────────────────────── function RegisterFormInline({ saveAuth, onClose, onSwitch }) { const { t } = useTranslation(); const [form, setForm] = useState({ name: "", login: "", password: "", password2: "", }); const [loading, setLoading] = useState(false); const [error, setError] = useState(""); const [errors, setErrors] = useState({}); const setField = (key, val) => { setForm(p => ({ ...p, [key]: val })); setErrors(p => ({ ...p, [key]: "" })); }; const validate = () => { const e = {}; if (!form.name.trim()) e.name = t('auth.validateNameRequired'); if (!form.login.trim()) e.login = t('auth.validateLoginRequired'); else if (form.login.length < 3) e.login = t('auth.loginMinChars'); if (form.password.length < 6) e.password = t('auth.validatePasswordMin'); if (form.password !== form.password2) e.password2 = t('auth.validatePasswordMatch'); setErrors(e); return !Object.keys(e).length; }; const handleSubmit = async (e) => { e.preventDefault(); if (!validate()) return; setLoading(true); setError(""); try { await apiRegister(form.name, form.login, form.password, t('auth.registrationError')); let session; try { session = await apiLogin(form.login, form.password, t('auth.autoLoginFailed')); } catch { throw new Error(t('auth.accountCreatedLoginManually')); } const { token, refreshToken, user } = session; saveAuth(user, token, refreshToken); onClose(); } catch (err) { setError(err.message); } finally { setLoading(false); } }; return (
setField("name", e.target.value)} /> {errors.name &&

{errors.name}

}
setField("login", e.target.value)} /> {errors.login &&

{errors.login}

}
setField("password", e.target.value)} /> {errors.password &&

{errors.password}

}
setField("password2", e.target.value)} /> {errors.password2 &&

{errors.password2}

}
{error &&

{error}

}

{t('auth.hasAccount')}{" "}

); } // ─── Shared submit button ────────────────────────────────────────────────── function SubmitButton({ loading, label }) { return ( ); }