Nuevo sidebar.js compartido que reemplaza el sidebar de cada pagina con una version consistente: - Misma estructura y orden de links en todas las paginas - Nombre y rol del empleado real (de POS_USER) - Link activo resaltado segun pagina actual - Boton de logout - Responsive (colapsa a iconos en <768px) - Elimina inconsistencias de estilo entre paginas Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
168 lines
7.2 KiB
JavaScript
168 lines
7.2 KiB
JavaScript
/**
|
|
* sidebar.js — Shared sidebar component for all POS pages
|
|
*
|
|
* Injects a consistent sidebar into any page that has a <aside class="sidebar"> or
|
|
* <div id="pos-sidebar-container">. Overrides the page's own sidebar content
|
|
* with a standardized navigation.
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
var employee = window.POS_USER || {};
|
|
var name = employee.name || 'Usuario';
|
|
var roleLabel = employee.roleLabel || '';
|
|
var initials = employee.initials || '?';
|
|
var currentPath = window.location.pathname;
|
|
|
|
var navItems = [
|
|
{ label: 'Dashboard', icon: '📊', href: '/pos/dashboard' },
|
|
{ label: 'Punto de Venta', icon: '💰', href: '/pos/sale' },
|
|
{ label: 'Catálogo', icon: '📦', href: '/pos/catalog' },
|
|
{ label: 'Inventario', icon: '📋', href: '/pos/inventory' },
|
|
{ label: 'Clientes', icon: '👥', href: '/pos/customers' },
|
|
{ label: 'Facturación', icon: '🧾', href: '/pos/invoicing' },
|
|
{ label: 'Contabilidad', icon: '📒', href: '/pos/accounting' },
|
|
{ label: 'Reportes', icon: '📈', href: '/pos/reports' },
|
|
{ label: 'Configuración', icon: '⚙️', href: '/pos/config' },
|
|
];
|
|
|
|
// Build sidebar HTML
|
|
var linksHtml = navItems.map(function(item) {
|
|
var isActive = currentPath === item.href;
|
|
var cls = 'pos-nav__item' + (isActive ? ' is-active' : '');
|
|
return '<a class="' + cls + '" href="' + item.href + '">'
|
|
+ '<span class="pos-nav__icon">' + item.icon + '</span>'
|
|
+ '<span class="pos-nav__label">' + item.label + '</span>'
|
|
+ '</a>';
|
|
}).join('');
|
|
|
|
var sidebarHtml = ''
|
|
+ '<div class="pos-sidebar__brand">'
|
|
+ ' <div class="pos-sidebar__logo">N</div>'
|
|
+ ' <div class="pos-sidebar__title">Nexus POS</div>'
|
|
+ '</div>'
|
|
+ '<nav class="pos-sidebar__nav">' + linksHtml + '</nav>'
|
|
+ '<div class="pos-sidebar__footer">'
|
|
+ ' <div class="pos-sidebar__user">'
|
|
+ ' <div class="pos-sidebar__avatar">' + initials + '</div>'
|
|
+ ' <div class="pos-sidebar__user-info">'
|
|
+ ' <div class="pos-sidebar__user-name">' + name + '</div>'
|
|
+ ' <div class="pos-sidebar__user-role">' + roleLabel + '</div>'
|
|
+ ' </div>'
|
|
+ ' </div>'
|
|
+ ' <button class="pos-sidebar__logout" onclick="posLogout()" title="Cerrar sesión">⏻</button>'
|
|
+ '</div>';
|
|
|
|
// Inject CSS
|
|
var css = document.createElement('style');
|
|
css.textContent = ''
|
|
+ '.pos-sidebar {'
|
|
+ ' position: fixed; top: 0; left: 0; bottom: 0; width: 220px;'
|
|
+ ' background: var(--color-bg-elevated, #161B22);'
|
|
+ ' border-right: 1px solid var(--color-border, #30363D);'
|
|
+ ' display: flex; flex-direction: column;'
|
|
+ ' z-index: 100; overflow-y: auto;'
|
|
+ ' font-family: var(--font-body, sans-serif);'
|
|
+ ' transition: background-color 0.3s;'
|
|
+ '}'
|
|
+ '.pos-sidebar__brand {'
|
|
+ ' display: flex; align-items: center; gap: 10px;'
|
|
+ ' padding: 16px 16px 12px; border-bottom: 1px solid var(--color-border, #30363D);'
|
|
+ '}'
|
|
+ '.pos-sidebar__logo {'
|
|
+ ' width: 36px; height: 36px; border-radius: 8px;'
|
|
+ ' background: var(--color-primary, #F5A623); color: #fff;'
|
|
+ ' display: flex; align-items: center; justify-content: center;'
|
|
+ ' font-weight: 800; font-size: 1.1rem;'
|
|
+ '}'
|
|
+ '.pos-sidebar__title {'
|
|
+ ' font-weight: 700; font-size: 1rem;'
|
|
+ ' color: var(--color-text-primary, #E6EDF3);'
|
|
+ '}'
|
|
+ '.pos-sidebar__nav {'
|
|
+ ' flex: 1; padding: 8px 8px; display: flex; flex-direction: column; gap: 2px;'
|
|
+ '}'
|
|
+ '.pos-nav__item {'
|
|
+ ' display: flex; align-items: center; gap: 10px;'
|
|
+ ' padding: 9px 12px; border-radius: 6px;'
|
|
+ ' color: var(--color-text-secondary, #8B949E);'
|
|
+ ' text-decoration: none; font-size: 0.88rem; font-weight: 500;'
|
|
+ ' transition: all 0.15s;'
|
|
+ '}'
|
|
+ '.pos-nav__item:hover {'
|
|
+ ' background: var(--color-bg-base, rgba(255,255,255,0.05));'
|
|
+ ' color: var(--color-text-primary, #E6EDF3);'
|
|
+ '}'
|
|
+ '.pos-nav__item.is-active {'
|
|
+ ' background: var(--color-primary, #F5A623);'
|
|
+ ' color: #fff; font-weight: 600;'
|
|
+ '}'
|
|
+ '.pos-nav__icon { font-size: 1rem; width: 20px; text-align: center; }'
|
|
+ '.pos-nav__label { white-space: nowrap; }'
|
|
+ '.pos-sidebar__footer {'
|
|
+ ' padding: 12px; border-top: 1px solid var(--color-border, #30363D);'
|
|
+ ' display: flex; align-items: center; justify-content: space-between;'
|
|
+ '}'
|
|
+ '.pos-sidebar__user {'
|
|
+ ' display: flex; align-items: center; gap: 8px;'
|
|
+ '}'
|
|
+ '.pos-sidebar__avatar {'
|
|
+ ' width: 32px; height: 32px; border-radius: 50%;'
|
|
+ ' background: var(--color-primary, #F5A623); color: #fff;'
|
|
+ ' display: flex; align-items: center; justify-content: center;'
|
|
+ ' font-size: 0.75rem; font-weight: 700;'
|
|
+ '}'
|
|
+ '.pos-sidebar__user-name {'
|
|
+ ' font-size: 0.82rem; font-weight: 600;'
|
|
+ ' color: var(--color-text-primary, #E6EDF3);'
|
|
+ '}'
|
|
+ '.pos-sidebar__user-role {'
|
|
+ ' font-size: 0.7rem; color: var(--color-text-muted, #6a6a7a);'
|
|
+ '}'
|
|
+ '.pos-sidebar__logout {'
|
|
+ ' background: none; border: 1px solid var(--color-border, #30363D);'
|
|
+ ' color: var(--color-text-muted, #6a6a7a); border-radius: 6px;'
|
|
+ ' padding: 6px 8px; cursor: pointer; font-size: 1rem;'
|
|
+ ' transition: all 0.15s;'
|
|
+ '}'
|
|
+ '.pos-sidebar__logout:hover {'
|
|
+ ' color: var(--color-error, #F85149);'
|
|
+ ' border-color: var(--color-error, #F85149);'
|
|
+ '}'
|
|
+ '/* Push main content right */'
|
|
+ '.pos-main-offset { margin-left: 220px; }'
|
|
+ '@media (max-width: 768px) {'
|
|
+ ' .pos-sidebar { width: 60px; }'
|
|
+ ' .pos-nav__label, .pos-sidebar__title,'
|
|
+ ' .pos-sidebar__user-info { display: none; }'
|
|
+ ' .pos-sidebar__footer { justify-content: center; }'
|
|
+ ' .pos-sidebar__user { justify-content: center; }'
|
|
+ ' .pos-main-offset { margin-left: 60px; }'
|
|
+ '}';
|
|
document.head.appendChild(css);
|
|
|
|
// Find or create sidebar container
|
|
// Strategy: replace existing sidebar content or create new one
|
|
var existingSidebar = document.querySelector('aside.sidebar, .sidebar, #sidebar');
|
|
|
|
if (existingSidebar) {
|
|
// Replace existing sidebar content
|
|
existingSidebar.className = 'pos-sidebar';
|
|
existingSidebar.innerHTML = sidebarHtml;
|
|
existingSidebar.removeAttribute('style');
|
|
} else {
|
|
// Create new sidebar
|
|
var sidebar = document.createElement('aside');
|
|
sidebar.className = 'pos-sidebar';
|
|
sidebar.innerHTML = sidebarHtml;
|
|
document.body.insertBefore(sidebar, document.body.firstChild);
|
|
}
|
|
|
|
// Add offset class to main content
|
|
var mainContent = document.querySelector('main, .main-content, #mainContent, .page-content');
|
|
if (mainContent) {
|
|
mainContent.classList.add('pos-main-offset');
|
|
}
|
|
|
|
})();
|