Files
PenaltyTracker/web/login.js
T

58 lines
2.2 KiB
JavaScript

(async function () {
const root = document.getElementById("app");
await setLang(detectInitialLang());
// If already signed in, skip the login form.
try {
const u = await API.me();
if (u) {
navigate(u.must_change_password ? "forcePassword" : "competitions");
return;
}
} catch (e) {}
function render() {
clearNode(root);
const usernameInput = el("input", { type: "text", autocomplete: "username", placeholder: t("username"),
oninput: (e) => { e.target.value = e.target.value.toLowerCase(); } });
const passwordInput = el("input", { type: "password", autocomplete: "current-password", placeholder: t("password") });
const errorBox = el("div", { class: "muted", style: { color: "var(--danger)", display: "none" } });
const langSelect = el("select",
{ onchange: async (e) => { await setLang(e.target.value); render(); } },
...I18N_AVAILABLE.map((l) => el("option", { value: l, selected: l === CURRENT_LANG }, I18N_NAMES[l]))
);
async function doLogin(e) {
e.preventDefault();
errorBox.style.display = "none";
try {
const u = await API.login(usernameInput.value, passwordInput.value);
if (u.must_change_password) navigate("forcePassword");
else navigate("competitions");
} catch (err) {
if (err.status === 429) errorBox.textContent = t("too_many_attempts");
else if (err.status === 401) errorBox.textContent = t("invalid_credentials");
else errorBox.textContent = err.message || t("invalid_credentials");
errorBox.style.display = "block";
}
}
const form = el("form", { onsubmit: doLogin, class: "col" },
el("h1", null, t("login_title")),
el("div", { class: "field" }, el("label", null, t("username")), usernameInput),
el("div", { class: "field" }, el("label", null, t("password")), passwordInput),
errorBox,
el("button", { type: "submit", class: "primary" }, t("sign_in")),
el("div", { class: "field", style: { marginTop: "0.5rem" } },
el("label", null, t("language")), langSelect
),
);
root.appendChild(el("div", { class: "login-wrap" }, el("div", { class: "login-box" }, form)));
usernameInput.focus();
}
render();
})();