2026-01-08 16:05:50 +00:00
{{template "base.html" .}}
2026-02-01 03:34:21 +00:00
{{define "title"}}Report Nuisance{{end}}
2026-01-08 16:05:50 +00:00
{{define "extraheader"}}
2026-01-30 20:41:02 +00:00
< script src = 'https://api.mapbox.com/mapbox-gl-js/v3.17.0-beta.1/mapbox-gl.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 >
2026-01-30 22:35:18 +00:00
< script src = "/static/js/photo-upload.js" > < / script >
2026-01-08 16:05:50 +00:00
< script >
2026-01-30 20:41:02 +00:00
const MAPBOX_ACCESS_TOKEN = "{{.MapboxToken}}";
2026-02-03 17:01:39 +00:00
async function handleMapClick(mapLocator, lngLat) {
mapLocator.SetMarker(lngLat);
2026-02-03 17:22:32 +00:00
mapLocator.PanTo(lngLat, {duration: 2000});
2026-02-03 17:01:39 +00:00
const response = await geocodeReverse(MAPBOX_ACCESS_TOKEN, {
lat: lngLat.lat,
lng: lngLat.lng,
});
console.log("click reverse geocode", response);
if (response !== undefined & & response.features.length > 0) {
const addressInput = document.querySelector("address-input");
addressInput.SetValue(response.features[0]);
setLocationInputs(response.features[0]);
}
}
2026-01-30 22:00:43 +00:00
async function handleMarkerDrag(lngLat) {
const response = await geocodeReverse(MAPBOX_ACCESS_TOKEN, {
lat: lngLat.lat,
lng: lngLat.lng,
})
console.log("marker drag reverse geocode", response);
if (response !== undefined & & response.features.length > 0) {
const addressInput = document.querySelector("address-input");
addressInput.SetValue(response.features[0]);
2026-02-02 07:14:03 +00:00
setLocationInputs(response.features[0]);
2026-01-30 22:00:43 +00:00
}
}
2026-01-08 16:05:50 +00:00
function selectInspectionType(type) {
// Remove selected class from both cards
document.getElementById('propertyInspection').classList.remove('selected');
document.getElementById('neighborhoodInspection').classList.remove('selected');
// Add selected class to chosen card
if (type === 'property') {
document.getElementById('propertyInspection').classList.add('selected');
document.getElementById('inspectionTypeProperty').checked = true;
document.getElementById('schedulingSection').style.display = 'block';
} else {
document.getElementById('neighborhoodInspection').classList.add('selected');
document.getElementById('inspectionTypeNeighborhood').checked = true;
document.getElementById('schedulingSection').style.display = 'none';
}
}
2026-01-30 21:28:07 +00:00
function setLocationInputs(location) {
let country = document.getElementById('address-country');
let latitude = document.getElementById('latitude');
let longitude = document.getElementById('longitude');
let latlngAccuracyType = document.getElementById('latlng-accuracy-type');
2026-01-31 22:25:11 +00:00
let latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
2026-01-30 21:28:07 +00:00
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 = location.properties;
const context = props.context || {};
// Populate structured fields
country.value = context.country.name;
latitude.value = props.coordinates.latitude;
longitude.value = props.coordinates.longitude;
latlngAccuracyType.value = props.coordinates.accuracy;
2026-01-31 22:25:11 +00:00
latlngAccuracyValue.value = "0";
2026-01-30 21:28:07 +00:00
postcode.value = context.postcode.name;
place.value = context.place.name;
region.value = context.region.name;
street.value = context.country.name;
}
2026-01-30 20:41:02 +00:00
function toggleCollapse(something) {
el = document.getElementById(something)
if (el.classList.contains('collapse')) {
el.classList.remove('collapse');
} else {
el.classList.add('collapse');
}
document.getElementById("toggle-additional").classList.add("visually-hidden");
}
2026-01-08 16:05:50 +00:00
// Check for source identification
document.addEventListener('DOMContentLoaded', function() {
2026-01-30 20:41:02 +00:00
// Elements
2026-01-30 22:00:43 +00:00
const addressInput = document.querySelector("address-input");
2026-01-31 22:25:11 +00:00
const latitudeInput = document.getElementById('latitude');
const longitudeInput = document.getElementById('longitude');
const latlngAccuracyType = document.getElementById('latlng-accuracy-type');
const latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
2026-01-30 20:41:02 +00:00
const mapLocator = document.querySelector("map-locator");
mapLocator.addEventListener("load", (event) => {
getGeolocation({
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
}).then(position => {
2026-01-31 22:25:11 +00:00
console.log("Got location", position);
latitudeInput.value = position.coords.latitude;
longitudeInput.value = position.coords.longitude;
2026-02-01 02:37:35 +00:00
latlngAccuracyType.value = 'browser';
latlngAccuracyValue.value = position.coords.accuracy;
2026-01-30 21:28:07 +00:00
mapLocator.JumpTo({
2026-01-30 20:41:02 +00:00
center: {
lng: position.coords.longitude,
lat: position.coords.latitude,
},
zoom: 14,
});
2026-02-03 17:22:32 +00:00
const coords = [
2026-01-30 20:41:02 +00:00
position.coords.longitude,
position.coords.latitude,
2026-02-03 17:22:32 +00:00
];
mapLocator.SetMarker(coords);
mapLocator.JumpTo({center: coords, zoom: 14});
2026-01-31 16:31:21 +00:00
handleMarkerDrag({
2026-01-30 20:41:02 +00:00
lat: position.coords.latitude,
lng: position.coords.longitude,
});
}).catch(error => {
console.log("location error", error);
})
})
let mapZoom = document.getElementById('map-zoom');
mapLocator.addEventListener("zoomend", function(e) {
2026-01-30 22:13:22 +00:00
mapZoom.value = e.target.GetZoom();
2026-01-30 20:41:02 +00:00
});
2026-02-03 17:01:39 +00:00
mapLocator.addEventListener("click", (e) => {
// We get some events without the lngLat
if (e.detail !== undefined & & e.detail.lngLat !== undefined) {
handleMapClick(mapLocator, e.detail.lngLat);
}
});
2026-01-30 20:41:02 +00:00
mapLocator.addEventListener("markerdragend", (e) => {
2026-01-30 21:38:29 +00:00
const marker = event.detail.marker;
2026-01-30 20:41:02 +00:00
const lngLat = marker.getLngLat();
2026-01-30 22:00:43 +00:00
handleMarkerDrag(lngLat);
2026-01-30 20:41:02 +00:00
});
const addressDisplay = document.querySelector("address-display");
addressInput.addEventListener("address-selected", (event) => {
const l = event.detail.location;
console.log("Address selected", l);
// Center map on selected address
2026-01-30 21:28:07 +00:00
mapLocator.SetMarker(l.geometry.coordinates);
mapLocator.JumpTo({
2026-01-30 20:41:02 +00:00
center: l.geometry.coordinates,
zoom: 14,
});
setLocationInputs(l);
});
2026-01-08 16:05:50 +00:00
});
< / script >
< style >
< / style >
{{end}}
{{define "content"}}
2026-01-30 20:41:02 +00:00
{{if (eq .District nil)}}
{{template "header-rmo" .}}
{{else}}
{{template "header-district" .District}}
{{end}}
2026-01-08 16:05:50 +00:00
< div class = "container" >
< div class = "row mb-4" >
< div class = "col-12" >
< h2 > Report Mosquito Nuisance< / h2 >
< p class = "lead" > Help us identify mosquito activity in your area< / p >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
<!-- Report Form -->
2026-01-31 02:18:22 +00:00
< form id = "mosquitoNuisanceForm" action = "{{ .URL.NuisanceSubmit }}" method = "POST" enctype = "multipart/form-data" >
2026-01-31 15:39:14 +00:00
<!-- Location Section -->
2026-01-30 20:41:02 +00:00
< div class = "form-section" >
< div class = "section-heading" >
< i class = "bi bi-geo-alt" > < / i >
< h3 > Nuisance Location Information< / h3 >
< / div >
< div class = "col-md-12" >
< div class = "alert alert-info" role = "info" >
< p class = "mb-0" > You can select the location by address or by moving the marker on the map.< / p >
< / div >
< / div >
< 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 >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
2026-01-30 20:41:02 +00:00
< 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" / >
2026-01-30 21:28:07 +00:00
< 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" / >
2026-01-08 16:05:50 +00:00
<!-- Mosquito Activity Section -->
< div class = "form-section" >
< div class = "section-heading" >
2026-01-30 20:41:02 +00:00
{{ template "mosquito-color.svg" }}
2026-01-08 16:05:50 +00:00
< h3 > Mosquito Activity Information< / h3 >
< / div >
< p class = "mb-4" > The time when mosquitoes are active can help us identify the species and likely breeding sources.< / p >
<!-- Time of Day -->
< div class = "row mb-4" >
< div class = "col-12" >
< label class = "form-label" > When do you typically notice mosquitoes? (Select all that apply)< / label >
< div class = "row" >
< div class = "col-6 col-md-3" >
2026-01-08 17:48:43 +00:00
< input type = "checkbox" class = "btn-check" id = "earlyMorning" name = "tod-early" autocomplete = "off" >
2026-01-08 16:05:50 +00:00
< label class = "btn btn-outline-primary time-of-day-btn" for = "earlyMorning" >
< span class = "time-of-day-icon" > < i class = "bi bi-sunrise" > < / i > < / span >
< span class = "time-label" > Early Morning< / span >
< small class = "text-muted" > 5am-8am< / small >
< / label >
< / div >
< div class = "col-6 col-md-3" >
2026-01-08 17:48:43 +00:00
< input type = "checkbox" class = "btn-check" id = "daytime" name = "tod-day" autocomplete = "off" >
2026-01-08 16:05:50 +00:00
< label class = "btn btn-outline-primary time-of-day-btn" for = "daytime" >
< span class = "time-of-day-icon" > < i class = "bi bi-sun" > < / i > < / span >
< span class = "time-label" > Daytime< / span >
< small class = "text-muted" > 8am-5pm< / small >
< / label >
< / div >
< div class = "col-6 col-md-3" >
2026-01-08 17:48:43 +00:00
< input type = "checkbox" class = "btn-check" id = "evening" name = "tod-evening" autocomplete = "off" >
2026-01-08 16:05:50 +00:00
< label class = "btn btn-outline-primary time-of-day-btn" for = "evening" >
< span class = "time-of-day-icon" > < i class = "bi bi-sunset" > < / i > < / span >
< span class = "time-label" > Evening< / span >
< small class = "text-muted" > 5pm-9pm< / small >
< / label >
< / div >
< div class = "col-6 col-md-3" >
2026-01-08 17:48:43 +00:00
< input type = "checkbox" class = "btn-check" id = "night" name = "tod-night" autocomplete = "off" >
2026-01-08 16:05:50 +00:00
< label class = "btn btn-outline-primary time-of-day-btn" for = "night" >
< span class = "time-of-day-icon" > < i class = "bi bi-moon-stars" > < / i > < / span >
< span class = "time-label" > Night< / span >
< small class = "text-muted" > 9pm-5am< / small >
< / label >
< / div >
< / div >
< / div >
< / div >
<!-- Duration -->
< div class = "row mb-4" >
< div class = "col-md-6" >
< label for = "duration" class = "form-label" > How long have you been experiencing this mosquito problem?< / label >
2026-01-08 17:48:43 +00:00
< select class = "form-select" name = "duration" >
2026-01-08 16:05:50 +00:00
< option value = "just-noticed" > Just noticed recently< / option >
< option value = "few-days" > A few days< / option >
< option value = "1-2-weeks" > 1-2 weeks< / option >
< option value = "2-4-weeks" > 2-4 weeks< / option >
< option value = "1-3-months" > 1-3 months< / option >
< option value = "seasonal" > All season (recurring issue)< / option >
< / select >
< / div >
< / div >
<!-- Location -->
< div class = "row" >
< div class = "col-md-12" >
2026-01-13 19:52:25 +00:00
< label for = "source-location" class = "form-label" > Where on your property do you notice the most mosquito activity?< / label >
2026-01-30 20:41:02 +00:00
< select class = "form-select tall" multiple = "true" name = "source-location" >
2026-02-05 16:56:36 +00:00
< option value = "frontyard" > Front yard< / option >
2026-01-08 16:05:50 +00:00
< option value = "backyard" > Back yard< / option >
< option value = "garden" > Garden< / option >
< option value = "pool-area" > Pool area< / option >
< option value = "other" > Other area< / option >
< / select >
< / div >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
< button id = "toggle-additional" class = "btn btn-warning" type = "button" onClick = "toggleCollapse('collapse-additional-fields')" >
Click here to answer a few more questions to better help us solve your mosquito problem
< / button >
< div class = "collapse" id = "collapse-additional-fields" >
<!-- Potential Sources Section -->
< div class = "form-section" >
< div class = "section-heading" >
< i class = "bi bi-search" > < / i >
< h3 > Potential Mosquito Sources< / h3 >
2026-01-08 16:05:50 +00:00
< / div >
2026-01-30 20:41:02 +00:00
< p class = "mb-3" > Have you noticed any of these common mosquito breeding sources in your area?< / p >
2026-01-08 16:05:50 +00:00
2026-01-30 20:41:02 +00:00
< div class = "card card-highlight mb-4" >
< div class = "card-body" >
< h5 class = "card-title" > Did you know?< / h5 >
< p class = "card-text" > Mosquitoes can breed in as little as a bottle cap of water! Eliminating standing water is the most effective way to reduce mosquito populations.< / p >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
2026-01-30 20:41:02 +00:00
< div class = "row g-4 mb-4" >
<!-- Source 1 -->
< div class = "col-md-4" >
< div class = "card source-card" >
< div class = "card-body text-center" >
< div class = "source-icon" >
< i class = "bi bi-water" > < / i >
< / div >
< h5 class = "card-title" > Stagnant Water< / h5 >
< p class = "card-text" > Green pools, ponds, fountains, or birdbaths that aren't maintained< / p >
< div class = "form-check" >
< input class = "form-check-input" type = "checkbox" name = "source-stagnant" id = "sourceStagnantWater" >
< label class = "form-check-label" for = "sourceStagnantWater" >
I've noticed this
< / label >
< / div >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
<!-- Source 2 -->
< div class = "col-md-4" >
< div class = "card source-card" >
< div class = "card-body text-center" >
< div class = "source-icon" >
< i class = "bi bi-droplet" > < / i >
< / div >
< h5 class = "card-title" > Containers< / h5 >
< p class = "card-text" > Buckets, planters, toys, tires, or any items that collect rainwater< / p >
< div class = "form-check" >
< input class = "form-check-input" type = "checkbox" name = "source-container" id = "sourceContainers" >
< label class = "form-check-label" for = "sourceContainers" >
I've noticed this
< / label >
< / div >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
<!-- Source 3 -->
< div class = "col-md-4" >
< div class = "card source-card" >
< div class = "card-body text-center" >
< div class = "source-icon" >
< i class = "bi bi-house" > < / i >
< / div >
< h5 class = "card-title" > Sprinklers & Gutters< / h5 >
< p class = "card-text" > Clogged street gutters, yard drains, or AC units that collect water< / p >
< div class = "form-check" >
< input class = "form-check-input" type = "checkbox" name = "source-gutters" id = "sourceGutters" >
< label class = "form-check-label" for = "sourceGutters" >
I've noticed this
< / label >
< / div >
< / div >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
< div class = "row" >
< 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 >
2026-01-30 22:35:18 +00:00
< photo-upload / >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
2026-01-30 20:41:02 +00:00
< div class = "form-section" >
< div class = "section-heading" >
< i class = "bi bi-card-text" > < / i >
< h3 > Additional Information< / h3 >
2026-01-08 16:05:50 +00:00
< / div >
2026-01-30 20:41:02 +00:00
< div class = "row" >
< div class = "col-md-12" >
< label for = "additionalInfo" class = "form-label" > Is there anything else you'd like us to know?< / label >
< textarea class = "form-control" id = "additionalInfo" name = "additional-info" rows = "4" placeholder = "Additional details about the mosquito issue..." > < / textarea >
< / div >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
<!-- Submit Section -->
< div class = "submit-container" >
< div class = "row align-items-center" >
< div class = "col-md-8" >
< p class = "mb-0" > < strong > Thank you for reporting this mosquito issue.< / strong > < / p >
< p class = "mb-0 small text-muted" > After submission, you'll receive a confirmation with a report ID and further information.< / p >
< / div >
< div class = "col-md-4 text-md-end mt-3 mt-md-0" >
2026-01-30 22:07:20 +00:00
< button type = "submit" class = "btn btn-primary btn-lg" >
2026-01-08 16:05:50 +00:00
Submit Report
2026-01-30 22:07:20 +00:00
< / button >
2026-01-08 16:05:50 +00:00
< / div >
< / div >
< / div >
< / form >
< / div >
{{end}}