282 lines
12 KiB
JavaScript
282 lines
12 KiB
JavaScript
// Layout Manager - Maneja el layout común de las páginas
|
|
const LayoutManager = {
|
|
config: {
|
|
title: '',
|
|
flag: '',
|
|
country: '',
|
|
user: ''
|
|
},
|
|
|
|
// Inicializar layout
|
|
init: function(config) {
|
|
this.config = { ...this.config, ...config };
|
|
this.renderNavbar();
|
|
this.renderFooter();
|
|
this.updateHeader();
|
|
this.setupEventListeners();
|
|
this.startClock();
|
|
this.protectPage();
|
|
},
|
|
|
|
// Renderizar navbar
|
|
renderNavbar: function() {
|
|
const navbarHTML = `
|
|
<nav class="bg-indigo-600 shadow-lg">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex justify-between items-center h-16">
|
|
<!-- Logo -->
|
|
<div class="flex items-center">
|
|
<a href="/login" class="text-white text-lg sm:text-xl font-bold flex items-center space-x-2">
|
|
<span>💰</span>
|
|
<span class="hidden sm:inline">Comparador de Precios</span>
|
|
<span class="sm:hidden">Comparador</span>
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Desktop Menu -->
|
|
<div class="hidden md:flex items-center space-x-2 lg:space-x-4">
|
|
<a href="/brasil" class="nav-link text-white px-3 lg:px-4 py-2 rounded-lg font-medium transition hover:bg-indigo-700" data-country="brasil">
|
|
🇧🇷 <span class="hidden lg:inline">Brasil</span>
|
|
</a>
|
|
<a href="/chile" class="nav-link text-white px-3 lg:px-4 py-2 rounded-lg font-medium transition hover:bg-indigo-700" data-country="chile">
|
|
🇨🇱 <span class="hidden lg:inline">Chile</span>
|
|
</a>
|
|
<button id="logoutBtn" class="text-white hover:bg-red-600 bg-red-500 px-3 lg:px-4 py-2 rounded-lg font-medium transition flex items-center space-x-2">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
|
|
</svg>
|
|
<span class="hidden lg:inline">Salir</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Mobile Menu Button -->
|
|
<button id="mobileMenuBtn" class="md:hidden text-white p-2 rounded-lg hover:bg-indigo-700 transition">
|
|
<svg id="menuIcon" class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
|
</svg>
|
|
<svg id="closeIcon" class="hidden w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Mobile Menu -->
|
|
<div id="mobileMenu" class="hidden md:hidden pb-4">
|
|
<div class="flex flex-col space-y-2">
|
|
<a href="/brasil" class="nav-link text-white px-4 py-3 rounded-lg font-medium transition hover:bg-indigo-700 flex items-center space-x-2" data-country="brasil">
|
|
<span>🇧🇷</span>
|
|
<span>Brasil</span>
|
|
</a>
|
|
<a href="/chile" class="nav-link text-white px-4 py-3 rounded-lg font-medium transition hover:bg-indigo-700 flex items-center space-x-2" data-country="chile">
|
|
<span>🇨🇱</span>
|
|
<span>Chile</span>
|
|
</a>
|
|
<button id="logoutBtnMobile" class="text-white bg-red-500 hover:bg-red-600 px-4 py-3 rounded-lg font-medium transition flex items-center space-x-2">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1"></path>
|
|
</svg>
|
|
<span>Salir</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</nav>`;
|
|
|
|
const navbarContainer = document.getElementById('navbar');
|
|
if (navbarContainer) {
|
|
navbarContainer.outerHTML = navbarHTML;
|
|
} else {
|
|
document.body.insertAdjacentHTML('afterbegin', navbarHTML);
|
|
}
|
|
|
|
this.updateNavbar();
|
|
},
|
|
|
|
// Renderizar footer
|
|
renderFooter: function() {
|
|
const footerHTML = `
|
|
<footer class="bg-gray-100 border-t mt-16">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 sm:py-6">
|
|
<div class="flex flex-col sm:flex-row items-center justify-between text-xs sm:text-sm text-gray-600 space-y-2 sm:space-y-0">
|
|
<div class="flex items-center space-x-2 sm:space-x-4">
|
|
<span class="hidden sm:inline">© 2025 Comparador de Precios</span>
|
|
<span class="sm:hidden">© 2025</span>
|
|
<span class="hidden sm:inline">•</span>
|
|
<span class="hidden sm:inline">Desarrollado con ❤️</span>
|
|
</div>
|
|
<div class="flex items-center space-x-2 sm:space-x-4">
|
|
<span id="version">v2.0.0</span>
|
|
<span>•</span>
|
|
<span id="currentTime">-</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</footer>`;
|
|
|
|
const footerContainer = document.getElementById('footer');
|
|
if (footerContainer) {
|
|
footerContainer.outerHTML = footerHTML;
|
|
} else {
|
|
document.body.insertAdjacentHTML('beforeend', footerHTML);
|
|
}
|
|
},
|
|
|
|
// Proteger página (require autenticación)
|
|
protectPage: async function() {
|
|
const sesionActiva = await authManager.protegerPagina();
|
|
if (sesionActiva) {
|
|
const usuario = authManager.obtenerUsuario();
|
|
document.getElementById('nombreUsuario').textContent = usuario;
|
|
}
|
|
},
|
|
|
|
// Actualizar navbar con país activo
|
|
updateNavbar: function() {
|
|
const navLinks = document.querySelectorAll('.nav-link');
|
|
navLinks.forEach(link => {
|
|
const country = link.dataset.country;
|
|
if (country === this.config.country) {
|
|
link.classList.remove('hover:bg-indigo-700');
|
|
link.classList.add('bg-indigo-700');
|
|
} else {
|
|
link.classList.remove('bg-indigo-700');
|
|
link.classList.add('hover:bg-indigo-700');
|
|
}
|
|
});
|
|
},
|
|
|
|
// Actualizar header
|
|
updateHeader: function() {
|
|
const flagElement = document.getElementById('country-flag');
|
|
const titleElement = document.getElementById('page-title');
|
|
|
|
if (flagElement) flagElement.textContent = this.config.flag;
|
|
if (titleElement) titleElement.textContent = this.config.title;
|
|
},
|
|
|
|
// Configurar event listeners
|
|
setupEventListeners: function() {
|
|
// Logout desktop
|
|
const logoutBtn = document.getElementById('logoutBtn');
|
|
if (logoutBtn) {
|
|
logoutBtn.addEventListener('click', () => {
|
|
authManager.cerrarSesion();
|
|
});
|
|
}
|
|
|
|
// Logout mobile
|
|
const logoutBtnMobile = document.getElementById('logoutBtnMobile');
|
|
if (logoutBtnMobile) {
|
|
logoutBtnMobile.addEventListener('click', () => {
|
|
authManager.cerrarSesion();
|
|
});
|
|
}
|
|
|
|
// Mobile menu toggle
|
|
const mobileMenuBtn = document.getElementById('mobileMenuBtn');
|
|
const mobileMenu = document.getElementById('mobileMenu');
|
|
const menuIcon = document.getElementById('menuIcon');
|
|
const closeIcon = document.getElementById('closeIcon');
|
|
|
|
if (mobileMenuBtn && mobileMenu) {
|
|
mobileMenuBtn.addEventListener('click', () => {
|
|
const isHidden = mobileMenu.classList.contains('hidden');
|
|
|
|
if (isHidden) {
|
|
mobileMenu.classList.remove('hidden');
|
|
menuIcon.classList.add('hidden');
|
|
closeIcon.classList.remove('hidden');
|
|
} else {
|
|
mobileMenu.classList.add('hidden');
|
|
menuIcon.classList.remove('hidden');
|
|
closeIcon.classList.add('hidden');
|
|
}
|
|
});
|
|
|
|
// Cerrar menú al hacer click en un link
|
|
const mobileLinks = mobileMenu.querySelectorAll('a');
|
|
mobileLinks.forEach(link => {
|
|
link.addEventListener('click', () => {
|
|
mobileMenu.classList.add('hidden');
|
|
menuIcon.classList.remove('hidden');
|
|
closeIcon.classList.add('hidden');
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
// Mostrar loading
|
|
showLoading: function() {
|
|
const spinner = document.getElementById('loadingSpinner');
|
|
const content = document.getElementById('pageContent');
|
|
|
|
if (spinner) spinner.classList.remove('hidden');
|
|
if (content) content.classList.add('hidden');
|
|
},
|
|
|
|
// Ocultar loading
|
|
hideLoading: function() {
|
|
const spinner = document.getElementById('loadingSpinner');
|
|
const content = document.getElementById('pageContent');
|
|
|
|
if (spinner) spinner.classList.add('hidden');
|
|
if (content) content.classList.remove('hidden');
|
|
},
|
|
|
|
// Insertar contenido en el área principal
|
|
insertContent: function(html) {
|
|
const content = document.getElementById('pageContent');
|
|
if (content) {
|
|
content.innerHTML = html;
|
|
content.classList.remove('hidden');
|
|
}
|
|
},
|
|
|
|
// Actualizar timestamp de última actualización
|
|
updateLastUpdate: function() {
|
|
const lastUpdate = document.getElementById('lastUpdate');
|
|
if (lastUpdate) {
|
|
const now = new Date();
|
|
lastUpdate.textContent = now.toLocaleTimeString('es-AR');
|
|
}
|
|
},
|
|
|
|
// Reloj en el footer
|
|
startClock: function() {
|
|
const updateTime = () => {
|
|
const currentTime = document.getElementById('currentTime');
|
|
if (currentTime) {
|
|
const now = new Date();
|
|
currentTime.textContent = now.toLocaleTimeString('es-AR');
|
|
}
|
|
};
|
|
|
|
updateTime();
|
|
setInterval(updateTime, 1000);
|
|
},
|
|
|
|
// Mostrar notificación toast
|
|
showToast: function(message, type = 'info') {
|
|
const colors = {
|
|
success: 'bg-green-500',
|
|
error: 'bg-red-500',
|
|
warning: 'bg-yellow-500',
|
|
info: 'bg-blue-500'
|
|
};
|
|
|
|
const toast = document.createElement('div');
|
|
toast.className = `fixed bottom-4 right-4 ${colors[type]} text-white px-6 py-3 rounded-lg shadow-lg z-50 animate-fade-in`;
|
|
toast.textContent = message;
|
|
|
|
document.body.appendChild(toast);
|
|
|
|
setTimeout(() => {
|
|
toast.classList.add('animate-fade-out');
|
|
setTimeout(() => toast.remove(), 300);
|
|
}, 3000);
|
|
}
|
|
};
|
|
|
|
// Exportar para uso global
|
|
window.LayoutManager = LayoutManager;
|