diff --git a/pos/static/css/catalog.css b/pos/static/css/catalog.css
index b27c8a1..882186b 100644
--- a/pos/static/css/catalog.css
+++ b/pos/static/css/catalog.css
@@ -88,7 +88,8 @@
.breadcrumb__link:hover { color: var(--color-primary); }
.breadcrumb__sep { color: var(--color-text-disabled); }
.breadcrumb__current { color: var(--color-text-primary); font-weight: var(--font-weight-semibold); }
-
+ .breadcrumb__back { display: inline-flex; align-items: center; gap: 4px; padding: 2px 10px; background: transparent; border: 1px solid var(--color-border); border-radius: var(--radius-sm); color: var(--color-text-muted); font-size: var(--text-body-sm); cursor: pointer; transition: var(--transition-fast); }
+ .breadcrumb__back:hover { background: var(--color-primary-muted); color: var(--color-primary); }
.header-actions { display: flex; align-items: center; gap: var(--space-3); }
/* ── Catalog mode toggle (OEM / Local) ── */
@@ -362,13 +363,29 @@
.bodega-table th { text-align: left; font-weight: var(--font-weight-semibold); color: var(--color-text-muted); font-size: var(--text-caption); text-transform: uppercase; letter-spacing: var(--tracking-wider); padding: var(--space-2) var(--space-2); border-bottom: 1px solid var(--color-border); }
.bodega-table td { padding: var(--space-2); border-bottom: 1px solid var(--color-border); color: var(--color-text-primary); }
- /* Alternatives list */
+/* Alternatives list */
.alt-item { display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) 0; border-bottom: 1px solid var(--color-border); }
.alt-item:last-child { border-bottom: none; }
.alt-item__pn { font-weight: var(--font-weight-semibold); color: var(--color-text-primary); font-size: var(--text-body-sm); }
.alt-item__mfr { font-size: var(--text-caption); color: var(--color-text-muted); }
.alt-item__stock { font-size: var(--text-caption); }
+ /* Compatible vehicles pagination */
+ .compat-pager {
+ display: flex; align-items: center; justify-content: space-between;
+ gap: var(--space-2); margin-top: var(--space-4); padding-top: var(--space-3);
+ border-top: 1px solid var(--color-border);
+ }
+ .compat-pager__btn {
+ font-family: inherit; font-size: var(--text-caption); font-weight: var(--font-weight-semibold);
+ color: var(--color-text-primary); background: var(--color-surface-2);
+ border: 1px solid var(--color-border); border-radius: var(--radius-sm);
+ padding: var(--space-2) var(--space-3); cursor: pointer; white-space: nowrap;
+ }
+ .compat-pager__btn:hover:not(:disabled) { background: var(--color-surface-3, var(--color-surface-2)); }
+ .compat-pager__btn:disabled { opacity: 0.4; cursor: not-allowed; }
+ .compat-pager__info { font-size: var(--text-caption); color: var(--color-text-muted); text-align: center; flex: 1; }
+
/* Add to cart section */
.detail-footer {
padding: var(--space-4) var(--space-5); border-top: 1px solid var(--color-border);
diff --git a/pos/static/js/brand-catalog.js b/pos/static/js/brand-catalog.js
index 8b32ade..5eeac00 100644
--- a/pos/static/js/brand-catalog.js
+++ b/pos/static/js/brand-catalog.js
@@ -52,7 +52,7 @@
return;
}
this.el('brandCatalogOverlay').style.display = 'block';
- document.body.style.overflow = 'hidden';
+ //document.body.style.overflow = 'hidden';
this.loadBrands();
},
@@ -61,7 +61,7 @@
document.body.style.overflow = '';
this.reset();
},
-
+
reset: function() {
this.state = 'brands';
this.nav = { brand: null, brandId: null, model: null, modelId: null, modelVariantIds: null, year: null, yearId: null, engine: null, myeId: null, category: null, categoryId: null };
diff --git a/pos/static/js/catalog.js b/pos/static/js/catalog.js
index 4ebc938..32746ca 100644
--- a/pos/static/js/catalog.js
+++ b/pos/static/js/catalog.js
@@ -276,7 +276,20 @@
if (nav.nxPartType) parts.push({ label: nav.nxPartType.name, action: null });
else if (nav.partType) parts.push({ label: nav.partType.name, action: null });
+ //Botón para retroceder
+ var backAction = null;
+ if (parts.length > 1) {
+ var prev = parts[parts.length - 2];
+ backAction = prev ? prev.action : 'loadBrands';
+ }
+
var html = '';
+ //Botón para retroceder
+ if (backAction) {
+ html += '';
+ html += '|';
+ }
+ //--------
for (var i = 0; i < parts.length; i++) {
if (i > 0) html += '/';
if (i < parts.length - 1 && parts[i].action) {
@@ -303,6 +316,7 @@
else if (action === 'loadNxPartTypes') { resetNavFrom('part_types'); loadNexpartPartTypes(); }
});
});
+
}
function resetNav() {
@@ -1272,10 +1286,8 @@
html += '';
}
- // Compatibilities — deduplicate by (make, model, year, engine)
+// Compatibilities — deduplicate by (make, model, year, engine)
if (p.compatibilities && p.compatibilities.length) {
- html += '
';
- html += '
Vehiculos compatibles
';
var seenCompat = {};
var uniqCompat = [];
p.compatibilities.forEach(function(c) {
@@ -1284,22 +1296,69 @@
seenCompat[key] = true;
uniqCompat.push(c);
});
- var currentMake = '';
- uniqCompat.forEach(function(c) {
- if (c.make !== currentMake) {
- currentMake = c.make;
- html += '
' + esc(c.make) + '
';
- }
- html += '
' +
- esc(c.model) + ' ' + c.year + ' ' + esc(c.engine || '') + '
';
- });
+ html += '
';
+ html += '
Vehiculos compatibles
';
+ html += '
';
+ html += '';
html += '
';
+ compatFullList = uniqCompat;
+ } else {
+ compatFullList = [];
}
detailBody.innerHTML = html;
+
+ if (compatFullList.length) {
+ renderCompatPage(1);
+ }
});
}
+ // --- Pagination for "Vehiculos compatibles" ---
+ var compatFullList = [];
+ var compatPageSize = 15;
+ var compatCurrentPage = 1;
+
+ function renderCompatPage(page) {
+ var listEl = document.getElementById('compat-list');
+ var pagerEl = document.getElementById('compat-pager');
+ if (!listEl || !pagerEl) return;
+
+ var totalItems = compatFullList.length;
+ var totalPages = Math.max(1, Math.ceil(totalItems / compatPageSize));
+ page = Math.min(Math.max(1, page), totalPages);
+ compatCurrentPage = page;
+
+ var start = (page - 1) * compatPageSize;
+ var pageItems = compatFullList.slice(start, start + compatPageSize);
+
+ var listHtml = '';
+ var currentMake = '';
+ pageItems.forEach(function(c) {
+ if (c.make !== currentMake) {
+ currentMake = c.make;
+ listHtml += '
' + esc(c.make) + '
';
+ }
+ listHtml += '
' +
+ esc(c.model) + ' ' + c.year + ' ' + esc(c.engine || '') + '
';
+ });
+ listEl.innerHTML = listHtml;
+
+ if (totalPages > 1) {
+ pagerEl.innerHTML =
+ '' +
+ '' +
+ '';
+
+ var prevBtn = document.getElementById('compat-prev');
+ var nextBtn = document.getElementById('compat-next');
+ if (prevBtn) prevBtn.addEventListener('click', function () { renderCompatPage(compatCurrentPage - 1); });
+ if (nextBtn) nextBtn.addEventListener('click', function () { renderCompatPage(compatCurrentPage + 1); });
+ } else {
+ pagerEl.innerHTML = '';
+ }
+ }
+
function closeDetail() {
detailPanel.classList.remove('is-open');
detailOverlay.classList.remove('is-visible');
@@ -1802,20 +1861,22 @@
});
}
+
function vsYearChanged() {
var yearId = vsYear.value;
- vsBrand.innerHTML = '
';
- vsModel.innerHTML = '
';
- vsEngine.innerHTML = '
';
- vsBrand.disabled = true;
- vsModel.disabled = true;
- vsEngine.disabled = true;
- vsClear.style.display = yearId ? '' : 'none';
+ vsClear.style.display = (yearId || vsBrand.value || vsModel.value) ? '' : 'none';
- if (!yearId) return;
-
- // Load brands filtered by year
+ // Resetear marca solo si no hay nada seleccionado en ella
vsBrand.disabled = false;
+ vsEngine.innerHTML = '
';
+ vsEngine.disabled = true;
+
+ if (!yearId) {
+ //carga todo
+ vsLoadAllBrands();
+ return;
+ }
+ // Filtrar marcas por año
apiFetch(API + '/brands?year_id=' + yearId + '&mode=' + catalogMode).then(function (data) {
var brands = data.data || data;
if (!brands) return;
@@ -1823,21 +1884,39 @@
brands.map(function (b) {
return '
';
}).join('');
+ // si hay marca seleccionada despliega modelos
+ if (vsBrand.value) vsBrandChanged();
+ });
+ }
+ function vsLoadAllBrands() {
+ apiFetch(API + '/brands?mode=' + catalogMode).then(function (data) {
+ var brands = data.data || data;
+ if (!brands) return;
+ var current = vsBrand.value;
+ vsBrand.innerHTML = '
' +
+ brands.map(function (b) {
+ return '
';
+ }).join('');
+ if (current) vsBrand.value = current;
});
}
function vsBrandChanged() {
var brandId = vsBrand.value;
var yearId = vsYear.value;
+ vsClear.style.display = (yearId || brandId) ? '' : 'none';
+
vsModel.innerHTML = '
';
vsEngine.innerHTML = '
';
- vsModel.disabled = true;
+ vsModel.disabled = false; // cambio
vsEngine.disabled = true;
- if (!brandId) return;
+ if (!brandId) {
+ vsModel.disabled = true;
+ return;
+ }
- // Load models filtered by brand AND year
- vsModel.disabled = false;
+ // Cargar modelos con o sin año
apiFetch(API + '/models?brand_id=' + brandId + (yearId ? '&year_id=' + yearId : '')).then(function (data) {
var models = data.data || data;
if (!models) return;
@@ -1846,9 +1925,12 @@
var variants = (m.variant_ids || [m.id_model]).join(',');
return '
';
}).join('');
+ // si hay modelo seleccionado despliega año
+ if (vsModel.value) vsModelChanged();
});
}
+
function vsModelChanged() {
var modelId = vsModel.value;
var yearVal = vsYear.value;
@@ -1856,27 +1938,45 @@
var variantIds = selectedOption && selectedOption.dataset.variantIds
? selectedOption.dataset.variantIds.split(',').map(function(x){ return parseInt(x); })
: (modelId ? [parseInt(modelId)] : []);
+
vsEngine.innerHTML = '
';
vsEngine.disabled = true;
- if (!modelId || !yearVal || !variantIds.length) return;
+ if (!modelId || !variantIds.length) return;
- vsEngine.disabled = false;
- apiFetch(API + '/engines?model_id=' + variantIds.join(',') + '&year_id=' + yearVal).then(function (data) {
- var engines = data.data || data;
- if (!engines) return;
- vsEngine.innerHTML = '
' +
- engines.map(function (e) {
- var name = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
- var label = name + (e.trim_level ? ' (' + e.trim_level + ')' : '');
- return '
';
- }).join('');
- // If only 1 engine, auto-select
- if (engines.length === 1) {
- vsEngine.value = engines[0].id_mye;
- vsEngineChanged();
- }
- });
+ // Si hay año carga motores usando todas las variantes del modelo
+ if (yearVal) {
+ vsEngine.disabled = false;
+ apiFetch(API + '/engines?model_id=' + variantIds.join(',') + '&year_id=' + yearVal).then(function (data) {
+ var engines = data.data || data;
+ if (!engines) return;
+ vsEngine.innerHTML = '
' +
+ engines.map(function (e) {
+ var name = (e.name_engine && e.name_engine !== 'N/A') ? e.name_engine : 'Sin especificar';
+ var label = name + (e.trim_level ? ' (' + e.trim_level + ')' : '');
+ return '
';
+ }).join('');
+ if (engines.length === 1) {
+ vsEngine.value = engines[0].id_mye;
+ vsEngineChanged();
+ }
+ });
+ } else {
+ // Sin año: cargar categorías a nivel modelo
+ var brandId = vsBrand.value;
+ if (!brandId) return;
+ nav.brand = { id: parseInt(brandId), name: vsBrand.options[vsBrand.selectedIndex].text };
+ nav.model = { id: parseInt(modelId), name: vsModel.options[vsModel.selectedIndex].text };
+ nav.year = null;
+ nav.engine = null;
+ nav.level = 'categories';
+ pushNavState();
+ loadCategoriesForMode();
+ setTimeout(function () {
+ var body = document.getElementById('pageBody');
+ if (body) body.scrollIntoView({ behavior: 'smooth', block: 'start' });
+ }, 300);
+ }
}
function vsEngineChanged() {
diff --git a/pos/static/js/config.js b/pos/static/js/config.js
index 836dbd2..e61ca6f 100644
--- a/pos/static/js/config.js
+++ b/pos/static/js/config.js
@@ -57,7 +57,7 @@ const Config = (() => {
// -------------------------------------------------------------------------
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
- try { localStorage.setItem('nexus-theme', theme); } catch(e) {}
+ try { localStorage.setItem('pos_theme', theme); } catch(e) {}
document.querySelectorAll('.theme-btn').forEach(function(btn) {
btn.classList.toggle('is-active', btn.dataset.themeTarget === theme);
@@ -802,7 +802,7 @@ const Config = (() => {
// Restore theme
try {
- var saved = localStorage.getItem('nexus-theme');
+ var saved = localStorage.getItem('pos_theme');
if (saved === 'industrial' || saved === 'modern') {
setTheme(saved);
}
diff --git a/pos/static/js/dashboard.js b/pos/static/js/dashboard.js
index 96c8591..4309215 100644
--- a/pos/static/js/dashboard.js
+++ b/pos/static/js/dashboard.js
@@ -48,7 +48,7 @@ const Dashboard = (() => {
// -------------------------------------------------------------------------
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
- try { localStorage.setItem('nexus-theme', theme); } catch(e) {}
+ try { localStorage.setItem('pos_theme', theme); } catch(e) {}
const btnInd = document.getElementById('btn-industrial');
const btnMod = document.getElementById('btn-modern');
if (btnInd) btnInd.classList.toggle('active', theme === 'industrial');
@@ -689,7 +689,7 @@ const Dashboard = (() => {
// Restore theme
try {
- const saved = localStorage.getItem('nexus-theme');
+ const saved = localStorage.getItem('pos_theme');
if (saved === 'industrial' || saved === 'modern') {
setTheme(saved);
}
diff --git a/pos/static/js/reports.js b/pos/static/js/reports.js
index 7e78c2d..4b9cf3e 100644
--- a/pos/static/js/reports.js
+++ b/pos/static/js/reports.js
@@ -61,7 +61,7 @@ const Reports = (() => {
// -------------------------------------------------------------------------
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
- try { localStorage.setItem('nexus-theme', theme); } catch(e) {}
+ try { localStorage.setItem('pos_theme', theme); } catch(e) {}
var btnInd = document.getElementById('btn-industrial');
var btnMod = document.getElementById('btn-modern');
if (btnInd) btnInd.classList.toggle('is-active', theme === 'industrial');
@@ -745,7 +745,7 @@ const Reports = (() => {
// Restore theme
try {
- var saved = localStorage.getItem('nexus-theme') || 'industrial';
+ var saved = localStorage.getItem('pos_theme') || 'industrial';
setTheme(saved);
} catch(e) {}
diff --git a/pos/templates/catalog.html b/pos/templates/catalog.html
index c203525..911209d 100644
--- a/pos/templates/catalog.html
+++ b/pos/templates/catalog.html
@@ -145,14 +145,14 @@
›
-
›
-
+
@@ -302,7 +302,7 @@
-