/* ============================================================ Engeradios Engeradios Admin — JS Produção Melhorias não destrutivas de UX/responsividade ============================================================ */ (function () { "use strict"; const LOGO_URL = "https://engeradios.com.br/xlogoengeradios.png.pagespeed.ic.mxsDoIKqSA.webp"; const TOKEN_ADMIN = "engeradios_admin_token"; const TOKEN_LEGACY = "access_token"; const menuGroups = [ { title: "Operação", items: [ ["📊", "Dashboard", "/dashboard"], ["👥", "Funcionários", "/funcionarios"], ["🕒", "Registros de ponto", "/pontos"], ["📱", "Aparelhos", "/aparelhos"], ["📅", "Jornadas", "/jornadas"], ["📄", "Relatório mensal", "/relatorios"], ["✅", "Fechamentos", "/fechamentos"] ] }, { title: "RH Digital", items: [ ["🔔", "Notificações", "/notificacoes"], ["📝", "Justificativas", "/justificativas"], ["📎", "Documentos", "/documentos"], ["💳", "Contracheques", "/contracheques"], ["⚠️", "Advertências", "/advertencias"], ["⚙️", "Config. mobile", "/configuracoes-mobile"] ] }, { title: "Administração", items: [ ["🛡️", "Permissões", "/"], ["🔍", "Auditoria", "/auditoria"], ["❤️", "Saúde", "/saude"], ["📈", "Painel SaaS", "/dashboard-saas"] ] } ]; const pageMeta = { "/": ["Permissões e ACL", "Controle de acesso administrativo"], "/dashboard": ["Dashboard administrativo", "Visão geral da operação"], "/dashboard-saas": ["Painel executivo", "Indicadores e gráficos do RH digital"], "/funcionarios": ["Funcionários", "Consulta de colaboradores, status e vínculos"], "/employees": ["Funcionários", "Consulta de colaboradores, status e vínculos"], "/pontos": ["Registros de ponto", "Batidas, GPS, offline, selfie e aparelho"], "/time-entries": ["Registros de ponto", "Batidas, GPS, offline, selfie e aparelho"], "/aparelhos": ["Aparelhos", "Autorização e bloqueio de dispositivos"], "/devices": ["Aparelhos", "Autorização e bloqueio de dispositivos"], "/device-auth": ["Aparelhos", "Autorização e bloqueio de dispositivos"], "/jornadas": ["Jornadas", "Escalas, horários e alertas"], "/schedules": ["Jornadas", "Escalas, horários e alertas"], "/relatorios": ["Relatório mensal", "Conferência mensal de ponto"], "/reports": ["Relatório mensal", "Conferência mensal de ponto"], "/fechamentos": ["Fechamentos", "Espelhos mensais e assinaturas"], "/timesheet-closings": ["Fechamentos", "Espelhos mensais e assinaturas"], "/documentos": ["Documentos", "Envio, análise e revisão de documentos"], "/justificativas": ["Justificativas", "Análise de atestados, atrasos e faltas"], "/contracheques": ["Contracheques", "Envio e consulta de holerites"], "/advertencias": ["Advertências e comunicados", "Comunicações com ciência do funcionário"], "/notificacoes": ["Notificações", "Central de avisos e regras automáticas"], "/auditoria": ["Auditoria", "Rastreabilidade de ações administrativas"], "/saude": ["Saúde do sistema", "Status operacional da plataforma"] }; function normalizePath() { let path = window.location.pathname || "/"; if (path.length > 1) path = path.replace(/\/+$/, ""); return path || "/"; } function syncTokens() { try { const adminToken = localStorage.getItem(TOKEN_ADMIN); const legacyToken = localStorage.getItem(TOKEN_LEGACY); const token = adminToken || legacyToken; if (token) { if (!adminToken) localStorage.setItem(TOKEN_ADMIN, token); if (!legacyToken) localStorage.setItem(TOKEN_LEGACY, token); } const originalSetItem = localStorage.setItem.bind(localStorage); localStorage.setItem = function (key, value) { originalSetItem(key, value); if (key === TOKEN_ADMIN && value) originalSetItem(TOKEN_LEGACY, value); if (key === TOKEN_LEGACY && value) originalSetItem(TOKEN_ADMIN, value); }; } catch (_) { /* Não interrompe a página se storage estiver bloqueado */ } } function ensureSkipLink() { if (document.querySelector(".er-skip-link")) return; const link = document.createElement("a"); link.className = "er-skip-link"; link.href = "#conteudo-principal"; link.textContent = "Ir para o conteúdo"; document.body.prepend(link); } function ensureMainId() { const main = document.querySelector("main") || document.body; if (!main.id) main.id = "conteudo-principal"; } function buildSidebar() { if (document.querySelector(".er-sidebar")) return; const aside = document.createElement("aside"); aside.className = "er-sidebar card"; aside.setAttribute("aria-label", "Menu principal"); EngeradiosDOM.setHTML(aside, `
Engeradios
Engeradios Ponto Painel administrativo
`); document.body.prepend(aside); } function buildTopbar() { if (document.querySelector(".er-topbar")) return; const path = normalizePath(); const meta = pageMeta[path] || ["Engeradios Admin", "Gestão operacional Engeradios"]; const bar = document.createElement("header"); bar.className = "er-topbar card"; EngeradiosDOM.setHTML(bar, `
${meta[0]} ${meta[1]}
🔴 Engeradios 🔒 Área administrativa
`); document.body.prepend(bar); } function ensureOverlay() { if (document.querySelector(".er-overlay")) return; const overlay = document.createElement("div"); overlay.className = "er-overlay"; overlay.setAttribute("aria-hidden", "true"); document.body.appendChild(overlay); } function bindMobileMenu() { const button = document.querySelector(".er-mobile-menu-btn"); const overlay = document.querySelector(".er-overlay"); if (!button || !overlay) return; function closeMenu() { document.body.classList.remove("er-sidebar-open"); button.setAttribute("aria-expanded", "false"); } function openMenu() { document.body.classList.add("er-sidebar-open"); button.setAttribute("aria-expanded", "true"); } button.addEventListener("click", () => { if (document.body.classList.contains("er-sidebar-open")) closeMenu(); else openMenu(); }); overlay.addEventListener("click", closeMenu); document.addEventListener("keydown", (event) => { if (event.key === "Escape") closeMenu(); }); document.querySelectorAll(".er-menu a").forEach((link) => { link.addEventListener("click", closeMenu); }); } function markActiveMenu() { const path = normalizePath(); document.querySelectorAll(".er-menu a").forEach((link) => { const href = link.getAttribute("data-er-href") || link.getAttribute("href") || ""; const normalizedHref = href.length > 1 ? href.replace(/\/+$/, "") : href; if (normalizedHref === path) { link.classList.add("er-active"); link.setAttribute("aria-current", "page"); } }); } function enhanceEmptyAreas() { const phrases = [ "Nenhum dado carregado.", "Nenhum registro carregado.", "Nenhum funcionário carregado.", "Nenhum documento carregado.", "Nenhuma justificativa carregada.", "Nenhum aviso carregado.", "Nenhum fechamento carregado.", "Nenhum log carregado.", "Clique em “Atualizar pendentes”.", "Aguardando login." ]; document.querySelectorAll("div, p").forEach((el) => { const text = (el.textContent || "").trim(); if (phrases.includes(text) && el.children.length === 0) { el.classList.add("er-empty"); } }); } function improveTables() { document.querySelectorAll("table").forEach((table) => { if (table.parentElement && table.parentElement.classList.contains("er-table-wrap")) return; const wrap = document.createElement("div"); wrap.className = "er-table-wrap"; wrap.style.overflowX = "auto"; wrap.style.webkitOverflowScrolling = "touch"; table.parentNode.insertBefore(wrap, table); wrap.appendChild(table); }); } function improveButtons() { document.querySelectorAll("button").forEach((button) => { if (!button.getAttribute("type")) { button.setAttribute("type", "button"); } const text = (button.textContent || "").trim(); if (!button.getAttribute("aria-label") && text) { button.setAttribute("aria-label", text); } }); } function exposeSafeHelpers() { window.ER = window.ER || {}; window.ER.escapeHTML = function (value) { return String(value ?? "") .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); }; window.ER.formatDateBR = function (value) { if (!value) return "-"; try { return new Date(value).toLocaleString("pt-BR"); } catch (_) { return String(value); } }; } function boot() { syncTokens(); exposeSafeHelpers(); document.body.classList.add("er-prod-ready"); ensureSkipLink(); ensureMainId(); buildSidebar(); buildTopbar(); ensureOverlay(); bindMobileMenu(); markActiveMenu(); window.setTimeout(() => { improveButtons(); improveTables(); enhanceEmptyAreas(); }, 0); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", boot); } else { boot(); } })();