// Vehicle Search System - Type-to-filter approach // Much more user-friendly than cascading dropdowns class VehicleSearchAutocomplete { constructor(containerId, onSelectionChange = null) { this.container = document.getElementById(containerId); this.onSelectionChange = onSelectionChange; this.selectedVehicle = null; this.isManualMode = false; this.init(); } init() { this.createSearchInterface(); this.bindEvents(); } createSearchInterface() { this.container.innerHTML = `
`; } updateTranslations() { // This will be called when language changes to update all translatable elements // The main translation system will handle the data-i18n attributes // Just trigger a re-render of any dynamic elements if needed // Update placeholder for search input if needed const searchInput = document.getElementById('vehicle-search-input'); if (searchInput && window.translations && window.currentLanguage) { const placeholder = window.translations[window.currentLanguage]['search.placeholder']; if (placeholder) { searchInput.setAttribute('placeholder', placeholder); } } } bindEvents() { const searchInput = document.getElementById('vehicle-search-input'); const resultsContainer = document.getElementById('vehicle-search-results'); const manualCheckbox = document.getElementById('manual-override-checkbox'); const manualFields = document.getElementById('manual-fields'); // Search input searchInput.addEventListener('input', (e) => { this.performSearch(e.target.value); }); // Filter dropdowns const yearFilter = document.getElementById('year-filter'); const fuelFilter = document.getElementById('fuel-filter'); const priceFilter = document.getElementById('price-filter'); [yearFilter, fuelFilter, priceFilter].forEach(filter => { filter.addEventListener('change', () => { this.performSearch(searchInput.value); }); }); // Result selection resultsContainer.addEventListener('click', (e) => { const resultItem = e.target.closest('.search-result-item'); if (resultItem) { const index = parseInt(resultItem.getAttribute('data-index')); this.selectResult(index); } }); // Hide results when clicking outside document.addEventListener('click', (e) => { if (!searchInput.contains(e.target) && !resultsContainer.contains(e.target)) { this.hideResults(); } }); // Manual override toggle manualCheckbox.addEventListener('change', (e) => { this.isManualMode = e.target.checked; if (this.isManualMode) { manualFields.style.display = 'block'; searchInput.disabled = true; searchInput.style.background = '#f8f9fa'; this.hideResults(); this.hideSelectedInfo(); } else { manualFields.style.display = 'none'; searchInput.disabled = false; searchInput.style.background = 'white'; this.updateSelectedVehicleInfo(); } }); // Manual field changes const manualFieldIds = ['manual-name', 'manual-price', 'manual-co2', 'manual-fuel']; manualFieldIds.forEach(fieldId => { const field = document.getElementById(fieldId); if (field) { field.addEventListener('input', () => { this.notifySelectionChange(); }); } }); } performSearch(searchTerm) { const filters = this.getActiveFilters(); const results = VehicleSearchDB.smartSearchWithFilters(searchTerm, filters, 12); this.displayResults(results); } getActiveFilters() { return { year: document.getElementById('year-filter')?.value || '', fuel: document.getElementById('fuel-filter')?.value || '', priceRange: document.getElementById('price-filter')?.value || '' }; } selectResult(index) { if (!this.currentResults || !this.currentResults[index]) { return; } const selectedVehicle = this.currentResults[index]; this.selectedVehicle = selectedVehicle; // Update search input with selected vehicle const searchInput = document.getElementById('vehicle-search-input'); searchInput.value = `${selectedVehicle.brand} ${selectedVehicle.model} ${selectedVehicle.variant.name} (${selectedVehicle.year})`; this.hideResults(); this.updateSelectedVehicleInfo(); this.notifySelectionChange(); // Add the selected vehicle to the car list if (window.addSelectedVehicle) { window.addSelectedVehicle(); } } displayResults(results) { const resultsContainer = document.getElementById('vehicle-search-results'); this.currentResults = results; // Store for selection if (results.length === 0) { this.hideResults(); return; } let html = ''; results.forEach((result, index) => { const variant = result.variant; const co2Badge = variant.co2 === 0 ? '0g CO₂' : ''; html += `
${result.brand} ${result.model} ${variant.name} (${result.year}) ${co2Badge}
€${variant.price.toLocaleString()} • ${variant.co2}g CO₂ • ${this.getFuelDisplay(variant.fuel)} • ${variant.power}hp
`; }); resultsContainer.innerHTML = html; resultsContainer.style.display = 'block'; // Bind click events resultsContainer.querySelectorAll('.search-result-item').forEach((item, index) => { item.addEventListener('click', () => { this.selectVehicle(results[index]); }); }); } selectVehicle(result) { const searchInput = document.getElementById('vehicle-search-input'); const vehicleName = `${result.brand} ${result.model} ${result.variant.name} (${result.year})`; searchInput.value = vehicleName; this.selectedVehicle = { name: vehicleName, price: result.variant.price, co2: result.variant.co2, fuel: result.variant.fuel, power: result.variant.power, brand: result.brand, model: result.model, year: result.year, variant: result.variant }; this.hideResults(); this.updateSelectedVehicleInfo(); this.notifySelectionChange(); } hideResults() { document.getElementById('vehicle-search-results').style.display = 'none'; } updateSelectedVehicleInfo() { const infoDiv = document.getElementById('selected-vehicle-info'); const detailsDiv = document.getElementById('vehicle-details'); if (this.isManualMode || !this.selectedVehicle) { infoDiv.style.display = 'none'; return; } const vehicle = this.selectedVehicle; const variant = vehicle.variant; const fuelBadge = variant.fuel === 'electric' ? 'Electric' : variant.fuel === 'hybrid' ? 'Hybrid' : `${this.getFuelDisplay(variant.fuel)}`; detailsDiv.innerHTML = `
Brand: ${vehicle.brand}
Model: ${vehicle.model}
Year: ${vehicle.year}
Price: €${variant.price.toLocaleString()}
CO₂: ${variant.co2}g/km
Fuel: ${fuelBadge}
Power: ${variant.power}hp
Variant: ${variant.name}
`; infoDiv.style.display = 'block'; } hideSelectedInfo() { document.getElementById('selected-vehicle-info').style.display = 'none'; } getFuelDisplay(fuelType) { const fuelMap = { electric: 'Electric', petrol: 'Petrol', diesel: 'Diesel', hybrid: 'Hybrid' }; return fuelMap[fuelType] || fuelType; } getSelectedVehicleData() { if (this.isManualMode) { return { name: document.getElementById('manual-name').value, price: parseFloat(document.getElementById('manual-price').value) || 0, co2: parseInt(document.getElementById('manual-co2').value) || 0, fuel: document.getElementById('manual-fuel').value }; } return this.selectedVehicle; } notifySelectionChange() { if (this.onSelectionChange) { const vehicleData = this.getSelectedVehicleData(); this.onSelectionChange(vehicleData); } } reset() { // Clear search input document.getElementById('vehicle-search-input').value = ''; document.getElementById('vehicle-search-input').disabled = false; document.getElementById('vehicle-search-input').style.background = 'white'; // Reset manual mode document.getElementById('manual-override-checkbox').checked = false; document.getElementById('manual-fields').style.display = 'none'; this.isManualMode = false; // Clear manual fields document.getElementById('manual-name').value = ''; document.getElementById('manual-price').value = ''; document.getElementById('manual-co2').value = ''; document.getElementById('manual-fuel').value = 'electric'; // Clear selected vehicle this.selectedVehicle = null; this.hideResults(); this.hideSelectedInfo(); } setVehicleData(vehicleData) { if (vehicleData.manual) { document.getElementById('manual-override-checkbox').checked = true; document.getElementById('manual-fields').style.display = 'block'; document.getElementById('manual-name').value = vehicleData.name || ''; document.getElementById('manual-price').value = vehicleData.price || ''; document.getElementById('manual-co2').value = vehicleData.co2 || ''; document.getElementById('manual-fuel').value = vehicleData.fuel || 'electric'; this.isManualMode = true; document.getElementById('vehicle-search-input').disabled = true; document.getElementById('vehicle-search-input').style.background = '#f8f9fa'; } } } // Enhanced Vehicle Database utilities for search const VehicleSearchDB = { // Get all vehicles as flat array for easier searching getAllVehicles() { const allVehicles = []; Object.keys(vehicleDatabase).forEach(brand => { Object.keys(vehicleDatabase[brand]).forEach(model => { Object.keys(vehicleDatabase[brand][model]).forEach(year => { vehicleDatabase[brand][model][year].forEach(variant => { allVehicles.push({ brand, model, year, variant, searchText: `${brand} ${model} ${variant.name} ${year}`.toLowerCase() }); }); }); }); }); return allVehicles; }, // Get popular suggestions for empty search getPopularSuggestions() { const popular = [ // BMW best sellers {brand: "BMW", model: "X1", year: "2024", variantIndex: 0}, {brand: "BMW", model: "3 Series", year: "2024", variantIndex: 0}, // Mercedes popular {brand: "Mercedes-Benz", model: "C-Class", year: "2024", variantIndex: 0}, {brand: "Mercedes-Benz", model: "GLC", year: "2024", variantIndex: 0}, // Audi favorites {brand: "Audi", model: "Q5", year: "2024", variantIndex: 0}, {brand: "Audi", model: "Q3", year: "2024", variantIndex: 0}, // VW popular {brand: "Volkswagen", model: "Tiguan", year: "2024", variantIndex: 0}, {brand: "Volkswagen", model: "Golf", year: "2024", variantIndex: 1}, // Tesla models {brand: "Tesla", model: "Model Y", year: "2024", variantIndex: 0}, {brand: "Tesla", model: "Model 3", year: "2024", variantIndex: 0} ]; return popular.map(item => { const variant = vehicleDatabase[item.brand][item.model][item.year][item.variantIndex]; return { brand: item.brand, model: item.model, year: item.year, variant }; }).filter(item => item.variant); // Filter out any missing variants }, // Smart search with filters smartSearchWithFilters(searchTerm, filters = {}, limit = 12) { if (!searchTerm || searchTerm.length < 2) { return this.getPopularSuggestions(filters).slice(0, limit); } return this.smartSearch(searchTerm, filters, limit); }, // Smart search with fuzzy matching smartSearch(searchTerm, filters = {}, limit = 12) { const term = searchTerm.toLowerCase(); const results = []; Object.keys(vehicleDatabase).forEach(brand => { Object.keys(vehicleDatabase[brand]).forEach(model => { Object.keys(vehicleDatabase[brand][model]).forEach(year => { vehicleDatabase[brand][model][year].forEach(variant => { // Apply filters first if (!this.passesFilters(variant, year, filters)) { return; } const searchText = `${brand} ${model} ${variant.name}`.toLowerCase(); const fullText = `${brand} ${model} ${variant.name} ${year}`.toLowerCase(); let score = 0; // Brand exact match if (brand.toLowerCase() === term) score += 1000; else if (brand.toLowerCase().includes(term)) score += 500; // Model exact match if (model.toLowerCase() === term) score += 800; else if (model.toLowerCase().includes(term)) score += 400; // Variant name match if (variant.name.toLowerCase().includes(term)) score += 300; // Full text contains term if (fullText.includes(term)) score += 100; // Partial brand + model match (e.g., "bmw x1") const brandModel = `${brand} ${model}`.toLowerCase(); if (brandModel.includes(term)) score += 600; // Year preference (newer = better) score += parseInt(year) * 0.1; // Electric/hybrid bonus for environmental preference if (variant.fuel === 'electric') score += 50; if (variant.fuel === 'hybrid') score += 25; if (score > 0) { results.push({ brand, model, year, variant, score }); } }); }); }); }); return results.sort((a, b) => b.score - a.score).slice(0, limit); }, // Check if vehicle passes all active filters passesFilters(variant, year, filters) { // Year filter if (filters.year && year !== filters.year) { return false; } // Fuel type filter if (filters.fuel && variant.fuel !== filters.fuel) { return false; } // Price range filter if (filters.priceRange && variant.price) { const [minPrice, maxPrice] = filters.priceRange.split('-').map(Number); if (variant.price < minPrice || variant.price > maxPrice) { return false; } } return true; }, // Get popular suggestions with filters applied getPopularSuggestions(filters = {}) { const popular = [ // BMW best sellers {brand: "BMW", model: "X1", year: "2024", variantIndex: 0}, {brand: "BMW", model: "3 Series", year: "2024", variantIndex: 0}, // Mercedes popular {brand: "Mercedes-Benz", model: "C-Class", year: "2024", variantIndex: 0}, {brand: "Mercedes-Benz", model: "GLC", year: "2024", variantIndex: 0}, // Audi favorites {brand: "Audi", model: "Q5", year: "2024", variantIndex: 0}, {brand: "Audi", model: "Q3", year: "2024", variantIndex: 0}, // VW popular {brand: "Volkswagen", model: "Tiguan", year: "2024", variantIndex: 0}, {brand: "Volkswagen", model: "Golf", year: "2024", variantIndex: 1}, // Tesla models {brand: "Tesla", model: "Model Y", year: "2024", variantIndex: 0}, {brand: "Tesla", model: "Model 3", year: "2024", variantIndex: 0} ]; return popular.map(item => { if (!vehicleDatabase[item.brand] || !vehicleDatabase[item.brand][item.model] || !vehicleDatabase[item.brand][item.model][item.year]) { return null; } const variant = vehicleDatabase[item.brand][item.model][item.year][item.variantIndex]; if (!variant) return null; // Apply filters to popular suggestions too if (!this.passesFilters(variant, item.year, filters)) { return null; } return { brand: item.brand, model: item.model, year: item.year, variant }; }).filter(item => item !== null); // Filter out any missing variants } }; // Utility functions for integration with existing tax calculator const VehicleAutocompleteUtils = { // Convert autocomplete selection to legacy custom car format convertToCustomCar(vehicleData) { // Handle both data structures: manual mode (flat) and search mode (nested) let name, price, co2, fuel; if (vehicleData.variant) { // Search mode: {brand, model, year, variant} const variant = vehicleData.variant; name = `${vehicleData.brand} ${vehicleData.model} ${variant.name} (${vehicleData.year})`; price = variant.price; co2 = variant.co2; fuel = variant.fuel; } else { // Manual mode: {name, price, co2, fuel} name = vehicleData.name; price = vehicleData.price; co2 = vehicleData.co2; fuel = vehicleData.fuel; } return { name, price, co2, fuel, examples: vehicleData.variant ? "Selected from database" : "Manual entry" }; }, // Validate vehicle data before adding validateVehicleData(vehicleData) { if (!vehicleData) { return { valid: false, message: "Please select a vehicle or enter all required fields" }; } // Handle both data structures: manual mode (flat) and search mode (nested) let name, price, co2, fuel; if (vehicleData.variant) { // Search mode: {brand, model, year, variant} const variant = vehicleData.variant; name = `${vehicleData.brand} ${vehicleData.model} ${variant.name} (${vehicleData.year})`; price = variant.price; co2 = variant.co2; fuel = variant.fuel; } else { // Manual mode: {name, price, co2, fuel} name = vehicleData.name; price = vehicleData.price; co2 = vehicleData.co2; fuel = vehicleData.fuel; } if (!name || !price) { return { valid: false, message: "Please select a vehicle or enter all required fields" }; } if (price < 15000 || price > 200000) { return { valid: false, message: "Price must be between €15,000 and €200,000" }; } if (co2 < 0 || co2 > 300) { return { valid: false, message: "CO2 emissions must be between 0 and 300 g/km" }; } return { valid: true }; }, // Get fuel type display name getFuelTypeDisplay(fuelType, language = 'en') { const fuelTypes = { en: { electric: "Electric", petrol: "Petrol", diesel: "Diesel", hybrid: "Hybrid" }, fr: { electric: "Électrique", petrol: "Essence", diesel: "Diesel", hybrid: "Hybride" }, nl: { electric: "Elektrisch", petrol: "Benzine", diesel: "Diesel", hybrid: "Hybride" } }; return fuelTypes[language][fuelType] || fuelType; } };