feat(catalog): full vehicle selector flow in brand catalog
Brand catalog now follows the same navigation as the regular catalog: 1. Brands -> 2. Models -> 3. Years -> 4. Engines -> 5. Categories -> 6. Parts Backend: - Add /mye-parts endpoint for MYE-specific parts with category filter - Uses existing /models, /years, /engines, /categories endpoints Frontend: - Complete rewrite of brand-catalog.js with breadcrumb navigation - State machine: brands -> models -> years -> engines -> categories -> parts - Search and pagination preserved at parts level - Breadcrumb allows jumping back to any previous step
This commit is contained in:
@@ -763,3 +763,107 @@ def brand_parts():
|
|||||||
finally:
|
finally:
|
||||||
cur.close()
|
cur.close()
|
||||||
return _with_conns(_query)
|
return _with_conns(_query)
|
||||||
|
|
||||||
|
|
||||||
|
@catalog_bp.route('/mye-parts', methods=['GET'])
|
||||||
|
@require_auth('catalog.view')
|
||||||
|
def mye_parts():
|
||||||
|
"""Return parts for a specific MYE + category (brand-catalog flow).
|
||||||
|
|
||||||
|
Skips the group/subgroup level and goes directly from category to parts.
|
||||||
|
"""
|
||||||
|
mye_id = request.args.get('mye_id', type=int)
|
||||||
|
category_id = request.args.get('category_id', type=int)
|
||||||
|
search = request.args.get('search', '').strip()
|
||||||
|
limit = request.args.get('limit', 50, type=int)
|
||||||
|
offset = request.args.get('offset', 0, type=int)
|
||||||
|
|
||||||
|
if not mye_id:
|
||||||
|
return jsonify({'error': 'mye_id required'}), 400
|
||||||
|
|
||||||
|
def _query(master, tenant, branch_id):
|
||||||
|
cur = master.cursor()
|
||||||
|
try:
|
||||||
|
# Build dynamic filters
|
||||||
|
cat_filter = ""
|
||||||
|
search_filter = ""
|
||||||
|
params = [mye_id]
|
||||||
|
|
||||||
|
if category_id:
|
||||||
|
cat_filter = "AND pc.id_part_category = %s"
|
||||||
|
params.append(category_id)
|
||||||
|
|
||||||
|
if search:
|
||||||
|
search_filter = "AND (p.oem_part_number ILIKE %s OR COALESCE(NULLIF(p.name_es, ''), p.name_part) ILIKE %s)"
|
||||||
|
like_term = f"%{search}%"
|
||||||
|
params.extend([like_term, like_term])
|
||||||
|
|
||||||
|
# Get parts
|
||||||
|
query_params = list(params)
|
||||||
|
cur.execute(f"""
|
||||||
|
SELECT DISTINCT p.id_part, p.oem_part_number,
|
||||||
|
COALESCE(NULLIF(p.name_es, ''), p.name_part) as name,
|
||||||
|
pg.id_part_group, pg.name_part_group,
|
||||||
|
pc.id_part_category, pc.name_part_category
|
||||||
|
FROM vehicle_parts vp
|
||||||
|
JOIN parts p ON p.id_part = vp.part_id
|
||||||
|
JOIN part_groups pg ON pg.id_part_group = p.group_id
|
||||||
|
JOIN part_categories pc ON pc.id_part_category = pg.category_id
|
||||||
|
WHERE vp.model_year_engine_id = %s
|
||||||
|
{cat_filter}
|
||||||
|
{search_filter}
|
||||||
|
ORDER BY p.id_part
|
||||||
|
LIMIT %s OFFSET %s
|
||||||
|
""", query_params + [limit, offset])
|
||||||
|
|
||||||
|
part_rows = cur.fetchall()
|
||||||
|
part_ids = [r[0] for r in part_rows]
|
||||||
|
|
||||||
|
# Count total
|
||||||
|
cur.execute(f"""
|
||||||
|
SELECT COUNT(DISTINCT p.id_part)
|
||||||
|
FROM vehicle_parts vp
|
||||||
|
JOIN parts p ON p.id_part = vp.part_id
|
||||||
|
JOIN part_groups pg ON pg.id_part_group = p.group_id
|
||||||
|
JOIN part_categories pc ON pc.id_part_category = pg.category_id
|
||||||
|
WHERE vp.model_year_engine_id = %s
|
||||||
|
{cat_filter}
|
||||||
|
{search_filter}
|
||||||
|
""", params)
|
||||||
|
total = cur.fetchone()[0]
|
||||||
|
|
||||||
|
# Enrich with local stock if available
|
||||||
|
local_stock = {}
|
||||||
|
if tenant and part_ids:
|
||||||
|
try:
|
||||||
|
from services.catalog_service import _get_local_stock_bulk
|
||||||
|
local_stock = _get_local_stock_bulk(tenant, part_ids)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
items = []
|
||||||
|
for r in part_rows:
|
||||||
|
part_id = r[0]
|
||||||
|
stock_info = local_stock.get(part_id, {})
|
||||||
|
items.append({
|
||||||
|
'id': part_id,
|
||||||
|
'oem_part_number': r[1],
|
||||||
|
'name': r[2],
|
||||||
|
'group': {'id': r[3], 'name': r[4]},
|
||||||
|
'category': {'id': r[5], 'name': r[6]},
|
||||||
|
'local_stock': stock_info.get('stock', 0),
|
||||||
|
'local_price': stock_info.get('price', None),
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'mye_id': mye_id,
|
||||||
|
'category_id': category_id,
|
||||||
|
'search': search,
|
||||||
|
'items': items,
|
||||||
|
'total': total,
|
||||||
|
'limit': limit,
|
||||||
|
'offset': offset,
|
||||||
|
})
|
||||||
|
finally:
|
||||||
|
cur.close()
|
||||||
|
return _with_conns(_query)
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
(function() {
|
(function() {
|
||||||
const BrandCatalog = {
|
const BrandCatalog = {
|
||||||
currentBrand: null,
|
|
||||||
currentCategory: null,
|
|
||||||
state: 'brands',
|
state: 'brands',
|
||||||
_lastItems: [],
|
|
||||||
_allBrands: [],
|
_allBrands: [],
|
||||||
|
_lastItems: [],
|
||||||
_offset: 0,
|
_offset: 0,
|
||||||
_limit: 50,
|
_limit: 50,
|
||||||
_total: 0,
|
_total: 0,
|
||||||
|
|
||||||
|
// Navigation state
|
||||||
|
nav: {
|
||||||
|
brand: null,
|
||||||
|
brandId: null,
|
||||||
|
model: null,
|
||||||
|
modelId: null,
|
||||||
|
year: null,
|
||||||
|
yearId: null,
|
||||||
|
engine: null,
|
||||||
|
myeId: null,
|
||||||
|
category: null,
|
||||||
|
categoryId: null
|
||||||
|
},
|
||||||
|
|
||||||
el: function(id) { return document.getElementById(id); },
|
el: function(id) { return document.getElementById(id); },
|
||||||
|
|
||||||
_getToken: function() {
|
_getToken: function() {
|
||||||
@@ -49,11 +61,10 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
reset: function() {
|
reset: function() {
|
||||||
this.currentBrand = null;
|
|
||||||
this.currentCategory = null;
|
|
||||||
this.state = 'brands';
|
this.state = 'brands';
|
||||||
this._lastItems = [];
|
this.nav = { brand: null, brandId: null, model: null, modelId: null, year: null, yearId: null, engine: null, myeId: null, category: null, categoryId: null };
|
||||||
this._allBrands = [];
|
this._allBrands = [];
|
||||||
|
this._lastItems = [];
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
this._total = 0;
|
this._total = 0;
|
||||||
this.el('brandCatalogSearch').innerHTML = '';
|
this.el('brandCatalogSearch').innerHTML = '';
|
||||||
@@ -75,10 +86,32 @@
|
|||||||
this.el('brandCatalogBreadcrumb').innerHTML = html;
|
this.el('brandCatalogBreadcrumb').innerHTML = html;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
buildBreadcrumb: function() {
|
||||||
|
var parts = [];
|
||||||
|
parts.push('<a href="javascript:void(0)" onclick="BrandCatalog.loadBrands()" style="color:var(--color-primary);text-decoration:none;">Marcas</a>');
|
||||||
|
if (this.nav.brand) {
|
||||||
|
parts.push('<a href="javascript:void(0)" onclick="BrandCatalog.selectBrand(' + JSON.stringify(this.nav.brand) + ',' + this.nav.brandId + ')" style="color:var(--color-primary);text-decoration:none;">' + escapeHtml(this.nav.brand) + '</a>');
|
||||||
|
}
|
||||||
|
if (this.nav.model) {
|
||||||
|
parts.push('<a href="javascript:void(0)" onclick="BrandCatalog.selectModel(' + this.nav.modelId + ',' + JSON.stringify(this.nav.model) + ')" style="color:var(--color-primary);text-decoration:none;">' + escapeHtml(this.nav.model) + '</a>');
|
||||||
|
}
|
||||||
|
if (this.nav.year) {
|
||||||
|
parts.push('<a href="javascript:void(0)" onclick="BrandCatalog.selectYear(' + this.nav.yearId + ',' + this.nav.year + ')" style="color:var(--color-primary);text-decoration:none;">' + this.nav.year + '</a>');
|
||||||
|
}
|
||||||
|
if (this.nav.engine) {
|
||||||
|
parts.push('<a href="javascript:void(0)" onclick="BrandCatalog.selectEngine(' + this.nav.myeId + ',' + JSON.stringify(this.nav.engine) + ')" style="color:var(--color-primary);text-decoration:none;">' + escapeHtml(this.nav.engine) + '</a>');
|
||||||
|
}
|
||||||
|
if (this.nav.category) {
|
||||||
|
parts.push('<strong>' + escapeHtml(this.nav.category) + '</strong>');
|
||||||
|
}
|
||||||
|
this.setBreadcrumb(parts.join(' › '));
|
||||||
|
},
|
||||||
|
|
||||||
// ---------- BRANDS ----------
|
// ---------- BRANDS ----------
|
||||||
loadBrands: function() {
|
loadBrands: function() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
this.state = 'brands';
|
this.state = 'brands';
|
||||||
|
this.reset();
|
||||||
this.setBreadcrumb('<strong>Marcas de vehiculo</strong>');
|
this.setBreadcrumb('<strong>Marcas de vehiculo</strong>');
|
||||||
this.setSearch(
|
this.setSearch(
|
||||||
'<input type="text" id="brandSearchInput" placeholder="Buscar marca..." ' +
|
'<input type="text" id="brandSearchInput" placeholder="Buscar marca..." ' +
|
||||||
@@ -111,9 +144,8 @@
|
|||||||
renderBrandList: function(brands) {
|
renderBrandList: function(brands) {
|
||||||
var html = '';
|
var html = '';
|
||||||
brands.forEach(function(b) {
|
brands.forEach(function(b) {
|
||||||
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectBrand(' + JSON.stringify(b.name) + ')">' +
|
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectBrand(' + JSON.stringify(b.name) + ',' + b.id + ')">' +
|
||||||
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(b.name) + '</div>' +
|
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(b.name) + '</div>' +
|
||||||
'<div style="font-size:var(--text-body-sm);color:var(--color-text-muted);">' + (b.part_count || 0) + ' refacciones</div>' +
|
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
this.setContent(html);
|
this.setContent(html);
|
||||||
@@ -131,21 +163,20 @@
|
|||||||
this.renderBrandList(filtered);
|
this.renderBrandList(filtered);
|
||||||
},
|
},
|
||||||
|
|
||||||
selectBrand: function(brandName) {
|
selectBrand: function(brandName, brandId) {
|
||||||
this.currentBrand = brandName;
|
this.nav.brand = brandName;
|
||||||
this.loadCategories(brandName);
|
this.nav.brandId = brandId;
|
||||||
|
this.loadModels(brandId);
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---------- CATEGORIES ----------
|
// ---------- MODELS ----------
|
||||||
loadCategories: function(brandName) {
|
loadModels: function(brandId) {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
this.state = 'categories';
|
this.state = 'models';
|
||||||
this.setSearch('');
|
this.setSearch('');
|
||||||
this.setBreadcrumb(
|
this.buildBreadcrumb();
|
||||||
'<a href="javascript:void(0)" onclick="BrandCatalog.loadBrands()" style="color:var(--color-primary);text-decoration:none;">Marcas</a> › <strong>' + escapeHtml(brandName) + '</strong>'
|
|
||||||
);
|
|
||||||
var self = this;
|
var self = this;
|
||||||
fetch('/pos/api/catalog/brand-categories?brand=' + encodeURIComponent(brandName), { headers: this._headers() })
|
fetch('/pos/api/catalog/models?brand_id=' + encodeURIComponent(brandId), { headers: this._headers() })
|
||||||
.then(function(r) {
|
.then(function(r) {
|
||||||
if (!self._checkAuth(r)) return null;
|
if (!self._checkAuth(r)) return null;
|
||||||
return r.json();
|
return r.json();
|
||||||
@@ -153,20 +184,137 @@
|
|||||||
.then(function(data) {
|
.then(function(data) {
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
self.loading(false);
|
self.loading(false);
|
||||||
if (!data.categories || !data.categories.length) {
|
var models = data.data || [];
|
||||||
self.setContent(
|
if (!models.length) {
|
||||||
'<div style="grid-column:1/-1;text-align:center;padding:var(--space-8);">' +
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-text-muted);">No se encontraron modelos.</p>');
|
||||||
'<p style="color:var(--color-text-muted);font-size:var(--text-body-lg);">No se encontraron categorias para <strong>' + escapeHtml(brandName) + '</strong>.</p>' +
|
|
||||||
'<button class="btn btn--primary" style="margin-top:var(--space-3);" onclick="BrandCatalog.loadBrands()">Volver a marcas</button>' +
|
|
||||||
'</div>'
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var html = '';
|
var html = '';
|
||||||
data.categories.forEach(function(c) {
|
models.forEach(function(m) {
|
||||||
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectCategory(' + c.id + ', ' + JSON.stringify(c.name) + ')">' +
|
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectModel(' + m.id_model + ',' + JSON.stringify(m.display_name || m.name_model) + ')">' +
|
||||||
|
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(m.display_name || m.name_model) + '</div>' +
|
||||||
|
'</div>';
|
||||||
|
});
|
||||||
|
self.setContent(html);
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
self.loading(false);
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-error);">Error al cargar modelos: ' + escapeHtml(err.message) + '</p>');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
selectModel: function(modelId, modelName) {
|
||||||
|
this.nav.model = modelName;
|
||||||
|
this.nav.modelId = modelId;
|
||||||
|
this.loadYears(modelId);
|
||||||
|
},
|
||||||
|
|
||||||
|
// ---------- YEARS ----------
|
||||||
|
loadYears: function(modelId) {
|
||||||
|
this.loading(true);
|
||||||
|
this.state = 'years';
|
||||||
|
this.setSearch('');
|
||||||
|
this.buildBreadcrumb();
|
||||||
|
var self = this;
|
||||||
|
fetch('/pos/api/catalog/years?model_id=' + encodeURIComponent(modelId), { headers: this._headers() })
|
||||||
|
.then(function(r) {
|
||||||
|
if (!self._checkAuth(r)) return null;
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (!data) return;
|
||||||
|
self.loading(false);
|
||||||
|
var years = data.data || [];
|
||||||
|
if (!years.length) {
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-text-muted);">No se encontraron años.</p>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var html = '';
|
||||||
|
years.forEach(function(y) {
|
||||||
|
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectYear(' + y.id_year + ',' + y.year_car + ')">' +
|
||||||
|
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + y.year_car + '</div>' +
|
||||||
|
'</div>';
|
||||||
|
});
|
||||||
|
self.setContent(html);
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
self.loading(false);
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-error);">Error al cargar años: ' + escapeHtml(err.message) + '</p>');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
selectYear: function(yearId, yearCar) {
|
||||||
|
this.nav.year = yearCar;
|
||||||
|
this.nav.yearId = yearId;
|
||||||
|
this.loadEngines(this.nav.modelId, yearId);
|
||||||
|
},
|
||||||
|
|
||||||
|
// ---------- ENGINES ----------
|
||||||
|
loadEngines: function(modelId, yearId) {
|
||||||
|
this.loading(true);
|
||||||
|
this.state = 'engines';
|
||||||
|
this.setSearch('');
|
||||||
|
this.buildBreadcrumb();
|
||||||
|
var self = this;
|
||||||
|
fetch('/pos/api/catalog/engines?model_id=' + encodeURIComponent(modelId) + '&year_id=' + encodeURIComponent(yearId), { headers: this._headers() })
|
||||||
|
.then(function(r) {
|
||||||
|
if (!self._checkAuth(r)) return null;
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (!data) return;
|
||||||
|
self.loading(false);
|
||||||
|
var engines = data.data || [];
|
||||||
|
if (!engines.length) {
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-text-muted);">No se encontraron motores.</p>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var html = '';
|
||||||
|
engines.forEach(function(e) {
|
||||||
|
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectEngine(' + e.id_mye + ',' + JSON.stringify(e.name_engine) + ')">' +
|
||||||
|
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(e.name_engine) + '</div>' +
|
||||||
|
'<div style="font-size:var(--text-body-sm);color:var(--color-text-muted);">' + escapeHtml(e.trim_level || '') + '</div>' +
|
||||||
|
'</div>';
|
||||||
|
});
|
||||||
|
self.setContent(html);
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
self.loading(false);
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-error);">Error al cargar motores: ' + escapeHtml(err.message) + '</p>');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
selectEngine: function(myeId, engineName) {
|
||||||
|
this.nav.engine = engineName;
|
||||||
|
this.nav.myeId = myeId;
|
||||||
|
this.loadCategories(myeId);
|
||||||
|
},
|
||||||
|
|
||||||
|
// ---------- CATEGORIES ----------
|
||||||
|
loadCategories: function(myeId) {
|
||||||
|
this.loading(true);
|
||||||
|
this.state = 'categories';
|
||||||
|
this.setSearch('');
|
||||||
|
this.buildBreadcrumb();
|
||||||
|
var self = this;
|
||||||
|
fetch('/pos/api/catalog/categories?mye_id=' + encodeURIComponent(myeId) + '&mode=oem', { headers: this._headers() })
|
||||||
|
.then(function(r) {
|
||||||
|
if (!self._checkAuth(r)) return null;
|
||||||
|
return r.json();
|
||||||
|
})
|
||||||
|
.then(function(data) {
|
||||||
|
if (!data) return;
|
||||||
|
self.loading(false);
|
||||||
|
var categories = data.data || [];
|
||||||
|
if (!categories.length) {
|
||||||
|
self.setContent('<p style="grid-column:1/-1;text-align:center;color:var(--color-text-muted);">No se encontraron categorias.</p>');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var html = '';
|
||||||
|
categories.forEach(function(c) {
|
||||||
|
html += '<div class="catalog-category-card" onclick="BrandCatalog.selectCategory(' + c.id_part_category + ',' + JSON.stringify(c.name) + ')">' +
|
||||||
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(c.name) + '</div>' +
|
'<div style="font-size:var(--text-h4);font-family:var(--font-heading);margin-bottom:4px;">' + escapeHtml(c.name) + '</div>' +
|
||||||
'<div style="font-size:var(--text-body-sm);color:var(--color-text-muted);">' + c.part_count + ' refacciones</div>' +
|
'<div style="font-size:var(--text-body-sm);color:var(--color-text-muted);">' + (c.part_count || 0) + ' refacciones</div>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
self.setContent(html);
|
self.setContent(html);
|
||||||
@@ -178,20 +326,17 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
selectCategory: function(catId, catName) {
|
selectCategory: function(catId, catName) {
|
||||||
this.currentCategory = { id: catId, name: catName };
|
this.nav.category = catName;
|
||||||
|
this.nav.categoryId = catId;
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
this.loadParts(this.currentBrand, catId, '');
|
this.loadParts(this.nav.myeId, catId, '');
|
||||||
},
|
},
|
||||||
|
|
||||||
// ---------- PARTS ----------
|
// ---------- PARTS ----------
|
||||||
loadParts: function(brandName, categoryId, searchTerm) {
|
loadParts: function(myeId, categoryId, searchTerm) {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
this.state = 'parts';
|
this.state = 'parts';
|
||||||
this.setBreadcrumb(
|
this.buildBreadcrumb();
|
||||||
'<a href="javascript:void(0)" onclick="BrandCatalog.loadBrands()" style="color:var(--color-primary);text-decoration:none;">Marcas</a> › ' +
|
|
||||||
'<a href="javascript:void(0)" onclick="BrandCatalog.selectBrand(' + JSON.stringify(brandName) + ')" style="color:var(--color-primary);text-decoration:none;">' + escapeHtml(brandName) + '</a> › ' +
|
|
||||||
'<strong>' + escapeHtml(this.currentCategory.name) + '</strong>'
|
|
||||||
);
|
|
||||||
this.setSearch(
|
this.setSearch(
|
||||||
'<div style="display:flex;gap:var(--space-2);flex-wrap:wrap;align-items:center;">' +
|
'<div style="display:flex;gap:var(--space-2);flex-wrap:wrap;align-items:center;">' +
|
||||||
'<input type="text" id="partsSearchInput" placeholder="Buscar refaccion..." value="' + escapeHtml(searchTerm || '') + '" ' +
|
'<input type="text" id="partsSearchInput" placeholder="Buscar refaccion..." value="' + escapeHtml(searchTerm || '') + '" ' +
|
||||||
@@ -202,7 +347,7 @@
|
|||||||
'<button class="btn btn--secondary btn--sm" onclick="BrandCatalog.clearPartsSearch()">Limpiar</button>' +
|
'<button class="btn btn--secondary btn--sm" onclick="BrandCatalog.clearPartsSearch()">Limpiar</button>' +
|
||||||
'</div>'
|
'</div>'
|
||||||
);
|
);
|
||||||
var url = '/pos/api/catalog/brand-parts?brand=' + encodeURIComponent(brandName) + '&category_id=' + encodeURIComponent(categoryId) +
|
var url = '/pos/api/catalog/mye-parts?mye_id=' + encodeURIComponent(myeId) + '&category_id=' + encodeURIComponent(categoryId) +
|
||||||
'&limit=' + this._limit + '&offset=' + this._offset;
|
'&limit=' + this._limit + '&offset=' + this._offset;
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
url += '&search=' + encodeURIComponent(searchTerm);
|
url += '&search=' + encodeURIComponent(searchTerm);
|
||||||
@@ -219,11 +364,7 @@
|
|||||||
self._lastItems = data.items || [];
|
self._lastItems = data.items || [];
|
||||||
self._total = data.total || 0;
|
self._total = data.total || 0;
|
||||||
self._offset = data.offset || 0;
|
self._offset = data.offset || 0;
|
||||||
if (!data.items || !data.items.length) {
|
self.renderPartsList(data.items || [], searchTerm);
|
||||||
self.renderPartsList([], searchTerm);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.renderPartsList(data.items, searchTerm);
|
|
||||||
})
|
})
|
||||||
.catch(function(err) {
|
.catch(function(err) {
|
||||||
self.loading(false);
|
self.loading(false);
|
||||||
@@ -236,7 +377,7 @@
|
|||||||
if (!items.length) {
|
if (!items.length) {
|
||||||
html += '<div style="grid-column:1/-1;text-align:center;padding:var(--space-8);">' +
|
html += '<div style="grid-column:1/-1;text-align:center;padding:var(--space-8);">' +
|
||||||
'<p style="color:var(--color-text-muted);font-size:var(--text-body-lg);">No se encontraron refacciones.</p>' +
|
'<p style="color:var(--color-text-muted);font-size:var(--text-body-lg);">No se encontraron refacciones.</p>' +
|
||||||
'<button class="btn btn--primary" style="margin-top:var(--space-3);" onclick="BrandCatalog.loadCategories(' + JSON.stringify(this.currentBrand) + ')">Volver a categorias</button>' +
|
'<button class="btn btn--primary" style="margin-top:var(--space-3);" onclick="BrandCatalog.loadCategories(' + this.nav.myeId + ')">Volver a categorias</button>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
this.setContent(html);
|
this.setContent(html);
|
||||||
return;
|
return;
|
||||||
@@ -286,12 +427,12 @@
|
|||||||
|
|
||||||
searchParts: function(term) {
|
searchParts: function(term) {
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
this.loadParts(this.currentBrand, this.currentCategory.id, term);
|
this.loadParts(this.nav.myeId, this.nav.categoryId, term);
|
||||||
},
|
},
|
||||||
|
|
||||||
clearPartsSearch: function() {
|
clearPartsSearch: function() {
|
||||||
this._offset = 0;
|
this._offset = 0;
|
||||||
this.loadParts(this.currentBrand, this.currentCategory.id, '');
|
this.loadParts(this.nav.myeId, this.nav.categoryId, '');
|
||||||
},
|
},
|
||||||
|
|
||||||
goToPage: function(newOffset) {
|
goToPage: function(newOffset) {
|
||||||
@@ -299,7 +440,7 @@
|
|||||||
this._offset = newOffset;
|
this._offset = newOffset;
|
||||||
var searchInput = document.getElementById('partsSearchInput');
|
var searchInput = document.getElementById('partsSearchInput');
|
||||||
var term = searchInput ? searchInput.value : '';
|
var term = searchInput ? searchInput.value : '';
|
||||||
this.loadParts(this.currentBrand, this.currentCategory.id, term);
|
this.loadParts(this.nav.myeId, this.nav.categoryId, term);
|
||||||
},
|
},
|
||||||
|
|
||||||
addToCart: function(partId, event) {
|
addToCart: function(partId, event) {
|
||||||
|
|||||||
@@ -308,6 +308,6 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="/pos/static/js/pwa-install.js" defer></script>
|
<script src="/pos/static/js/pwa-install.js" defer></script>
|
||||||
<script src="/pos/static/js/brand-catalog.js?v=3" defer></script>
|
<script src="/pos/static/js/brand-catalog.js?v=4" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user