206 lines
6.9 KiB
JavaScript
206 lines
6.9 KiB
JavaScript
document.addEventListener("DOMContentLoaded", async () => {
|
|
const openBtn = document.getElementById("ramais-btn");
|
|
const modal = document.getElementById("ramais-lookup-modal");
|
|
if (!openBtn || !modal) return;
|
|
|
|
const me = await pidGetMe();
|
|
if (!me) return;
|
|
|
|
const ramalPerms = (me.permissoes_efetivas && me.permissoes_efetivas["ramais"]) || {};
|
|
const canView = !!(ramalPerms.apps && ramalPerms.apps["ramais-visualizar"]);
|
|
if (!canView) {
|
|
openBtn.hidden = true;
|
|
return;
|
|
}
|
|
|
|
const closeBtn = document.getElementById("ramais-lookup-close-btn");
|
|
const closeBtn2 = document.getElementById("ramais-lookup-close-btn-2");
|
|
const searchInput = document.getElementById("ramais-lookup-search");
|
|
const pageSizeSelect = document.getElementById("ramais-lookup-pagesize");
|
|
const deptoFiltrosEl = document.getElementById("ramais-lookup-depto-filters");
|
|
const tableBody = document.getElementById("ramais-lookup-table-body");
|
|
const countEl = document.getElementById("ramais-lookup-count");
|
|
const paginationEl = document.getElementById("ramais-lookup-pagination");
|
|
const sortHeaders = Array.from(modal.querySelectorAll("th[data-sort]"));
|
|
|
|
const FIELD_BY_SORT_KEY = { nome: "nome_exibicao", departamento: "departamento_exibicao", numero: "numero_exibicao" };
|
|
|
|
let ramais = null; // carregado sob demanda na primeira abertura
|
|
let departamentos = null; // idem — alimenta os botões de filtro, um por departamento cadastrado
|
|
let activeDepto = ""; // "" = "Todos"
|
|
let sortKey = "nome";
|
|
let sortDir = 1;
|
|
let page = 1;
|
|
|
|
function renderDeptoFilters() {
|
|
const botoes = [`<button type="button" class="ram-lookup-depto-btn${activeDepto === "" ? " is-active" : ""}" data-depto="">Todos</button>`].concat(
|
|
departamentos.map(
|
|
(d) =>
|
|
`<button type="button" class="ram-lookup-depto-btn${activeDepto === d.nome ? " is-active" : ""}" data-depto="${d.nome}">${d.nome}</button>`
|
|
)
|
|
);
|
|
deptoFiltrosEl.innerHTML = botoes.join("");
|
|
}
|
|
|
|
function pageWindow(current, total) {
|
|
const delta = 1;
|
|
const middle = [];
|
|
for (let i = Math.max(2, current - delta); i <= Math.min(total - 1, current + delta); i++) {
|
|
middle.push(i);
|
|
}
|
|
const pages = [1];
|
|
if (middle[0] > 2) pages.push("...");
|
|
pages.push(...middle);
|
|
if (middle[middle.length - 1] < total - 1) pages.push("...");
|
|
if (total > 1) pages.push(total);
|
|
return pages;
|
|
}
|
|
|
|
function filteredSorted() {
|
|
const term = searchInput.value.trim().toLowerCase();
|
|
const field = FIELD_BY_SORT_KEY[sortKey];
|
|
let rows = ramais.filter((r) => {
|
|
if (activeDepto) {
|
|
const deptos = (r.departamento_exibicao || "").split(",").map((s) => s.trim());
|
|
if (!deptos.includes(activeDepto)) return false;
|
|
}
|
|
if (!term) return true;
|
|
return [r.nome_exibicao, r.departamento_exibicao, r.numero_exibicao].some((v) => (v || "").toLowerCase().includes(term));
|
|
});
|
|
rows.sort((a, b) => {
|
|
const av = (a[field] || "").toString().toLowerCase();
|
|
const bv = (b[field] || "").toString().toLowerCase();
|
|
if (av < bv) return -1 * sortDir;
|
|
if (av > bv) return 1 * sortDir;
|
|
return 0;
|
|
});
|
|
return rows;
|
|
}
|
|
|
|
function renderPagination(totalPages) {
|
|
if (totalPages <= 1) {
|
|
paginationEl.innerHTML = "";
|
|
return;
|
|
}
|
|
const parts = [];
|
|
parts.push(`<button type="button" class="ram-lookup-page-btn" data-page="${page - 1}" ${page === 1 ? "disabled" : ""}>Anterior</button>`);
|
|
pageWindow(page, totalPages).forEach((p) => {
|
|
if (p === "...") {
|
|
parts.push(`<span class="ram-lookup-page-ellipsis">…</span>`);
|
|
} else {
|
|
parts.push(`<button type="button" class="ram-lookup-page-btn${p === page ? " is-active" : ""}" data-page="${p}">${p}</button>`);
|
|
}
|
|
});
|
|
parts.push(
|
|
`<button type="button" class="ram-lookup-page-btn" data-page="${page + 1}" ${page === totalPages ? "disabled" : ""}>Próxima</button>`
|
|
);
|
|
paginationEl.innerHTML = parts.join("");
|
|
}
|
|
|
|
function render() {
|
|
sortHeaders.forEach((th) => {
|
|
th.classList.toggle("is-sort-asc", th.dataset.sort === sortKey && sortDir === 1);
|
|
th.classList.toggle("is-sort-desc", th.dataset.sort === sortKey && sortDir === -1);
|
|
});
|
|
|
|
const rows = filteredSorted();
|
|
const pageSize = Number(pageSizeSelect.value);
|
|
const totalPages = Math.max(1, Math.ceil(rows.length / pageSize));
|
|
page = Math.min(page, totalPages);
|
|
const start = (page - 1) * pageSize;
|
|
const pageRows = rows.slice(start, start + pageSize);
|
|
|
|
tableBody.innerHTML = pageRows.length
|
|
? pageRows
|
|
.map(
|
|
(r) => `
|
|
<tr>
|
|
<td>${r.nome_exibicao}</td>
|
|
<td>${r.departamento_exibicao || "—"}</td>
|
|
<td>${r.numero_exibicao || "—"}</td>
|
|
</tr>`
|
|
)
|
|
.join("")
|
|
: `<tr class="ram-lookup-empty-row"><td colspan="3">Nenhum ramal encontrado.</td></tr>`;
|
|
|
|
const from = rows.length === 0 ? 0 : start + 1;
|
|
const to = Math.min(start + pageSize, rows.length);
|
|
countEl.textContent = `Mostrando ${from} a ${to} de ${rows.length} registros`;
|
|
renderPagination(totalPages);
|
|
}
|
|
|
|
async function openModal() {
|
|
modal.hidden = false;
|
|
if (!ramais) {
|
|
tableBody.innerHTML = `<tr class="ram-lookup-empty-row"><td colspan="3">Carregando...</td></tr>`;
|
|
try {
|
|
const [ramaisResp, departamentosResp] = await Promise.all([
|
|
pidApiRequest("/ramais/"),
|
|
pidApiRequest("/departamentos-resumo/"),
|
|
]);
|
|
ramais = ramaisResp || [];
|
|
departamentos = departamentosResp || [];
|
|
} catch (e) {
|
|
ramais = [];
|
|
departamentos = [];
|
|
}
|
|
renderDeptoFilters();
|
|
}
|
|
page = 1;
|
|
render();
|
|
}
|
|
|
|
function closeModal() {
|
|
modal.hidden = true;
|
|
}
|
|
|
|
openBtn.addEventListener("click", openModal);
|
|
if (closeBtn) closeBtn.addEventListener("click", closeModal);
|
|
if (closeBtn2) closeBtn2.addEventListener("click", closeModal);
|
|
modal.addEventListener("click", (event) => {
|
|
if (event.target === modal) closeModal();
|
|
});
|
|
|
|
searchInput.addEventListener("input", () => {
|
|
page = 1;
|
|
render();
|
|
});
|
|
|
|
deptoFiltrosEl.addEventListener("click", (event) => {
|
|
const btn = event.target.closest("[data-depto]");
|
|
if (!btn) return;
|
|
activeDepto = btn.getAttribute("data-depto");
|
|
renderDeptoFilters();
|
|
page = 1;
|
|
render();
|
|
});
|
|
|
|
pageSizeSelect.addEventListener("change", () => {
|
|
page = 1;
|
|
render();
|
|
});
|
|
|
|
sortHeaders.forEach((th) => {
|
|
th.addEventListener("click", () => {
|
|
const key = th.dataset.sort;
|
|
if (sortKey === key) {
|
|
sortDir *= -1;
|
|
} else {
|
|
sortKey = key;
|
|
sortDir = 1;
|
|
}
|
|
page = 1;
|
|
render();
|
|
});
|
|
});
|
|
|
|
paginationEl.addEventListener("click", (event) => {
|
|
const btn = event.target.closest("[data-page]");
|
|
if (!btn || btn.disabled) return;
|
|
const target = Number(btn.getAttribute("data-page"));
|
|
if (!target || target < 1) return;
|
|
page = target;
|
|
render();
|
|
});
|
|
});
|