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 = [``].concat( departamentos.map( (d) => `` ) ); 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)); }); // Ordem do português (acentos) e numérica nos ramais ("92" antes de "150"). rows.sort( (a, b) => (a[field] || "").toString().localeCompare((b[field] || "").toString(), "pt-BR", { numeric: true, sensitivity: "base" }) * sortDir ); return rows; } function renderPagination(totalPages) { if (totalPages <= 1) { paginationEl.innerHTML = ""; return; } const parts = []; parts.push(``); pageWindow(page, totalPages).forEach((p) => { if (p === "...") { parts.push(`…`); } else { parts.push(``); } }); parts.push( `` ); paginationEl.innerHTML = parts.join(""); } function render() { // Ainda sem dados (carregando ou falhou): busca/ordenação não têm o que mostrar. if (!ramais) return; 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) => ` ${pidEscapeHtml(r.nome_exibicao)} ${pidEscapeHtml(r.departamento_exibicao || "—")} ${pidEscapeHtml(r.numero_exibicao || "—")} ` ) .join("") : `Nenhum ramal encontrado.`; 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 = `Carregando…`; try { const [ramaisResp, departamentosResp] = await Promise.all([ pidApiRequest("/ramais/"), pidApiRequest("/departamentos-resumo/"), ]); ramais = ramaisResp || []; departamentos = departamentosResp || []; } catch (e) { // Falha não vira "Nenhum ramal encontrado." nem fica em cache: // `ramais` continua null e a próxima abertura tenta de novo. tableBody.innerHTML = `Não foi possível carregar. Recarregue a página; se persistir, contate a Inovação.`; countEl.textContent = ""; paginationEl.innerHTML = ""; return; } 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(); }); });