feat: selector de region en catalogo publico (MX/USA/CA, Europa, Asia, Todos)
Filtra marcas por mercado regional. 4 opciones: - Mexico/USA/Canada (36 marcas) - Europa (27 marcas) - Asia (15 marcas) - Todos (546 marcas) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -87,6 +87,34 @@
|
||||
}
|
||||
.search-wrapper button:hover { background: var(--btn-primary-bg-hover); }
|
||||
|
||||
/* ── Region bar ── */
|
||||
.region-bar {
|
||||
background: var(--color-bg-elevated);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
padding: var(--space-2) 0;
|
||||
}
|
||||
.region-inner {
|
||||
max-width: var(--content-xl); margin: 0 auto;
|
||||
padding: 0 var(--space-6);
|
||||
display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap;
|
||||
}
|
||||
.region-label {
|
||||
font-size: var(--text-caption); font-weight: var(--font-weight-semibold);
|
||||
color: var(--color-text-muted); text-transform: uppercase;
|
||||
letter-spacing: var(--tracking-wider); margin-right: var(--space-2);
|
||||
}
|
||||
.region-btn {
|
||||
background: var(--btn-ghost-bg); border: 1px solid var(--btn-ghost-border);
|
||||
color: var(--btn-ghost-text); padding: var(--space-1) var(--space-3);
|
||||
border-radius: var(--radius-md); cursor: pointer; font-size: var(--text-caption);
|
||||
font-family: var(--font-body); transition: var(--transition-fast);
|
||||
}
|
||||
.region-btn:hover { background: var(--color-surface-2); color: var(--color-text-primary); }
|
||||
.region-btn.is-active {
|
||||
background: var(--color-primary-muted); color: var(--color-primary);
|
||||
border-color: var(--color-primary); font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
|
||||
/* ── Breadcrumb ── */
|
||||
.breadcrumb {
|
||||
max-width: var(--content-xl); margin: 0 auto;
|
||||
@@ -309,6 +337,17 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Country / Region selector -->
|
||||
<div class="region-bar">
|
||||
<div class="region-inner">
|
||||
<span class="region-label">Región:</span>
|
||||
<button class="region-btn is-active" data-region="north-america" onclick="setRegion('north-america')">🇲🇽 México, 🇺🇸 USA, 🇨🇦 Canadá</button>
|
||||
<button class="region-btn" data-region="europe" onclick="setRegion('europe')">🇪🇺 Europa</button>
|
||||
<button class="region-btn" data-region="asia" onclick="setRegion('asia')">🇯🇵 Asia</button>
|
||||
<button class="region-btn" data-region="all" onclick="setRegion('all')">🌐 Todos</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-bar">
|
||||
<div class="search-wrapper">
|
||||
<input type="text" id="searchInput" placeholder="Buscar por numero de parte o nombre..." autocomplete="off">
|
||||
|
||||
@@ -16,10 +16,22 @@
|
||||
engine: null, // {id_mye, name, trim}
|
||||
category: null, // {id, name}
|
||||
group: null, // {id, name}
|
||||
region: 'north-america',
|
||||
page: 1,
|
||||
totalPages: 1,
|
||||
};
|
||||
|
||||
// ── Region selector (global) ──
|
||||
window.setRegion = function (region) {
|
||||
state.region = region;
|
||||
document.querySelectorAll('.region-btn').forEach(function (b) {
|
||||
b.classList.toggle('is-active', b.dataset.region === region);
|
||||
});
|
||||
// Reload brands with new region
|
||||
state.brand = state.model = state.year = state.engine = state.category = state.group = null;
|
||||
loadBrands();
|
||||
};
|
||||
|
||||
var API = '/api/catalog';
|
||||
var content = document.getElementById('content');
|
||||
var breadcrumbEl = document.getElementById('breadcrumb');
|
||||
@@ -170,7 +182,7 @@
|
||||
state.level = 'brands';
|
||||
renderBreadcrumb();
|
||||
content.innerHTML = '<div class="loading">Cargando marcas...</div>';
|
||||
fetch(API + '/brands')
|
||||
fetch(API + '/brands?region=' + (state.region || 'north-america'))
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (brands) {
|
||||
var html = '<h2>Selecciona una Marca</h2><div class="nav-grid">';
|
||||
|
||||
@@ -220,20 +220,46 @@ def enhanced_search_js():
|
||||
# Public Catalog API — No auth required
|
||||
# ============================================================================
|
||||
|
||||
NORTH_AMERICA_BRANDS = (
|
||||
REGION_BRANDS = {
|
||||
'north-america': (
|
||||
'ACURA', 'AUDI', 'BMW', 'BUICK', 'CADILLAC', 'CHEVROLET', 'CHRYSLER',
|
||||
'DODGE', 'FIAT', 'FORD', 'GMC', 'HONDA', 'HYUNDAI', 'INFINITI',
|
||||
'JAGUAR', 'JEEP', 'KIA', 'LAND ROVER', 'LEXUS', 'LINCOLN', 'MAZDA',
|
||||
'MERCEDES-BENZ', 'MINI', 'MITSUBISHI', 'NISSAN', 'PEUGEOT', 'PORSCHE',
|
||||
'RAM', 'RENAULT', 'SEAT', 'SUBARU', 'SUZUKI', 'TESLA', 'TOYOTA',
|
||||
'VOLVO', 'VW',
|
||||
)
|
||||
),
|
||||
'europe': (
|
||||
'ALFA ROMEO', 'ASTON MARTIN', 'AUDI', 'BENTLEY', 'BMW', 'CITROEN',
|
||||
'DACIA', 'DS', 'FERRARI', 'FIAT', 'JAGUAR', 'LAMBORGHINI', 'LAND ROVER',
|
||||
'MASERATI', 'MERCEDES-BENZ', 'MINI', 'OPEL', 'PEUGEOT', 'PORSCHE',
|
||||
'RENAULT', 'ROLLS-ROYCE', 'SAAB', 'SEAT', 'SKODA', 'SMART',
|
||||
'VAUXHALL', 'VOLVO', 'VW',
|
||||
),
|
||||
'asia': (
|
||||
'ACURA', 'DAIHATSU', 'HONDA', 'HYUNDAI', 'INFINITI', 'ISUZU', 'KIA',
|
||||
'LEXUS', 'MAZDA', 'MITSUBISHI', 'NISSAN', 'SSANGYONG', 'SUBARU',
|
||||
'SUZUKI', 'TOYOTA',
|
||||
),
|
||||
}
|
||||
NORTH_AMERICA_BRANDS = REGION_BRANDS['north-america']
|
||||
|
||||
|
||||
@app.route('/api/catalog/brands')
|
||||
def api_catalog_brands():
|
||||
region = request.args.get('region', 'north-america')
|
||||
session = Session()
|
||||
try:
|
||||
if region == 'all':
|
||||
rows = session.execute(text("""
|
||||
SELECT DISTINCT b.id_brand, b.name_brand
|
||||
FROM brands b
|
||||
JOIN models m ON m.brand_id = b.id_brand
|
||||
JOIN model_year_engine mye ON mye.model_id = m.id_model
|
||||
ORDER BY b.name_brand
|
||||
""")).mappings().all()
|
||||
else:
|
||||
brand_list = list(REGION_BRANDS.get(region, NORTH_AMERICA_BRANDS))
|
||||
rows = session.execute(text("""
|
||||
SELECT DISTINCT b.id_brand, b.name_brand
|
||||
FROM brands b
|
||||
@@ -241,7 +267,7 @@ def api_catalog_brands():
|
||||
JOIN model_year_engine mye ON mye.model_id = m.id_model
|
||||
WHERE b.name_brand = ANY(:brands)
|
||||
ORDER BY b.name_brand
|
||||
"""), {'brands': list(NORTH_AMERICA_BRANDS)}).mappings().all()
|
||||
"""), {'brands': brand_list}).mappings().all()
|
||||
return jsonify([{'id_brand': r['id_brand'], 'name_brand': r['name_brand']} for r in rows])
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
Reference in New Issue
Block a user