Show a map of the user's current location for setting a pool.

This commit is contained in:
Eli Ribble 2026-01-08 23:20:41 +00:00
parent 12ad9fa483
commit 0cd6697fd4
No known key found for this signature in database
5 changed files with 239 additions and 55 deletions

View file

@ -41,7 +41,7 @@ var (
Status = buildTemplate("status", "base")
)
var components = [...]string{"footer", "location-geocode", "location-geocode-header", "photo-upload", "photo-upload-header"}
var components = [...]string{"footer", "location-geocode", "location-geocode-header", "map", "map-header", "photo-upload", "photo-upload-header"}
func buildTemplate(files ...string) *htmlpage.BuiltTemplate {
subdir := "public-report"

View file

@ -36,9 +36,6 @@
}
</style>
<script>
// Replace with your actual Mapbox access token
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
// Display suggestions in the dropdown
function displaySuggestions(suggestions) {
const suggestionsContainer = document.getElementById('suggestions');
@ -85,6 +82,9 @@ function displaySuggestions(suggestions) {
// 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}`;

View file

@ -0,0 +1,103 @@
{{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>
function onLoadMap() {
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
console.log("Setting up the map...");
mapboxgl.accessToken = MAPBOX_ACCESS_TOKEN;
const 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,
});
const marker = new mapboxgl.Marker({
color: "#FF0000",
draggable: true
}).setLngLat({
lat: position.coords.latitude,
lng: position.coords.longitude,
}).addTo(map);
},
// 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}}

View file

@ -0,0 +1,84 @@
{{define "map"}}
<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>
const geojson = JSON.parse({{.GeoJSON}})
function addMarkers(map, markers) {
for (let i = 0; i < markers.length; i++) {
let marker = markers[i];
marker.addTo(map);
}
}
function mapMarkers() {
const markers = [
{{ range .Markers }}
new mapboxgl.Marker().setLngLat([{{.LatLng.Lng}}, {{.LatLng.Lat}}])
{{end}}
];
return markers;
}
function onLoad() {
console.log("Setting up the map...", geojson);
mapboxgl.accessToken = {{ .MapboxToken }};
const map = new mapboxgl.Map({
container: "map",
center: [{{.Center.Lng}}, {{.Center.Lat}}],
style: 'mapbox://styles/mapbox/streets-v12', // style URL
zoom: {{.Zoom}},
});
map.on("load", function() {
console.log("Map post-load...");
addMarkers(map, mapMarkers());
const sourceId = 'h3-hexes';
const layerId = 'h3-hexes-layer';
let source = map.getSource(sourceId);
if (!source) {
map.addSource(sourceId, {
type: 'geojson',
data: geojson
});
map.addLayer({
id: layerId,
source: sourceId,
type: 'fill',
interactive: false,
paint: {
'fill-color': '#F00000',
'fill-opacity': 0.3
}
});
source = map.getSource(sourceId);
}
source.setData(geojson);
console.log("Map post-load done.");
});
console.log("Map init done.");
}
window.addEventListener("load", onLoad);
</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}}

View file

@ -3,54 +3,55 @@
{{define "title"}}Green Pool{{end}}
{{define "extraheader"}}
{{template "location-geocode-header" .}}
{{template "map-header" .}}
{{template "photo-upload-header"}}
<style>
.district-logo {
max-height: 80px;
width: auto;
}
.map-container {
height: 300px;
background-color: #e9ecef;
border-radius: 5px;
border: 1px solid #dee2e6;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
.form-section {
margin-bottom: 2.5rem;
padding-bottom: 2rem;
border-bottom: 1px solid #dee2e6;
}
.form-section:last-child {
border-bottom: none;
margin-bottom: 1rem;
padding-bottom: 0;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.optional-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: normal;
margin-left: 8px;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
.district-logo {
max-height: 80px;
width: auto;
}
.map-container {
height: 500px;
background-color: #e9ecef;
border-radius: 5px;
border: 1px solid #dee2e6;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
.form-section {
margin-bottom: 2.5rem;
padding-bottom: 2rem;
border-bottom: 1px solid #dee2e6;
}
.form-section:last-child {
border-bottom: none;
margin-bottom: 1rem;
padding-bottom: 0;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.optional-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: normal;
margin-left: 8px;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
</style>
{{end}}
{{define "content"}}
@ -106,11 +107,7 @@
<p class="small text-muted mb-2">You can also click on the map to mark the location precisely</p>
<div class="map-container">
<div class="text-center">
<i class="bi bi-map fs-1 text-secondary"></i>
<p class="mb-0">Interactive Map</p>
<p class="text-muted small">Click to set the location of the mosquito source</p>
</div>
<div id="map"></div>
</div>
</div>