58 lines
2.2 KiB
JavaScript
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();
|
|
})();
|