Add admin panel, enhanced search, Gonher import and expand API
- Add admin interface (admin.html, admin.js) for managing catalog data - Add enhanced search module with advanced filtering capabilities - Expand server.py with new API endpoints and admin functionality - Add Gonher catalog import scripts (import_gonher_catalog.py, import_gonher_complete.py) - Add demo data population script and sample CSV data - Update customer landing page and dashboard with UI improvements - Update database with enriched vehicle and parts data Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -503,16 +503,16 @@ class VehicleDashboard {
|
||||
const myeRecords = await myeRes.json();
|
||||
|
||||
// Merge mye_id into vehicles based on matching fields
|
||||
// Only keep vehicles that have a matching mye_id (i.e., have parts)
|
||||
this.allVehicles = vehicles.map(v => {
|
||||
const mye = myeRecords.find(m =>
|
||||
m.brand === v.brand &&
|
||||
m.model === v.model &&
|
||||
m.year === v.year &&
|
||||
m.engine === v.engine &&
|
||||
(m.trim_level === v.trim_level || (!m.trim_level && !v.trim_level) || (m.trim_level === 'unknown' && v.trim_level === 'unknown'))
|
||||
m.engine === v.engine
|
||||
);
|
||||
return { ...v, mye_id: mye ? mye.id : null };
|
||||
});
|
||||
}).filter(v => v.mye_id !== null); // Only show vehicles with parts
|
||||
this.filteredVehicles = [...this.allVehicles];
|
||||
|
||||
// Poblar filtros
|
||||
@@ -714,7 +714,79 @@ class VehicleDashboard {
|
||||
document.getElementById('filtersBar').classList.remove('visible');
|
||||
}
|
||||
|
||||
// Navigate to vehicle from search results
|
||||
async navigateToVehicle(myeId, brand, model, year) {
|
||||
// Set the state for breadcrumb navigation
|
||||
this.selectedBrand = brand;
|
||||
this.selectedModel = model;
|
||||
this.selectedYear = year;
|
||||
|
||||
// Add vehicle to allVehicles if not already there (for breadcrumb)
|
||||
if (!this.allVehicles.find(v => v.mye_id === myeId)) {
|
||||
this.allVehicles.push({
|
||||
mye_id: myeId,
|
||||
brand: brand,
|
||||
model: model,
|
||||
year: year
|
||||
});
|
||||
}
|
||||
|
||||
// Navigate to categories
|
||||
await this.goToCategories(myeId);
|
||||
}
|
||||
|
||||
// Navigate to vehicle and directly to a specific category
|
||||
async navigateToVehicleCategory(myeId, brand, model, year, categoryId) {
|
||||
// Set the state for breadcrumb navigation
|
||||
this.selectedBrand = brand;
|
||||
this.selectedModel = model;
|
||||
this.selectedYear = year;
|
||||
|
||||
// Add vehicle to allVehicles if not already there (for breadcrumb)
|
||||
if (!this.allVehicles.find(v => v.mye_id === myeId)) {
|
||||
this.allVehicles.push({
|
||||
mye_id: myeId,
|
||||
brand: brand,
|
||||
model: model,
|
||||
year: year
|
||||
});
|
||||
}
|
||||
|
||||
this.selectedVehicleId = myeId;
|
||||
|
||||
// Load categories if not available (needed for breadcrumb)
|
||||
if (this.allCategories.length === 0) {
|
||||
try {
|
||||
const response = await fetch('/api/categories');
|
||||
if (response.ok) {
|
||||
this.allCategories = await response.json();
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error loading categories:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate directly to the category's groups
|
||||
await this.goToGroups(categoryId);
|
||||
}
|
||||
|
||||
async goToCategories(myeId) {
|
||||
// Validate myeId before proceeding
|
||||
if (!myeId || myeId === 'null' || myeId === 'undefined') {
|
||||
const container = document.getElementById('mainContent');
|
||||
container.innerHTML = `
|
||||
<div class="empty-state">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<h4>Vehículo sin partes disponibles</h4>
|
||||
<p>Este vehículo no tiene partes registradas en el catálogo.</p>
|
||||
<button class="btn btn-back mt-3" onclick="dashboard.goToModels('${this.selectedBrand}')">
|
||||
<i class="fas fa-arrow-left"></i> Volver a modelos
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentView = 'categories';
|
||||
this.selectedVehicleId = myeId;
|
||||
this.selectedCategory = null;
|
||||
@@ -737,8 +809,8 @@ class VehicleDashboard {
|
||||
`;
|
||||
|
||||
try {
|
||||
// Get all categories (since we don't have vehicle-specific parts yet, show all categories)
|
||||
const response = await fetch('/api/categories');
|
||||
// Get vehicle-specific categories (only categories with parts for this vehicle)
|
||||
const response = await fetch(`/api/vehicles/${myeId}/categories`);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al cargar categorías');
|
||||
@@ -824,7 +896,15 @@ class VehicleDashboard {
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/categories/${categoryId}/groups`);
|
||||
// Use vehicle-specific endpoint when a vehicle is selected
|
||||
let url;
|
||||
if (this.selectedVehicleId) {
|
||||
url = `/api/vehicles/${this.selectedVehicleId}/groups?category_id=${categoryId}`;
|
||||
} else {
|
||||
url = `/api/categories/${categoryId}/groups`;
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al cargar grupos');
|
||||
@@ -921,15 +1001,23 @@ class VehicleDashboard {
|
||||
`;
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/parts?group_id=${groupId}`);
|
||||
// Use vehicle-specific endpoint when a vehicle is selected
|
||||
let url;
|
||||
if (this.selectedVehicleId) {
|
||||
url = `/api/vehicles/${this.selectedVehicleId}/parts?group_id=${groupId}`;
|
||||
} else {
|
||||
url = `/api/parts?group_id=${groupId}`;
|
||||
}
|
||||
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Error al cargar partes');
|
||||
}
|
||||
|
||||
const partsData = await response.json();
|
||||
// Handle paginated response
|
||||
this.allParts = partsData.data || partsData;
|
||||
// Handle both array response (vehicle parts) and paginated response
|
||||
this.allParts = Array.isArray(partsData) ? partsData : (partsData.data || partsData);
|
||||
this.displayParts();
|
||||
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user