nidus-sync/public-report/template/component/location-geocode-header.html
Eli Ribble 01ed2d6086
Finish green pool report submission
Also start the pattern of breaking out pool pages together in their own
file. I think its easier to read this way.
2026-01-09 19:43:19 +00:00

206 lines
6 KiB
HTML

{{define "location-geocode-header"}}
<style>
.detail-label {
font-size: 0.8rem;
text-transform: uppercase;
color: #6c757d;
margin-bottom: 2px;
font-weight: 600;
}
.detail-value {
font-weight: 500;
}
.main-address {
font-weight: 500;
}
.place-info {
font-size: 0.85rem;
color: #6c757d;
margin-top: 2px;
}
.suggestions-container {
position: absolute;
width: 100%;
max-height: 300px;
overflow-y: auto;
z-index: 1000;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.suggestion-item {
cursor: pointer;
padding: 10px 12px;
border-bottom: 1px solid #f0f0f0;
}
.suggestion-item:hover {
background-color: #f8f9fa;
}
</style>
<script>
// Display suggestions in the dropdown
function displaySuggestions(suggestions) {
const suggestionsContainer = document.getElementById('suggestions');
// Clear previous suggestions
suggestionsContainer.innerHTML = '';
if (suggestions.length === 0) {
suggestionsContainer.classList.add('d-none');
return;
}
// Create and append suggestion items
suggestions.forEach(suggestion => {
const item = document.createElement('div');
item.className = 'suggestion-item list-group-item';
// Create structure for the main address and place info
const mainAddressDiv = document.createElement('div');
mainAddressDiv.className = 'main-address';
mainAddressDiv.textContent = suggestion.properties.name || suggestion.properties.full_address;
item.appendChild(mainAddressDiv);
if (suggestion.properties.place_formatted) {
const placeInfoDiv = document.createElement('div');
placeInfoDiv.className = 'place-info';
placeInfoDiv.textContent = suggestion.properties.place_formatted || '';
item.appendChild(placeInfoDiv);
}
// Handle click on a suggestion
item.addEventListener('click', function() {
// Hide the suggestions container
setLocationInputs(suggestion);
suggestionsContainer.classList.add('d-none');
displaySelectedLocation(suggestion);
const locationSelected = new CustomEvent("locationselected", {
detail: {
coordinates: suggestion.geometry.coordinates,
},
});
suggestionsContainer.dispatchEvent(locationSelected);
});
suggestionsContainer.appendChild(item);
});
// Show the suggestions container
suggestionsContainer.classList.remove('d-none');
}
// Fetch suggestions from Mapbox API
async function fetchGeocodingSuggestions(query) {
// Replace with your actual Mapbox access token
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
try {
const url = `https://api.mapbox.com/search/geocode/v6/forward?q=${encodeURIComponent(query)}&access_token=${MAPBOX_ACCESS_TOKEN}`;
const response = await fetch(url);
const data = await response.json();
displaySuggestions(data.features || []);
} catch (error) {
console.error('Error fetching geocoding suggestions:', error);
}
}
function displaySelectedLocation(suggestion) {
const locationDisplayContainer = document.getElementById('locationDisplayContainer');
// Show location display container
locationDisplayContainer.classList.remove('d-none');
// Extract context data from properties
const props = suggestion.properties;
const context = props.context || {};
// Populate structured fields
// Street Address - combine address, street, housenumber if available
let addressStr = '';
if (context.address) addressStr += context.address.address_number;
if (context.street) {
if (addressStr) addressStr += ' ';
addressStr += context.street.name;
}
if (addressStr === '') {
addressStr = props.name || props.full_address || '-';
}
streetAddress.textContent = addressStr;
// Post Code
postCode.textContent = context.postcode.name || '-';
// District (could be district, locality, or place)
district.textContent = context.district.name || context.place.name || context.locality.name || '-';
// Region (state, province, etc.)
region.textContent = context.region.name || '-';
// Country
country.textContent = context.country.name || '-';
}
function onAddressInput() {
const suggestionsContainer = document.getElementById('suggestions');
let debounceTimer;
const query = this.value.trim();
// Clear previous timer
clearTimeout(debounceTimer);
// Clear suggestions if input is less than 3 characters
if (query.length < 3) {
suggestionsContainer.classList.add('d-none');
suggestionsContainer.innerHTML = '';
return;
}
// Debounce API calls (wait 300ms after typing stops)
debounceTimer = setTimeout(() => {
fetchGeocodingSuggestions(query);
}, 300);
}
function setLocationInputs(suggestion) {
let address = document.getElementById('address');
let country = document.getElementById('address-country');
let latitude = document.getElementById('latitude');
let longitude = document.getElementById('longitude');
let latlngAccuracyType = document.getElementById('latlng-accuracy-type');
let postcode = document.getElementById('address-postcode');
let place = document.getElementById('address-place');
let region = document.getElementById('address-region');
let street = document.getElementById('address-street');
// Extract context data from properties
const props = suggestion.properties;
const context = props.context || {};
// Populate structured fields
address.value = props.full_address;
country.value = context.country.name;
latitude.value = props.coordinates.latitude;
longitude.value = props.coordinates.longitude;
latlngAccuracyType.value = props.coordinates.accuracy;
postcode.value = context.postcode.name;
place.value = context.place.name;
region.value = context.region.name;
street.value = context.country.name;
}
document.addEventListener('DOMContentLoaded', function() {
const address = document.getElementById('address');
const suggestionsContainer = document.getElementById('suggestions');
const locationDetails = document.getElementById('locationDetails');
// Listen for input changes
address.addEventListener('input', onAddressInput);
// Close suggestions when clicking outside
document.addEventListener('click', function(event) {
if (!address.contains(event.target) && !suggestionsContainer.contains(event.target)) {
suggestionsContainer.classList.add('d-none');
}
});
});
</script>
{{end}}