// login.js document.addEventListener("DOMContentLoaded", () => { const form = document.getElementById("login-form"); const errorBox = document.getElementById("error"); const usernameInput = document.getElementById("username"); const passwordInput = document.getElementById("password"); const twoFactorInput = document.getElementById("two-factor-code"); const twoFactorGroup = document.getElementById("two-factor-group"); const submitButton = document.getElementById("login-submit"); let pendingTwoFactorToken = null; if (!form) return; function showError(message) { errorBox.textContent = message || "Login failed."; errorBox.style.display = "block"; } function storeTokens(data) { localStorage.setItem("access_token", data.access_token); localStorage.setItem("refresh_token", data.refresh_token); } function switchToTwoFactorMode(token) { pendingTwoFactorToken = token; usernameInput.disabled = true; passwordInput.disabled = true; twoFactorGroup.style.display = "block"; twoFactorInput.required = true; twoFactorInput.focus(); submitButton.textContent = "Verify code"; } form.addEventListener("submit", async (e) => { e.preventDefault(); errorBox.style.display = "none"; submitButton.disabled = true; try { let response; if (pendingTwoFactorToken) { response = await fetch("/api/login/2fa", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ two_factor_token: pendingTwoFactorToken, code: twoFactorInput.value.trim() }) }); } else { response = await fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ username: usernameInput.value, password: passwordInput.value }) }); } if (!response.ok) { const text = await response.text(); throw new Error(text); } const data = await response.json(); if (data.requires_2fa) { switchToTwoFactorMode(data.two_factor_token); return; } storeTokens(data); window.location.href = "/dashboard"; } catch (err) { showError(err.message); } finally { submitButton.disabled = false; } }); });