fix(pos): reemplazar datos demo con datos reales del empleado logueado
- Nuevo app-init.js: auth check, inyecta nombre/rol real del empleado en sidebar, header, y status bar de TODAS las páginas - Eliminados 6 productos demo hardcodeados del catálogo - Sidebar muestra nombre real del usuario logueado - Links de navegación marcan la página activa correctamente - Función posLogout() global para cerrar sesión Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
143
pos/static/js/app-init.js
Normal file
143
pos/static/js/app-init.js
Normal file
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* app-init.js — Shared initialization for all POS pages
|
||||
*
|
||||
* Handles:
|
||||
* 1. Auth check (redirect to login if no valid token)
|
||||
* 2. Set real employee name/role in sidebar and header
|
||||
* 3. Set navigation links as active based on current page
|
||||
* 4. Sidebar toggle for mobile
|
||||
*/
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// ─── Auth Check ───
|
||||
var token = localStorage.getItem('pos_token');
|
||||
if (!token) {
|
||||
window.location.href = '/pos/login';
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate token not expired
|
||||
try {
|
||||
var payload = JSON.parse(atob(token.split('.')[1]));
|
||||
if (payload.exp * 1000 < Date.now()) {
|
||||
localStorage.removeItem('pos_token');
|
||||
localStorage.removeItem('pos_employee');
|
||||
window.location.href = '/pos/login';
|
||||
return;
|
||||
}
|
||||
} catch(e) {
|
||||
localStorage.removeItem('pos_token');
|
||||
window.location.href = '/pos/login';
|
||||
return;
|
||||
}
|
||||
|
||||
// ─── Get employee info ───
|
||||
var employee = {};
|
||||
try {
|
||||
employee = JSON.parse(localStorage.getItem('pos_employee') || '{}');
|
||||
} catch(e) {}
|
||||
|
||||
var name = employee.name || payload.name || 'Usuario';
|
||||
var role = employee.role || payload.role || '';
|
||||
var roleLabels = {
|
||||
'owner': 'Dueño', 'admin': 'Administrador', 'cashier': 'Cajero',
|
||||
'warehouse': 'Almacén', 'accountant': 'Contador'
|
||||
};
|
||||
var roleLabel = roleLabels[role] || role;
|
||||
var initials = name.split(' ').map(function(p) { return p[0]; }).join('').toUpperCase().substring(0, 2);
|
||||
|
||||
// ─── Replace hardcoded names in sidebar ───
|
||||
// Sidebar user name
|
||||
document.querySelectorAll('.sidebar__user-name').forEach(function(el) {
|
||||
el.textContent = name;
|
||||
});
|
||||
// Sidebar user role
|
||||
document.querySelectorAll('.sidebar__user-role').forEach(function(el) {
|
||||
el.textContent = roleLabel;
|
||||
});
|
||||
// Sidebar user initials/avatar
|
||||
document.querySelectorAll('.sidebar__user-avatar, .sidebar__avatar').forEach(function(el) {
|
||||
el.textContent = initials;
|
||||
});
|
||||
|
||||
// Profile info in headers (catalog uses this pattern)
|
||||
document.querySelectorAll('.profile-info__name').forEach(function(el) {
|
||||
el.textContent = name;
|
||||
});
|
||||
document.querySelectorAll('.profile-info__role').forEach(function(el) {
|
||||
el.textContent = roleLabel;
|
||||
});
|
||||
|
||||
// Theme bar user labels
|
||||
document.querySelectorAll('.theme-bar__label').forEach(function(el) {
|
||||
if (el.textContent.indexOf('Usuario:') !== -1 || el.textContent.indexOf('Sucursal') !== -1) {
|
||||
el.textContent = 'Sucursal Principal — ' + name;
|
||||
}
|
||||
});
|
||||
|
||||
// Status bar user names
|
||||
document.querySelectorAll('.status-bar .user-name, .status-info span').forEach(function(el) {
|
||||
var text = el.textContent;
|
||||
// Replace common demo names
|
||||
['Hugo M.', 'Hugo García', 'J. Ramírez', 'José Ramírez', 'Carlos M.', 'Admin'].forEach(function(demo) {
|
||||
if (text.indexOf(demo) !== -1) {
|
||||
el.textContent = text.replace(demo, name);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Set active nav link ───
|
||||
var path = window.location.pathname;
|
||||
var navMap = {
|
||||
'/pos/dashboard': 'dashboard',
|
||||
'/pos/sale': 'pos',
|
||||
'/pos/catalog': 'catalogo',
|
||||
'/pos/inventory': 'inventario',
|
||||
'/pos/customers': 'clientes',
|
||||
'/pos/invoicing': 'facturacion',
|
||||
'/pos/accounting': 'contabilidad',
|
||||
'/pos/reports': 'reportes',
|
||||
'/pos/config': 'configuracion'
|
||||
};
|
||||
|
||||
document.querySelectorAll('.nav-item, .nav-link').forEach(function(link) {
|
||||
link.classList.remove('is-active', 'active');
|
||||
var href = link.getAttribute('href') || '';
|
||||
if (href === path) {
|
||||
link.classList.add('is-active');
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Logout ───
|
||||
window.posLogout = function() {
|
||||
localStorage.removeItem('pos_token');
|
||||
localStorage.removeItem('pos_employee');
|
||||
localStorage.removeItem('pos_tenant_id');
|
||||
localStorage.removeItem('pos_cart');
|
||||
window.location.href = '/pos/login';
|
||||
};
|
||||
|
||||
// Wire any logout buttons
|
||||
document.querySelectorAll('[data-action="logout"], .btn-logout, .logout-btn').forEach(function(btn) {
|
||||
btn.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
posLogout();
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Expose globally ───
|
||||
window.POS_USER = {
|
||||
name: name,
|
||||
role: role,
|
||||
roleLabel: roleLabel,
|
||||
initials: initials,
|
||||
token: token,
|
||||
tenantId: payload.tenant_id,
|
||||
employeeId: payload.employee_id,
|
||||
branchId: payload.branch_id,
|
||||
permissions: payload.permissions || []
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -2249,6 +2249,7 @@
|
||||
</main>
|
||||
</div><!-- /app-shell -->
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/accounting.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1890,206 +1890,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product grid -->
|
||||
<!-- Product grid — populated dynamically by catalog.js -->
|
||||
<div class="product-grid" id="productGrid" role="list" aria-label="Resultados del catálogo">
|
||||
|
||||
<!-- Card 1: Pastillas de Freno -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="5"/><circle cx="12" cy="12" r="1.5" fill="currentColor"/><path d="M12 3v2M12 19v2M3 12h2M19 12h2"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Frenos</div>
|
||||
<div class="product-card__name">Pastillas de Freno Delanteras Cerámicas</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: 04465-02260</div>
|
||||
<div class="product-card__brand">
|
||||
<span>Akebono</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">Japón</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2018–2022">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2018–2022
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$485.00</div>
|
||||
<div class="product-card__price-unit">MXN / juego</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Agregar Pastillas de Freno Delanteras al carrito">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Card 2: Amortiguador -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><line x1="12" y1="2" x2="12" y2="22"/><path d="M8 6h8M8 10h8M6 14h12M7 18h10"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Suspensión</div>
|
||||
<div class="product-card__name">Amortiguador Delantero Gas KYB Excel-G</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: 339175</div>
|
||||
<div class="product-card__brand">
|
||||
<span>KYB</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">Japón</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2014–2019">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2014–2019
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$1,250.00</div>
|
||||
<div class="product-card__price-unit">MXN / pieza</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Agregar Amortiguador KYB al carrito">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Card 3: Sensor de Oxígeno -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><path d="M12 22V12M12 12C12 8 8 6 8 6s4-2 4 2M12 12c0-4 4-6 4-6s-4-2-4 2"/><circle cx="12" cy="5" r="2"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-low" role="status" aria-label="Stock bajo">Últimas 3</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Eléctrico</div>
|
||||
<div class="product-card__name">Sensor de Oxígeno Aguas Arriba Denso</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: 234-4209</div>
|
||||
<div class="product-card__brand">
|
||||
<span>Denso</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">Japón</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2009–2019">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2009–2019
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$890.00</div>
|
||||
<div class="product-card__price-unit">MXN / pieza</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Agregar Sensor de Oxígeno Denso al carrito">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Card 4: Filtro de Aceite -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><path d="M4 4h16v4L12 20 4 8z"/><path d="M4 8h16"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Motor</div>
|
||||
<div class="product-card__name">Filtro de Aceite Motor Toyota Original</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: 90915-YZZE1</div>
|
||||
<div class="product-card__brand">
|
||||
<span>Toyota Genuine</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">OEM</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2014–2024">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2014–2024
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$145.00</div>
|
||||
<div class="product-card__price-unit">MXN / pieza</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Agregar Filtro de Aceite Toyota al carrito">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Card 5: Banda de Distribución Kit -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="7" cy="17" r="3"/><circle cx="17" cy="7" r="3"/><path d="M7 14V10a2 2 0 012-2h6"/><path d="M17 10v4a2 2 0 01-2 2H9"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-ok" role="status" aria-label="En stock">En stock</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Motor</div>
|
||||
<div class="product-card__name">Kit Banda de Distribución con Bomba de Agua Gates</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: TCK328B</div>
|
||||
<div class="product-card__brand">
|
||||
<span>Gates</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">EUA</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2009–2020">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2009–2020
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$2,380.00</div>
|
||||
<div class="product-card__price-unit">MXN / kit</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Agregar Kit Banda de Distribución Gates al carrito">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>
|
||||
Agregar
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<!-- Card 6: Disco de Freno -->
|
||||
<article class="product-card" role="listitem">
|
||||
<div class="product-card__image">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" aria-hidden="true"><circle cx="12" cy="12" r="9"/><circle cx="12" cy="12" r="4"/><path d="M12 3v3M12 18v3M3 12h3M18 12h3"/></svg>
|
||||
<span class="product-card__image-label" aria-hidden="true">IMG</span>
|
||||
<div class="stock-badge stock-out" role="status" aria-label="Sin stock">Agotado</div>
|
||||
</div>
|
||||
<div class="product-card__body">
|
||||
<div class="product-card__category">Frenos</div>
|
||||
<div class="product-card__name">Disco de Freno Ventilado Delantero Brembo</div>
|
||||
<div class="product-card__oem" title="Número OEM">OEM: 09.9807.11</div>
|
||||
<div class="product-card__brand">
|
||||
<span>Brembo</span>
|
||||
<div class="product-card__brand-dot" aria-hidden="true"></div>
|
||||
<span style="color:var(--color-text-muted);">Italia</span>
|
||||
</div>
|
||||
<div class="product-card__compatibility" aria-label="Compatible con Toyota Corolla 2014–2022">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><polyline points="20,6 9,17 4,12"/></svg>
|
||||
Compatible con: Toyota Corolla 2014–2022
|
||||
</div>
|
||||
</div>
|
||||
<div class="product-card__footer">
|
||||
<div class="product-card__pricing">
|
||||
<div class="product-card__price">$1,940.00</div>
|
||||
<div class="product-card__price-unit">MXN / pieza</div>
|
||||
</div>
|
||||
<button class="btn-add" aria-label="Producto agotado" disabled style="opacity:0.45;cursor:not-allowed;">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M4.93 4.93l14.14 14.14"/></svg>
|
||||
Agotado
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
<!-- Cards loaded from API -->
|
||||
|
||||
</div>
|
||||
<!-- /product-grid -->
|
||||
@@ -2334,6 +2137,7 @@
|
||||
<button class="banner__dismiss" onclick="document.getElementById('offlineBanner').style.display='none'" aria-label="Cerrar">×</button>
|
||||
</div>
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/catalog.js"></script>
|
||||
<script src="/pos/static/js/offline-banner.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -1820,6 +1820,7 @@
|
||||
</main>
|
||||
</div><!-- /app-shell -->
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/config.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -2144,6 +2144,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/customers.js"></script>
|
||||
<script src="/pos/static/js/offline-banner.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -1948,6 +1948,7 @@
|
||||
</div><!-- end app-shell -->
|
||||
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/dashboard.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -2522,6 +2522,7 @@
|
||||
<button class="banner__dismiss" onclick="document.getElementById('offlineBanner').style.display='none'" aria-label="Cerrar">×</button>
|
||||
</div>
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/inventory.js"></script>
|
||||
<script src="/pos/static/js/offline-banner.js"></script>
|
||||
</body>
|
||||
|
||||
@@ -2698,6 +2698,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/invoicing.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -1472,6 +1472,7 @@
|
||||
<!-- ================================================================
|
||||
JAVASCRIPT
|
||||
================================================================ -->
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/pos.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -2914,6 +2914,7 @@
|
||||
</div>
|
||||
<!-- End app-shell -->
|
||||
|
||||
<script src="/pos/static/js/app-init.js"></script>
|
||||
<script src="/pos/static/js/reports.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user