fix(website): show login form errors

This commit is contained in:
suiyuebaobao committed 2026-07-28 22:27:41 +08:00
1 parent f72988e562
commit 1b22b7684c
2 files changed
+77 -1

No files matched your search

@@ -49,6 +49,71 @@ function synchronizeMenu() {
setMenuState(elements, false);
}
function accountFormFromHtmxEvent(event) {
const candidates = [
event.detail?.requestConfig?.elt,
event.detail?.elt,
event.detail?.target,
event.target,
];
for (const candidate of candidates) {
if (candidate instanceof HTMLFormElement && candidate.matches(".account-form")) {
return candidate;
}
if (candidate instanceof Element) {
const form = candidate.closest("form.account-form");
if (form instanceof HTMLFormElement) {
return form;
}
}
}
return null;
}
function accountErrorMessage(status, networkFailure = false) {
const english = document.documentElement.lang.toLowerCase().startsWith("en");
if (networkFailure) {
return english
? "Unable to reach the service. Check your connection and try again."
: "暂时无法连接服务,请检查网络后重试。";
}
if (status === 401) {
return english ? "The username or password is incorrect." : "账号或密码错误。";
}
if (status === 429) {
return english
? "Too many attempts. Please wait and try again."
: "尝试次数过多,请稍后再试。";
}
if (status === 400 || status === 422) {
return english
? "Check the information you entered and try again."
: "请检查填写内容后重试。";
}
if (status >= 500) {
return english
? "The service is temporarily unavailable. Please try again later."
: "服务暂时不可用,请稍后重试。";
}
return english
? "The request could not be completed. Please try again."
: "请求未能完成,请稍后重试。";
}
function accountShowError(event, networkFailure = false) {
const form = accountFormFromHtmxEvent(event);
const feedback = form?.querySelector("#auth-feedback");
if (!(feedback instanceof HTMLElement)) {
return;
}
const status = Number(event.detail?.xhr?.status) || 0;
feedback.textContent = accountErrorMessage(status, networkFailure);
feedback.setAttribute("data-tone", "error");
feedback.setAttribute("tabindex", "-1");
feedback.focus({ preventScroll: true });
}
document.addEventListener("click", (event) => {
if (!(event.target instanceof Element)) {
return;
@@ -88,3 +153,14 @@ desktopMedia.addEventListener("change", (event) => {
document.addEventListener("DOMContentLoaded", synchronizeMenu);
document.addEventListener("htmx:beforeSwap", () => closeMenu());
document.addEventListener("htmx:load", synchronizeMenu);
document.addEventListener("htmx:beforeRequest", (event) => {
const feedback = accountFormFromHtmxEvent(event)?.querySelector("#auth-feedback");
if (feedback instanceof HTMLElement) {
feedback.textContent = "";
feedback.removeAttribute("data-tone");
feedback.removeAttribute("tabindex");
}
});
document.addEventListener("htmx:responseError", (event) => accountShowError(event));
document.addEventListener("htmx:sendError", (event) => accountShowError(event, true));
document.addEventListener("htmx:timeout", (event) => accountShowError(event, true));
@@ -34,7 +34,7 @@
<link rel="stylesheet" href="/static/css/pages.css?v=20260719-industrial">
{% block styles %}{% endblock %}
<script src="/static/js/htmx.min.js?v=2.0.10" defer></script>
<script src="/static/js/site.js?v=20260720-github" defer></script>
<script src="/static/js/site.js?v=20260728-auth-feedback" defer></script>
{% block scripts %}{% endblock %}
</head>
<body hx-indicator="#page-progress">