diff --git a/dashboard/admin.js b/dashboard/admin.js index 43da4ef..fcde228 100644 --- a/dashboard/admin.js +++ b/dashboard/admin.js @@ -849,9 +849,28 @@ async function openAftermarketModal(id = null) { openModal('aftermarketModal'); } -function editAftermarket(id) { - // TODO: Fetch and populate for edit - openAftermarketModal(id); +async function editAftermarket(id) { + await openAftermarketModal(id); + try { + const res = await fetch(`/api/aftermarket?search=&per_page=200`); + const data = await res.json(); + const items = data.data || data; + const item = items.find(a => a.id === id); + if (item) { + document.getElementById('aftermarketId').value = item.id; + document.getElementById('aftermarketPartNumber').value = item.part_number || ''; + document.getElementById('aftermarketName').value = item.name || ''; + document.getElementById('aftermarketNameEs').value = item.name_es || ''; + document.getElementById('aftermarketQuality').value = item.quality_tier || 'standard'; + document.getElementById('aftermarketPrice').value = item.price_usd || ''; + document.getElementById('aftermarketWarranty').value = item.warranty_months || ''; + if (item.oem_part_id) document.getElementById('aftermarketOemPart').value = item.oem_part_id; + if (item.manufacturer_id) document.getElementById('aftermarketManufacturer').value = item.manufacturer_id; + document.getElementById('aftermarketModalTitle').textContent = 'Editar Parte Aftermarket'; + } + } catch (e) { + console.error('Error loading aftermarket for edit:', e); + } } async function saveAftermarket() { diff --git a/dashboard/customer-landing.html b/dashboard/customer-landing.html index a0af19f..8e8da05 100644 --- a/dashboard/customer-landing.html +++ b/dashboard/customer-landing.html @@ -1277,12 +1277,13 @@ // Load stats async function loadStats() { try { - const [partsRes, brandsRes, categoriesRes, manufacturersRes, aftermarketRes] = await Promise.all([ + const [partsRes, brandsRes, categoriesRes, manufacturersRes, aftermarketRes, modelsRes] = await Promise.all([ fetch(`${API_BASE}/api/parts?per_page=1`), fetch(`${API_BASE}/api/brands`), fetch(`${API_BASE}/api/categories`), fetch(`${API_BASE}/api/manufacturers`), - fetch(`${API_BASE}/api/aftermarket?per_page=1`) + fetch(`${API_BASE}/api/aftermarket?per_page=1`), + fetch(`${API_BASE}/api/models`) ]); const parts = await partsRes.json(); @@ -1290,11 +1291,13 @@ const categories = await categoriesRes.json(); const manufacturers = await manufacturersRes.json(); const aftermarket = await aftermarketRes.json(); + const models = await modelsRes.json(); document.getElementById('stat-parts').textContent = (parts.pagination?.total || parts.length || 0) + '+'; document.getElementById('stat-brands').textContent = brands.length || 0; document.getElementById('stat-categories').textContent = categories.length || 0; - document.getElementById('stat-models').textContent = '13K+'; + const modelCount = models.length || 0; + document.getElementById('stat-models').textContent = modelCount >= 1000 ? Math.floor(modelCount / 1000) + 'K+' : modelCount; document.getElementById('stat-manufacturers').textContent = manufacturers.length || 0; document.getElementById('stat-aftermarket').textContent = (aftermarket.pagination?.total || aftermarket.length || 0) + '+'; } catch (e) { @@ -1444,13 +1447,15 @@ try { const res = await fetch(`${API_BASE}/api/vin/decode/${vin}`); - const data = await res.json(); + const raw = await res.json(); + const data = raw.vehicle || raw; if (data.error) { resultDiv.innerHTML = `

${data.error}

`; return; } + const engineInfo = data.engine_info || {}; resultDiv.innerHTML = `

Vehículo Identificado

@@ -1459,7 +1464,7 @@

Año: ${data.year || 'N/A'}

Tipo: ${data.body_class || 'N/A'}

Tracción: ${data.drive_type || 'N/A'}

- ${data.engine_info ? `

Motor: ${data.engine_info.displacement_l || ''}L ${data.engine_info.cylinders || ''} cil.

` : ''} + ${engineInfo.raw || engineInfo.displacement_l ? `

Motor: ${engineInfo.raw || (engineInfo.displacement_l + 'L ' + (engineInfo.cylinders || '') + ' cil.')}

` : ''} Ver partes compatibles
`; diff --git a/dashboard/dashboard.js b/dashboard/dashboard.js index 9f1ddd3..ce81f7b 100644 --- a/dashboard/dashboard.js +++ b/dashboard/dashboard.js @@ -93,26 +93,26 @@ class VehicleDashboard { items.push({ label: this.selectedBrand, active: true }); } else if (this.currentView === 'vehicles') { items.push({ label: ' Marcas', action: 'dashboard.goToBrands()' }); - items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand}')` }); + items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand.replace(/'/g, "\\'")}')` }); items.push({ label: this.selectedModel, active: true }); } else if (this.currentView === 'categories') { items.push({ label: ' Marcas', action: 'dashboard.goToBrands()' }); - items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand}')` }); - items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand}', '${this.selectedModel}')` }); + items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand.replace(/'/g, "\\'")}')` }); + items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand.replace(/'/g, "\\'")}', '${this.selectedModel.replace(/'/g, "\\'")}')` }); if (this.selectedYear) items.push({ label: this.selectedYear }); items.push({ label: 'Categorías', active: true }); } else if (this.currentView === 'groups') { items.push({ label: ' Marcas', action: 'dashboard.goToBrands()' }); - items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand}')` }); - items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand}', '${this.selectedModel}')` }); + items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand.replace(/'/g, "\\'")}')` }); + items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand.replace(/'/g, "\\'")}', '${this.selectedModel.replace(/'/g, "\\'")}')` }); if (this.selectedYear) items.push({ label: this.selectedYear }); items.push({ label: 'Categorías', action: `dashboard.goToCategories(${this.selectedVehicleId})` }); items.push({ label: this.selectedCategory ? (this.selectedCategory.name_es || this.selectedCategory.name) : 'Grupos', active: true }); } else if (this.currentView === 'parts') { const groupName = this.selectedGroup ? (this.selectedGroup.name_es || this.selectedGroup.name) : 'Grupo'; items.push({ label: ' Marcas', action: 'dashboard.goToBrands()' }); - items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand}')` }); - items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand}', '${this.selectedModel}')` }); + items.push({ label: this.selectedBrand, action: `dashboard.goToModels('${this.selectedBrand.replace(/'/g, "\\'")}')` }); + items.push({ label: this.selectedModel, action: `dashboard.goToVehicles('${this.selectedBrand.replace(/'/g, "\\'")}', '${this.selectedModel.replace(/'/g, "\\'")}')` }); if (this.selectedYear) items.push({ label: this.selectedYear }); items.push({ label: 'Categorías', action: `dashboard.goToCategories(${this.selectedVehicleId})` }); items.push({ label: this.selectedCategory ? (this.selectedCategory.name_es || this.selectedCategory.name) : 'Categoría', action: `dashboard.goToGroups(${this.selectedCategory ? this.selectedCategory.id : 0})` }); @@ -980,9 +980,10 @@ class VehicleDashboard { // FASE 5: Fetch group details for breadcrumb try { - const response = await fetch(`/api/groups/${groupId}`); + const response = await fetch(`/api/categories/${this.selectedCategory ? this.selectedCategory.id : 0}/groups`); if (response.ok) { - this.selectedGroup = await response.json(); + const groups = await response.json(); + this.selectedGroup = groups.find(g => g.id === groupId) || { id: groupId, name: 'Grupo' }; } } catch (error) { console.error('Error fetching group details:', error); @@ -1354,9 +1355,9 @@ class VehicleDashboard { // FASE 2: Show part detail from search results (closes search modal first) showPartDetailFromSearch(partId) { // Close search results modal - const searchModal = bootstrap.Modal.getInstance(document.getElementById('searchResultsModal')); - if (searchModal) { - searchModal.hide(); + const searchModalEl = document.getElementById('searchResultsModal'); + if (searchModalEl) { + searchModalEl.classList.remove('active'); } // Small delay to allow modal transition, then show part detail @@ -1453,7 +1454,7 @@ class VehicleDashboard { async showDiagram(diagramId) { // FASE 5: Use focus management for modal const contentContainer = document.getElementById('diagramModalContent'); - const modalTitle = document.getElementById('diagramModalLabel'); + const modalTitle = document.getElementById('diagramModalTitle'); contentContainer.innerHTML = `
@@ -1567,9 +1568,9 @@ class VehicleDashboard { onHotspotClick(hotspot) { if (hotspot.part_id) { // Close diagram modal first - const diagramModal = bootstrap.Modal.getInstance(document.getElementById('diagramModal')); - if (diagramModal) { - diagramModal.hide(); + const diagramModalEl = document.getElementById('diagramModal'); + if (diagramModalEl) { + diagramModalEl.classList.remove('active'); } // Small delay to allow modal transition, then show part detail @@ -1790,9 +1791,9 @@ class VehicleDashboard { // FASE 4: View parts for a VIN async viewVinParts(vin, myeId) { // Close VIN modal - const vinModal = bootstrap.Modal.getInstance(document.getElementById('vinDecoderModal')); - if (vinModal) { - vinModal.hide(); + const vinModalEl = document.getElementById('vinDecoderModal'); + if (vinModalEl) { + vinModalEl.classList.remove('active'); } // FASE 5: Use focus management for modal