- Complete refactored single-page interface - 1,326 vehicles from 35 brands (2020-2025 model years) - Advanced search with year, fuel type, and price filters - Comprehensive pension impact analysis - Multi-language support (EN/FR/NL) - Docker deployment ready - Streamlined UX with required fields first Features: - Vehicle database with BMW, Mercedes, Audi, VW, Tesla, Toyota, etc. - Real-time search with fuzzy matching - Validation for required fields and vehicle selection - Advanced calculation parameters (collapsible) - Responsive design for mobile and desktop 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
701 lines
28 KiB
JavaScript
701 lines
28 KiB
JavaScript
// 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 = `
|
|
<div class="vehicle-search-container">
|
|
<div class="search-filters" style="display: flex; gap: 16px; margin-bottom: 16px; flex-wrap: wrap;">
|
|
<div class="filter-group">
|
|
<label for="year-filter">Year</label>
|
|
<select id="year-filter" class="filter-dropdown">
|
|
<option value="">All Years</option>
|
|
<option value="2025">2025</option>
|
|
<option value="2024">2024</option>
|
|
<option value="2023">2023</option>
|
|
<option value="2022">2022</option>
|
|
<option value="2021">2021</option>
|
|
<option value="2020">2020</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label for="fuel-filter">Fuel Type</label>
|
|
<select id="fuel-filter" class="filter-dropdown">
|
|
<option value="">All Fuel Types</option>
|
|
<option value="electric">⚡ Electric</option>
|
|
<option value="hybrid">🔋 Hybrid</option>
|
|
<option value="petrol">⛽ Petrol</option>
|
|
<option value="diesel">🛢️ Diesel</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label for="price-filter">Price Range</label>
|
|
<select id="price-filter" class="filter-dropdown">
|
|
<option value="">All Prices</option>
|
|
<option value="0-30000">Under €30,000</option>
|
|
<option value="30000-50000">€30,000 - €50,000</option>
|
|
<option value="50000-75000">€50,000 - €75,000</option>
|
|
<option value="75000-100000">€75,000 - €100,000</option>
|
|
<option value="100000-999999">Above €100,000</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="input-group" style="position: relative;">
|
|
<label for="vehicle-search-input">Search Vehicle</label>
|
|
<input type="text"
|
|
id="vehicle-search-input"
|
|
class="vehicle-search-input"
|
|
placeholder="Type to search... (e.g., BMW X1, Mercedes C200, Audi Q5)"
|
|
autocomplete="off">
|
|
<div id="vehicle-search-results" class="vehicle-search-results" style="display: none;"></div>
|
|
</div>
|
|
|
|
<div class="manual-override" style="margin-top: 16px;">
|
|
<label>
|
|
<input type="checkbox" id="manual-override-checkbox">
|
|
<span style="margin-left: 8px; font-size: 0.9rem; color: #6c757d;">Enter vehicle details manually</span>
|
|
</label>
|
|
</div>
|
|
|
|
<div id="manual-fields" class="manual-fields" style="display: none; margin-top: 16px;">
|
|
<div class="input-row">
|
|
<div class="input-group">
|
|
<label for="manual-name">Vehicle Name</label>
|
|
<input type="text" id="manual-name" placeholder="e.g., Tesla Model 3">
|
|
</div>
|
|
|
|
<div class="input-group">
|
|
<label for="manual-price">List Price (€)</label>
|
|
<input type="number" id="manual-price" placeholder="50000" min="15000" max="200000">
|
|
</div>
|
|
|
|
<div class="input-group">
|
|
<label for="manual-co2">CO2 Emissions (g/km)</label>
|
|
<input type="number" id="manual-co2" placeholder="120" min="0" max="300">
|
|
</div>
|
|
|
|
<div class="input-group">
|
|
<label for="manual-fuel">Fuel Type</label>
|
|
<select id="manual-fuel">
|
|
<option value="electric">Electric</option>
|
|
<option value="petrol">Petrol</option>
|
|
<option value="diesel">Diesel</option>
|
|
<option value="hybrid">Hybrid</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="selected-vehicle-info" id="selected-vehicle-info" style="display: none; margin-top: 16px; padding: 16px; background: #f8f9fa; border-radius: 6px;">
|
|
<h4 style="margin-bottom: 12px; font-size: 0.95rem; font-weight: 500; color: #28a745;">✓ Selected Vehicle:</h4>
|
|
<div id="vehicle-details"></div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
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 ?
|
|
'<span style="background: #d1fae5; color: #065f46; padding: 2px 6px; border-radius: 3px; font-size: 0.75rem; margin-left: 8px;">0g CO₂</span>' :
|
|
'';
|
|
|
|
html += `
|
|
<div class="search-result-item" data-index="${index}">
|
|
<div class="result-main">
|
|
<strong>${result.brand} ${result.model}</strong>
|
|
<span class="result-variant">${variant.name}</span>
|
|
<span class="result-year">(${result.year})</span>
|
|
${co2Badge}
|
|
</div>
|
|
<div class="result-details">
|
|
€${variant.price.toLocaleString()} • ${variant.co2}g CO₂ • ${this.getFuelDisplay(variant.fuel)} • ${variant.power}hp
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
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' ?
|
|
'<span style="background: #d1fae5; color: #065f46; padding: 2px 6px; border-radius: 3px; font-size: 0.75rem;">Electric</span>' :
|
|
variant.fuel === 'hybrid' ?
|
|
'<span style="background: #fef3c7; color: #92400e; padding: 2px 6px; border-radius: 3px; font-size: 0.75rem;">Hybrid</span>' :
|
|
`<span style="background: #f3f4f6; color: #374151; padding: 2px 6px; border-radius: 3px; font-size: 0.75rem;">${this.getFuelDisplay(variant.fuel)}</span>`;
|
|
|
|
detailsDiv.innerHTML = `
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; font-size: 0.9rem;">
|
|
<div><strong>Brand:</strong> ${vehicle.brand}</div>
|
|
<div><strong>Model:</strong> ${vehicle.model}</div>
|
|
<div><strong>Year:</strong> ${vehicle.year}</div>
|
|
<div><strong>Price:</strong> €${variant.price.toLocaleString()}</div>
|
|
<div><strong>CO₂:</strong> ${variant.co2}g/km</div>
|
|
<div><strong>Fuel:</strong> ${fuelBadge}</div>
|
|
<div><strong>Power:</strong> ${variant.power}hp</div>
|
|
<div><strong>Variant:</strong> ${variant.name}</div>
|
|
</div>
|
|
`;
|
|
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;
|
|
}
|
|
}; |