Add map and photo upload to nuisance report page
This commit is contained in:
parent
03a97f30a8
commit
ee1ee1e901
4 changed files with 113 additions and 31 deletions
|
|
@ -12,7 +12,7 @@ class MapLocator extends HTMLElement {
|
|||
this.render();
|
||||
|
||||
// markers shown on the map. Should be none or 1, generally.
|
||||
this._markers = null;
|
||||
this._markers = [];
|
||||
}
|
||||
|
||||
// Lifecycle: when element is added to the DOM
|
||||
|
|
@ -34,9 +34,9 @@ class MapLocator extends HTMLElement {
|
|||
const lng = Number(this.getAttribute('longitude') || -119.2);
|
||||
const zoom = Number(this.getAttribute('zoom') || 15);
|
||||
|
||||
const mapElement = this.shadowRoot.querySelector("#map");
|
||||
mapboxgl.accessToken = apiKey;
|
||||
map = new mapboxgl.Map({
|
||||
const mapElement = this.shadowRoot.querySelector("#map");
|
||||
this._map = new mapboxgl.Map({
|
||||
container: mapElement,
|
||||
center: {
|
||||
lat: lat,
|
||||
|
|
@ -45,6 +45,7 @@ class MapLocator extends HTMLElement {
|
|||
style: 'mapbox://styles/mapbox/streets-v12', // style URL
|
||||
zoom: zoom,
|
||||
});
|
||||
/*
|
||||
map.addControl(new mapboxgl.GeolocateControl({
|
||||
positionOptions: {
|
||||
enableHighAccuracy: true
|
||||
|
|
@ -53,7 +54,9 @@ class MapLocator extends HTMLElement {
|
|||
showUserHeading: true
|
||||
}));
|
||||
map.addControl(new mapboxgl.NavigationControl());
|
||||
map.on("load", function() {
|
||||
*/
|
||||
this._map.on("load", () => {
|
||||
console.log("map loaded");
|
||||
this.dispatchEvent(new CustomEvent('load'), {
|
||||
bubbles: true,
|
||||
composed: true, // Allows event to cross shadow DOM boundary
|
||||
|
|
@ -67,6 +70,7 @@ class MapLocator extends HTMLElement {
|
|||
// Initial render of component
|
||||
render() {
|
||||
this.shadowRoot.innerHTML = `
|
||||
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.53.0/mapbox-gl.css' rel='stylesheet' />
|
||||
<style>
|
||||
.map-container {
|
||||
background-color: #e9ecef;
|
||||
|
|
@ -111,7 +115,7 @@ class MapLocator extends HTMLElement {
|
|||
const marker = new mapboxgl.Marker({
|
||||
color: "#FF0000",
|
||||
draggable: true
|
||||
}).setLngLat(coords).addTo(map);
|
||||
}).setLngLat(coords).addTo(this._map);
|
||||
marker.on('dragend', function(e) {
|
||||
const markerDraggedEvent = new CustomEvent("markerdragend", {
|
||||
detail: {
|
||||
|
|
|
|||
|
|
@ -22,8 +22,9 @@ type ContentURL struct {
|
|||
Nuisance string
|
||||
}
|
||||
type ContentMock struct {
|
||||
District ContentDistrict
|
||||
URL ContentURL
|
||||
District ContentDistrict
|
||||
MapboxToken string
|
||||
URL ContentURL
|
||||
}
|
||||
|
||||
func addMockRoutes(r chi.Router) {
|
||||
|
|
@ -52,7 +53,8 @@ func renderMock(t *htmlpage.BuiltTemplate) func(http.ResponseWriter, *http.Reque
|
|||
Name: "Delta MCD",
|
||||
URLLogo: config.MakeURLNidus("/api/district/%s/logo", slug),
|
||||
},
|
||||
URL: makeContentURL(),
|
||||
MapboxToken: config.MapboxToken,
|
||||
URL: makeContentURL(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,15 @@
|
|||
|
||||
{{define "title"}}Nuisance{{end}}
|
||||
{{define "extraheader"}}
|
||||
<script src='https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.js'></script>
|
||||
<script src="/static/js/address-display.js"></script>
|
||||
<script src="/static/js/address-suggestion.js"></script>
|
||||
<script src="/static/js/geocode.js"></script>
|
||||
<script src="/static/js/location.js"></script>
|
||||
<script src="/static/js/map-locator.js"></script>
|
||||
{{template "photo-upload-header"}}
|
||||
<script>
|
||||
const MAPBOX_ACCESS_TOKEN = "{{.MapboxToken}}";
|
||||
// Handle inspection type selection
|
||||
function selectInspectionType(type) {
|
||||
// Remove selected class from both cards
|
||||
|
|
@ -41,6 +49,84 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
}
|
||||
});
|
||||
});
|
||||
// Elements
|
||||
const photoInput = document.getElementById('photos');
|
||||
|
||||
// Handle photo selection
|
||||
photoInput.addEventListener('change', handlePhotoSelection);
|
||||
|
||||
// Handle drag and drop
|
||||
const photoDropArea = document.getElementById('photoDropArea');
|
||||
|
||||
photoDropArea.addEventListener('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
photoDropArea.style.backgroundColor = '#e9ecef';
|
||||
});
|
||||
|
||||
photoDropArea.addEventListener('dragleave', function() {
|
||||
photoDropArea.style.backgroundColor = '#f8f9fa';
|
||||
});
|
||||
|
||||
photoDropArea.addEventListener('drop', function(e) {
|
||||
e.preventDefault();
|
||||
photoDropArea.style.backgroundColor = '#f8f9fa';
|
||||
|
||||
if (e.dataTransfer.files.length) {
|
||||
handleFiles(e.dataTransfer.files);
|
||||
}
|
||||
});
|
||||
const mapLocator = document.querySelector("map-locator");
|
||||
mapLocator.addEventListener("load", (event) => {
|
||||
getGeolocation({
|
||||
enableHighAccuracy: true,
|
||||
timeout: 10000,
|
||||
maximumAge: 0
|
||||
}).then(position => {
|
||||
mapLocator.jumpTo({
|
||||
center: {
|
||||
lng: position.coords.longitude,
|
||||
lat: position.coords.latitude,
|
||||
},
|
||||
zoom: 14,
|
||||
});
|
||||
mapLocator.setMarker([
|
||||
position.coords.longitude,
|
||||
position.coords.latitude,
|
||||
]);
|
||||
geocodeReverse(MAPBOX_ACCESS_TOKEN, {
|
||||
lat: position.coords.latitude,
|
||||
lng: position.coords.longitude,
|
||||
});
|
||||
}).catch(error => {
|
||||
console.log("location error", error);
|
||||
})
|
||||
})
|
||||
//mapLocator.addEventListener("markerdragend",
|
||||
let mapZoom = document.getElementById('map-zoom');
|
||||
mapLocator.addEventListener("zoomend", function(e) {
|
||||
mapZoom.value = e.target.getZoom();
|
||||
});
|
||||
mapLocator.addEventListener("markerdragend", (e) => {
|
||||
const lngLat = marker.getLngLat();
|
||||
//displaySelectedCoordinates(lngLat);
|
||||
geocodeReverse(MAPBOX_ACCESS_TOKEN, lngLat);
|
||||
});
|
||||
|
||||
const addressDisplay = document.querySelector("address-display");
|
||||
const addressInput = document.querySelector("address-input");
|
||||
addressInput.addEventListener("address-selected", (event) => {
|
||||
const l = event.detail.location;
|
||||
console.log("Address selected", l);
|
||||
// Center map on selected address
|
||||
mapSetMarker(l.geometry.coordinates);
|
||||
mapJumpTo({
|
||||
center: l.geometry.coordinates,
|
||||
zoom: 14,
|
||||
});
|
||||
|
||||
addressDisplay.show(l);
|
||||
setLocationInputs(l);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style>
|
||||
|
|
@ -144,7 +230,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
{{end}}
|
||||
{{define "content"}}
|
||||
<div class="container">
|
||||
<!-- Page Title -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h2>Report Mosquito Nuisance</h2>
|
||||
|
|
@ -152,7 +237,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info Alert -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info" role="alert">
|
||||
|
|
@ -168,32 +252,24 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
<div class="form-section">
|
||||
<div class="section-heading">
|
||||
<i class="bi bi-geo-alt"></i>
|
||||
<h3>Location & Contact Information</h3>
|
||||
<h3>Nuisance Location Information</h3>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-12">
|
||||
<label for="address" class="form-label">Your Address</label>
|
||||
<input type="text" class="form-control" name="address" placeholder="Enter your street address">
|
||||
<div class="col-md-6">
|
||||
<div class="mb-3 position-relative">
|
||||
<address-input
|
||||
placeholder="Start typing an address (min 3 characters)"
|
||||
api-key="{{ .MapboxToken }}">
|
||||
</address-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="name" class="form-label">Your Name</label>
|
||||
<input type="text" class="form-control" name="name">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="phone" class="form-label">Phone Number</label>
|
||||
<input type="tel" class="form-control" id="phone" name="phone">
|
||||
</div>
|
||||
<div class="col-md-12 mb-3">
|
||||
<label for="email" class="form-label">Email Address</label>
|
||||
<input type="email" class="form-control" id="email" name="email">
|
||||
<div class="form-text">We'll use this to send you a confirmation and follow-up information.</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<address-display></address-display>
|
||||
</div>
|
||||
</div>
|
||||
<p class="small text-muted mb-2">You can also click on the map to mark the location precisely</p>
|
||||
<map-locator api-key="{{ .MapboxToken }}"></map-locator>
|
||||
<input type="hidden" id="map-zoom" name="map-zoom"/>
|
||||
|
||||
<!-- Mosquito Activity Section -->
|
||||
<div class="form-section">
|
||||
|
|
@ -386,6 +462,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
<div class="col-md-12">
|
||||
<label for="otherSources" class="form-label">Have you noticed any other potential mosquito breeding sources?</label>
|
||||
<textarea class="form-control" id="otherSources" name="source-description" rows="2" placeholder="Describe any other potential breeding sites you've noticed..."></textarea>
|
||||
{{template "photo-upload"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
{{define "title"}}Green Pool{{end}}
|
||||
{{define "extraheader"}}
|
||||
<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 src="/static/js/address-display.js"></script>
|
||||
<script src="/static/js/address-suggestion.js"></script>
|
||||
<script src="/static/js/geocode.js"></script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue