import { useState } from "react"; import { useTranslation } from "react-i18next"; import { api } from "../lib/api"; import { setLanguage, type LangCode } from "../i18n"; import LanguageSwitcher from "./LanguageSwitcher"; type Phase = "idle" | "sending" | "requested" | "approved" | "error"; export default function Login() { const { t, i18n } = useTranslation(); // A denied Google login bounces back here with ?access=requested (we recorded it) or // ?access=denied (no usable email). Surface that so the user isn't left on a raw error. const params = new URLSearchParams(window.location.search); const bounced = params.get("access"); // "requested" | "denied" | null const [email, setEmail] = useState(""); const [phase, setPhase] = useState(bounced === "requested" ? "requested" : "idle"); const [error, setError] = useState(""); async function submit(e: React.FormEvent) { e.preventDefault(); setError(""); setPhase("sending"); try { const r = await api.requestAccess(email.trim()); setPhase(r.status === "approved" ? "approved" : "requested"); } catch { setError(t("login.submitError")); setPhase("error"); } } const done = phase === "requested" || phase === "approved"; return (
Siftlode

{t("login.tagline")}

{t("login.signIn")}
{phase === "approved" ? (

{t("login.approved")}

) : done ? (

{t("login.requested")}

) : ( <>
{t("login.noAccessYet")}
{bounced === "denied" && (

{t("login.denied")}

)}
setEmail(e.target.value)} placeholder={t("login.emailPlaceholder")} className="flex-1 min-w-0 bg-card border border-border rounded-xl px-3 py-2 text-sm outline-none focus:border-accent" />
{error &&

{error}

} )}
); }