fix(login): show backend-health banner before the operator types
Pre-checks /api/v1/auth/me on mount. The status code IS the signal: - 200/401/403 → backend up, login can succeed - 502/504 → proxy down (canvas nginx → demo unreachable) - 503 → auth service is down upstream Surfaces a yellow banner above the form when proxy or auth is down so a regional store manager doesn't type their password into a flow that's guaranteed to fail. Matches the friendlyAuthError() copy from PR #3. 31/31 vitest tests pass.
This commit is contained in:
@@ -2237,3 +2237,15 @@ select.studio-input { background: var(--bp-paper); }
|
||||
@media (max-width: 700px) {
|
||||
.tab-badge { min-width: 14px; height: 12px; font-size: 8px; padding: 0 3px; }
|
||||
}
|
||||
|
||||
.login-banner {
|
||||
padding: 10px 12px;
|
||||
margin-bottom: 12px;
|
||||
border: 1px solid var(--bp-line, #b08a4a);
|
||||
background: var(--bg-2, #fff6e0);
|
||||
color: var(--text-1, #5a3a00);
|
||||
font-size: 11.5px;
|
||||
line-height: 1.45;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
.login-banner-warn { border-color: #b08a4a; background: #fff6e0; color: #5a3a00; }
|
||||
|
||||
@@ -12,6 +12,7 @@ export default function Login() {
|
||||
const buildAllowsDev = (import.meta.env.VITE_ENABLE_DEV_LOGIN ?? "true") !== "false";
|
||||
const [devLoginEnabled, setDevLoginEnabled] = useState(buildAllowsDev);
|
||||
const [ssoState, setSsoState] = useState<"unknown" | "ready" | "not-configured" | "not-wired">("unknown");
|
||||
const [backendState, setBackendState] = useState<"unknown" | "up" | "auth-down" | "proxy-down">("unknown");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
@@ -30,6 +31,18 @@ export default function Login() {
|
||||
else setSsoState("not-wired");
|
||||
})
|
||||
.catch(() => setSsoState("not-wired"));
|
||||
// Backend health precheck. /api/v1/auth/me with no token should return 401
|
||||
// when the backend is up. 502/504 means the proxy is down; 503 means the
|
||||
// auth service is down. We surface this so the operator knows BEFORE they
|
||||
// type their password.
|
||||
fetch("/api/v1/auth/me", { method: "GET" })
|
||||
.then((r) => {
|
||||
if (r.status === 401 || r.status === 403 || r.status === 200) setBackendState("up");
|
||||
else if (r.status === 502 || r.status === 504) setBackendState("proxy-down");
|
||||
else if (r.status === 503) setBackendState("auth-down");
|
||||
else setBackendState("up");
|
||||
})
|
||||
.catch(() => setBackendState("proxy-down"));
|
||||
}, [buildAllowsDev]);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
@@ -106,6 +119,17 @@ export default function Login() {
|
||||
<div className="login-sub">MISSION CONTROL VERIFICATION REQUIRED</div>
|
||||
</div>
|
||||
|
||||
{backendState === "proxy-down" && (
|
||||
<div className="login-banner login-banner-warn">
|
||||
The FlowMaster backend is not reachable from this environment right now. Sign-in will fail until it is restored.
|
||||
</div>
|
||||
)}
|
||||
{backendState === "auth-down" && (
|
||||
<div className="login-banner login-banner-warn">
|
||||
The authentication service is temporarily down. Sign-in will fail until it is restored.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && <div className="login-error">{error}</div>}
|
||||
|
||||
<form className="login-form" onSubmit={handleSubmit}>
|
||||
|
||||
Reference in New Issue
Block a user