add top bar

This commit is contained in:
2026-06-16 11:17:28 +07:00
parent 9aee5f4100
commit 1156e1ab29
19 changed files with 1625 additions and 80 deletions

View File

@@ -12,10 +12,8 @@
const loginPinErrorEl = el("loginPinError");
const loginTabPasswordEl = el("loginTabPassword");
const loginTabPinEl = el("loginTabPin");
const userMenuBtnEl = el("userMenuBtn");
const userMenuPanelEl = el("userMenuPanel");
const userMenuNameEl = el("userMenuName");
const userMenuGroupEl = el("userMenuGroup");
const userMenuBtnEl = el("mirUserBtn");
const userMenuPanelEl = el("mirUserPanel");
const changePasswordDialogEl = el("changePasswordDialog");
const changePasswordFormEl = el("changePasswordForm");
const changePasswordErrorEl = el("changePasswordError");
@@ -168,17 +166,21 @@
function updateUserMenu() {
if (!currentUser) return;
if (userMenuNameEl) userMenuNameEl.textContent = currentUser.display_name || currentUser.username || "—";
if (userMenuGroupEl) userMenuGroupEl.textContent = currentUser.group_name || "—";
if (window.TopbarApp?.updateUserMenu) {
window.TopbarApp.updateUserMenu(currentUser);
return;
}
if (userMenuBtnEl) {
const label = currentUser.display_name || currentUser.username || "User";
userMenuBtnEl.textContent = label;
userMenuBtnEl.title = `${label} (${currentUser.group_name || ""})`;
const label = (currentUser.group_name || "USER").toUpperCase();
userMenuBtnEl.title = `${currentUser.display_name || currentUser.username} (${currentUser.group_name || ""})`;
const labelEl = el("mirUserLabel");
if (labelEl) labelEl.textContent = label;
}
}
function unlockApp() {
setLoginLoading(false);
document.body.classList.remove("auth-logged-out");
if (loginScreenEl) {
loginScreenEl.setAttribute("hidden", "");
loginScreenEl.style.display = "none";
@@ -188,14 +190,16 @@
shellEl.style.display = "";
}
applyNavPermissions();
updateUserMenu();
ready = true;
window.dispatchEvent(new CustomEvent("lm:auth-ready", { detail: { user: currentUser } }));
updateUserMenu();
}
function lockApp() {
ready = false;
currentUser = null;
document.body.classList.add("auth-logged-out");
window.TopbarApp?.hideJoystickOverlay?.();
if (shellEl) shellEl.classList.add("auth-locked");
if (loginScreenEl) {
loginScreenEl.removeAttribute("hidden");
@@ -239,6 +243,12 @@
}
async function logout() {
try {
await window.TopbarApp?.disengageJoystick?.();
} catch {
/* ignore */
}
window.TopbarApp?.hideJoystickOverlay?.();
try {
await apiJson("/api/auth/logout", { method: "POST", body: "{}" });
} catch {
@@ -251,6 +261,17 @@
window.dispatchEvent(new Event("lm:auth-logout"));
}
async function saveProfile() {
const display_name = el("mirProfileDisplayName")?.value?.trim() || "";
if (!display_name) throw new Error("Tên hiển thị không được trống");
const data = await apiJson("/api/auth/profile", {
method: "PUT",
body: JSON.stringify({ display_name }),
});
currentUser = data.user;
updateUserMenu();
}
function bindEvents() {
loginTabPasswordEl?.addEventListener("click", (evt) => {
evt.preventDefault();
@@ -308,29 +329,28 @@
}
});
userMenuBtnEl?.addEventListener("click", (evt) => {
evt.stopPropagation();
const open = userMenuPanelEl?.hasAttribute("hidden");
if (open) userMenuPanelEl?.removeAttribute("hidden");
else userMenuPanelEl?.setAttribute("hidden", "");
});
document.addEventListener("click", () => {
userMenuPanelEl?.setAttribute("hidden", "");
});
el("userMenuSignOutBtn")?.addEventListener("click", (evt) => {
el("mirUserSignOutBtn")?.addEventListener("click", (evt) => {
evt.preventDefault();
logout();
});
el("userMenuChangePasswordBtn")?.addEventListener("click", (evt) => {
el("mirUserChangePasswordBtn")?.addEventListener("click", (evt) => {
evt.preventDefault();
userMenuPanelEl?.setAttribute("hidden", "");
changePasswordErrorEl && (changePasswordErrorEl.textContent = "");
changePasswordDialogEl?.showModal();
});
el("mirProfileSaveBtn")?.addEventListener("click", async (evt) => {
evt.preventDefault();
try {
await saveProfile();
userMenuPanelEl?.setAttribute("hidden", "");
} catch (e) {
alert(e.message || "Lưu thông tin thất bại");
}
});
changePasswordFormEl?.addEventListener("submit", async (evt) => {
evt.preventDefault();
const current = el("changePasswordCurrent")?.value || "";
@@ -368,5 +388,12 @@
bindEvents();
setLoginMode("password");
shellEl?.classList.add("auth-locked");
if (window.location.search) {
try {
history.replaceState({}, "", window.location.pathname);
} catch {
/* ignore */
}
}
tryRestoreSession();
})();