(() => { const menuController = window.WarpBoxUI?.bindMenuBar?.() || { close() {} }; const toastTarget = document.getElementById("toast"); const body = document.getElementById("users-body"); const search = document.getElementById("users-search"); const status = document.getElementById("users-status"); const role = document.getElementById("users-role-filter"); const sort = document.getElementById("users-sort"); const size = document.getElementById("users-size"); const masterCheck = document.getElementById("users-master-check"); const pageInfo = document.getElementById("users-page-info"); const visiblePill = document.getElementById("visible-pill"); const selectedPill = document.getElementById("users-selected-pill"); const prevBtn = document.getElementById("users-prev"); const nextBtn = document.getElementById("users-next"); const selectVisible = document.getElementById("select-visible"); const form = document.getElementById("users-form"); const modeInput = document.getElementById("users-mode"); const usernameInput = document.getElementById("users-username"); const emailInput = document.getElementById("users-email"); const roleInput = document.getElementById("users-role"); const planInput = document.getElementById("users-plan"); const statusLeft = document.getElementById("users-status-left"); if (!body || !search || !status || !role || !sort || !size) return; const users = [ { id: "u_admin", username: "admin", email: "admin@warpbox.local", status: "active", role: "admin", plan: "unlimited", boxes: 18, created: "2026-04-12", lastSeen: "active now" }, { id: "u_geo", username: "geo", email: "geo@example.test", status: "active", role: "uploader", plan: "trusted", boxes: 7, created: "2026-04-21", lastSeen: "today 12:10" }, { id: "u_reo", username: "reo", email: "reo@example.test", status: "active", role: "uploader", plan: "standard", boxes: 3, created: "2026-04-20", lastSeen: "today 09:44" }, { id: "u_teo", username: "teo", email: "teo@example.test", status: "active", role: "uploader", plan: "trusted", boxes: 5, created: "2026-04-19", lastSeen: "yesterday" }, { id: "u_mara", username: "mara", email: "mara@example.test", status: "pending", role: "viewer", plan: "guest-like", boxes: 0, created: "2026-04-28", lastSeen: "never" }, { id: "u_ion", username: "ion", email: "ion@example.test", status: "disabled", role: "uploader", plan: "standard", boxes: 2, created: "2026-04-01", lastSeen: "2026-04-15" }, { id: "u_sara", username: "sara", email: "sara@example.test", status: "active", role: "operator", plan: "trusted", boxes: 12, created: "2026-03-30", lastSeen: "today 08:25" }, { id: "u_vlad", username: "vlad", email: "vlad@example.test", status: "pending", role: "uploader", plan: "standard", boxes: 0, created: "2026-04-27", lastSeen: "never" }, { id: "u_lina", username: "lina", email: "lina@example.test", status: "active", role: "viewer", plan: "guest-like", boxes: 1, created: "2026-03-22", lastSeen: "2026-04-29" }, { id: "u_adi", username: "adi", email: "adi@example.test", status: "active", role: "uploader", plan: "standard", boxes: 4, created: "2026-02-18", lastSeen: "2026-04-26" }, { id: "u_nora", username: "nora", email: "nora@example.test", status: "disabled", role: "viewer", plan: "guest-like", boxes: 0, created: "2026-01-14", lastSeen: "2026-03-02" }, { id: "u_alex", username: "alex", email: "alex@example.test", status: "active", role: "uploader", plan: "trusted", boxes: 9, created: "2026-04-10", lastSeen: "2026-04-30" }, { id: "u_rina", username: "rina", email: "rina@example.test", status: "pending", role: "uploader", plan: "standard", boxes: 0, created: "2026-04-29", lastSeen: "never" }, { id: "u_mihai", username: "mihai", email: "mihai@example.test", status: "active", role: "operator", plan: "trusted", boxes: 6, created: "2026-02-08", lastSeen: "2026-04-22" } ]; const state = { page: 1, selected: new Set() }; function toast(message, type = "info") { if (window.WarpBoxUI) { window.WarpBoxUI.toast(message, type, { target: toastTarget, duration: 2200 }); return; } if (!toastTarget) return; toastTarget.textContent = message; toastTarget.classList.add("is-visible"); } function filtered() { const query = search.value.trim().toLowerCase(); const statusFilter = status.value; const roleFilter = role.value; const sortBy = sort.value; const rows = users.filter((user) => { const matchesQuery = !query || user.username.toLowerCase().includes(query) || user.email.toLowerCase().includes(query); const matchesStatus = statusFilter === "all" || user.status === statusFilter; const matchesRole = roleFilter === "all" || user.role === roleFilter; return matchesQuery && matchesStatus && matchesRole; }); rows.sort((a, b) => { if (sortBy === "createdDesc") return b.created.localeCompare(a.created); if (sortBy === "lastSeenDesc") return b.lastSeen.localeCompare(a.lastSeen); if (sortBy === "boxesDesc") return b.boxes - a.boxes; return a.username.localeCompare(b.username); }); return rows; } function paged(rows) { const perPage = Number(size.value || 12); const pages = Math.max(1, Math.ceil(rows.length / perPage)); if (state.page > pages) state.page = pages; if (state.page < 1) state.page = 1; const start = (state.page - 1) * perPage; return { rows: rows.slice(start, start + perPage), pages, start }; } function statusPill(value) { return `${value}`; } function renderRow(user) { const checked = state.selected.has(user.id) ? " checked" : ""; const row = document.createElement("tr"); row.innerHTML = `
${user.username}${user.id}
${user.email} ${statusPill(user.status)} ${user.role} ${user.plan} ${user.boxes} ${user.lastSeen}
`; row.querySelector(".row-check")?.addEventListener("change", (event) => { if (event.target.checked) state.selected.add(user.id); else state.selected.delete(user.id); syncSelected(); syncMasterCheck(); }); row.querySelector('[data-action="open"]')?.addEventListener("click", () => { toast(`Mock user preview: ${user.username}`); }); return row; } function syncSelected() { selectedPill.textContent = `${state.selected.size} selected`; } function syncMasterCheck() { const checks = Array.from(body.querySelectorAll(".row-check")); masterCheck.checked = checks.length > 0 && checks.every((item) => item.checked); } function renderStats() { document.getElementById("stat-total").textContent = String(users.length); document.getElementById("stat-active").textContent = String(users.filter((u) => u.status === "active").length); document.getElementById("stat-pending").textContent = String(users.filter((u) => u.status === "pending").length); document.getElementById("stat-disabled").textContent = String(users.filter((u) => u.status === "disabled").length); } function render() { const rows = filtered(); const page = paged(rows); body.innerHTML = ""; page.rows.forEach((user) => body.appendChild(renderRow(user))); visiblePill.textContent = `${rows.length} visible`; pageInfo.textContent = `Page ${state.page} / ${page.pages}`; prevBtn.disabled = state.page <= 1; nextBtn.disabled = state.page >= page.pages; statusLeft.textContent = `Ready. ${rows.length} user rows in current filter.`; syncSelected(); syncMasterCheck(); } function clearFilters() { search.value = ""; status.value = "all"; role.value = "all"; sort.value = "username"; state.page = 1; render(); } function applyBulk(nextStatus) { const selected = users.filter((user) => state.selected.has(user.id)); if (!selected.length) { toast("Select one or more users first", "warning"); return; } selected.forEach((user) => { user.status = nextStatus; }); toast(`Updated ${selected.length} user(s) to ${nextStatus}`); renderStats(); render(); } function runCommand(command) { switch (command) { case "invite": modeInput.value = "invite"; toast("Invite mode selected"); break; case "create": modeInput.value = "create"; toast("Create mode selected"); break; case "export": toast("Mock CSV export complete"); break; case "bulk-disable": applyBulk("disabled"); break; case "bulk-enable": applyBulk("active"); break; case "bulk-revoke": toast("Mock session revocation queued"); break; case "refresh": toast("Users list refreshed"); render(); break; case "pending-only": status.value = "pending"; state.page = 1; render(); break; case "clear-filters": clearFilters(); break; case "policy-help": toast("Policy editor will be added in user details later."); break; case "mock-note": toast("Mock-only page: no backend writes yet."); break; default: toast(`Mock action: ${command}`); break; } } [search, status, role, sort, size].forEach((el) => { el.addEventListener(el.tagName === "INPUT" ? "input" : "change", () => { state.page = 1; render(); }); }); prevBtn.addEventListener("click", () => { state.page -= 1; render(); }); nextBtn.addEventListener("click", () => { state.page += 1; render(); }); masterCheck.addEventListener("change", () => { Array.from(body.querySelectorAll("tr")).forEach((row) => { const checkbox = row.querySelector(".row-check"); if (!checkbox) return; checkbox.checked = masterCheck.checked; const userID = row.querySelector(".users-muted")?.textContent || ""; if (masterCheck.checked) state.selected.add(userID); else state.selected.delete(userID); }); syncSelected(); }); selectVisible.addEventListener("click", () => { Array.from(body.querySelectorAll("tr")).forEach((row) => { const checkbox = row.querySelector(".row-check"); const userID = row.querySelector(".users-muted")?.textContent || ""; if (!checkbox) return; checkbox.checked = true; state.selected.add(userID); }); syncSelected(); syncMasterCheck(); }); form.addEventListener("submit", (event) => { event.preventDefault(); const username = usernameInput.value.trim(); const email = emailInput.value.trim(); const mode = modeInput.value; if (!username || !email) { toast("Username and email are required", "warning"); return; } users.unshift({ id: `u_${username.toLowerCase().replaceAll(/[^a-z0-9]+/g, "_")}`, username, email, status: mode === "invite" ? "pending" : "active", role: roleInput.value, plan: planInput.value, boxes: 0, created: new Date().toISOString().slice(0, 10), lastSeen: "never" }); form.reset(); modeInput.value = "invite"; renderStats(); render(); toast(mode === "invite" ? "Mock invite created" : "Mock user created"); }); document.querySelectorAll("[data-command]").forEach((button) => { button.addEventListener("click", () => { menuController.close(); runCommand(button.dataset.command); }); }); document.addEventListener("keydown", (event) => { if (event.key === "Escape") menuController.close(); if (event.key === "F5") { event.preventDefault(); runCommand("refresh"); } if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "i") { event.preventDefault(); runCommand("invite"); } }); renderStats(); render(); })();