Add prettier for formatting html files automatically

Because I was wasting time doing it myself
This commit is contained in:
Eli Ribble 2026-02-06 16:10:09 +00:00
parent dbd84c1c09
commit 49b10a7d7e
No known key found for this signature in database
30 changed files with 4272 additions and 2673 deletions

12
.prettierrc Normal file
View file

@ -0,0 +1,12 @@
{
"plugins": ["/nix/store/6kfm5qrd2bckffxphb5ylvbg3sz1657r-prettier-plugin-go-template-0.0.15-unstable-2023-07-26/lib/node_modules/prettier-plugin-go-template/lib/index.js"],
"overrides": [
{
"files": ["*.html"],
"options": {
"parser": "go-template",
"useTabs": true,
},
},
],
}

View file

@ -26,6 +26,8 @@
pkgs.goose
pkgs.gotools
pkgs.lefthook
pkgs.prettier
pkgs.prettier-plugin-go-template
pkgs.watchexec
];
};

View file

@ -12,3 +12,7 @@ pre-commit:
glob: "*.go"
run: gofmt -w {staged_files}
stage_fixed: true
htmlfmt:
glob: "*.html"
run: prettier -w {staged_files}
stage_fixed: true

View file

@ -1,36 +1,42 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{template "title" .}} - Report Mosquitoes Online</title>
<!-- Bootstrap & Custom CSS -->
<link href="/static/css/bootstrap.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<!-- favicon -->
<link rel="icon" href="/static/favicon-rmo.ico" type="image/x-icon"/>
{{block "extraheader" .}} {{end}}
<script>
document.addEventListener("DOMContentLoaded", function() {
var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl)
});
console.log("Initialized ", popoverTriggerList.length, " popovers");
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ template "title" . }} - Report Mosquitoes Online</title>
<!-- Bootstrap & Custom CSS -->
<link href="/static/css/bootstrap.css" rel="stylesheet" />
<!-- Bootstrap Icons -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css"
/>
<!-- favicon -->
<link rel="icon" href="/static/favicon-rmo.ico" type="image/x-icon" />
{{ block "extraheader" . }}{{ end }}
<script>
document.addEventListener("DOMContentLoaded", function () {
var popoverTriggerList = [].slice.call(
document.querySelectorAll('[data-bs-toggle="popover"]'),
);
var popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl);
});
console.log("Initialized ", popoverTriggerList.length, " popovers");
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
console.log("Initialized ", tooltipTriggerList.length, " tooltips");
});
</script>
</head>
<body>
{{template "content" .}}
{{template "footer" .}}
<script src="/static/vendor/js/bootstrap.bundle.min.js"></script>
</body>
var tooltipTriggerList = [].slice.call(
document.querySelectorAll('[data-bs-toggle="tooltip"]'),
);
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
console.log("Initialized ", tooltipTriggerList.length, " tooltips");
});
</script>
</head>
<body>
{{ template "content" . }}
{{ template "footer" . }}
<script src="/static/vendor/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View file

@ -1,15 +1,15 @@
{{define "footer"}}
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
<div class="col-md-6">
<p>Powered by <a href="/">Report Mosquitoes Online</a></p>
<p class="mb-0">&copy; 2025 Gleipnir LLC</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">Contact: support@mosquitoes.online</p>
{{ define "footer" }}
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
<div class="col-md-6">
<p>Powered by <a href="/">Report Mosquitoes Online</a></p>
<p class="mb-0">&copy; 2025 Gleipnir LLC</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">Contact: support@mosquitoes.online</p>
</div>
</div>
</div>
</div>
</footer>
{{end}}
</footer>
{{ end }}

View file

@ -1,2 +1,2 @@
{{define "map-header"}}
{{end}}
{{ define "map-header" }}
{{ end }}

View file

@ -1,6 +1,9 @@
{{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' />
{{ 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) {
@ -59,26 +62,26 @@ function onLoad() {
}
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}}
<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

@ -1,126 +1,128 @@
{{define "photo-upload-header"}}
<style>
.photo-upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
background-color: #f9f9f9;
}
.photo-preview {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.photo-preview img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 4px;
}
</style>
<script>
/**
* Handle photo selection and preview
*/
function handlePhotoSelection() {
const photoInput = document.getElementById('photos');
const photoPreviewContainer = document.getElementById('photoPreviewContainer');
// Clear previous previews
photoPreviewContainer.innerHTML = '';
// Check if files were selected
if (photoInput.files && photoInput.files.length > 0) {
// Loop through selected files
Array.from(photoInput.files).forEach((file, index) => {
console.log("Handling", index, file);
if (!file.type.match('image.*')) {
console.log("Skipping non-image file", file.type);
return; // Skip non-image files
}
// Create preview container
const previewContainer = document.createElement('div');
previewContainer.className = 'position-relative m-1';
// Create image preview
const img = document.createElement('img');
img.className = 'img-thumbnail';
img.style.width = '100px';
img.style.height = '100px';
img.style.objectFit = 'cover';
// Read file and set preview
const reader = new FileReader();
reader.onload = (e) => {
img.src = e.target.result;
};
reader.readAsDataURL(file);
// Create remove button
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
removeBtn.className = 'btn btn-sm btn-danger position-absolute top-0 end-0';
removeBtn.innerHTML = '&times;';
removeBtn.style.fontSize = '10px';
removeBtn.style.padding = '0 5px';
// Handle remove button click
removeBtn.addEventListener('click', function() {
// Create a new FileList without this file
// Since FileList is immutable, we need to reset the input
// This is a bit tricky and requires recreating the input
previewContainer.remove();
// If this was the last image, clear the input entirely
if (photoPreviewContainer.children.length === 0) {
photoInput.value = '';
}
// Note: Unfortunately, selectively removing files from a FileList isn't straightforward
// In a real implementation, we might track selected files in an array and recreate the input
});
// Add elements to the preview container
previewContainer.appendChild(img);
previewContainer.appendChild(removeBtn);
photoPreviewContainer.appendChild(previewContainer);
});
}
}
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);
{{ define "photo-upload-header" }}
<style>
.photo-upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
background-color: #f9f9f9;
}
});
});
</script>
{{end}}
.photo-preview {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.photo-preview img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 4px;
}
</style>
<script>
/**
* Handle photo selection and preview
*/
function handlePhotoSelection() {
const photoInput = document.getElementById("photos");
const photoPreviewContainer = document.getElementById(
"photoPreviewContainer",
);
// Clear previous previews
photoPreviewContainer.innerHTML = "";
// Check if files were selected
if (photoInput.files && photoInput.files.length > 0) {
// Loop through selected files
Array.from(photoInput.files).forEach((file, index) => {
console.log("Handling", index, file);
if (!file.type.match("image.*")) {
console.log("Skipping non-image file", file.type);
return; // Skip non-image files
}
// Create preview container
const previewContainer = document.createElement("div");
previewContainer.className = "position-relative m-1";
// Create image preview
const img = document.createElement("img");
img.className = "img-thumbnail";
img.style.width = "100px";
img.style.height = "100px";
img.style.objectFit = "cover";
// Read file and set preview
const reader = new FileReader();
reader.onload = (e) => {
img.src = e.target.result;
};
reader.readAsDataURL(file);
// Create remove button
const removeBtn = document.createElement("button");
removeBtn.type = "button";
removeBtn.className =
"btn btn-sm btn-danger position-absolute top-0 end-0";
removeBtn.innerHTML = "&times;";
removeBtn.style.fontSize = "10px";
removeBtn.style.padding = "0 5px";
// Handle remove button click
removeBtn.addEventListener("click", function () {
// Create a new FileList without this file
// Since FileList is immutable, we need to reset the input
// This is a bit tricky and requires recreating the input
previewContainer.remove();
// If this was the last image, clear the input entirely
if (photoPreviewContainer.children.length === 0) {
photoInput.value = "";
}
// Note: Unfortunately, selectively removing files from a FileList isn't straightforward
// In a real implementation, we might track selected files in an array and recreate the input
});
// Add elements to the preview container
previewContainer.appendChild(img);
previewContainer.appendChild(removeBtn);
photoPreviewContainer.appendChild(previewContainer);
});
}
}
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);
}
});
});
</script>
{{ end }}

View file

@ -1,18 +1,44 @@
{{define "photo-upload"}}
<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"/>
<path d="M8 11a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 1a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7zM3 6.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z"/>
</svg>
<div class="file-upload-container" id="photoDropArea">
<input type="file" id="photos" name="photos" class="d-none" accept="image/*" multiple>
<button type="button" class="btn btn-outline-primary mb-2" onclick="document.getElementById('photos').click()">Add Photos</button>
</div>
<small class="d-block text-muted">Take pictures of the mosquito problem area</small>
{{ define "photo-upload" }}
<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"
/>
<path
d="M8 11a2.5 2.5 0 1 1 0-5 2.5 2.5 0 0 1 0 5zm0 1a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7zM3 6.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z"
/>
</svg>
<div class="file-upload-container" id="photoDropArea">
<input
type="file"
id="photos"
name="photos"
class="d-none"
accept="image/*"
multiple
/>
<button
type="button"
class="btn btn-outline-primary mb-2"
onclick="document.getElementById('photos').click()"
>
Add Photos
</button>
</div>
<small class="d-block text-muted"
>Take pictures of the mosquito problem area</small
>
<!-- Photo Preview Area -->
<div id="photoPreviewContainer" class="photo-preview mt-3 d-flex flex-wrap">
<!-- Image previews will be added here by JavaScript -->
<!-- Photo Preview Area -->
<div id="photoPreviewContainer" class="photo-preview mt-3 d-flex flex-wrap">
<!-- Image previews will be added here by JavaScript -->
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,24 +1,23 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Thanks!</h1>
<p>You've allowed emails from Report Mosquitoes Online.</p>
<p>Go ahead and close this page/tab/window whenever you're ready...</p>
<p>...or maybe <a href="/">check out the site</a></p>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Thanks!</h1>
<p>You've allowed emails from Report Mosquitoes Online.</p>
<p>Go ahead and close this page/tab/window whenever you're ready...</p>
<p>...or maybe <a href="/">check out the site</a></p>
</div>
</section>
</main>
{{ end }}

View file

@ -1,29 +1,33 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/confirm" method="POST">
<div class="form-section">
<label for="email" class="form-label">Email address</label>
<input type="email" name="email" placeholder="you@domain.com" value="{{.Email}}">
</div>
<button type="submit" class="btn btn-primary btn-lg">
Confirm email address
</button>
</form>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/confirm" method="POST">
<div class="form-section">
<label for="email" class="form-label">Email address</label>
<input
type="email"
name="email"
placeholder="you@domain.com"
value="{{ .Email }}"
/>
</div>
<button type="submit" class="btn btn-primary btn-lg">
Confirm email address
</button>
</form>
</div>
</section>
</main>
{{ end }}

View file

@ -1,24 +1,25 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Thanks!</h1>
<p>You've allowed emails from Report Mosquitoes Online to {{.Email}}.</p>
<p>Go ahead and close this page/tab/window whenever you're ready...</p>
<p>...or maybe <a href="/">check out the site</a></p>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Thanks!</h1>
<p>
You've allowed emails from Report Mosquitoes Online to {{ .Email }}.
</p>
<p>Go ahead and close this page/tab/window whenever you're ready...</p>
<p>...or maybe <a href="/">check out the site</a></p>
</div>
</section>
</main>
{{ end }}

View file

@ -1,28 +1,27 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/confirm" method="POST">
<div class="form-section">
<input type="email" name="email">
</div>
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
</form>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/confirm" method="POST">
<div class="form-section">
<input type="email" name="email" />
</div>
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
</form>
</div>
</section>
</main>
{{ end }}

View file

@ -1,23 +1,27 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Unsubscribed!</h1>
<p>You will not receive any further emails from Report Mosquitoes Online.</p>
<p>If this was an accident, or you changed your mind, you can <a href="/email/confirm">re-subscribe</a></p>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<h1>Unsubscribed!</h1>
<p>
You will not receive any further emails from Report Mosquitoes Online.
</p>
<p>
If this was an accident, or you changed your mind, you can
<a href="/email/confirm">re-subscribe</a>
</p>
</div>
</section>
</main>
{{ end }}

View file

@ -1,29 +1,33 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/unsubscribe" method="POST">
<div class="form-section">
<label for="email" class="form-label">Email address</label>
<input type="email" name="email" placeholder="you@domain.com" value="{{.Email}}">
</div>
<button type="submit" class="btn btn-warning btn-lg">
Unsubscribe from all communications
</button>
</form>
</div>
</section>
</main>
{{end}}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<section class="py-3 row text-center">
<div class="container">
<form action="/email/unsubscribe" method="POST">
<div class="form-section">
<label for="email" class="form-label">Email address</label>
<input
type="email"
name="email"
placeholder="you@domain.com"
value="{{ .Email }}"
/>
</div>
<button type="submit" class="btn btn-warning btn-lg">
Unsubscribe from all communications
</button>
</form>
</div>
</section>
</main>
{{ end }}

View file

@ -1,86 +1,108 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
<style>
.service-card {
transition: transform 0.3s;
height: 100%;
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}
.quick-report-mobile {
background-color: #ff9800;
}
.quick-report-desktop {
background-color: #ffefd5;
border-left: 4px solid #ff9800;
}
</style>
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<h2 class="text-center mb-4">Report a Mosquito Problem</h2>
<p class="lead text-center">Submit a report to help reduce mosquito activity in your neighborhood.</p>
<p class="lead text-center">Report Mosquitoes Online works with local mosquito control agencies to receive public reports. For this area, mosquito control services are provided by Delta Mosquito and Vector Control District.</p>
<img class="district-logo" src="{{.District.URLLogo}}" />
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
<style>
.service-card {
transition: transform 0.3s;
height: 100%;
}
.service-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.quick-report-mobile {
background-color: #ff9800;
}
.quick-report-desktop {
background-color: #ffefd5;
border-left: 4px solid #ff9800;
}
</style>
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<h2 class="text-center mb-4">Report a Mosquito Problem</h2>
<p class="lead text-center">
Submit a report to help reduce mosquito activity in your
neighborhood.
</p>
<p class="lead text-center">
Report Mosquitoes Online works with local mosquito control
agencies to receive public reports. For this area, mosquito
control services are provided by Delta Mosquito and Vector Control
District.
</p>
<img class="district-logo" src="{{ .District.URLLogo }}" />
</div>
</div>
</div>
</div>
</section>
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito-color.svg" }}
</section>
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito-color.svg" }}
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">
Report areas with high adult mosquito activity causing
discomfort or concern.
</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3"
>Report Problem</a
>
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">Report areas with high adult mosquito activity causing discomfort or concern.</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3">Report Problem</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond-color.svg" }}
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond-color.svg" }}
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">
Report any water that has been sitting for several days, where
mosquitoes can live.
</p>
<a href="{{ .URL.Water }}" class="btn btn-primary mt-3"
>Report Water</a
>
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">Report any water that has been sitting for several days, where mosquitoes can live.</p>
<a href="{{.URL.Water}}" class="btn btn-primary mt-3">Report Water</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report-color.svg" }}
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report-color.svg" }}
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">
Check on a previous request or view current mosquito activity
in your area.
</p>
<a href="{{ .URL.Status }}" class="btn btn-primary mt-3"
>Get Status</a
>
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">Check on a previous request or view current mosquito activity in your area.</p>
<a href="{{.URL.Status}}" class="btn btn-primary mt-3">Get Status</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
{{end}}
</section>
</main>
{{ end }}

View file

@ -1,132 +1,225 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Quick Report Complete{{end}}
{{define "extraheader"}}
<style>
</style>
<script>
</script>
{{end}}
{{define "content"}}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-check-circle-fill me-2" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
{{ define "title" }}Quick Report Complete{{ end }}
{{ define "extraheader" }}
<style></style>
<script></script>
{{ end }}
{{ define "content" }}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-check-circle-fill me-2"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg>
Report Successfully Submitted
</h3>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{ .ReportID|publicReportID }}</span>
</div>
</div>
<hr class="my-4" />
<div>
<h4 class="mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-bell me-2"
viewBox="0 0 16 16"
>
<path
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"
/>
</svg>
Get Updates
</h4>
<p>
Provide your contact information to receive updates about your
report.
</p>
<form
id="notificationForm"
action="/register-notifications"
method="post"
class="needs-validation"
>
<input type="hidden" name="report_id" value="{{ .ReportID }}" />
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope"
viewBox="0 0 16 16"
>
<path
d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"
/>
</svg>
</span>
<input
type="email"
class="form-control"
id="email"
name="email"
placeholder="your@email.com"
/>
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label"
>Phone Number (for SMS updates)</label
>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-phone"
viewBox="0 0 16 16"
>
<path
d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"
/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />
</svg>
</span>
<input
type="tel"
class="form-control"
id="phone"
name="phone"
placeholder="(123) 456-7890"
/>
</div>
</div>
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
type="checkbox"
name="consent"
required
/>
<label class="form-check-label" for="consent">
I consent to receiving updates about this report
</label>
<div class="invalid-feedback">
You must consent to receive notifications.
</div>
</div>
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
type="checkbox"
name="subscribe"
/>
<label class="form-check-label" for="subscribe">
I'd like to subscribe to periodic updates from
{{ .District.Name }}
</label>
</div>
<button type="submit" class="btn btn-primary">
Register for Updates
</button>
</form>
</div>
<hr class="my-4" />
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-search me-2"
viewBox="0 0 16 16"
>
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
/>
</svg>
Check Your Report Status
</h4>
<p>
You can check the status of your report at any time using your
Report ID.
</p>
<a href="/status/{{ .ReportID }}" class="btn btn-outline-primary">
Check Status
</a>
</div>
<div class="row">
<div class="mb-4 text-center">
{{ if not (eq .District nil) }}
<p>Your report will be handled by</p>
<p><b>{{ .District.Name }}</b></p>
<a href="{{ .District.URLWebsite }}"
><img class="logo" src="{{ .District.URLLogo }}"
/></a>
{{ end }}
</div>
</div>
</div>
</div>
<!-- Navigation Links -->
<div class="text-center">
<a href="{{ .URL.Nuisance }}" class="btn btn-outline-success">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-plus-circle me-1"
viewBox="0 0 16 16"
>
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"
/>
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"
/>
</svg>
Report Successfully Submitted
</h3>
Submit Another Report
</a>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{.ReportID|publicReportID}}</span>
</div>
</div>
<hr class="my-4">
<div>
<h4 class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-bell me-2" viewBox="0 0 16 16">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/>
</svg>
Get Updates
</h4>
<p>Provide your contact information to receive updates about your report.</p>
<form id="notificationForm" action="/register-notifications" method="post" class="needs-validation">
<input type="hidden" name="report_id" value="{{.ReportID}}">
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
</svg>
</span>
<input type="email" class="form-control" id="email" name="email" placeholder="your@email.com">
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone Number (for SMS updates)</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-phone" viewBox="0 0 16 16">
<path d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</svg>
</span>
<input type="tel" class="form-control" id="phone" name="phone" placeholder="(123) 456-7890">
</div>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" type="checkbox" name="consent" required>
<label class="form-check-label" for="consent">
I consent to receiving updates about this report
</label>
<div class="invalid-feedback">
You must consent to receive notifications.
</div>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" type="checkbox" name="subscribe"/>
<label class="form-check-label" for="subscribe">
I'd like to subscribe to periodic updates from {{ .District.Name }}
</label>
</div>
<button type="submit" class="btn btn-primary">Register for Updates</button>
</form>
</div>
<hr class="my-4">
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-search me-2" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
</svg>
Check Your Report Status
</h4>
<p>You can check the status of your report at any time using your Report ID.</p>
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary">
Check Status
</a>
</div>
<div class="row">
<div class="mb-4 text-center">
{{ if not (eq .District nil) }}
<p>Your report will be handled by</p>
<p><b>{{ .District.Name }}</b></p>
<a href="{{ .District.URLWebsite }}"><img class="logo" src="{{ .District.URLLogo }}" /></a>
{{ end }}
</div>
</div>
</div>
</div>
<!-- Navigation Links -->
<div class="text-center">
<a href="{{ .URL.Nuisance }}" class="btn btn-outline-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle me-1" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg>
Submit Another Report
</a>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,14 +1,14 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{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"}}
{{ 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
@ -16,7 +16,7 @@ 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');
@ -44,9 +44,9 @@ document.addEventListener('DOMContentLoaded', function() {
document.getElementById('sourceContainers'),
document.getElementById('sourceGutters')
];
const sourceAlert = document.getElementById('sourceFoundAlert');
sourceCheckboxes.forEach(checkbox => {
checkbox.addEventListener('change', function() {
// If any source is checked, show the alert
@ -65,20 +65,20 @@ document.addEventListener('DOMContentLoaded', function() {
// 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);
}
@ -109,7 +109,7 @@ document.addEventListener('DOMContentLoaded', function() {
console.log("location error", error);
})
})
//mapLocator.addEventListener("markerdragend",
//mapLocator.addEventListener("markerdragend",
let mapZoom = document.getElementById('map-zoom');
mapLocator.addEventListener("zoomend", function(e) {
mapZoom.value = e.target.getZoom();
@ -137,249 +137,389 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
</script>
<style>
</style>
{{end}}
{{define "content"}}
{{if .District}}
{{template "header" .}}
{{end}}
<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>
<!-- Report Form -->
<form id="mosquitoNuisanceForm" action="/nuisance-submit" method="POST">
<!-- Location & Contact Section -->
<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>
<style></style>
{{ end }}
{{ define "content" }}
{{ if .District }}
{{ template "header" . }}
{{ end }}
<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>
<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">
<div class="section-heading">
{{ template "mosquito-color.svg" }}
<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">
<input type="checkbox" class="btn-check" id="earlyMorning" name="tod-early" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="daytime" name="tod-day" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="evening" name="tod-evening" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="night" name="tod-night" autocomplete="off">
<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>
<!-- Report Form -->
<form id="mosquitoNuisanceForm" action="/nuisance-submit" method="POST">
<!-- Location & Contact Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Nuisance Location Information</h3>
</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>
<select class="form-select" name="duration">
<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">
<label for="source-location" class="form-label">Where on your property do you notice the most mosquito activity?</label>
<select class="form-select tall" multiple="true" name="source-location">
<option value="">Please select</option>
<option value="front-yard">Front yard</option>
<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 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>
</div>
</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" />
<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 -->
<!-- Mosquito Activity Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-search"></i>
<h3>Potential Mosquito Sources</h3>
{{ template "mosquito-color.svg" }}
<h3>Mosquito Activity Information</h3>
</div>
<p class="mb-3">Have you noticed any of these common mosquito breeding sources in your area?</p>
<p class="mb-4">
The time when mosquitoes are active can help us identify the species
and likely breeding sources.
</p>
<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>
</div>
</div>
<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>
<!-- 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">
<input
type="checkbox"
class="btn-check"
id="earlyMorning"
name="tod-early"
autocomplete="off"
/>
<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>
</div>
<!-- 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>
<div class="col-6 col-md-3">
<input
type="checkbox"
class="btn-check"
id="daytime"
name="tod-day"
autocomplete="off"
/>
<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>
</div>
<!-- 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 class="col-6 col-md-3">
<input
type="checkbox"
class="btn-check"
id="evening"
name="tod-evening"
autocomplete="off"
/>
<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">
<input
type="checkbox"
class="btn-check"
id="night"
name="tod-night"
autocomplete="off"
/>
<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>
<div class="alert alert-warning mb-4" id="sourceFoundAlert" style="display: none;">
<h5 class="alert-heading"><i class="bi bi-exclamation-triangle me-2"></i>Potential Breeding Source Found!</h5>
<p>It looks like you may have identified a mosquito breeding source. If you'd like to report a specific source (like a green pool), please use our <a href="/report-green-pool" class="alert-link">Report a Green Pool</a> form for faster service.</p>
<!-- 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
>
<select class="form-select" name="duration">
<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">
<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"}}
<label for="source-location" class="form-label"
>Where on your property do you notice the most mosquito
activity?</label
>
<select
class="form-select tall"
multiple="true"
name="source-location"
>
<option value="">Please select</option>
<option value="front-yard">Front yard</option>
<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>
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<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>
</div>
<p class="mb-3">
Have you noticed any of these common mosquito breeding sources in
your area?
</p>
<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>
</div>
</div>
<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>
</div>
</div>
</div>
<!-- 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>
</div>
</div>
</div>
<!-- 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>
</div>
</div>
</div>
<div
class="alert alert-warning mb-4"
id="sourceFoundAlert"
style="display: none;"
>
<h5 class="alert-heading">
<i class="bi bi-exclamation-triangle me-2"></i>Potential Breeding
Source Found!
</h5>
<p>
It looks like you may have identified a mosquito breeding source.
If you'd like to report a specific source (like a green pool),
please use our
<a href="/report-green-pool" class="alert-link"
>Report a Green Pool</a
>
form for faster service.
</p>
</div>
<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>
{{ template "photo-upload" }}
</div>
</div>
</div>
<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 class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
</div>
<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>
</div>
</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">
<a class="btn btn-primary btn-lg" href="{{.URL.NuisanceSubmitComplete}}">
Submit Report
</a>
<!-- 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">
<a
class="btn btn-primary btn-lg"
href="{{ .URL.NuisanceSubmitComplete }}"
>
Submit Report
</a>
</div>
</div>
</div>
</div>
</form>
</div>
{{end}}
</form>
</div>
{{ end }}

View file

@ -1,62 +1,76 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="banner-container">
<img class="banner-image" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito.svg" }}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="banner-container">
<img class="banner-image" src="/static/img/rmo/banner.jpg" />
</div>
</section>
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito.svg" }}
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">
Report areas with high adult mosquito activity causing
discomfort or concern.
</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3"
>Report Problem</a
>
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">Report areas with high adult mosquito activity causing discomfort or concern.</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3">Report Problem</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond.svg" }}
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond.svg" }}
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">
Report any water that has been sitting for several days, where
mosquitoes can live.
</p>
<a href="{{ .URL.Water }}" class="btn btn-primary mt-3"
>Report Source</a
>
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">Report any water that has been sitting for several days, where mosquitoes can live.</p>
<a href="{{ .URL.Water }}" class="btn btn-primary mt-3">Report Source</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report.svg" }}
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report.svg" }}
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">
Check on a previous request or view current mosquito activity
in your area.
</p>
<a href="{{ .URL.Status }}" class="btn btn-primary mt-3"
>Get Status</a
>
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">Check on a previous request or view current mosquito activity in your area.</p>
<a href="{{ .URL.Status }}" class="btn btn-primary mt-3">Get Status</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
{{end}}
</section>
</main>
{{ end }}

View file

@ -1,68 +1,68 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Standing Water{{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"}}
<style>
.district-logo {
max-height: 80px;
width: auto;
}
.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;
}
.photo-upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
background-color: #f9f9f9;
}
{{ define "title" }}Standing Water{{ 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" }}
<style>
.district-logo {
max-height: 80px;
width: auto;
}
.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;
}
.photo-upload-area {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
background-color: #f9f9f9;
}
.photo-preview {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.photo-preview {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.photo-preview img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 4px;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
</style>
.photo-preview img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 4px;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
</style>
<script>
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
function handlePhotoSelection() {
@ -81,25 +81,25 @@ function handlePhotoSelection() {
console.log("Skipping non-image file", file.type);
return; // Skip non-image files
}
// Create preview container
const previewContainer = document.createElement('div');
previewContainer.className = 'position-relative m-1';
// Create image preview
const img = document.createElement('img');
img.className = 'img-thumbnail';
img.style.width = '100px';
img.style.height = '100px';
img.style.objectFit = 'cover';
// Read file and set preview
const reader = new FileReader();
reader.onload = (e) => {
img.src = e.target.result;
};
reader.readAsDataURL(file);
// Create remove button
const removeBtn = document.createElement('button');
removeBtn.type = 'button';
@ -107,14 +107,14 @@ function handlePhotoSelection() {
removeBtn.innerHTML = '&times;';
removeBtn.style.fontSize = '10px';
removeBtn.style.padding = '0 5px';
// Handle remove button click
removeBtn.addEventListener('click', function() {
// Create a new FileList without this file
// Since FileList is immutable, we need to reset the input
// This is a bit tricky and requires recreating the input
previewContainer.remove();
// If this was the last image, clear the input entirely
if (photoPreviewContainer.children.length === 0) {
photoInput.value = '';
@ -122,7 +122,7 @@ function handlePhotoSelection() {
// Note: Unfortunately, selectively removing files from a FileList isn't straightforward
// In a real implementation, we might track selected files in an array and recreate the input
});
// Add elements to the preview container
previewContainer.appendChild(img);
previewContainer.appendChild(removeBtn);
@ -182,20 +182,20 @@ document.addEventListener('DOMContentLoaded', function() {
// 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);
}
@ -259,305 +259,499 @@ function displaySelectedCoordinates(lngLat) {
latitude.textContent = lngLat.lat;
}
</script>
{{end}}
{{define "content"}}
{{if .District}}
{{template "header" .}}
{{end}}
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<div class="row mb-4">
<div class="col-12">
<h2>Report Standing Water</h2>
<p class="lead">Help us locate and treat potential mosquito production sources in your area</p>
</div>
</div>
<!-- Report Form -->
<form id="standingWater" action="/water-submit" method="POST" enctype="multipart/form-data">
<!-- Photo Upload Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-camera"></i>
<h3>Photos</h3>
</div>
<p class="mb-3">Photos help us identify the severity of the issue and may contain location data that can help us find the production source.</p>
<div class="mb-4">
{{template "photo-upload"}}
{{ end }}
{{ define "content" }}
{{ if .District }}
{{ template "header" . }}
{{ end }}
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<div class="row mb-4">
<div class="col-12">
<h2>Report Standing Water</h2>
<p class="lead">
Help us locate and treat potential mosquito production sources in
your area
</p>
</div>
</div>
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<!-- Report Form -->
<form
id="standingWater"
action="/water-submit"
method="POST"
enctype="multipart/form-data"
>
<!-- Photo Upload Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-camera"></i>
<h3>Photos</h3>
</div>
<p class="mb-3">
Photos help us identify the severity of the issue and may contain
location data that can help us find the production source.
</p>
<div class="mb-4">
{{ template "photo-upload" }}
</div>
</div>
<p class="mb-3">Please provide any other information that might help us address this mosquito production source.</p>
<div class="row">
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
</div>
<p class="mb-3">
Please provide any other information that might help us address this
mosquito production source.
</p>
<div class="row">
<div class="col-md-12">
<label for="comments" class="form-label"
>Additional Details</label
>
<textarea
class="form-control"
id="comments"
name="comments"
rows="4"
placeholder="Example: The house appears to be vacant. There is algae growth in the pool. I've noticed increased mosquito activity in the evenings."
></textarea>
</div>
</div>
</div>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location</h3>
</div>
<p class="mb-3">
Please provide the location of the potential mosquito production
source. We may be able to extract this information from your photos
if they contain location data.
</p>
<div class="col-md-12">
<label for="comments" class="form-label">Additional Details</label>
<textarea class="form-control" id="comments" name="comments" rows="4" placeholder="Example: The house appears to be vacant. There is algae growth in the pool. I've noticed increased mosquito activity in the evenings."></textarea>
<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>
</div>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location</h3>
</div>
<p class="mb-3">Please provide the location of the potential mosquito production source. We may be able to extract this information from your photos if they contain location data.</p>
<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="row mb-3">
<!-- 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">
<div class="mb-3 position-relative">
<address-input
<div class="row mb-3">
<!-- 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">
<div class="mb-3 position-relative">
<address-input
placeholder="Start typing an address (min 3 characters)"
api-key="{{ .MapboxToken }}">
</address-input>
api-key="{{ .MapboxToken }}"
>
</address-input>
</div>
</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" />
</div>
<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">
<!-- Source Details Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-water"></i>
<h3>Source Details</h3>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label for="duration" class="form-label"
>How long has this production source been present?</label
>
<select
class="form-select"
id="duration"
name="source-duration"
>
<option value="none">I don't know</option>
<option value="less-than-week">Less than a week</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="more-than-3-months">More than 3 months</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label d-block"
>Have you observed any of the following?
<a
href="#"
data-bs-toggle="modal"
data-bs-target="#larvaeInfoModal"
><i class="bi bi-question-circle small ms-1"></i></a
></label>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="larvae"
name="has-larvae"
/>
<label class="form-check-label" for="larvae">
Larvae (wigglers) in water
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="pupae"
name="has-pupae"
/>
<label class="form-check-label" for="pupae">
Pupae (tumblers) in water
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="adult"
name="has-adult"
/>
<label class="form-check-label" for="adult">
Adult mosquitoes near the source
</label>
</div>
</div>
</div>
</div>
<!-- Access Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-unlock"></i>
<h3>Access Information</h3>
</div>
<p class="mb-3">
Please provide any details about how to access the mosquito
source. This helps our technicians when they visit the site.
</p>
<div class="row mb-3">
<div class="col-md-12">
<label for="access-comments" class="form-label"
>How can the source be accessed?</label
>
<textarea
class="form-control"
id="access-comments"
name="access-comments"
rows="3"
placeholder="Example: The pool is in the backyard, which can be accessed through a side gate on the right side of the house."
></textarea>
</div>
</div>
<div class="row mb-3">
<div class="col-md-12">
<label class="form-label d-block"
>Access obstacles (check all that apply):</label
>
<div class="row">
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="gate"
name="access-gate"
/>
<label class="form-check-label" for="gate">Gate</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="fence"
name="access-fence"
/>
<label class="form-check-label" for="fence">Fence</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="locked"
name="access-locked"
/>
<label class="form-check-label" for="locked"
>Locked entrance</label
>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="dogs"
name="access-dog"
/>
<label class="form-check-label" for="dogs"
>Dogs/pets</label
>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="access-other"
name="access-other"
/>
<label class="form-check-label" for="access-other"
>Other obstacle</label
>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Contact Information Sections -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-person-lines-fill"></i>
<h3>Property Owner Information (if known)</h3>
</div>
<div class="row mb-4">
<div class="col-md-4 mb-3">
<label for="owner-name" class="form-label">Owner Name</label>
<input
type="text"
class="form-control"
id="owner-name"
name="owner-name"
/>
</div>
<div class="col-md-4 mb-3">
<label for="owner-phone" class="form-label">Owner Phone</label>
<input
type="tel"
class="form-control"
id="owner-phone"
name="owner-phone"
/>
</div>
<div class="col-md-4 mb-3">
<label for="owner-email" class="form-label">Owner Email</label>
<input
type="email"
class="form-control"
id="owner-email"
name="owner-email"
/>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6 mb-3 row">
<div class="form-check mt-4">
<input
type="checkbox"
class="form-check-input"
name="property-ownership"
/>
<label class="form-check-label" for="property-ownership"
>This is my property</label
>
</div>
<div class="form-check mt-4">
<input
type="checkbox"
class="form-check-input"
name="backyard-permission"
/>
<label class="form-check-label" for="backyard-permission"
>I grant permission to enter the back yard of this
property.</label
>
</div>
<div class="form-check mt-4">
<input
type="checkbox"
class="form-check-input"
name="reporter-confidential"
/>
<label class="form-check-label" for="reporter-confidential">
<i
class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We share your information with mosquito control districts so they can follow up with any questions they may have about your report. Check this box if you would like the district to be careful not to share your information outside of the district operations team."
></i>
I would like my personal information kept
confidential.</label
>
</div>
</div>
</div>
</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"/>
</div>
<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">
<!-- Source Details Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-water"></i>
<h3>Source Details</h3>
<!-- 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 helping us keep our community safe from
mosquito-borne illnesses.</strong
>
</p>
<p class="mb-0 small text-muted">
After submission, you will receive a confirmation with a report
ID for tracking purposes.
</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<a
class="btn btn-primary btn-lg"
href="{{ .URL.NuisanceSubmitComplete }}"
>
Submit Report
</a>
</div>
</div>
</div>
</form>
</div>
</main>
<!-- Larvae Info Modal -->
<div
class="modal fade"
id="larvaeInfoModal"
tabindex="-1"
aria-labelledby="larvaeInfoModalLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="larvaeInfoModalLabel">
How to Identify Mosquito Larvae and Pupae
</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<div class="row mb-4">
<div class="col-md-6">
<label for="duration" class="form-label">How long has this production source been present?</label>
<select class="form-select" id="duration" name="source-duration">
<option value="none">I don't know</option>
<option value="less-than-week">Less than a week</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="more-than-3-months">More than 3 months</option>
</select>
<h6>Mosquito Larvae (Wigglers)</h6>
<p>Mosquito larvae, often called "wigglers," are:</p>
<ul>
<li>Small, worm-like aquatic organisms</li>
<li>Usually 1/4 to 1/2 inch long</li>
<li>Move with a wiggling motion in water</li>
<li>Hang upside-down at the water surface to breathe</li>
<li>Visible to the naked eye in standing water</li>
</ul>
</div>
<div class="col-md-6">
<label class="form-label d-block">Have you observed any of the following? <a href="#" data-bs-toggle="modal" data-bs-target="#larvaeInfoModal"><i class="bi bi-question-circle small ms-1"></i></a></label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="larvae" name="has-larvae">
<label class="form-check-label" for="larvae">
Larvae (wigglers) in water
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="pupae" name="has-pupae">
<label class="form-check-label" for="pupae">
Pupae (tumblers) in water
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="adult" name="has-adult">
<label class="form-check-label" for="adult">
Adult mosquitoes near the source
</label>
</div>
<h6>Mosquito Pupae (Tumblers)</h6>
<p>Mosquito pupae, often called "tumblers," are:</p>
<ul>
<li>Comma-shaped organisms</li>
<li>Typically darker than larvae</li>
<li>Move with a tumbling motion when disturbed</li>
<li>Rest at the water surface</li>
<li>The stage just before adult mosquitoes emerge</li>
</ul>
</div>
</div>
<p>
When looking for mosquito larvae and pupae, check standing water
sources like:
</p>
<ul>
<li>Swimming pools</li>
<li>Bird baths</li>
<li>Buckets or containers</li>
<li>Drainage ditches</li>
<li>Plant saucers</li>
<li>Rain gutters</li>
</ul>
<p>
If you see small creatures moving in standing water, there's a good
chance they're mosquito larvae or pupae.
</p>
<div class="text-center">
<a href="#" class="btn btn-outline-primary"
>View Detailed Identification Guide</a
>
</div>
</div>
<!-- Access Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-unlock"></i>
<h3>Access Information</h3>
</div>
<p class="mb-3">Please provide any details about how to access the mosquito source. This helps our technicians when they visit the site.</p>
<div class="row mb-3">
<div class="col-md-12">
<label for="access-comments" class="form-label">How can the source be accessed?</label>
<textarea class="form-control" id="access-comments" name="access-comments" rows="3" placeholder="Example: The pool is in the backyard, which can be accessed through a side gate on the right side of the house."></textarea>
</div>
</div>
<div class="row mb-3">
<div class="col-md-12">
<label class="form-label d-block">Access obstacles (check all that apply):</label>
<div class="row">
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gate" name="access-gate">
<label class="form-check-label" for="gate">Gate</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="fence" name="access-fence">
<label class="form-check-label" for="fence">Fence</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="locked" name="access-locked">
<label class="form-check-label" for="locked">Locked entrance</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dogs" name="access-dog">
<label class="form-check-label" for="dogs">Dogs/pets</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="access-other" name="access-other">
<label class="form-check-label" for="access-other">Other obstacle</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
<!-- Contact Information Sections -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-person-lines-fill"></i>
<h3>Property Owner Information (if known)</h3>
</div>
<div class="row mb-4">
<div class="col-md-4 mb-3">
<label for="owner-name" class="form-label">Owner Name</label>
<input type="text" class="form-control" id="owner-name" name="owner-name">
</div>
<div class="col-md-4 mb-3">
<label for="owner-phone" class="form-label">Owner Phone</label>
<input type="tel" class="form-control" id="owner-phone" name="owner-phone">
</div>
<div class="col-md-4 mb-3">
<label for="owner-email" class="form-label">Owner Email</label>
<input type="email" class="form-control" id="owner-email" name="owner-email">
</div>
</div>
<div class="row mb-4">
<div class="col-md-6 mb-3 row">
<div class="form-check mt-4">
<input type="checkbox" class="form-check-input" name="property-ownership">
<label class="form-check-label" for="property-ownership">This is my property</label>
</div>
<div class="form-check mt-4">
<input type="checkbox" class="form-check-input" name="backyard-permission">
<label class="form-check-label" for="backyard-permission">I grant permission to enter the back yard of this property.</label>
</div>
<div class="form-check mt-4">
<input type="checkbox" class="form-check-input" name="reporter-confidential">
<label class="form-check-label" for="reporter-confidential">
<i class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We share your information with mosquito control districts so they can follow up with any questions they may have about your report. Check this box if you would like the district to be careful not to share your information outside of the district operations team."></i>
I would like my personal information kept confidential.</label>
</div>
</div>
</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 helping us keep our community safe from mosquito-borne illnesses.</strong></p>
<p class="mb-0 small text-muted">After submission, you will receive a confirmation with a report ID for tracking purposes.</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<a class="btn btn-primary btn-lg" href="{{.URL.NuisanceSubmitComplete}}">
Submit Report
</a>
</div>
</div>
</div>
</form>
</div>
</main>
<!-- Larvae Info Modal -->
<div class="modal fade" id="larvaeInfoModal" tabindex="-1" aria-labelledby="larvaeInfoModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="larvaeInfoModalLabel">How to Identify Mosquito Larvae and Pupae</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mb-4">
<div class="col-md-6">
<h6>Mosquito Larvae (Wigglers)</h6>
<p>Mosquito larvae, often called "wigglers," are:</p>
<ul>
<li>Small, worm-like aquatic organisms</li>
<li>Usually 1/4 to 1/2 inch long</li>
<li>Move with a wiggling motion in water</li>
<li>Hang upside-down at the water surface to breathe</li>
<li>Visible to the naked eye in standing water</li>
</ul>
</div>
<div class="col-md-6">
<h6>Mosquito Pupae (Tumblers)</h6>
<p>Mosquito pupae, often called "tumblers," are:</p>
<ul>
<li>Comma-shaped organisms</li>
<li>Typically darker than larvae</li>
<li>Move with a tumbling motion when disturbed</li>
<li>Rest at the water surface</li>
<li>The stage just before adult mosquitoes emerge</li>
</ul>
</div>
</div>
<p>When looking for mosquito larvae and pupae, check standing water sources like:</p>
<ul>
<li>Swimming pools</li>
<li>Bird baths</li>
<li>Buckets or containers</li>
<li>Drainage ditches</li>
<li>Plant saucers</li>
<li>Rain gutters</li>
</ul>
<p>If you see small creatures moving in standing water, there's a good chance they're mosquito larvae or pupae.</p>
<div class="text-center">
<a href="#" class="btn btn-outline-primary">View Detailed Identification Guide</a>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,13 +1,13 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Report 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-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>
<script src="/static/js/photo-upload.js"></script>
{{ define "title" }}Report 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-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>
<script src="/static/js/photo-upload.js"></script>
<script>
const MAPBOX_ACCESS_TOKEN = "{{.MapboxToken}}";
async function handleMapClick(mapLocator, lngLat) {
@ -40,7 +40,7 @@ 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');
@ -96,7 +96,7 @@ document.addEventListener('DOMContentLoaded', function() {
const longitudeInput = document.getElementById('longitude');
const latlngAccuracyType = document.getElementById('latlng-accuracy-type');
const latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
const mapLocator = document.querySelector("map-locator");
mapLocator.addEventListener("load", (event) => {
getGeolocation({
@ -161,254 +161,389 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
</script>
<style>
</style>
{{end}}
{{define "content"}}
{{if (eq .District nil)}}
{{template "header-rmo" .}}
{{else}}
{{template "header-district" .District}}
{{end}}
<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>
<!-- Report Form -->
<form id="mosquitoNuisanceForm" action="{{ .URL.NuisanceSubmit }}" method="POST" enctype="multipart/form-data">
<!-- Location Section -->
<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>
<style></style>
{{ end }}
{{ define "content" }}
{{ if (eq .District nil) }}
{{ template "header-rmo" . }}
{{ else }}
{{ template "header-district" .District }}
{{ end }}
<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>
<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"/>
<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"/>
<!-- Mosquito Activity Section -->
<div class="form-section">
<div class="section-heading">
{{ template "mosquito-color.svg" }}
<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">
<input type="checkbox" class="btn-check" id="earlyMorning" name="tod-early" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="daytime" name="tod-day" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="evening" name="tod-evening" autocomplete="off">
<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">
<input type="checkbox" class="btn-check" id="night" name="tod-night" autocomplete="off">
<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>
<!-- Report Form -->
<form
id="mosquitoNuisanceForm"
action="{{ .URL.NuisanceSubmit }}"
method="POST"
enctype="multipart/form-data"
>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Nuisance Location Information</h3>
</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>
<select class="form-select" name="duration">
<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">
<label for="source-location" class="form-label">Where on your property do you notice the most mosquito activity?</label>
<select class="form-select tall" multiple="true" name="source-location">
<option value="frontyard">Front yard</option>
<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 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>
</div>
</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" />
<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"
/>
<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 -->
<!-- Mosquito Activity Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-search"></i>
<h3>Potential Mosquito Sources</h3>
{{ template "mosquito-color.svg" }}
<h3>Mosquito Activity Information</h3>
</div>
<p class="mb-3">Have you noticed any of these common mosquito breeding sources in your area?</p>
<p class="mb-4">
The time when mosquitoes are active can help us identify the species
and likely breeding sources.
</p>
<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>
</div>
</div>
<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>
<!-- 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">
<input
type="checkbox"
class="btn-check"
id="earlyMorning"
name="tod-early"
autocomplete="off"
/>
<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>
</div>
<!-- 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>
<div class="col-6 col-md-3">
<input
type="checkbox"
class="btn-check"
id="daytime"
name="tod-day"
autocomplete="off"
/>
<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>
</div>
<!-- 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 class="col-6 col-md-3">
<input
type="checkbox"
class="btn-check"
id="evening"
name="tod-evening"
autocomplete="off"
/>
<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">
<input
type="checkbox"
class="btn-check"
id="night"
name="tod-night"
autocomplete="off"
/>
<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
>
<select class="form-select" name="duration">
<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">
<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>
<photo-upload/>
<label for="source-location" class="form-label"
>Where on your property do you notice the most mosquito
activity?</label
>
<select
class="form-select tall"
multiple="true"
name="source-location"
>
<option value="frontyard">Front yard</option>
<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>
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<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>
</div>
<p class="mb-3">
Have you noticed any of these common mosquito breeding sources in
your area?
</p>
<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>
</div>
</div>
<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>
</div>
</div>
</div>
<!-- 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>
</div>
</div>
</div>
<!-- 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>
</div>
</div>
</div>
<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>
<photo-upload />
</div>
</div>
</div>
<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 class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
</div>
<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>
</div>
</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">
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
<!-- 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">
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
</div>
</div>
</div>
</div>
</form>
</div>
{{end}}
</form>
</div>
{{ end }}

View file

@ -1,211 +1,546 @@
{{template "base.html" .}}
{{define "title"}}Privacy Policy{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<div class="container">
<h1>Privacy Policy</h1>
<p>Last updated: January 20, 2026</p>
<p>This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You.</p>
<p>We use Your Personal Data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy.</p>
<h2>Interpretation and Definitions</h2>
<h3>Interpretation</h3>
<p>The words whose initial letters are capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.</p>
<h3>Definitions</h3>
<p>For the purposes of this Privacy Policy:</p>
<ul>
<li>
<p><strong>Account</strong> means a unique account created for You to access our Service or parts of our Service.</p>
</li>
<li>
<p><strong>Affiliate</strong> means an entity that controls, is controlled by, or is under common control with a party, where &quot;control&quot; means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.</p>
</li>
<li>
<p><strong>Company</strong> (referred to as either &quot;the Company&quot;, &quot;We&quot;, &quot;Us&quot; or &quot;Our&quot; in this Privacy Policy) refers to {{.Company}}, {{.Address}}</p>
</li>
<li>
<p><strong>Cookies</strong> are small files that are placed on Your computer, mobile device or any other device by a website, containing the details of Your browsing history on that website among its many uses.</p>
</li>
<li>
<p><strong>Country</strong> refers to: Arizona, United States</p>
</li>
<li>
<p><strong>Device</strong> means any device that can access the Service such as a computer, a cell phone or a digital tablet.</p>
</li>
<li>
<p><strong>Personal Data</strong> (or &quot;Personal Information&quot;) is any information that relates to an identified or identifiable individual.</p>
<p>We use &quot;Personal Data&quot; and &quot;Personal Information&quot; interchangeably unless a law uses a specific term.</p>
</li>
<li>
<p><strong>Service</strong> refers to the Website.</p>
</li>
<li>
<p><strong>Service Provider</strong> means any natural or legal person who processes the data on behalf of the Company. It refers to third-party companies or individuals employed by the Company to facilitate the Service, to provide the Service on behalf of the Company, to perform services related to the Service or to assist the Company in analyzing how the Service is used.</p>
</li>
<li>
<p><strong>Usage Data</strong> refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit).</p>
</li>
<li>
<p><strong>Website</strong> refers to {{.Site}} accessible from <a href="{{.URLReport}}" rel="external nofollow noopener" target="_blank">{{.URLReport}}</a>.</p>
</li>
<li>
<p><strong>You</strong> means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.</p>
</li>
</ul>
<h2>Collecting and Using Your Personal Data</h2>
<h3>Types of Data Collected</h3>
<h4>Personal Data</h4>
<p>While using Our Service, We may ask You to provide Us with certain personally identifiable information that can be used to contact or identify You. Personally identifiable information may include, but is not limited to:</p>
<ul>
<li>Email address</li>
<li>First name and last name</li>
<li>Phone number</li>
<li>Address, State, Province, ZIP/Postal code, City</li>
</ul>
<h4>Usage Data</h4>
<p>Usage Data is collected automatically when using the Service.</p>
<p>Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.</p>
<p>When You access the Service by or through a mobile device, We may collect certain information automatically, including, but not limited to, the type of mobile device You use, Your mobile device's unique ID, the IP address of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device identifiers and other diagnostic data.</p>
<p>We may also collect information that Your browser sends whenever You visit Our Service or when You access the Service by or through a mobile device.</p>
<h4>Tracking Technologies and Cookies</h4>
<p>We use Cookies and similar tracking technologies to track the activity on Our Service and store certain information. Tracking technologies We use include beacons, tags, and scripts to collect and track information and to improve and analyze Our Service. The technologies We use may include:</p>
<ul>
<li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on Your Device. You can instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do not accept Cookies, You may not be able to use some parts of our Service.</li>
</ul>
<p>Cookies can be &quot;Persistent&quot; or &quot;Session&quot; Cookies. Persistent Cookies remain on Your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web browser.</p>
<p>Where required by law, we use non-essential cookies (such as analytics, advertising, and remarketing cookies) only with Your consent. You can withdraw or change Your consent at any time using Our cookie preferences tool (if available) or through Your browser/device settings. Withdrawing consent does not affect the lawfulness of processing based on consent before its withdrawal.</p>
<p>We use both Session and Persistent Cookies for the purposes set out below:</p>
<ul>
<li>
<p><strong>Necessary / Essential Cookies</strong></p>
<p>Type: Session Cookies</p>
<p>Administered by: Us</p>
<p>Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services.</p>
</li>
<li>
<p><strong>Functionality Cookies</strong></p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>Purpose: These Cookies allow Us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website.</p>
</li>
</ul>
<p>For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy or the Cookies section of Our Privacy Policy.</p>
<h3>Use of Your Personal Data</h3>
<p>The Company may use Personal Data for the following purposes:</p>
<ul>
<li>
<p><strong>To provide and maintain our Service</strong>, including to monitor the usage of our Service.</p>
</li>
<li>
<p><strong>To manage Your Account:</strong> to manage Your registration as a user of the Service. The Personal Data You provide can give You access to different functionalities of the Service that are available to You as a registered user.</p>
</li>
<li>
<p><strong>For the performance of a contract:</strong> the development, compliance and undertaking of the purchase contract for the products, items or services You have purchased or of any other contract with Us through the Service.</p>
</li>
<li>
<p><strong>To contact You:</strong> To contact You by email, telephone calls, SMS, or other equivalent forms of electronic communication, such as a mobile application's push notifications regarding updates or informative communications related to the functionalities, products or contracted services, including the security updates, when necessary or reasonable for their implementation.</p>
</li>
<li>
<p><strong>To provide You</strong> with news, special offers, and general information about other goods, services and events which We offer that are similar to those that you have already purchased or inquired about unless You have opted not to receive such information.</p>
</li>
<li>
<p><strong>To manage Your requests:</strong> To attend and manage Your requests to Us.</p>
</li>
<li>
<p><strong>For business transfers:</strong> We may use Your Personal Data to evaluate or conduct a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which Personal Data held by Us about our Service users is among the assets transferred.</p>
</li>
<li>
<p><strong>For other purposes</strong>: We may use Your information for other purposes, such as data analysis, identifying usage trends, determining the effectiveness of our promotional campaigns and to evaluate and improve our Service, products, services, marketing and your experience.</p>
</li>
</ul>
<p>We may share Your Personal Data in the following situations:</p>
<ul>
<li><strong>With Service Providers:</strong> We may share Your Personal Data with Service Providers to monitor and analyze the use of our Service, to contact You.</li>
<li><strong>For business transfers:</strong> We may share or transfer Your Personal Data in connection with, or during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a portion of Our business to another company.</li>
<li><strong>With Affiliates:</strong> We may share Your Personal Data with Our affiliates, in which case we will require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and any other subsidiaries, joint venture partners or other companies that We control or that are under common control with Us.</li>
<li><strong>With business partners:</strong> We may share Your Personal Data with Our business partners to offer You certain products, services or promotions.</li>
<li><strong>With other users:</strong> If Our Service offers public areas, when You share Personal Data or otherwise interact in the public areas with other users, such information may be viewed by all users and may be publicly distributed outside.</li>
<li><strong>With Your consent</strong>: We may disclose Your Personal Data for any other purpose with Your consent.</li>
</ul>
<h3>Retention of Your Personal Data</h3>
<p>The Company will retain Your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply with our legal obligations (for example, if We are required to retain Your data to comply with applicable laws), resolve disputes, and enforce our legal agreements and policies.</p>
<p>Where possible, We apply shorter retention periods and/or reduce identifiability by deleting, aggregating, or anonymizing data. Unless otherwise stated, the retention periods below are maximum periods (&quot;up to&quot;) and We may delete or anonymize data sooner when it is no longer needed for the relevant purpose. We apply different retention periods to different categories of Personal Data based on the purpose of processing and legal obligations:</p>
<ul>
<li>
<p>Account Information</p>
<ul>
<li>User Accounts: retained for the duration of your account relationship plus up to 24 months after account closure to handle any post-termination issues or resolve disputes.</li>
</ul>
</li>
<li>
<p>Customer Support Data</p>
<ul>
<li>Support tickets and correspondence: up to 24 months from the date of ticket closure to resolve follow-up inquiries, track service quality, and defend against potential legal claims</li>
<li>Chat transcripts: up to 24 months for quality assurance and staff training purposes.</li>
</ul>
</li>
<li>
<p>Usage Data</p>
<ul>
<li>
<p>Website analytics data (cookies, IP addresses, device identifiers): up to 24 months from the date of collection, which allows us to analyze trends while respecting privacy principles.</p>
</li>
<li>
<p>Server logs (IP addresses, access times): up to 24 months for security monitoring and troubleshooting purposes.</p>
</li>
</ul>
</li>
</ul>
<p>Usage Data is retained in accordance with the retention periods described above, and may be retained longer only where necessary for security, fraud prevention, or legal compliance.</p>
<p>We may retain Personal Data beyond the periods stated above for different reasons:</p>
<ul>
<li>Legal obligation: We are required by law to retain specific data (e.g., financial records for tax authorities).</li>
<li>Legal claims: Data is necessary to establish, exercise, or defend legal claims.</li>
<li>Your explicit request: You ask Us to retain specific information.</li>
<li>Technical limitations: Data exists in backup systems that are scheduled for routine deletion.</li>
</ul>
<p>You may request information about how long We will retain Your Personal Data by contacting Us.</p>
<p>When retention periods expire, We securely delete or anonymize Personal Data according to the following procedures:</p>
<ul>
<li>Deletion: Personal Data is removed from Our systems and no longer actively processed.</li>
<li>Backup retention: Residual copies may remain in encrypted backups for a limited period consistent with our backup retention schedule and are not restored except where necessary for security, disaster recovery, or legal compliance.</li>
<li>Anonymization: In some cases, We convert Personal Data into anonymous statistical data that cannot be linked back to You. This anonymized data may be retained indefinitely for research and analytics.</li>
</ul>
<h3>Transfer of Your Personal Data</h3>
<p>Your information, including Personal Data, is processed at the Company's operating offices and in any other places where the parties involved in the processing are located. It means that this information may be transferred to — and maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where the data protection laws may differ from those from Your jurisdiction.</p>
<p>Where required by applicable law, We will ensure that international transfers of Your Personal Data are subject to appropriate safeguards and supplementary measures where appropriate. The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information.</p>
<h3>Delete Your Personal Data</h3>
<p>You have the right to delete or request that We assist in deleting the Personal Data that We have collected about You.</p>
<p>Our Service may give You the ability to delete certain information about You from within the Service.</p>
<p>You may update, amend, or delete Your information at any time by signing in to Your Account, if you have one, and visiting the account settings section that allows you to manage Your personal information. You may also contact Us to request access to, correct, or delete any Personal Data that You have provided to Us.</p>
<p>Please note, however, that We may need to retain certain information when we have a legal obligation or lawful basis to do so.</p>
<h3>Disclosure of Your Personal Data</h3>
<h4>Business Transactions</h4>
<p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be transferred. We will provide notice before Your Personal Data is transferred and becomes subject to a different Privacy Policy.</p>
<h4>Law enforcement</h4>
<p>Under certain circumstances, the Company may be required to disclose Your Personal Data if required to do so by law or in response to valid requests by public authorities (e.g. a court or a government agency).</p>
<h4>Other legal requirements</h4>
<p>The Company may disclose Your Personal Data in the good faith belief that such action is necessary to:</p>
<ul>
<li>Comply with a legal obligation</li>
<li>Protect and defend the rights or property of the Company</li>
<li>Prevent or investigate possible wrongdoing in connection with the Service</li>
<li>Protect the personal safety of Users of the Service or the public</li>
<li>Protect against legal liability</li>
</ul>
<h3>Security of Your Personal Data</h3>
<p>The security of Your Personal Data is important to Us, but remember that no method of transmission over the Internet, or method of electronic storage is 100% secure. While We strive to use commercially reasonable means to protect Your Personal Data, We cannot guarantee its absolute security.</p>
<h2>Links to Other Websites</h2>
<p>Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site You visit.</p>
<p>We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.</p>
<h2>Changes to this Privacy Policy</h2>
<p>We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page.</p>
<p>We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective and update the &quot;Last updated&quot; date at the top of this Privacy Policy.</p>
<p>You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.</p>
<h2>Contact Us</h2>
<p>If you have any questions about this Privacy Policy, You can contact us:</p>
<ul>
<li>By email: privacy@gleipnir.technology</li>
</ul>
</div>
{{end}}
{{ template "base.html" . }}
{{ define "title" }}Privacy Policy{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<div class="container">
<h1>Privacy Policy</h1>
<p>Last updated: January 20, 2026</p>
<p>
This Privacy Policy describes Our policies and procedures on the
collection, use and disclosure of Your information when You use the
Service and tells You about Your privacy rights and how the law protects
You.
</p>
<p>
We use Your Personal Data to provide and improve the Service. By using the
Service, You agree to the collection and use of information in accordance
with this Privacy Policy.
</p>
<h2>Interpretation and Definitions</h2>
<h3>Interpretation</h3>
<p>
The words whose initial letters are capitalized have meanings defined
under the following conditions. The following definitions shall have the
same meaning regardless of whether they appear in singular or in plural.
</p>
<h3>Definitions</h3>
<p>For the purposes of this Privacy Policy:</p>
<ul>
<li>
<p>
<strong>Account</strong> means a unique account created for You to
access our Service or parts of our Service.
</p>
</li>
<li>
<p>
<strong>Affiliate</strong> means an entity that controls, is
controlled by, or is under common control with a party, where
&quot;control&quot; means ownership of 50% or more of the shares,
equity interest or other securities entitled to vote for election of
directors or other managing authority.
</p>
</li>
<li>
<p>
<strong>Company</strong> (referred to as either &quot;the
Company&quot;, &quot;We&quot;, &quot;Us&quot; or &quot;Our&quot; in
this Privacy Policy) refers to {{ .Company }},
{{ .Address }}
</p>
</li>
<li>
<p>
<strong>Cookies</strong> are small files that are placed on Your
computer, mobile device or any other device by a website, containing
the details of Your browsing history on that website among its many
uses.
</p>
</li>
<li>
<p><strong>Country</strong> refers to: Arizona, United States</p>
</li>
<li>
<p>
<strong>Device</strong> means any device that can access the Service
such as a computer, a cell phone or a digital tablet.
</p>
</li>
<li>
<p>
<strong>Personal Data</strong> (or &quot;Personal Information&quot;)
is any information that relates to an identified or identifiable
individual.
</p>
<p>
We use &quot;Personal Data&quot; and &quot;Personal Information&quot;
interchangeably unless a law uses a specific term.
</p>
</li>
<li>
<p><strong>Service</strong> refers to the Website.</p>
</li>
<li>
<p>
<strong>Service Provider</strong> means any natural or legal person
who processes the data on behalf of the Company. It refers to
third-party companies or individuals employed by the Company to
facilitate the Service, to provide the Service on behalf of the
Company, to perform services related to the Service or to assist the
Company in analyzing how the Service is used.
</p>
</li>
<li>
<p>
<strong>Usage Data</strong> refers to data collected automatically,
either generated by the use of the Service or from the Service
infrastructure itself (for example, the duration of a page visit).
</p>
</li>
<li>
<p>
<strong>Website</strong> refers to {{ .Site }} accessible from
<a
href="{{ .URLReport }}"
rel="external nofollow noopener"
target="_blank"
>{{ .URLReport }}</a
>.
</p>
</li>
<li>
<p>
<strong>You</strong> means the individual accessing or using the
Service, or the company, or other legal entity on behalf of which such
individual is accessing or using the Service, as applicable.
</p>
</li>
</ul>
<h2>Collecting and Using Your Personal Data</h2>
<h3>Types of Data Collected</h3>
<h4>Personal Data</h4>
<p>
While using Our Service, We may ask You to provide Us with certain
personally identifiable information that can be used to contact or
identify You. Personally identifiable information may include, but is not
limited to:
</p>
<ul>
<li>Email address</li>
<li>First name and last name</li>
<li>Phone number</li>
<li>Address, State, Province, ZIP/Postal code, City</li>
</ul>
<h4>Usage Data</h4>
<p>Usage Data is collected automatically when using the Service.</p>
<p>
Usage Data may include information such as Your Device's Internet Protocol
address (e.g. IP address), browser type, browser version, the pages of our
Service that You visit, the time and date of Your visit, the time spent on
those pages, unique device identifiers and other diagnostic data.
</p>
<p>
When You access the Service by or through a mobile device, We may collect
certain information automatically, including, but not limited to, the type
of mobile device You use, Your mobile device's unique ID, the IP address
of Your mobile device, Your mobile operating system, the type of mobile
Internet browser You use, unique device identifiers and other diagnostic
data.
</p>
<p>
We may also collect information that Your browser sends whenever You visit
Our Service or when You access the Service by or through a mobile device.
</p>
<h4>Tracking Technologies and Cookies</h4>
<p>
We use Cookies and similar tracking technologies to track the activity on
Our Service and store certain information. Tracking technologies We use
include beacons, tags, and scripts to collect and track information and to
improve and analyze Our Service. The technologies We use may include:
</p>
<ul>
<li>
<strong>Cookies or Browser Cookies.</strong> A cookie is a small file
placed on Your Device. You can instruct Your browser to refuse all
Cookies or to indicate when a Cookie is being sent. However, if You do
not accept Cookies, You may not be able to use some parts of our
Service.
</li>
</ul>
<p>
Cookies can be &quot;Persistent&quot; or &quot;Session&quot; Cookies.
Persistent Cookies remain on Your personal computer or mobile device when
You go offline, while Session Cookies are deleted as soon as You close
Your web browser.
</p>
<p>
Where required by law, we use non-essential cookies (such as analytics,
advertising, and remarketing cookies) only with Your consent. You can
withdraw or change Your consent at any time using Our cookie preferences
tool (if available) or through Your browser/device settings. Withdrawing
consent does not affect the lawfulness of processing based on consent
before its withdrawal.
</p>
<p>
We use both Session and Persistent Cookies for the purposes set out below:
</p>
<ul>
<li>
<p><strong>Necessary / Essential Cookies</strong></p>
<p>Type: Session Cookies</p>
<p>Administered by: Us</p>
<p>
Purpose: These Cookies are essential to provide You with services
available through the Website and to enable You to use some of its
features. They help to authenticate users and prevent fraudulent use
of user accounts. Without these Cookies, the services that You have
asked for cannot be provided, and We only use these Cookies to provide
You with those services.
</p>
</li>
<li>
<p><strong>Functionality Cookies</strong></p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>
Purpose: These Cookies allow Us to remember choices You make when You
use the Website, such as remembering your login details or language
preference. The purpose of these Cookies is to provide You with a more
personal experience and to avoid You having to re-enter your
preferences every time You use the Website.
</p>
</li>
</ul>
<p>
For more information about the cookies we use and your choices regarding
cookies, please visit our Cookies Policy or the Cookies section of Our
Privacy Policy.
</p>
<h3>Use of Your Personal Data</h3>
<p>The Company may use Personal Data for the following purposes:</p>
<ul>
<li>
<p>
<strong>To provide and maintain our Service</strong>, including to
monitor the usage of our Service.
</p>
</li>
<li>
<p>
<strong>To manage Your Account:</strong> to manage Your registration
as a user of the Service. The Personal Data You provide can give You
access to different functionalities of the Service that are available
to You as a registered user.
</p>
</li>
<li>
<p>
<strong>For the performance of a contract:</strong> the development,
compliance and undertaking of the purchase contract for the products,
items or services You have purchased or of any other contract with Us
through the Service.
</p>
</li>
<li>
<p>
<strong>To contact You:</strong> To contact You by email, telephone
calls, SMS, or other equivalent forms of electronic communication,
such as a mobile application's push notifications regarding updates or
informative communications related to the functionalities, products or
contracted services, including the security updates, when necessary or
reasonable for their implementation.
</p>
</li>
<li>
<p>
<strong>To provide You</strong> with news, special offers, and general
information about other goods, services and events which We offer that
are similar to those that you have already purchased or inquired about
unless You have opted not to receive such information.
</p>
</li>
<li>
<p>
<strong>To manage Your requests:</strong> To attend and manage Your
requests to Us.
</p>
</li>
<li>
<p>
<strong>For business transfers:</strong> We may use Your Personal Data
to evaluate or conduct a merger, divestiture, restructuring,
reorganization, dissolution, or other sale or transfer of some or all
of Our assets, whether as a going concern or as part of bankruptcy,
liquidation, or similar proceeding, in which Personal Data held by Us
about our Service users is among the assets transferred.
</p>
</li>
<li>
<p>
<strong>For other purposes</strong>: We may use Your information for
other purposes, such as data analysis, identifying usage trends,
determining the effectiveness of our promotional campaigns and to
evaluate and improve our Service, products, services, marketing and
your experience.
</p>
</li>
</ul>
<p>We may share Your Personal Data in the following situations:</p>
<ul>
<li>
<strong>With Service Providers:</strong> We may share Your Personal Data
with Service Providers to monitor and analyze the use of our Service, to
contact You.
</li>
<li>
<strong>For business transfers:</strong> We may share or transfer Your
Personal Data in connection with, or during negotiations of, any merger,
sale of Company assets, financing, or acquisition of all or a portion of
Our business to another company.
</li>
<li>
<strong>With Affiliates:</strong> We may share Your Personal Data with
Our affiliates, in which case we will require those affiliates to honor
this Privacy Policy. Affiliates include Our parent company and any other
subsidiaries, joint venture partners or other companies that We control
or that are under common control with Us.
</li>
<li>
<strong>With business partners:</strong> We may share Your Personal Data
with Our business partners to offer You certain products, services or
promotions.
</li>
<li>
<strong>With other users:</strong> If Our Service offers public areas,
when You share Personal Data or otherwise interact in the public areas
with other users, such information may be viewed by all users and may be
publicly distributed outside.
</li>
<li>
<strong>With Your consent</strong>: We may disclose Your Personal Data
for any other purpose with Your consent.
</li>
</ul>
<h3>Retention of Your Personal Data</h3>
<p>
The Company will retain Your Personal Data only for as long as is
necessary for the purposes set out in this Privacy Policy. We will retain
and use Your Personal Data to the extent necessary to comply with our
legal obligations (for example, if We are required to retain Your data to
comply with applicable laws), resolve disputes, and enforce our legal
agreements and policies.
</p>
<p>
Where possible, We apply shorter retention periods and/or reduce
identifiability by deleting, aggregating, or anonymizing data. Unless
otherwise stated, the retention periods below are maximum periods
(&quot;up to&quot;) and We may delete or anonymize data sooner when it is
no longer needed for the relevant purpose. We apply different retention
periods to different categories of Personal Data based on the purpose of
processing and legal obligations:
</p>
<ul>
<li>
<p>Account Information</p>
<ul>
<li>
User Accounts: retained for the duration of your account
relationship plus up to 24 months after account closure to handle
any post-termination issues or resolve disputes.
</li>
</ul>
</li>
<li>
<p>Customer Support Data</p>
<ul>
<li>
Support tickets and correspondence: up to 24 months from the date of
ticket closure to resolve follow-up inquiries, track service
quality, and defend against potential legal claims
</li>
<li>
Chat transcripts: up to 24 months for quality assurance and staff
training purposes.
</li>
</ul>
</li>
<li>
<p>Usage Data</p>
<ul>
<li>
<p>
Website analytics data (cookies, IP addresses, device
identifiers): up to 24 months from the date of collection, which
allows us to analyze trends while respecting privacy principles.
</p>
</li>
<li>
<p>
Server logs (IP addresses, access times): up to 24 months for
security monitoring and troubleshooting purposes.
</p>
</li>
</ul>
</li>
</ul>
<p>
Usage Data is retained in accordance with the retention periods described
above, and may be retained longer only where necessary for security, fraud
prevention, or legal compliance.
</p>
<p>
We may retain Personal Data beyond the periods stated above for different
reasons:
</p>
<ul>
<li>
Legal obligation: We are required by law to retain specific data (e.g.,
financial records for tax authorities).
</li>
<li>
Legal claims: Data is necessary to establish, exercise, or defend legal
claims.
</li>
<li>Your explicit request: You ask Us to retain specific information.</li>
<li>
Technical limitations: Data exists in backup systems that are scheduled
for routine deletion.
</li>
</ul>
<p>
You may request information about how long We will retain Your Personal
Data by contacting Us.
</p>
<p>
When retention periods expire, We securely delete or anonymize Personal
Data according to the following procedures:
</p>
<ul>
<li>
Deletion: Personal Data is removed from Our systems and no longer
actively processed.
</li>
<li>
Backup retention: Residual copies may remain in encrypted backups for a
limited period consistent with our backup retention schedule and are not
restored except where necessary for security, disaster recovery, or
legal compliance.
</li>
<li>
Anonymization: In some cases, We convert Personal Data into anonymous
statistical data that cannot be linked back to You. This anonymized data
may be retained indefinitely for research and analytics.
</li>
</ul>
<h3>Transfer of Your Personal Data</h3>
<p>
Your information, including Personal Data, is processed at the Company's
operating offices and in any other places where the parties involved in
the processing are located. It means that this information may be
transferred to — and maintained on — computers located outside of Your
state, province, country or other governmental jurisdiction where the data
protection laws may differ from those from Your jurisdiction.
</p>
<p>
Where required by applicable law, We will ensure that international
transfers of Your Personal Data are subject to appropriate safeguards and
supplementary measures where appropriate. The Company will take all steps
reasonably necessary to ensure that Your data is treated securely and in
accordance with this Privacy Policy and no transfer of Your Personal Data
will take place to an organization or a country unless there are adequate
controls in place including the security of Your data and other personal
information.
</p>
<h3>Delete Your Personal Data</h3>
<p>
You have the right to delete or request that We assist in deleting the
Personal Data that We have collected about You.
</p>
<p>
Our Service may give You the ability to delete certain information about
You from within the Service.
</p>
<p>
You may update, amend, or delete Your information at any time by signing
in to Your Account, if you have one, and visiting the account settings
section that allows you to manage Your personal information. You may also
contact Us to request access to, correct, or delete any Personal Data that
You have provided to Us.
</p>
<p>
Please note, however, that We may need to retain certain information when
we have a legal obligation or lawful basis to do so.
</p>
<h3>Disclosure of Your Personal Data</h3>
<h4>Business Transactions</h4>
<p>
If the Company is involved in a merger, acquisition or asset sale, Your
Personal Data may be transferred. We will provide notice before Your
Personal Data is transferred and becomes subject to a different Privacy
Policy.
</p>
<h4>Law enforcement</h4>
<p>
Under certain circumstances, the Company may be required to disclose Your
Personal Data if required to do so by law or in response to valid requests
by public authorities (e.g. a court or a government agency).
</p>
<h4>Other legal requirements</h4>
<p>
The Company may disclose Your Personal Data in the good faith belief that
such action is necessary to:
</p>
<ul>
<li>Comply with a legal obligation</li>
<li>Protect and defend the rights or property of the Company</li>
<li>
Prevent or investigate possible wrongdoing in connection with the
Service
</li>
<li>Protect the personal safety of Users of the Service or the public</li>
<li>Protect against legal liability</li>
</ul>
<h3>Security of Your Personal Data</h3>
<p>
The security of Your Personal Data is important to Us, but remember that
no method of transmission over the Internet, or method of electronic
storage is 100% secure. While We strive to use commercially reasonable
means to protect Your Personal Data, We cannot guarantee its absolute
security.
</p>
<h2>Links to Other Websites</h2>
<p>
Our Service may contain links to other websites that are not operated by
Us. If You click on a third party link, You will be directed to that third
party's site. We strongly advise You to review the Privacy Policy of every
site You visit.
</p>
<p>
We have no control over and assume no responsibility for the content,
privacy policies or practices of any third party sites or services.
</p>
<h2>Changes to this Privacy Policy</h2>
<p>
We may update Our Privacy Policy from time to time. We will notify You of
any changes by posting the new Privacy Policy on this page.
</p>
<p>
We will let You know via email and/or a prominent notice on Our Service,
prior to the change becoming effective and update the &quot;Last
updated&quot; date at the top of this Privacy Policy.
</p>
<p>
You are advised to review this Privacy Policy periodically for any
changes. Changes to this Privacy Policy are effective when they are posted
on this page.
</p>
<h2>Contact Us</h2>
<p>
If you have any questions about this Privacy Policy, You can contact us:
</p>
<ul>
<li>By email: privacy@gleipnir.technology</li>
</ul>
</div>
{{ end }}

View file

@ -1,130 +1,228 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Quick Report Complete{{end}}
{{define "extraheader"}}
<style>
</style>
<script>
</script>
{{end}}
{{define "content"}}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-check-circle-fill me-2" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>
Report Successfully Submitted
</h3>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<p class="lead">Thank you for helping us control mosquito populations in your area!</p>
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{.ReportID|publicReportID}}</span>
{{ define "title" }}Quick Report Complete{{ end }}
{{ define "extraheader" }}
<style></style>
<script></script>
{{ end }}
{{ define "content" }}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-check-circle-fill me-2"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg>
Report Successfully Submitted
</h3>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<p class="lead">
Thank you for helping us control mosquito populations in your
area!
</p>
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{ .ReportID|publicReportID }}</span>
</div>
<p class="text-muted">Please save this ID for your reference.</p>
{{ if not (eq .District nil) }}
<p>Your report has been assigned to</p>
<p><b>{{ .District.Name }}</b></p>
<img src="{{ .District.LogoURL }}" width="256" />
{{ end }}
</div>
<p class="text-muted">Please save this ID for your reference.</p>
{{ if not (eq .District nil) }}
<p>Your report has been assigned to</p>
<p><b>{{ .District.Name }}</b></p>
<img src="{{ .District.LogoURL }}" width="256"/>
{{ end }}
</div>
<hr class="my-4">
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-search me-2" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
</svg>
Check Your Report Status
</h4>
<p>You can check the status of your report at any time using your Report ID.</p>
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary">
Check Status
</a>
</div>
<hr class="my-4">
<!-- Notifications Section -->
<div>
<h4 class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-bell me-2" viewBox="0 0 16 16">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"/>
</svg>
Get Updates
</h4>
<p>Provide your contact information to receive updates about your report.</p>
<form id="notificationForm" action="/register-notifications" method="post" class="needs-validation">
<input type="hidden" name="report_id" value="{{.ReportID}}">
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
</svg>
</span>
<input type="email" class="form-control" id="email" name="email" placeholder="your@email.com">
<hr class="my-4" />
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-search me-2"
viewBox="0 0 16 16"
>
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
/>
</svg>
Check Your Report Status
</h4>
<p>
You can check the status of your report at any time using your
Report ID.
</p>
<a href="/status/{{ .ReportID }}" class="btn btn-outline-primary">
Check Status
</a>
</div>
<hr class="my-4" />
<!-- Notifications Section -->
<div>
<h4 class="mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-bell me-2"
viewBox="0 0 16 16"
>
<path
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zM8 1.918l-.797.161A4.002 4.002 0 0 0 4 6c0 .628-.134 2.197-.459 3.742-.16.767-.376 1.566-.663 2.258h10.244c-.287-.692-.502-1.49-.663-2.258C12.134 8.197 12 6.628 12 6a4.002 4.002 0 0 0-3.203-3.92L8 1.917zM14.22 12c.223.447.481.801.78 1H1c.299-.199.557-.553.78-1C2.68 10.2 3 6.88 3 6c0-2.42 1.72-4.44 4.005-4.901a1 1 0 1 1 1.99 0A5.002 5.002 0 0 1 13 6c0 .88.32 4.2 1.22 6z"
/>
</svg>
Get Updates
</h4>
<p>
Provide your contact information to receive updates about your
report.
</p>
<form
id="notificationForm"
action="/register-notifications"
method="post"
class="needs-validation"
>
<input type="hidden" name="report_id" value="{{ .ReportID }}" />
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope"
viewBox="0 0 16 16"
>
<path
d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"
/>
</svg>
</span>
<input
type="email"
class="form-control"
id="email"
name="email"
placeholder="your@email.com"
/>
</div>
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone Number (for SMS updates)</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-phone" viewBox="0 0 16 16">
<path d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</svg>
</span>
<input type="tel" class="form-control" id="phone" name="phone" placeholder="(123) 456-7890">
<div class="mb-3">
<label for="phone" class="form-label"
>Phone Number (for SMS updates)</label
>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-phone"
viewBox="0 0 16 16"
>
<path
d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"
/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />
</svg>
</span>
<input
type="tel"
class="form-control"
id="phone"
name="phone"
placeholder="(123) 456-7890"
/>
</div>
</div>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" type="checkbox" name="consent" required>
<label class="form-check-label" for="consent">
I consent to receiving updates about this report
</label>
<div class="invalid-feedback">
You must consent to receive notifications.
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
type="checkbox"
name="consent"
required
/>
<label class="form-check-label" for="consent">
I consent to receiving updates about this report
</label>
<div class="invalid-feedback">
You must consent to receive notifications.
</div>
</div>
</div>
<button type="submit" class="btn btn-primary">Register for Updates</button>
</form>
<button type="submit" class="btn btn-primary">
Register for Updates
</button>
</form>
</div>
</div>
</div>
</div>
<!-- Navigation Links -->
<div class="text-center">
<a href="/" class="btn btn-outline-secondary me-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house me-1" viewBox="0 0 16 16">
<path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.707 1.5ZM13 7.207V13.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V7.207l5-5 5 5Z"/>
</svg>
Return to Home
</a>
<a href="/report-mosquito" class="btn btn-outline-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle me-1" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg>
Submit Another Report
</a>
<!-- Navigation Links -->
<div class="text-center">
<a href="/" class="btn btn-outline-secondary me-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-house me-1"
viewBox="0 0 16 16"
>
<path
d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.707 1.5ZM13 7.207V13.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V7.207l5-5 5 5Z"
/>
</svg>
Return to Home
</a>
<a href="/report-mosquito" class="btn btn-outline-success">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-plus-circle me-1"
viewBox="0 0 16 16"
>
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"
/>
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"
/>
</svg>
Submit Another Report
</a>
</div>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,193 +1,240 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Quick Report{{end}}
{{define "extraheader"}}
{{template "photo-upload-header"}}
<style>
.district-logo {
max-height: 60px;
width: auto;
}
.submit-btn {
padding: 15px 0;
font-size: 1.25rem;
border-radius: 8px;
}
.location-info {
background-color: #e9f5ff;
border-radius: 8px;
padding: 12px;
margin-bottom: 20px;
font-size: 0.9rem;
}
@media (max-width: 767px) {
.header-title {
font-size: 1.5rem;
}
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Elements
const form = document.getElementById('mosquitoReportForm');
const locationStatus = document.getElementById('locationStatus');
const latitudeInput = document.getElementById('latitude');
const longitudeInput = document.getElementById('longitude');
const submitButton = document.getElementById('submitButton');
const loadingOverlay = document.getElementById('loadingOverlay');
// Get current location
requestLocation();
// Handle form submission
form.addEventListener('submit', handleFormSubmission);
/**
* Request user's geolocation
*/
function requestLocation() {
if (navigator.geolocation) {
locationStatus.textContent = "Requesting your location...";
navigator.geolocation.getCurrentPosition(
// Success callback
function(position) {
locationStatus.textContent = "Location successfully added";
locationStatus.classList.add('text-success');
// Store location in hidden fields
latitudeInput.value = position.coords.latitude;
longitudeInput.value = position.coords.longitude;
},
// Error callback
function(error) {
let errorMessage = "Unable to get your location";
switch(error.code) {
case error.PERMISSION_DENIED:
errorMessage = "Location access denied. Please enable location services.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information unavailable.";
break;
case error.TIMEOUT:
errorMessage = "Location request timed out.";
break;
}
locationStatus.textContent = errorMessage;
locationStatus.classList.add('text-danger');
},
// Options
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
}
);
} else {
locationStatus.textContent = "Geolocation is not supported by your browser";
locationStatus.classList.add('text-danger');
{{ define "title" }}Quick Report{{ end }}
{{ define "extraheader" }}
{{ template "photo-upload-header" }}
<style>
.district-logo {
max-height: 60px;
width: auto;
}
}
/**
* Handle form submission
*/
function handleFormSubmission(event) {
event.preventDefault();
.submit-btn {
padding: 15px 0;
font-size: 1.25rem;
border-radius: 8px;
}
// Show loading overlay
loadingOverlay.classList.remove('d-none');
.location-info {
background-color: #e9f5ff;
border-radius: 8px;
padding: 12px;
margin-bottom: 20px;
font-size: 0.9rem;
}
// Disable submit button to prevent double submission
submitButton.disabled = true;
// Create FormData object
const formData = new FormData(form);
// Send AJAX request
fetch(form.action, {
method: 'POST',
body: formData,
})
.then(response => {
if (response.ok) {
// Navigate to the URL the server specified
window.location.href = response.url;
return;
@media (max-width: 767px) {
.header-title {
font-size: 1.5rem;
}
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function () {
// Elements
const form = document.getElementById("mosquitoReportForm");
const locationStatus = document.getElementById("locationStatus");
const latitudeInput = document.getElementById("latitude");
const longitudeInput = document.getElementById("longitude");
const submitButton = document.getElementById("submitButton");
const loadingOverlay = document.getElementById("loadingOverlay");
// Get current location
requestLocation();
// Handle form submission
form.addEventListener("submit", handleFormSubmission);
/**
* Request user's geolocation
*/
function requestLocation() {
if (navigator.geolocation) {
locationStatus.textContent = "Requesting your location...";
navigator.geolocation.getCurrentPosition(
// Success callback
function (position) {
locationStatus.textContent = "Location successfully added";
locationStatus.classList.add("text-success");
// Store location in hidden fields
latitudeInput.value = position.coords.latitude;
longitudeInput.value = position.coords.longitude;
},
// Error callback
function (error) {
let errorMessage = "Unable to get your location";
switch (error.code) {
case error.PERMISSION_DENIED:
errorMessage =
"Location access denied. Please enable location services.";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "Location information unavailable.";
break;
case error.TIMEOUT:
errorMessage = "Location request timed out.";
break;
}
locationStatus.textContent = errorMessage;
locationStatus.classList.add("text-danger");
},
// Options
{
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0,
},
);
} else {
locationStatus.textContent =
"Geolocation is not supported by your browser";
locationStatus.classList.add("text-danger");
}
}
/**
* Handle form submission
*/
function handleFormSubmission(event) {
event.preventDefault();
// Show loading overlay
loadingOverlay.classList.remove("d-none");
// Disable submit button to prevent double submission
submitButton.disabled = true;
// Create FormData object
const formData = new FormData(form);
// Send AJAX request
fetch(form.action, {
method: "POST",
body: formData,
})
.then((response) => {
if (response.ok) {
// Navigate to the URL the server specified
window.location.href = response.url;
return;
}
console.error("not ok server response", response);
throw new Error("Server error " + response.status);
})
.catch((error) => {
console.error("Error:", error);
alert(
"There was a problem submitting your report. Please try again. If this happens a few times, please let us know.",
);
// Re-enable submit button
submitButton.disabled = false;
// Hide loading overlay
loadingOverlay.classList.add("d-none");
});
}
console.error("not ok server response", response);
throw new Error("Server error " + response.status);
})
.catch(error => {
console.error('Error:', error);
alert('There was a problem submitting your report. Please try again. If this happens a few times, please let us know.');
// Re-enable submit button
submitButton.disabled = false;
// Hide loading overlay
loadingOverlay.classList.add('d-none');
});
}
});
</script>
{{end}}
{{define "content"}}
<!-- Main Content -->
<main class="container mb-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-body p-4">
<h2 class="card-title text-center mb-4">Quick Mosquito Report</h2>
</script>
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main class="container mb-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card shadow-sm">
<div class="card-body p-4">
<h2 class="card-title text-center mb-4">Quick Mosquito Report</h2>
<!-- Form -->
<form id="mosquitoReportForm" action="/quick-submit" method="POST" enctype="multipart/form-data">
<!-- Location Automatic Collection Note -->
<div class="location-info d-flex align-items-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-geo-alt me-2" viewBox="0 0 16 16">
<path d="M12.166 8.94c-.524 1.062-1.234 2.12-1.96 3.07A31.493 31.493 0 0 1 8 14.58a31.481 31.481 0 0 1-2.206-2.57c-.726-.95-1.436-2.008-1.96-3.07C3.304 7.867 3 6.862 3 6a5 5 0 0 1 10 0c0 .862-.305 1.867-.834 2.94zM8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10z"/>
<path d="M8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 1a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
</svg>
<span id="locationStatus">Requesting your location...</span>
<!-- Hidden fields for location data -->
<input type="hidden" id="latitude" name="latitude">
<input type="hidden" id="longitude" name="longitude">
</div>
<!-- Form -->
<form
id="mosquitoReportForm"
action="/quick-submit"
method="POST"
enctype="multipart/form-data"
>
<!-- Location Automatic Collection Note -->
<div class="location-info d-flex align-items-center mb-4">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-geo-alt me-2"
viewBox="0 0 16 16"
>
<path
d="M12.166 8.94c-.524 1.062-1.234 2.12-1.96 3.07A31.493 31.493 0 0 1 8 14.58a31.481 31.481 0 0 1-2.206-2.57c-.726-.95-1.436-2.008-1.96-3.07C3.304 7.867 3 6.862 3 6a5 5 0 0 1 10 0c0 .862-.305 1.867-.834 2.94zM8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10z"
/>
<path
d="M8 8a2 2 0 1 1 0-4 2 2 0 0 1 0 4zm0 1a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"
/>
</svg>
<span id="locationStatus">Requesting your location...</span>
<!-- Hidden fields for location data -->
<input type="hidden" id="latitude" name="latitude" />
<input type="hidden" id="longitude" name="longitude" />
</div>
<!-- Photo Upload -->
<div class="mb-4">
{{template "photo-upload"}}
</div>
<!-- Photo Upload -->
<div class="mb-4">
{{ template "photo-upload" }}
</div>
<!-- Comments -->
<div class="mb-4">
<label for="comments" class="form-label fw-bold">Comments</label>
<textarea class="form-control" id="comments" name="comments" rows="4" placeholder="Describe the mosquito issue (e.g., standing water, high mosquito activity, time of day they're most active)"></textarea>
</div>
<!-- Comments -->
<div class="mb-4">
<label for="comments" class="form-label fw-bold"
>Comments</label
>
<textarea
class="form-control"
id="comments"
name="comments"
rows="4"
placeholder="Describe the mosquito issue (e.g., standing water, high mosquito activity, time of day they're most active)"
></textarea>
</div>
<!-- Submit Button -->
<button type="submit" class="btn btn-success w-100 submit-btn mt-4" id="submitButton">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-send-fill me-2" viewBox="0 0 16 16">
<path d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z"/>
</svg>
Submit Report
</button>
</form>
<!-- Submit Button -->
<button
type="submit"
class="btn btn-success w-100 submit-btn mt-4"
id="submitButton"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-send-fill me-2"
viewBox="0 0 16 16"
>
<path
d="M15.964.686a.5.5 0 0 0-.65-.65L.767 5.855H.766l-.452.18a.5.5 0 0 0-.082.887l.41.26.001.002 4.995 3.178 3.178 4.995.002.002.26.41a.5.5 0 0 0 .886-.083l6-15Zm-1.833 1.89L6.637 10.07l-.215-.338a.5.5 0 0 0-.154-.154l-.338-.215 7.494-7.494 1.178-.471-.47 1.178Z"
/>
</svg>
Submit Report
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
</main>
<!-- Loading Indicator Overlay (Initially hidden) -->
<div id="loadingOverlay" class="position-fixed top-0 start-0 w-100 h-100 d-none" style="background-color: rgba(0,0,0,0.5); z-index: 1050;">
<div class="position-absolute top-50 start-50 translate-middle text-white text-center">
<div class="spinner-border" role="status"></div>
<p class="mt-2">Submitting your report...</p>
<!-- Loading Indicator Overlay (Initially hidden) -->
<div
id="loadingOverlay"
class="position-fixed top-0 start-0 w-100 h-100 d-none"
style="background-color: rgba(0,0,0,0.5); z-index: 1050;"
>
<div
class="position-absolute top-50 start-50 translate-middle text-white text-center"
>
<div class="spinner-border" role="status"></div>
<p class="mt-2">Submitting your report...</p>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,95 +1,172 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Notification Request Complete{{end}}
{{define "extraheader"}}
<style>
</style>
<script>
</script>
{{end}}
{{define "content"}}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-7">
<!-- Confirmation Card -->
<div class="card shadow-sm border-info mb-4">
<div class="card-header bg-info text-white">
<h3 class="my-2">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-bell-fill me-2" viewBox="0 0 16 16">
<path d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zm.995-14.901a1 1 0 1 0-1.99 0A5.002 5.002 0 0 0 3 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"/>
</svg>
Notifications Registered
</h3>
</div>
<div class="card-body p-4 text-center">
<div class="mb-4">
<div class="display-1 text-info mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
{{ define "title" }}Notification Request Complete{{ end }}
{{ define "extraheader" }}
<style></style>
<script></script>
{{ end }}
{{ define "content" }}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-7">
<!-- Confirmation Card -->
<div class="card shadow-sm border-info mb-4">
<div class="card-header bg-info text-white">
<h3 class="my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-bell-fill me-2"
viewBox="0 0 16 16"
>
<path
d="M8 16a2 2 0 0 0 2-2H6a2 2 0 0 0 2 2zm.995-14.901a1 1 0 1 0-1.99 0A5.002 5.002 0 0 0 3 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"
/>
</svg>
</div>
<h4 class="mb-3">Thank You!</h4>
<p class="lead">Your contact information has been successfully registered for report updates.</p>
<div class="alert alert-secondary py-3 mt-3">
<strong>Report ID:</strong>
<span class="fs-5">{{.ReportID|publicReportID}}</span>
</div>
Notifications Registered
</h3>
</div>
<hr class="my-4">
<!-- What to Expect Section -->
<div class="text-start mb-4">
<h5>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor" class="bi bi-info-circle me-2" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
</svg>
What to Expect
</h5>
<ul class="list-group list-group-flush">
<li class="list-group-item bg-transparent">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope-check me-2 text-success" viewBox="0 0 16 16">
<path d="M2 2a2 2 0 0 0-2 2v8.01A2 2 0 0 0 2 14h5.5a.5.5 0 0 0 0-1H2a1 1 0 0 1-.966-.741l5.64-3.471L8 9.583l7-4.2V8.5a.5.5 0 0 0 1 0V4a2 2 0 0 0-2-2H2Zm3.708 6.208L1 11.105V5.383l4.708 2.825ZM1 4.217V4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v.217l-7 4.2-7-4.2Z"/>
<path d="M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Zm-1.993-1.679a.5.5 0 0 0-.686.172l-1.17 1.95-.547-.547a.5.5 0 0 0-.708.708l.774.773a.75.75 0 0 0 1.174-.144l1.335-2.226a.5.5 0 0 0-.172-.686Z"/>
<div class="card-body p-4 text-center">
<div class="mb-4">
<div class="display-1 text-info mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="80"
height="80"
fill="currentColor"
class="bi bi-check-circle-fill"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg>
A confirmation message has been sent to your contact information.
</li>
<li class="list-group-item bg-transparent">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard-check me-2 text-success" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10.854 7.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 9.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>
<path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
<path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
</div>
<h4 class="mb-3">Thank You!</h4>
<p class="lead">
Your contact information has been successfully registered for
report updates.
</p>
<div class="alert alert-secondary py-3 mt-3">
<strong>Report ID:</strong>
<span class="fs-5">{{ .ReportID|publicReportID }}</span>
</div>
</div>
<hr class="my-4" />
<!-- What to Expect Section -->
<div class="text-start mb-4">
<h5>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
fill="currentColor"
class="bi bi-info-circle me-2"
viewBox="0 0 16 16"
>
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"
/>
<path
d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"
/>
</svg>
You will receive updates when:
<ul class="mt-2">
<li>Your report is assigned to a specialist</li>
<li>A site visit is scheduled</li>
<li>Treatment or remediation is completed</li>
<li>The case is resolved</li>
</ul>
</li>
<li class="list-group-item bg-transparent">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search me-2 text-success" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
What to Expect
</h5>
<ul class="list-group list-group-flush">
<li class="list-group-item bg-transparent">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope-check me-2 text-success"
viewBox="0 0 16 16"
>
<path
d="M2 2a2 2 0 0 0-2 2v8.01A2 2 0 0 0 2 14h5.5a.5.5 0 0 0 0-1H2a1 1 0 0 1-.966-.741l5.64-3.471L8 9.583l7-4.2V8.5a.5.5 0 0 0 1 0V4a2 2 0 0 0-2-2H2Zm3.708 6.208L1 11.105V5.383l4.708 2.825ZM1 4.217V4a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v.217l-7 4.2-7-4.2Z"
/>
<path
d="M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Zm-1.993-1.679a.5.5 0 0 0-.686.172l-1.17 1.95-.547-.547a.5.5 0 0 0-.708.708l.774.773a.75.75 0 0 0 1.174-.144l1.335-2.226a.5.5 0 0 0-.172-.686Z"
/>
</svg>
A confirmation message has been sent to your contact
information.
</li>
<li class="list-group-item bg-transparent">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-clipboard-check me-2 text-success"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M10.854 7.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 9.793l2.646-2.647a.5.5 0 0 1 .708 0z"
/>
<path
d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"
/>
<path
d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"
/>
</svg>
You will receive updates when:
<ul class="mt-2">
<li>Your report is assigned to a specialist</li>
<li>A site visit is scheduled</li>
<li>Treatment or remediation is completed</li>
<li>The case is resolved</li>
</ul>
</li>
<li class="list-group-item bg-transparent">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-search me-2 text-success"
viewBox="0 0 16 16"
>
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
/>
</svg>
You can check your report status anytime using your Report ID.
</li>
</ul>
</div>
<!-- Navigation Buttons -->
<div class="mt-4">
<a
href="/status/{{ .ReportID }}"
class="btn btn-outline-primary me-2"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-search me-1"
viewBox="0 0 16 16"
>
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
/>
</svg>
You can check your report status anytime using your Report ID.
</li>
</ul>
</div>
<!-- Navigation Buttons -->
<div class="mt-4">
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary me-2">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search me-1" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
</svg>
Check Report Status
</a>
Check Report Status
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,84 +1,105 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Main{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<!-- Main Content -->
<main>
{{ if eq .District nil }}
<!-- Introduction Section -->
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg"/>
</div>
</section>
{{ else }}
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<h2 class="text-center mb-4">Report a Mosquito Problem</h2>
<p class="lead text-center">Submit a report to help reduce mosquito activity in your neighborhood.</p>
<p class="lead text-center">Report Mosquitoes Online works with local mosquito control agencies to receive public reports.</p>
{{ if not (eq .District nil) }}
<p class="lead text-center">For this area, mosquito control services are provided by</p>
<h3 class="text-center">{{.District.Name}}</h3>
<img class="district-logo" src="{{.District.URLLogo}}" />
{{ end }}
{{ define "title" }}Main{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<!-- Main Content -->
<main>
{{ if eq .District nil }}
<!-- Introduction Section -->
<section class="py-2 bg-primary text-white">
<div class="banner-container d-flex justify-content-center">
<img class="banner" src="/static/img/rmo/banner.jpg" />
</div>
</section>
{{ else }}
<!-- Introduction Section -->
<section class="py-5 bg-primary text-white">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-10">
<h2 class="text-center mb-4">Report a Mosquito Problem</h2>
<p class="lead text-center">
Submit a report to help reduce mosquito activity in your
neighborhood.
</p>
<p class="lead text-center">
Report Mosquitoes Online works with local mosquito control
agencies to receive public reports.
</p>
{{ if not (eq .District nil) }}
<p class="lead text-center">
For this area, mosquito control services are provided by
</p>
<h3 class="text-center">{{ .District.Name }}</h3>
<img class="district-logo" src="{{ .District.URLLogo }}" />
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito-color.svg" }}
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">
Report areas with high adult mosquito activity causing
discomfort or concern.
</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3"
>Report Problem</a
>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond-color.svg" }}
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">
Report any water that has been sitting for several days, where
mosquitoes can live.
</p>
<a href="{{ .URL.Water }}" class="btn btn-primary mt-3"
>Report Source</a
>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report-color.svg" }}
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">
Check on a previous request or view current mosquito activity
in your area.
</p>
<a href="{{ .URL.Status }}" class="btn btn-primary mt-3"
>Get Status</a
>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
{{ end }}
<!-- Services Section -->
<section class="py-5">
<div class="container">
<h3 class="text-center mb-4">How Can We Help You Today?</h3>
<div class="row g-4">
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "mosquito-color.svg" }}
</div>
<h4 class="card-title">Report Mosquito Nuisance</h4>
<p class="card-text">Report areas with high adult mosquito activity causing discomfort or concern.</p>
<a href="{{ .URL.Nuisance }}" class="btn btn-primary mt-3">Report Problem</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "pond-color.svg" }}
</div>
<h4 class="card-title">Report Standing Water</h4>
<p class="card-text">Report any water that has been sitting for several days, where mosquitoes can live.</p>
<a href="{{ .URL.Water }}" class="btn btn-primary mt-3">Report Source</a>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
{{ template "check-report-color.svg" }}
</div>
<h4 class="card-title">Follow-up or Check Status</h4>
<p class="card-text">Check on a previous request or view current mosquito activity in your area.</p>
<a href="{{ .URL.Status }}" class="btn btn-primary mt-3">Get Status</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
{{end}}
</section>
</main>
{{ end }}

View file

@ -1,45 +1,45 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Status of report {{.Report.ID|publicReportID}}{{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/map-with-markers.js"></script>
<style>
.timeline {
border-left: 3px solid #dee2e6;
padding-left: 20px;
margin-left: 10px;
}
.timeline-item {
position: relative;
margin-bottom: 25px;
}
.timeline-item:before {
content: '';
position: absolute;
left: -29px;
top: 0;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: #0d6efd;
}
.timeline-date {
font-size: 0.85rem;
color: #6c757d;
}
.map-container {
height: 300px;
}
@media (max-width: 768px) {
.map-container {
height: 200px;
}
}
.status-badge {
font-size: 1rem;
}
</style>
{{ define "title" }}Status of report {{ .Report.ID|publicReportID }}{{ 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/map-with-markers.js"></script>
<style>
.timeline {
border-left: 3px solid #dee2e6;
padding-left: 20px;
margin-left: 10px;
}
.timeline-item {
position: relative;
margin-bottom: 25px;
}
.timeline-item:before {
content: "";
position: absolute;
left: -29px;
top: 0;
width: 16px;
height: 16px;
border-radius: 50%;
background-color: #0d6efd;
}
.timeline-date {
font-size: 0.85rem;
color: #6c757d;
}
.map-container {
height: 300px;
}
@media (max-width: 768px) {
.map-container {
height: 200px;
}
}
.status-badge {
font-size: 1rem;
}
</style>
<script>
const GEOJSON_LOCATION = {{.Report.Location|json}};
function onLoad() {
@ -54,89 +54,107 @@ function onLoad() {
}
document.addEventListener("DOMContentLoaded", onLoad);
</script>
{{end}}
{{define "content"}}
{{if (eq .District nil)}}
{{template "header-rmo" .}}
{{else}}
{{template "header-district" .District}}
{{end}}
<div class="container my-4">
<!-- Report ID and Status Section -->
<div class="card mb-4">
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
<h5 class="mb-0">Report {{.Report.ID|publicReportID}}</h5>
<span class="badge bg-warning text-dark status-badge">{{.Report.Status}}</span>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4 mb-3">
<strong><i class="bi bi-tag me-2"></i>Type:</strong>
<span>{{.Report.Type}}</span>
</div>
<div class="col-md-4 mb-3">
<strong><i class="bi bi-calendar me-2"></i>Created:</strong>
<span>{{.Report.Created|timeSince}}</span>
</div>
<div class="col-md-4 mb-3">
<strong><i class="bi bi-crosshair me-2"></i>District:</strong>
<span>{{if (eq .District nil)}}Unknown{{else}}{{.District.Name}}{{end}}</span>
</div>
{{ end }}
{{ define "content" }}
{{ if (eq .District nil) }}
{{ template "header-rmo" . }}
{{ else }}
{{ template "header-district" .District }}
{{ end }}
<div class="container my-4">
<!-- Report ID and Status Section -->
<div class="card mb-4">
<div
class="card-header bg-primary text-white d-flex justify-content-between align-items-center"
>
<h5 class="mb-0">Report {{ .Report.ID|publicReportID }}</h5>
<span class="badge bg-warning text-dark status-badge"
>{{ .Report.Status }}</span
>
</div>
<div class="row">
<div class="col-md-12">
<strong><i class="bi bi-pin-map me-2"></i>Location:</strong>
<span>{{.Report.Address}}</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<strong><i class="bi bi-images me-2"></i>Images:</strong>
<span>{{ if gt .Report.ImageCount 0 }}{{.Report.ImageCount}}{{else}}None provided{{end}}</span>
</div>
</div>
{{range .Report.Details}}
<div class="card-body">
<div class="row">
<div class="col-md-4">
<strong>{{.Name}}</strong>
<div class="col-md-4 mb-3">
<strong><i class="bi bi-tag me-2"></i>Type:</strong>
<span>{{ .Report.Type }}</span>
</div>
<div class="col-md-6">
<span>{{.Value}}</span>
<div class="col-md-4 mb-3">
<strong><i class="bi bi-calendar me-2"></i>Created:</strong>
<span>{{ .Report.Created|timeSince }}</span>
</div>
<div class="col-md-4 mb-3">
<strong><i class="bi bi-crosshair me-2"></i>District:</strong>
<span
>{{ if (eq .District nil) }}
Unknown
{{ else }}
{{ .District.Name }}
{{ end }}</span
>
</div>
</div>
{{end}}
</div>
</div>
<!-- Map Section -->
<div class="card mb-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0"><i class="bi bi-pin-map-fill me-2"></i>Location Map</h5>
</div>
<div class="card-body p-0">
<map-with-markers
api-key="{{ .MapboxToken }}"
zoom="14"/>
</div>
</div>
<!-- History Timeline -->
<div class="card">
<div class="card-header bg-success text-white">
<h5 class="mb-0"><i class="bi bi-clock-history me-2"></i>Request History</h5>
</div>
<div class="card-body">
<div class="timeline">
{{range .Timeline}}
<div class="timeline-item">
<div class="timeline-date">{{.At|timeSince}}</div>
<h5 class="mb-1">{{.Title}}</h5>
<p class="mb-0">{{.Detail}}</p>
<div class="row">
<div class="col-md-12">
<strong><i class="bi bi-pin-map me-2"></i>Location:</strong>
<span>{{ .Report.Address }}</span>
</div>
</div>
<div class="row">
<div class="col-md-12">
<strong><i class="bi bi-images me-2"></i>Images:</strong>
<span
>{{ if gt .Report.ImageCount 0 }}
{{ .Report.ImageCount }}
{{ else }}
None provided
{{ end }}</span
>
</div>
</div>
{{ range .Report.Details }}
<div class="row">
<div class="col-md-4">
<strong>{{ .Name }}</strong>
</div>
<div class="col-md-6">
<span>{{ .Value }}</span>
</div>
</div>
{{ end }}
</div>
</div>
<!-- Map Section -->
<div class="card mb-4">
<div class="card-header bg-info text-white">
<h5 class="mb-0">
<i class="bi bi-pin-map-fill me-2"></i>Location Map
</h5>
</div>
<div class="card-body p-0">
<map-with-markers api-key="{{ .MapboxToken }}" zoom="14" />
</div>
</div>
<!-- History Timeline -->
<div class="card">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="bi bi-clock-history me-2"></i>Request History
</h5>
</div>
<div class="card-body">
<div class="timeline">
{{ range .Timeline }}
<div class="timeline-item">
<div class="timeline-date">{{ .At|timeSince }}</div>
<h5 class="mb-1">{{ .Title }}</h5>
<p class="mb-0">{{ .Detail }}</p>
</div>
{{ end }}
</div>
{{end}}
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,149 +1,248 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Report Submission Complete{{end}}
{{define "extraheader"}}
<style>
</style>
<script>
</script>
{{end}}
{{define "content"}}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-check-circle-fill me-2" viewBox="0 0 16 16">
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
</svg>
Report Successfully Submitted
</h3>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{.ReportID|publicReportID}}</span>
</div>
</div>
<hr class="my-4">
<div>
<h4 class="mb-3">
<i class="bi bi-person-rolodex"></i>
Follow-up
</h4>
<p>Please provide your contact information in case the district has any follow-up questions.</p>
<form id="notificationForm" action="/register-notifications" method="post" class="needs-validation">
<input type="hidden" name="report_id" value="{{.ReportID}}">
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<div class="input-group">
<span class="input-group-text">
<i class="bi bi-person-lines-fill"></i>
</span>
<input type="text" class="form-control" id="name" name="name" placeholder="Adam Smith">
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-envelope" viewBox="0 0 16 16">
<path d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"/>
</svg>
</span>
<input type="email" class="form-control" id="email" name="email" placeholder="your@email.com">
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone Number</label>
<div class="input-group">
<span class="input-group-text">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-phone" viewBox="0 0 16 16">
<path d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>
</svg>
</span>
<input type="tel" class="form-control" id="phone" name="phone" placeholder="(123) 456-7890">
</div>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" id="consent" type="checkbox" name="consent" checked>
<label class="form-check-label" for="consent">
I consent to being contacted at my email address or phone number above just for the purposes of this report.
<i class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We will never sell your information. We'll send you notifications, but only if you ask us to. We'll share your information with the district that is in change of mosquito control in the area you've reported, but not with anybody else."></i>
</label>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" id="notification" type="checkbox" name="notification"/>
<label class="form-check-label" for="notification">
I'd like to get updates about my report as it gets handled.
</label>
</div>
<div class="form-check mb-3 form-check">
<input class="form-check-input" id="subscribe" type="checkbox" name="subscribe"/>
<label class="form-check-label" for="subscribe">
{{ if eq .District nil }}
I'd like to subscribe to periodic updates from my mosquito control district.
{{ else }}
I'd like to subscribe to periodic updates from {{ .District.Name }}
{{ end }}
</label>
</div>
<button type="submit" class="btn btn-primary">Update report</button>
</form>
</div>
<hr class="my-4">
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-search me-2" viewBox="0 0 16 16">
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
{{ define "title" }}Report Submission Complete{{ end }}
{{ define "extraheader" }}
<style></style>
<script></script>
{{ end }}
{{ define "content" }}
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<!-- Success Card -->
<div class="card shadow-sm border-success mb-4">
<div class="card-header bg-success text-white">
<h3 class="my-2">
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
fill="currentColor"
class="bi bi-check-circle-fill me-2"
viewBox="0 0 16 16"
>
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"
/>
</svg>
Check Your Report Status
</h4>
<p>You can check the status of your report at any time using your Report ID.</p>
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary">
Check Status
</a>
Report Successfully Submitted
</h3>
</div>
<div class="card-body p-4">
<div class="text-center mb-4">
<div class="alert alert-info py-3">
<strong>Your Report ID:</strong>
<span class="fs-4 fw-bold">{{ .ReportID|publicReportID }}</span>
</div>
</div>
<div class="row">
<div class="mb-4 text-center">
{{ if not (eq .District nil) }}
<p>Your report will be handled by</p>
<p><b>{{ .District.Name }}</b></p>
<a href="{{ .District.URLWebsite }}"><img class="logo" src="{{ .District.URLLogo }}" /></a>
{{ end }}
<hr class="my-4" />
<div>
<h4 class="mb-3">
<i class="bi bi-person-rolodex"></i>
Follow-up
</h4>
<p>
Please provide your contact information in case the district has
any follow-up questions.
</p>
<form
id="notificationForm"
action="/register-notifications"
method="post"
class="needs-validation"
>
<input type="hidden" name="report_id" value="{{ .ReportID }}" />
<div class="mb-3">
<label class="form-label" for="name">Name</label>
<div class="input-group">
<span class="input-group-text">
<i class="bi bi-person-lines-fill"></i>
</span>
<input
type="text"
class="form-control"
id="name"
name="name"
placeholder="Adam Smith"
/>
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-envelope"
viewBox="0 0 16 16"
>
<path
d="M0 4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V4Zm2-1a1 1 0 0 0-1 1v.217l7 4.2 7-4.2V4a1 1 0 0 0-1-1H2Zm13 2.383-4.708 2.825L15 11.105V5.383Zm-.034 6.876-5.64-3.471L8 9.583l-1.326-.795-5.64 3.47A1 1 0 0 0 2 13h12a1 1 0 0 0 .966-.741ZM1 11.105l4.708-2.897L1 5.383v5.722Z"
/>
</svg>
</span>
<input
type="email"
class="form-control"
id="email"
name="email"
placeholder="your@email.com"
/>
</div>
</div>
<div class="mb-3">
<label for="phone" class="form-label">Phone Number</label>
<div class="input-group">
<span class="input-group-text">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-phone"
viewBox="0 0 16 16"
>
<path
d="M11 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h6zM5 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H5z"
/>
<path d="M8 14a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />
</svg>
</span>
<input
type="tel"
class="form-control"
id="phone"
name="phone"
placeholder="(123) 456-7890"
/>
</div>
</div>
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
id="consent"
type="checkbox"
name="consent"
checked
/>
<label class="form-check-label" for="consent">
I consent to being contacted at my email address or phone
number above just for the purposes of this report.
<i
class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We will never sell your information. We'll send you notifications, but only if you ask us to. We'll share your information with the district that is in change of mosquito control in the area you've reported, but not with anybody else."
></i>
</label>
</div>
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
id="notification"
type="checkbox"
name="notification"
/>
<label class="form-check-label" for="notification">
I'd like to get updates about my report as it gets handled.
</label>
</div>
<div class="form-check mb-3 form-check">
<input
class="form-check-input"
id="subscribe"
type="checkbox"
name="subscribe"
/>
<label class="form-check-label" for="subscribe">
{{ if eq .District nil }}
I'd like to subscribe to periodic updates from my mosquito
control district.
{{ else }}
I'd like to subscribe to periodic updates from
{{ .District.Name }}
{{ end }}
</label>
</div>
<button type="submit" class="btn btn-primary">
Update report
</button>
</form>
</div>
<hr class="my-4" />
<!-- Status Check Section -->
<div class="mb-4">
<h4 class="mb-3">
<svg
xmlns="http://www.w3.org/2000/svg"
width="20"
height="20"
fill="currentColor"
class="bi bi-search me-2"
viewBox="0 0 16 16"
>
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
/>
</svg>
Check Your Report Status
</h4>
<p>
You can check the status of your report at any time using your
Report ID.
</p>
<a href="/status/{{ .ReportID }}" class="btn btn-outline-primary">
Check Status
</a>
</div>
<div class="row">
<div class="mb-4 text-center">
{{ if not (eq .District nil) }}
<p>Your report will be handled by</p>
<p><b>{{ .District.Name }}</b></p>
<a href="{{ .District.URLWebsite }}"
><img class="logo" src="{{ .District.URLLogo }}"
/></a>
{{ end }}
</div>
</div>
</div>
</div>
</div>
<!-- Navigation Links -->
<div class="text-center">
<a href="{{ .URL.Nuisance }}" class="btn btn-outline-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle me-1" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg>
Submit Another Report
</a>
<!-- Navigation Links -->
<div class="text-center">
<a href="{{ .URL.Nuisance }}" class="btn btn-outline-success">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-plus-circle me-1"
viewBox="0 0 16 16"
>
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"
/>
<path
d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"
/>
</svg>
Submit Another Report
</a>
</div>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}

View file

@ -1,26 +1,72 @@
{{template "base.html" .}}
{{define "title"}}Privacy Policy{{end}}
{{define "extraheader"}}
{{end}}
{{define "content"}}
<div class="container">
<h1>Terms of Service</h1>
<p>Look, we don't like having terms of service, and we're confident you don't find them interesting to read. But we have to have them as a business.</p>
<h2>Service provider</h2>
<p>Report Mosquitoes Online is provided by Gleipnir LLC. By using the website you agree to these terms. If you don't agree, don't tell a computer to access our site.</p>
<p>Gleipnir LLC is a company organized under the laws of the state of Arizona, USA, and operates under Arizona law.</p>
<p>Gleipnir LLC is located at 2726 S Quinn Ave, Gilbert, AZ</p>
<h2>What you can expect from us</h2>
<p>We provide services free to the public. We'll occasionally make changes to these services. We won't notify members of the public, like you, of those changes. We may notify our customers, but we may not, since we may changes very frequently. In general, we have additional agreements beyond this one with entities that are our customers.</p>
<p>The data you provide to us is used for public health. That generally means passing some or all of your data on to our customers that work in mosquito abatement. Any information you give to us we may give to them. You can request at any time that we stop sharing your information and we will honor that request.</p>
<p>We will only contact you if you give us express permission to do so</p>
<p>We won't sell your information to marketers, data aggregators, or anyone who makes money off your data. We only share data with entities engaged in public health work.</p>
<p>We are so vehemently opposed to selling your data that we agree to a contractual obligation of at least $1000 USD in damages per person if your data is every sold by the Company, or by any company in the future that aquires a stake in the Company.</p>
<h2>What we expect from you</h2>
<p>Don't provide false data. This include shenanigans like using our system to send messages to other people's email address or phone.</p>
<p>Don't try to scrape/exfiltrate/steal our data. If you've got a legitimate use for our data, contact us, if you've got a worthy project we may be willing to work with you.</p>
<p>Don't try to break into our systems, infect them with malware, use us as a tool in a phishing campaign, or generally hack about. We like hackers, but we prefer to work with them intentionally.</p>
<p>Don't misrepresent who you are</p>
<p>You agree we can use any data you provide to us as we see fit. This may include doing nothing with it, but generally includes improving public health by fighting mosquitoes and mosquito-born illnesses.</p>
</div>
{{end}}
{{ template "base.html" . }}
{{ define "title" }}Privacy Policy{{ end }}
{{ define "extraheader" }}
{{ end }}
{{ define "content" }}
<div class="container">
<h1>Terms of Service</h1>
<p>
Look, we don't like having terms of service, and we're confident you don't
find them interesting to read. But we have to have them as a business.
</p>
<h2>Service provider</h2>
<p>
Report Mosquitoes Online is provided by Gleipnir LLC. By using the website
you agree to these terms. If you don't agree, don't tell a computer to
access our site.
</p>
<p>
Gleipnir LLC is a company organized under the laws of the state of
Arizona, USA, and operates under Arizona law.
</p>
<p>Gleipnir LLC is located at 2726 S Quinn Ave, Gilbert, AZ</p>
<h2>What you can expect from us</h2>
<p>
We provide services free to the public. We'll occasionally make changes to
these services. We won't notify members of the public, like you, of those
changes. We may notify our customers, but we may not, since we may changes
very frequently. In general, we have additional agreements beyond this one
with entities that are our customers.
</p>
<p>
The data you provide to us is used for public health. That generally means
passing some or all of your data on to our customers that work in mosquito
abatement. Any information you give to us we may give to them. You can
request at any time that we stop sharing your information and we will
honor that request.
</p>
<p>We will only contact you if you give us express permission to do so</p>
<p>
We won't sell your information to marketers, data aggregators, or anyone
who makes money off your data. We only share data with entities engaged in
public health work.
</p>
<p>
We are so vehemently opposed to selling your data that we agree to a
contractual obligation of at least $1000 USD in damages per person if your
data is every sold by the Company, or by any company in the future that
aquires a stake in the Company.
</p>
<h2>What we expect from you</h2>
<p>
Don't provide false data. This include shenanigans like using our system
to send messages to other people's email address or phone.
</p>
<p>
Don't try to scrape/exfiltrate/steal our data. If you've got a legitimate
use for our data, contact us, if you've got a worthy project we may be
willing to work with you.
</p>
<p>
Don't try to break into our systems, infect them with malware, use us as a
tool in a phishing campaign, or generally hack about. We like hackers, but
we prefer to work with them intentionally.
</p>
<p>Don't misrepresent who you are</p>
<p>
You agree we can use any data you provide to us as we see fit. This may
include doing nothing with it, but generally includes improving public
health by fighting mosquitoes and mosquito-born illnesses.
</p>
</div>
{{ end }}

View file

@ -1,13 +1,13 @@
{{template "base.html" .}}
{{ template "base.html" . }}
{{define "title"}}Report Standing Water{{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-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>
<script src="/static/js/photo-upload.js"></script>
{{ define "title" }}Report Standing Water{{ 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-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>
<script src="/static/js/photo-upload.js"></script>
<script>
const MAPBOX_ACCESS_TOKEN = '{{.MapboxToken}}';
async function handleMapClick(mapLocator, lngLat) {
@ -78,7 +78,7 @@ document.addEventListener('DOMContentLoaded', function() {
const longitudeInput = document.getElementById('longitude');
const latlngAccuracyType = document.getElementById('latlng-accuracy-type');
const latlngAccuracyValue = document.getElementById('latlng-accuracy-value');
const mapLocator = document.querySelector("map-locator");
mapLocator.addEventListener("load", (event) => {
getGeolocation({
@ -143,307 +143,501 @@ document.addEventListener('DOMContentLoaded', function() {
});
});
</script>
{{end}}
{{define "content"}}
{{if (eq .District nil)}}
{{template "header-rmo" .}}
{{else}}
{{template "header-district" .District}}
{{end}}
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<div class="row mb-4">
<div class="col-12">
<h2>Report Standing Water</h2>
<p class="lead">Help us locate and treat potential mosquito production sources in your area</p>
</div>
</div>
<!-- Report Form -->
<form id="standingWater" action="{{ .URL.WaterSubmit }}" method="POST" enctype="multipart/form-data">
<!-- Photo Upload Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-camera"></i>
<h3>Photos</h3>
</div>
<p class="mb-3">Photos help us identify the severity of the issue and may contain location data that can help us find the production source.</p>
<div class="mb-4">
<photo-upload/>
{{ end }}
{{ define "content" }}
{{ if (eq .District nil) }}
{{ template "header-rmo" . }}
{{ else }}
{{ template "header-district" .District }}
{{ end }}
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<div class="row mb-4">
<div class="col-12">
<h2>Report Standing Water</h2>
<p class="lead">
Help us locate and treat potential mosquito production sources in
your area
</p>
</div>
</div>
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<!-- Report Form -->
<form
id="standingWater"
action="{{ .URL.WaterSubmit }}"
method="POST"
enctype="multipart/form-data"
>
<!-- Photo Upload Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-camera"></i>
<h3>Photos</h3>
</div>
<p class="mb-3">
Photos help us identify the severity of the issue and may contain
location data that can help us find the production source.
</p>
<div class="mb-4">
<photo-upload />
</div>
</div>
<p class="mb-3">Please provide any other information that might help us address this mosquito production source.</p>
<div class="row">
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
</div>
<p class="mb-3">
Please provide any other information that might help us address this
mosquito production source.
</p>
<div class="row">
<div class="col-md-12">
<label for="comments" class="form-label"
>Additional Details</label
>
<textarea
class="form-control"
id="comments"
name="comments"
rows="4"
placeholder="Example: The house appears to be vacant. There is algae growth in the pool. I've noticed increased mosquito activity in the evenings."
></textarea>
</div>
</div>
</div>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location</h3>
</div>
<p class="mb-3">
Please provide the location of the potential mosquito production
source. We may be able to extract this information from your photos
if they contain location data.
</p>
<div class="col-md-12">
<label for="comments" class="form-label">Additional Details</label>
<textarea class="form-control" id="comments" name="comments" rows="4" placeholder="Example: The house appears to be vacant. There is algae growth in the pool. I've noticed increased mosquito activity in the evenings."></textarea>
<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>
</div>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location</h3>
</div>
<p class="mb-3">Please provide the location of the potential mosquito production source. We may be able to extract this information from your photos if they contain location data.</p>
<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="row mb-3">
<!-- 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">
<div class="mb-3 position-relative">
<address-input
<div class="row mb-3">
<!-- 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">
<div class="mb-3 position-relative">
<address-input
placeholder="Start typing an address (min 3 characters)"
api-key="{{ .MapboxToken }}">
</address-input>
api-key="{{ .MapboxToken }}"
>
</address-input>
</div>
</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" />
</div>
<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">
<!-- Source Details Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-water"></i>
<h3>Source Details</h3>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label for="duration" class="form-label"
>How long has this production source been present?</label
>
<select
class="form-select"
id="duration"
name="source-duration"
>
<option value="none">I don't know</option>
<option value="less-than-week">Less than a week</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="more-than-3-months">More than 3 months</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label d-block"
>Have you observed any of the following?
<a
href="#"
data-bs-toggle="modal"
data-bs-target="#larvaeInfoModal"
><i class="bi bi-question-circle small ms-1"></i></a
></label>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="larvae"
name="has-larvae"
/>
<label class="form-check-label" for="larvae">
Larvae (wigglers) in water
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="pupae"
name="has-pupae"
/>
<label class="form-check-label" for="pupae">
Pupae (tumblers) in water
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="adult"
name="has-adult"
/>
<label class="form-check-label" for="adult">
Adult mosquitoes near the source
</label>
</div>
</div>
</div>
</div>
<!-- Access Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-unlock"></i>
<h3>Access Information</h3>
</div>
<p class="mb-3">
Please provide any details about how to access the mosquito
source. This helps our technicians when they visit the site.
</p>
<div class="row mb-3">
<div class="col-md-12">
<label for="access-comments" class="form-label"
>How can the source be accessed?</label
>
<textarea
class="form-control"
id="access-comments"
name="access-comments"
rows="3"
placeholder="Example: The pool is in the backyard, which can be accessed through a side gate on the right side of the house."
></textarea>
</div>
</div>
<div class="row mb-3">
<div class="col-md-12">
<label class="form-label d-block"
>Access obstacles (check all that apply):</label
>
<div class="row">
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="gate"
name="access-gate"
/>
<label class="form-check-label" for="gate">Gate</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="fence"
name="access-fence"
/>
<label class="form-check-label" for="fence">Fence</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="locked"
name="access-locked"
/>
<label class="form-check-label" for="locked"
>Locked entrance</label
>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="dogs"
name="access-dog"
/>
<label class="form-check-label" for="dogs"
>Dogs/pets</label
>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
id="access-other"
name="access-other"
/>
<label class="form-check-label" for="access-other"
>Other obstacle</label
>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Contact Information Sections -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-person-lines-fill"></i>
<h3>Property Owner Information (if known)</h3>
</div>
<div class="row mb-4">
<div class="col-md-4 mb-3">
<label for="owner-name" class="form-label">Owner Name</label>
<input
type="text"
class="form-control"
id="owner-name"
name="owner-name"
/>
</div>
<div class="col-md-4 mb-3">
<label for="owner-phone" class="form-label">Owner Phone</label>
<input
type="tel"
class="form-control"
id="owner-phone"
name="owner-phone"
/>
</div>
<div class="col-md-4 mb-3">
<label for="owner-email" class="form-label">Owner Email</label>
<input
type="email"
class="form-control"
id="owner-email"
name="owner-email"
/>
</div>
</div>
<div class="row mb-4">
<div class="col-md-6 mb-3 row">
<div class="form-check mt-4">
<input
class="form-check-input"
id="property-ownership"
name="property-ownership"
type="checkbox"
/>
<label class="form-check-label" for="property-ownership"
>This is my property</label
>
</div>
<div class="form-check mt-4">
<input
class="form-check-input"
id="backyard-permission"
name="backyard-permission"
type="checkbox"
/>
<label class="form-check-label" for="backyard-permission"
>I grant permission to enter the back yard of this
property.</label
>
</div>
<div class="form-check mt-4">
<input
class="form-check-input"
id="reporter-confidential"
name="reporter-confidential"
type="checkbox"
/>
<label class="form-check-label" for="reporter-confidential">
<i
class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We share your information with mosquito control districts so they can follow up with any questions they may have about your report. Check this box if you would like the district to be careful not to share your information outside of the district operations team."
></i>
I would like my personal information kept
confidential.</label
>
</div>
</div>
</div>
</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"/>
</div>
<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">
<!-- Source Details Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-water"></i>
<h3>Source Details</h3>
<!-- 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 helping us keep our community safe from
mosquito-borne illnesses.</strong
>
</p>
<p class="mb-0 small text-muted">
After submission, you will receive a confirmation with a report
ID for tracking purposes.
</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
</div>
</div>
</div>
</form>
</div>
</main>
<!-- Larvae Info Modal -->
<div
class="modal fade"
id="larvaeInfoModal"
tabindex="-1"
aria-labelledby="larvaeInfoModalLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="larvaeInfoModalLabel">
How to Identify Mosquito Larvae and Pupae
</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<div class="row mb-4">
<div class="col-md-6">
<label for="duration" class="form-label">How long has this production source been present?</label>
<select class="form-select" id="duration" name="source-duration">
<option value="none">I don't know</option>
<option value="less-than-week">Less than a week</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="more-than-3-months">More than 3 months</option>
</select>
<h6>Mosquito Larvae (Wigglers)</h6>
<p>Mosquito larvae, often called "wigglers," are:</p>
<ul>
<li>Small, worm-like aquatic organisms</li>
<li>Usually 1/4 to 1/2 inch long</li>
<li>Move with a wiggling motion in water</li>
<li>Hang upside-down at the water surface to breathe</li>
<li>Visible to the naked eye in standing water</li>
</ul>
</div>
<div class="col-md-6">
<label class="form-label d-block">Have you observed any of the following? <a href="#" data-bs-toggle="modal" data-bs-target="#larvaeInfoModal"><i class="bi bi-question-circle small ms-1"></i></a></label>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="larvae" name="has-larvae">
<label class="form-check-label" for="larvae">
Larvae (wigglers) in water
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="pupae" name="has-pupae">
<label class="form-check-label" for="pupae">
Pupae (tumblers) in water
</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="adult" name="has-adult">
<label class="form-check-label" for="adult">
Adult mosquitoes near the source
</label>
</div>
<h6>Mosquito Pupae (Tumblers)</h6>
<p>Mosquito pupae, often called "tumblers," are:</p>
<ul>
<li>Comma-shaped organisms</li>
<li>Typically darker than larvae</li>
<li>Move with a tumbling motion when disturbed</li>
<li>Rest at the water surface</li>
<li>The stage just before adult mosquitoes emerge</li>
</ul>
</div>
</div>
<p>
When looking for mosquito larvae and pupae, check standing water
sources like:
</p>
<ul>
<li>Swimming pools</li>
<li>Bird baths</li>
<li>Buckets or containers</li>
<li>Drainage ditches</li>
<li>Plant saucers</li>
<li>Rain gutters</li>
</ul>
<p>
If you see small creatures moving in standing water, there's a good
chance they're mosquito larvae or pupae.
</p>
<div class="text-center">
<a href="#" class="btn btn-outline-primary"
>View Detailed Identification Guide</a
>
</div>
</div>
<!-- Access Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-unlock"></i>
<h3>Access Information</h3>
</div>
<p class="mb-3">Please provide any details about how to access the mosquito source. This helps our technicians when they visit the site.</p>
<div class="row mb-3">
<div class="col-md-12">
<label for="access-comments" class="form-label">How can the source be accessed?</label>
<textarea class="form-control" id="access-comments" name="access-comments" rows="3" placeholder="Example: The pool is in the backyard, which can be accessed through a side gate on the right side of the house."></textarea>
</div>
</div>
<div class="row mb-3">
<div class="col-md-12">
<label class="form-label d-block">Access obstacles (check all that apply):</label>
<div class="row">
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gate" name="access-gate">
<label class="form-check-label" for="gate">Gate</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="fence" name="access-fence">
<label class="form-check-label" for="fence">Fence</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="locked" name="access-locked">
<label class="form-check-label" for="locked">Locked entrance</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dogs" name="access-dog">
<label class="form-check-label" for="dogs">Dogs/pets</label>
</div>
</div>
<div class="col-md-4">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="access-other" name="access-other">
<label class="form-check-label" for="access-other">Other obstacle</label>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
<!-- Contact Information Sections -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-person-lines-fill"></i>
<h3>Property Owner Information (if known)</h3>
</div>
<div class="row mb-4">
<div class="col-md-4 mb-3">
<label for="owner-name" class="form-label">Owner Name</label>
<input type="text" class="form-control" id="owner-name" name="owner-name">
</div>
<div class="col-md-4 mb-3">
<label for="owner-phone" class="form-label">Owner Phone</label>
<input type="tel" class="form-control" id="owner-phone" name="owner-phone">
</div>
<div class="col-md-4 mb-3">
<label for="owner-email" class="form-label">Owner Email</label>
<input type="email" class="form-control" id="owner-email" name="owner-email">
</div>
</div>
<div class="row mb-4">
<div class="col-md-6 mb-3 row">
<div class="form-check mt-4">
<input class="form-check-input" id="property-ownership" name="property-ownership" type="checkbox">
<label class="form-check-label" for="property-ownership">This is my property</label>
</div>
<div class="form-check mt-4">
<input class="form-check-input" id="backyard-permission" name="backyard-permission" type="checkbox">
<label class="form-check-label" for="backyard-permission">I grant permission to enter the back yard of this property.</label>
</div>
<div class="form-check mt-4">
<input class="form-check-input" id="reporter-confidential" name="reporter-confidential" type="checkbox">
<label class="form-check-label" for="reporter-confidential">
<i class="bi bi-info-circle-fill text-primary ms-1"
data-bs-toggle="tooltip"
data-bs-placement="top"
title="We share your information with mosquito control districts so they can follow up with any questions they may have about your report. Check this box if you would like the district to be careful not to share your information outside of the district operations team."></i>
I would like my personal information kept confidential.</label>
</div>
</div>
</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 helping us keep our community safe from mosquito-borne illnesses.</strong></p>
<p class="mb-0 small text-muted">After submission, you will receive a confirmation with a report ID for tracking purposes.</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<button type="submit" class="btn btn-primary btn-lg">
Submit Report
</button>
</div>
</div>
</div>
</form>
</div>
</main>
<!-- Larvae Info Modal -->
<div class="modal fade" id="larvaeInfoModal" tabindex="-1" aria-labelledby="larvaeInfoModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="larvaeInfoModalLabel">How to Identify Mosquito Larvae and Pupae</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mb-4">
<div class="col-md-6">
<h6>Mosquito Larvae (Wigglers)</h6>
<p>Mosquito larvae, often called "wigglers," are:</p>
<ul>
<li>Small, worm-like aquatic organisms</li>
<li>Usually 1/4 to 1/2 inch long</li>
<li>Move with a wiggling motion in water</li>
<li>Hang upside-down at the water surface to breathe</li>
<li>Visible to the naked eye in standing water</li>
</ul>
</div>
<div class="col-md-6">
<h6>Mosquito Pupae (Tumblers)</h6>
<p>Mosquito pupae, often called "tumblers," are:</p>
<ul>
<li>Comma-shaped organisms</li>
<li>Typically darker than larvae</li>
<li>Move with a tumbling motion when disturbed</li>
<li>Rest at the water surface</li>
<li>The stage just before adult mosquitoes emerge</li>
</ul>
</div>
</div>
<p>When looking for mosquito larvae and pupae, check standing water sources like:</p>
<ul>
<li>Swimming pools</li>
<li>Bird baths</li>
<li>Buckets or containers</li>
<li>Drainage ditches</li>
<li>Plant saucers</li>
<li>Rain gutters</li>
</ul>
<p>If you see small creatures moving in standing water, there's a good chance they're mosquito larvae or pupae.</p>
<div class="text-center">
<a href="#" class="btn btn-outline-primary">View Detailed Identification Guide</a>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{{end}}
{{ end }}