feat(catalog): brand search, parts pagination, and parts search
Backend: - Add 'search' param to /brand-parts endpoint (filters oem_part_number and name via ILIKE) - Keep count query accurate with search filter Frontend (brand-catalog.js): - Brand search input: filters 619 brands locally while typing - Parts pagination: Previous/Next buttons with page counter (50 per page) - Parts search within category: search input + Enter key triggers backend search - Visual polish: stock badges, empty-state messages, responsive layout - Loading states and breadcrumbs improved
This commit is contained in:
@@ -663,9 +663,10 @@ def brand_categories():
|
||||
@catalog_bp.route('/brand-parts', methods=['GET'])
|
||||
@require_auth('catalog.view')
|
||||
def brand_parts():
|
||||
"""Return parts for a given vehicle brand + category."""
|
||||
"""Return parts for a given vehicle brand + category, optionally filtered by search term."""
|
||||
brand = request.args.get('brand', '')
|
||||
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)
|
||||
|
||||
@@ -675,13 +676,22 @@ def brand_parts():
|
||||
def _query(master, tenant, branch_id):
|
||||
cur = master.cursor()
|
||||
try:
|
||||
# Get parts from the brand catalog
|
||||
# Build dynamic filters
|
||||
params = [brand]
|
||||
cat_filter = ""
|
||||
search_filter = ""
|
||||
|
||||
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 from the brand catalog
|
||||
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,
|
||||
@@ -693,9 +703,10 @@ def brand_parts():
|
||||
JOIN part_categories pc ON pc.id_part_category = pg.category_id
|
||||
WHERE pvp.name_brand = %s
|
||||
{cat_filter}
|
||||
{search_filter}
|
||||
ORDER BY p.id_part
|
||||
LIMIT %s OFFSET %s
|
||||
""", params + [limit, offset])
|
||||
""", query_params + [limit, offset])
|
||||
|
||||
part_rows = cur.fetchall()
|
||||
part_ids = [r[0] for r in part_rows]
|
||||
@@ -709,6 +720,7 @@ def brand_parts():
|
||||
JOIN part_categories pc ON pc.id_part_category = pg.category_id
|
||||
WHERE pvp.name_brand = %s
|
||||
{cat_filter}
|
||||
{search_filter}
|
||||
""", params)
|
||||
total = cur.fetchone()[0]
|
||||
|
||||
@@ -738,6 +750,7 @@ def brand_parts():
|
||||
return jsonify({
|
||||
'brand': brand,
|
||||
'category_id': category_id,
|
||||
'search': search,
|
||||
'items': items,
|
||||
'total': total,
|
||||
'limit': limit,
|
||||
|
||||
Reference in New Issue
Block a user