99 lines
4.1 KiB
JavaScript
99 lines
4.1 KiB
JavaScript
|
|
class ZipCodeCityUpdater {
|
||
|
|
constructor(zipCodeInputSelector, citySelectSelector, apiUrl) {
|
||
|
|
this.zipCodeInput = document.querySelector(zipCodeInputSelector);
|
||
|
|
this.citySelect = document.querySelector(citySelectSelector); // Changed to citySelect
|
||
|
|
this.apiUrl = apiUrl;
|
||
|
|
this.timer = null;
|
||
|
|
this.debounceTime = 500; // ms
|
||
|
|
|
||
|
|
// Store initial value from the select element (if any was pre-selected by Twig)
|
||
|
|
this.initialCityValue = this.citySelect ? this.citySelect.value : '';
|
||
|
|
|
||
|
|
if (this.zipCodeInput && this.citySelect) {
|
||
|
|
this.zipCodeInput.addEventListener('input', this.debounce(this.handleZipCodeChange.bind(this)));
|
||
|
|
// Trigger on page load if a zip code is already present
|
||
|
|
if (this.zipCodeInput.value) {
|
||
|
|
this.handleZipCodeChange();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
debounce(func) {
|
||
|
|
return function(...args) {
|
||
|
|
const context = this;
|
||
|
|
clearTimeout(context.timer);
|
||
|
|
context.timer = setTimeout(() => func.apply(context, args), context.debounceTime);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
async handleZipCodeChange() {
|
||
|
|
const zipCode = this.zipCodeInput.value.trim();
|
||
|
|
|
||
|
|
// Save current city selection if any, before clearing
|
||
|
|
const currentlySelectedCity = this.citySelect.value;
|
||
|
|
|
||
|
|
// Clear existing options, but keep the default placeholder if any
|
||
|
|
this.citySelect.innerHTML = '<option value="">Sélectionnez une ville</option>';
|
||
|
|
this.citySelect.value = '';
|
||
|
|
this.citySelect.disabled = true; // Disable until cities are loaded or cleared
|
||
|
|
|
||
|
|
if (zipCode.length !== 5 || !/^\d+$/.test(zipCode)) {
|
||
|
|
// If zip code is invalid or empty, disable and reset select
|
||
|
|
this.citySelect.disabled = false; // Re-enable for placeholder
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await fetch(this.apiUrl, {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json',
|
||
|
|
},
|
||
|
|
body: JSON.stringify({ zipCode: zipCode }),
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!response.ok) {
|
||
|
|
console.error(`HTTP error! status: ${response.status}`);
|
||
|
|
this.citySelect.disabled = false; // Re-enable for placeholder
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.cities && data.cities.length > 0) {
|
||
|
|
data.cities.forEach(city => {
|
||
|
|
const option = document.createElement('option');
|
||
|
|
option.value = city;
|
||
|
|
option.textContent = city;
|
||
|
|
this.citySelect.appendChild(option);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Attempt to re-select the city that was previously selected, or the initial one
|
||
|
|
if (data.cities.includes(currentlySelectedCity)) {
|
||
|
|
this.citySelect.value = currentlySelectedCity;
|
||
|
|
} else if (data.cities.includes(this.initialCityValue)) {
|
||
|
|
this.citySelect.value = this.initialCityValue;
|
||
|
|
} else if (data.cities.length === 1) {
|
||
|
|
// Automatically select if only one city is returned and no previous match
|
||
|
|
this.citySelect.value = data.cities[0];
|
||
|
|
}
|
||
|
|
this.citySelect.disabled = false; // Enable once options are loaded
|
||
|
|
} else {
|
||
|
|
// If no cities found, ensure select is enabled but shows only placeholder
|
||
|
|
this.citySelect.disabled = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error fetching city:', error);
|
||
|
|
this.citySelect.disabled = false; // Re-enable on error
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Global initialization - run when the DOM is fully loaded or Turbo loads a new page
|
||
|
|
document.addEventListener('turbo:load', () => {
|
||
|
|
// Note: Use CSS selectors for querySelector
|
||
|
|
new ZipCodeCityUpdater('input[name="billingZipCode"]', '#billingTownSelect', '/cities/lookup');
|
||
|
|
new ZipCodeCityUpdater('input[name="zipCodeEvent"]', '#townEventSelect', '/cities/lookup');
|
||
|
|
});
|