Actualizar js/layout.js

This commit is contained in:
2026-02-11 21:56:33 +00:00
parent 0949492bf3
commit 53666b6c87

View File

@@ -1,117 +1,115 @@
// CONFIGURACIÓN GLOBAL // CONFIGURACIÓN GLOBAL
const API_URL = "https://integrarepara-api.integrarepara.es"; const API_URL = "https://integrarepara-api.integrarepara.es";
document.addEventListener("DOMContentLoaded", async () => { document.addEventListener("DOMContentLoaded", () => {
// 1. Verificar Token // 1. Verificar Token
const token = localStorage.getItem("token"); const token = localStorage.getItem("token");
if (!token) { if (!token) {
if (!window.location.pathname.endsWith("index.html") && window.location.pathname !== "/") {
window.location.href = "index.html"; window.location.href = "index.html";
return; return;
} }
}
// 2. Generar Sidebar (Con los nuevos enlaces) // 2. Generar Sidebar y Header
renderSidebar(); renderSidebar();
renderHeader();
// 3. Cargar Header (Mantenemos carga externa para la cabecera) // 3. Inicializar Iconos
await loadComponent("header-container", "header.html");
// 4. Inicializar Iconos
if (window.lucide) lucide.createIcons(); if (window.lucide) lucide.createIcons();
// 5. Lógica del Usuario (Header) // 4. Datos usuario
setupUserInfo(token); if (token) setupUserInfo(token);
// 6. Configurar Logout (Ahora manejado dentro de renderSidebar para asegurar que existe el botón)
const btnLogout = document.getElementById("globalBtnLogout");
if(btnLogout) {
btnLogout.addEventListener("click", () => {
localStorage.removeItem("token");
window.location.href = "index.html";
});
}
}); });
// --- GENERADOR DE SIDEBAR (NUEVO) --- // --- GENERADOR DE BARRA LATERAL (DISEÑO ORIGINAL RESTAURADO) ---
function renderSidebar() { function renderSidebar() {
const container = document.getElementById('sidebar-container'); const container = document.getElementById('sidebar-container');
if (!container) return; if (!container) return;
// Detectar página actual
const path = window.location.pathname.split("/").pop() || "index.html"; const path = window.location.pathname.split("/").pop() || "index.html";
// DEFINICIÓN DE MENÚ (Aquí añadimos Calendario y Automatizaciones) // MENU ITEMS (Recuperados Dashboard y Usuarios)
const menuItems = [ const menuItems = [
{ name: "Dashboard", link: "panel.html", icon: "layout-dashboard" },
{ name: "Servicios", link: "servicios.html", icon: "briefcase" }, { name: "Servicios", link: "servicios.html", icon: "briefcase" },
{ name: "Calendario", link: "calendario.html", icon: "calendar-days" }, // ✅ NUEVO { name: "Calendario", link: "calendario.html", icon: "calendar" },
{ name: "Clientes", link: "clientes.html", icon: "users" }, { name: "Clientes", link: "clientes.html", icon: "users" },
{ name: "Automatizaciones", link: "automatizaciones.html", icon: "zap" }, // ✅ NUEVO (Icono rayo) { name: "Usuarios", link: "usuarios.html", icon: "user-cog" },
{ name: "Automatizaciones", link: "automatizaciones.html", icon: "zap" },
{ name: "Configuración", link: "configuracion.html", icon: "settings" }, { name: "Configuración", link: "configuracion.html", icon: "settings" },
]; ];
// Construir HTML de los enlaces
const linksHtml = menuItems.map(item => { const linksHtml = menuItems.map(item => {
const isActive = path === item.link; const isActive = path === item.link;
// Estilos basados en tu diseño actual (Slate oscuro) // ESTILOS ORIGINALES (Texto Slate-400, Hover Blanco/Slate-800)
const baseClasses = "flex items-center gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 font-medium mb-1 text-sm"; const baseClasses = "nav-item flex items-center gap-3 px-4 py-3 rounded-lg transition-all text-sm font-medium";
const activeClasses = "bg-blue-600 text-white shadow-lg shadow-blue-500/30"; // Si está activo, usamos el azul original de tu diseño, si no, el gris
const inactiveClasses = "text-slate-400 hover:text-white hover:bg-slate-800"; const activeClasses = isActive
? "bg-blue-600 text-white shadow-lg shadow-blue-500/30"
: "text-slate-400 hover:text-white hover:bg-slate-800";
return ` return `
<a href="${item.link}" class="${baseClasses} ${isActive ? activeClasses : inactiveClasses}"> <a href="${item.link}" class="${baseClasses} ${activeClasses}">
<i data-lucide="${item.icon}" class="w-5 h-5"></i> <i data-lucide="${item.icon}" class="w-5 h-5"></i>
${item.name} <span>${item.name}</span>
</a> </a>
`; `;
}).join(""); }).join("");
// Inyectar HTML completo del Sidebar
container.innerHTML = ` container.innerHTML = `
<aside class="w-64 bg-slate-900 h-full flex flex-col text-white shadow-xl"> <aside class="w-64 bg-slate-900 text-white flex flex-col shadow-xl z-20 h-full transition-all">
<div class="p-6 border-b border-slate-800 flex items-center gap-3"> <div class="h-16 flex items-center justify-center border-b border-slate-800 shrink-0">
<div class="w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-700 rounded-lg flex items-center justify-center font-bold text-white shadow-lg">I</div> <h1 class="text-xl font-bold tracking-wider text-blue-400">INTEGRA<span class="text-white">REPARA</span></h1>
<div>
<h1 class="font-bold text-lg tracking-tight leading-none">Integra</h1>
<span class="text-[10px] text-slate-400 uppercase tracking-widest font-semibold">Repara</span>
</div>
</div> </div>
<nav class="flex-1 overflow-y-auto p-4 no-scrollbar"> <nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto no-scrollbar">
<p class="text-[11px] font-bold text-slate-500 uppercase tracking-wider mb-4 px-2 mt-2">Principal</p>
${linksHtml} ${linksHtml}
</nav> </nav>
<div class="p-4 border-t border-slate-800 bg-slate-900/50"> <div class="p-4 border-t border-slate-800 shrink-0">
<button id="globalBtnLogout" class="flex items-center gap-3 px-3 py-2.5 rounded-lg text-slate-400 hover:text-red-400 hover:bg-red-500/10 transition-all w-full text-left text-sm font-medium"> <button onclick="logout()" class="flex items-center gap-2 text-slate-400 hover:text-red-400 transition-colors w-full p-2 rounded hover:bg-slate-800 font-medium text-sm">
<i data-lucide="log-out" class="w-5 h-5"></i> <i data-lucide="log-out" class="w-5 h-5"></i>
Cerrar Sesión <span>Cerrar Sesión</span>
</button> </button>
</div> </div>
</aside> </aside>
`; `;
} }
// --- FUNCIONES AUXILIARES --- // --- GENERADOR DE CABECERA (HEADER) ---
function renderHeader() {
const container = document.getElementById('header-container');
if (!container) return;
async function loadComponent(elementId, filePath) { // Fecha actual
try { const dateStr = new Date().toLocaleDateString('es-ES', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
const response = await fetch(filePath); const dateCapitalized = dateStr.charAt(0).toUpperCase() + dateStr.slice(1);
if (response.ok) {
const html = await response.text(); container.innerHTML = `
document.getElementById(elementId).innerHTML = html; <header class="bg-white h-16 border-b border-gray-200 flex justify-between items-center px-6 shadow-sm z-10 shrink-0">
} else { <div class="flex items-center text-gray-500 text-sm gap-2">
console.warn(`No se pudo cargar ${filePath} (puede que no sea necesario si usas el sidebar generado)`); <i data-lucide="calendar" class="w-4 h-4"></i>
} <span class="font-medium">${dateCapitalized}</span>
} catch (e) { </div>
// Ignoramos errores silenciosos para no molestar en consola
} <div class="flex items-center gap-4">
<div class="text-right hidden md:block">
<p class="text-sm font-bold text-gray-800 leading-none" id="headerUserName">Cargando...</p>
<p class="text-xs text-gray-500 mt-1" id="headerUserRole">...</p>
</div>
<div class="w-9 h-9 rounded-full bg-blue-100 border border-blue-200 flex items-center justify-center text-blue-700 font-bold shadow-sm" id="headerUserAvatar">
U
</div>
</div>
</header>
`;
} }
// --- UTILIDADES ---
function setupUserInfo(token) { function setupUserInfo(token) {
try { try {
const payload = JSON.parse(atob(token.split('.')[1])); const payload = JSON.parse(atob(token.split('.')[1]));
// Elementos del Header
const nameEl = document.getElementById("headerUserName"); const nameEl = document.getElementById("headerUserName");
const roleEl = document.getElementById("headerUserRole"); const roleEl = document.getElementById("headerUserRole");
const avatarEl = document.getElementById("headerUserAvatar"); const avatarEl = document.getElementById("headerUserAvatar");
@@ -120,7 +118,12 @@ function setupUserInfo(token) {
if (roleEl) roleEl.innerText = (payload.role || "Operario").toUpperCase(); if (roleEl) roleEl.innerText = (payload.role || "Operario").toUpperCase();
if (avatarEl) avatarEl.innerText = (payload.email?.[0] || "U").toUpperCase(); if (avatarEl) avatarEl.innerText = (payload.email?.[0] || "U").toUpperCase();
} catch (e) { } catch (e) {
console.error("Error decodificando token", e); localStorage.removeItem("token");
}
}
function logout() {
if(confirm("¿Cerrar sesión?")) {
localStorage.removeItem("token"); localStorage.removeItem("token");
window.location.href = "index.html"; window.location.href = "index.html";
} }