Archived
63 lines
4.4 KiB
TypeScript
63 lines
4.4 KiB
TypeScript
import React, { useState } from "react";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useTranslation } from "react-i18n-lite";
|
|
import { useAuth } from "../context/AuthContext";
|
|
import { getApiErrorMessage } from "../api/errors";
|
|
|
|
function AuthForm({ isLogin, onToggle }: { isLogin: boolean; onToggle: () => void }) {
|
|
const { t } = useTranslation();
|
|
const [email, setEmail] = useState("");
|
|
const [password, setPassword] = useState("");
|
|
const [confirmPassword, setConfirmPassword] = useState("");
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(false);
|
|
const { login, register } = useAuth();
|
|
const navigate = useNavigate();
|
|
|
|
const handleSubmit = async (e: React.FormEvent) => {
|
|
e.preventDefault(); setError(null);
|
|
if (!isLogin && password !== confirmPassword) { setError(t("auth.passwordsMismatch")); return; }
|
|
setLoading(true);
|
|
try {
|
|
if (isLogin) await login(email, password);
|
|
else await register(email, password);
|
|
navigate("/");
|
|
} catch (err) { setError(getApiErrorMessage(err, isLogin ? t("auth.loginFailed") : t("auth.registrationFailed"))); }
|
|
finally { setLoading(false); }
|
|
};
|
|
|
|
return (
|
|
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", background: "#f8f9fa", padding: 16 }}>
|
|
<div style={{ width: "100%", maxWidth: 400, background: "#fff", borderRadius: 12, padding: 32, boxShadow: "0 2px 16px rgba(0,0,0,0.08)" }}>
|
|
<h1 style={{ fontSize: 28, fontWeight: 700, color: "#1a1a2e", textAlign: "center", marginBottom: 4 }}>{t("common.appName")}</h1>
|
|
<h2 style={{ fontSize: 16, color: "#888", textAlign: "center", marginBottom: 24, fontWeight: 400 }}>{isLogin ? t("auth.signIn") : t("auth.createAccount")}</h2>
|
|
<form onSubmit={handleSubmit} style={{ display: "flex", flexDirection: "column", gap: 16 }}>
|
|
{error && <div style={{ background: "#fde8e8", padding: 12, borderRadius: 6, color: "#e74c3c", fontSize: 14 }}>{error}</div>}
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
|
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>{t("auth.email")}</label>
|
|
<input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder={t("auth.emailPlaceholder")} required style={{ padding: "10px 12px", borderRadius: 6, border: "1px solid #ddd", fontSize: 16, outline: "none" }} />
|
|
</div>
|
|
<div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
|
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>{t("auth.password")}</label>
|
|
<input type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder={t("auth.passwordPlaceholder")} required minLength={8} style={{ padding: "10px 12px", borderRadius: 6, border: "1px solid #ddd", fontSize: 16, outline: "none" }} />
|
|
</div>
|
|
{!isLogin && <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
|
|
<label style={{ fontSize: 14, fontWeight: 600, color: "#555" }}>{t("auth.confirmPassword")}</label>
|
|
<input type="password" value={confirmPassword} onChange={(e) => setConfirmPassword(e.target.value)} placeholder={t("auth.confirmPasswordPlaceholder")} required minLength={8} style={{ padding: "10px 12px", borderRadius: 6, border: "1px solid #ddd", fontSize: 16, outline: "none" }} />
|
|
</div>}
|
|
<button type="submit" disabled={loading} style={{ padding: "12px 24px", borderRadius: 8, border: "none", background: "#1a1a2e", color: "#fff", fontSize: 16, fontWeight: 600, cursor: "pointer", opacity: loading ? 0.6 : 1, marginTop: 8 }}>{loading ? (isLogin ? t("auth.signingIn") : t("auth.creatingAccount")) : (isLogin ? t("auth.signIn") : t("auth.createAccount"))}</button>
|
|
</form>
|
|
<p style={{ textAlign: "center", marginTop: 20, color: "#888", fontSize: 14 }}>
|
|
{isLogin ? t("auth.noAccount") + " " : t("auth.hasAccount") + " "}
|
|
<button onClick={onToggle} style={{ background: "none", border: "none", color: "#1a1a2e", fontWeight: 600, cursor: "pointer", fontSize: 14, textDecoration: "underline" }}>{isLogin ? t("auth.register") : t("auth.signIn")}</button>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default function AuthPage() {
|
|
const [isLogin, setIsLogin] = useState(true);
|
|
return <AuthForm isLogin={isLogin} onToggle={() => setIsLogin((v) => !v)} />;
|
|
}
|