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.
This commit is contained in:
parent
9680fb6a68
commit
01ed2d6086
31 changed files with 5925 additions and 375 deletions
|
|
@ -66,12 +66,16 @@ function displaySuggestions(suggestions) {
|
|||
}
|
||||
// Handle click on a suggestion
|
||||
item.addEventListener('click', function() {
|
||||
addressInput.value = suggestion.properties.name || suggestion.properties.full_address;
|
||||
// Hide the suggestions container
|
||||
setLocationInputs(suggestion);
|
||||
suggestionsContainer.classList.add('d-none');
|
||||
|
||||
// Display the selected location details
|
||||
displaySelectedLocation(suggestion);
|
||||
setMapMarker(suggestion.geometry.coordinates);
|
||||
const locationSelected = new CustomEvent("locationselected", {
|
||||
detail: {
|
||||
coordinates: suggestion.geometry.coordinates,
|
||||
},
|
||||
});
|
||||
suggestionsContainer.dispatchEvent(locationSelected);
|
||||
});
|
||||
|
||||
suggestionsContainer.appendChild(item);
|
||||
|
|
@ -155,18 +159,45 @@ function onAddressInput() {
|
|||
}, 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 addressInput = document.getElementById('addressInput');
|
||||
const address = document.getElementById('address');
|
||||
const suggestionsContainer = document.getElementById('suggestions');
|
||||
const locationDetails = document.getElementById('locationDetails');
|
||||
|
||||
|
||||
// Listen for input changes
|
||||
addressInput.addEventListener('input', onAddressInput);
|
||||
address.addEventListener('input', onAddressInput);
|
||||
|
||||
// Close suggestions when clicking outside
|
||||
document.addEventListener('click', function(event) {
|
||||
if (!addressInput.contains(event.target) && !suggestionsContainer.contains(event.target)) {
|
||||
if (!address.contains(event.target) && !suggestionsContainer.contains(event.target)) {
|
||||
suggestionsContainer.classList.add('d-none');
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
{{define "location-geocode"}}
|
||||
<!-- Hidden fields for location data -->
|
||||
<input type="hidden" id="address-country" name="address-country"/>
|
||||
<input type="hidden" id="address-postcode" name="address-postcode"/>
|
||||
<input type="hidden" id="address-place" name="address-place"/>
|
||||
<input type="hidden" id="address-region" name="address-region"/>
|
||||
<input type="hidden" id="address-street" name="address-street"/>
|
||||
<input type="hidden" id="latitude" name="latitude"/>
|
||||
<input type="hidden" id="longitude" name="longitude"/>
|
||||
<input type="hidden" id="latlng-accuracy-type" name="latlng-accuracy-type"/>
|
||||
<input type="hidden" id="latlng-accuracy-value" name="latlng-accuracy-value"/>
|
||||
<div class="col-md-6">
|
||||
<h2 class="mb-4">Address Search</h2>
|
||||
<div class="mb-3 position-relative">
|
||||
<label for="addressInput" class="form-label">Enter address</label>
|
||||
<input type="text" class="form-control" id="addressInput"
|
||||
<input type="text" class="form-control" id="address" name="address"
|
||||
placeholder="Start typing an address (min 3 characters)">
|
||||
<div id="suggestions" class="suggestions-container list-group d-none"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,144 +1,2 @@
|
|||
{{define "map-header"}}
|
||||
<script src='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.js'></script>
|
||||
<link href='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.css' rel='stylesheet' />
|
||||
<script>
|
||||
var map = null;
|
||||
var markers = [];
|
||||
function setMapMarker(coords) {
|
||||
console.log("Setting map marker", coords);
|
||||
map.jumpTo({
|
||||
center: coords,
|
||||
zoom: 14,
|
||||
});
|
||||
markers.forEach((marker) => marker.remove());
|
||||
addMarker(coords);
|
||||
}
|
||||
function addMarker(coords) {
|
||||
const marker = new mapboxgl.Marker({
|
||||
color: "#FF0000",
|
||||
draggable: true
|
||||
}).setLngLat(coords).addTo(map);
|
||||
marker.on('dragend', onMapMarkerDragEnd(marker));
|
||||
markers.push(marker);
|
||||
}
|
||||
function onMapMarkerDragEnd(marker) {
|
||||
return function() {
|
||||
const lngLat = marker.getLngLat();
|
||||
displaySelectedCoordinates(lngLat);
|
||||
reverseGeocode(lngLat);
|
||||
}
|
||||
}
|
||||
function displaySelectedCoordinates(lngLat) {
|
||||
const gpsDisplay = document.getElementById("gps-display");
|
||||
gpsDisplay.classList.remove('d-none');
|
||||
longitude.textContent = lngLat.lng;
|
||||
latitude.textContent = lngLat.lat;
|
||||
}
|
||||
async function reverseGeocode(lngLat) {
|
||||
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
|
||||
const url = `https://api.mapbox.com/search/geocode/v6/reverse?longitude=${lngLat.lng}&latitude=${lngLat.lat}&access_token=${MAPBOX_ACCESS_TOKEN}`
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
console.log("reverse geocoded to", data);
|
||||
if (data.features.length == 0) {
|
||||
console.warn("No results for reverse geocode");
|
||||
return;
|
||||
}
|
||||
const match = data.features[0];
|
||||
displaySelectedLocation(match);
|
||||
}
|
||||
function onLoadMap() {
|
||||
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
|
||||
console.log("Setting up the map...");
|
||||
mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
|
||||
map = new mapboxgl.Map({
|
||||
container: "map",
|
||||
center: {
|
||||
lat: 36.2,
|
||||
lng: -119.2
|
||||
},
|
||||
style: 'mapbox://styles/mapbox/streets-v12', // style URL
|
||||
zoom: 15,
|
||||
});
|
||||
map.addControl(new mapboxgl.GeolocateControl({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: true
|
||||
},
|
||||
trackUserLocation: true,
|
||||
showUserHeading: true
|
||||
}));
|
||||
map.on("load", function() {
|
||||
console.log("Map post-load...");
|
||||
updateMapWithLocation(map);
|
||||
console.log("Map post-load done.");
|
||||
});
|
||||
console.log("Map init done.");
|
||||
}
|
||||
function updateMapWithLocation(map) {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
// on success
|
||||
function(position) {
|
||||
console.log("Got location", position);
|
||||
map.jumpTo({
|
||||
center: {
|
||||
lng: position.coords.longitude,
|
||||
lat: position.coords.latitude,
|
||||
},
|
||||
zoom: 14,
|
||||
});
|
||||
addMarker([
|
||||
position.coords.longitude,
|
||||
position.coords.latitude,
|
||||
]);
|
||||
},
|
||||
// on error
|
||||
function(error) {
|
||||
switch (error.code) {
|
||||
case error.PERMISSION_DENIED:
|
||||
console.log("permission denied");
|
||||
break;
|
||||
case error.POSITION_UNAVAILABLE:
|
||||
console.log("location unavailable");
|
||||
break;
|
||||
case error.TIMEOUT:
|
||||
console.log("request timed out");
|
||||
break;
|
||||
}
|
||||
},
|
||||
// options
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.log("location is not supported");
|
||||
}
|
||||
}
|
||||
window.addEventListener("load", onLoadMap);
|
||||
</script>
|
||||
<style>
|
||||
.map-container {
|
||||
background-color: #e9ecef;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
|
||||
height: 500px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#map {
|
||||
height: 500px;
|
||||
width:100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#map img {
|
||||
max-width: none;
|
||||
min-width: 0px;
|
||||
height: auto;
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
{{define "photo-upload"}}
|
||||
<label for="photos" class="form-label fw-bold">Photos (Optional)</label>
|
||||
<div class="photo-upload-area">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" class="bi bi-camera mb-2" viewBox="0 0 16 16">
|
||||
<path d="M15 12a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h1.172a3 3 0 0 0 2.12-.879l.83-.828A1 1 0 0 1 6.827 3h2.344a1 1 0 0 1 .707.293l.828.828A3 3 0 0 0 12.828 5H14a1 1 0 0 1 1 1v6zM2 4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1.172a2 2 0 0 1-1.414-.586l-.828-.828A2 2 0 0 0 9.172 2H6.828a2 2 0 0 0-1.414.586l-.828.828A2 2 0 0 1 3.172 4H2z"/>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue