Add basic pages for status, pool report, and nuisance.

This commit is contained in:
Eli Ribble 2026-01-07 21:47:33 +00:00
parent d8fd73ca1f
commit bba22ec039
8 changed files with 1224 additions and 23 deletions

View file

@ -13,13 +13,19 @@ var embeddedFiles embed.FS
//go:embed static/*
var EmbeddedStaticFS embed.FS
type RootContext struct{}
type ContextNuisance struct{}
type ContextPool struct{}
type ContextRoot struct{}
type ContextStatus struct{}
var (
Nuisance = buildTemplate("nuisance", "base")
Pool = buildTemplate("pool", "base")
Root = buildTemplate("root", "base")
Status = buildTemplate("status", "base")
)
var components = [...]string{}
var components = [...]string{"footer"}
func buildTemplate(files ...string) *htmlpage.BuiltTemplate {
subdir := "htmlpage/public-reports"
@ -28,7 +34,7 @@ func buildTemplate(files ...string) *htmlpage.BuiltTemplate {
full_files = append(full_files, fmt.Sprintf("%s/template/%s.html", subdir, f))
}
for _, c := range components {
full_files = append(full_files, fmt.Sprintf("%s/template/components/%s.html", subdir, c))
full_files = append(full_files, fmt.Sprintf("%s/template/component/%s.html", subdir, c))
}
return htmlpage.NewBuiltTemplate(embeddedFiles, "htmlpage/public-reports/", full_files...)
}

View file

@ -14,6 +14,7 @@
</head>
<body>
{{template "content" .}}
{{template "footer" .}}
<script src="/static/vendor/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View file

@ -0,0 +1,14 @@
{{define "footer"}}
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
<div class="col-md-6">
<p class="mb-0">&copy; 2025 Gleipnir Technology</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">Contact: support@mosquitoes.online</p>
</div>
</div>
</div>
</footer>
{{end}}

View file

@ -0,0 +1,541 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "extraheader"}}
<script>
// Handle inspection type selection
function selectInspectionType(type) {
// Remove selected class from both cards
document.getElementById('propertyInspection').classList.remove('selected');
document.getElementById('neighborhoodInspection').classList.remove('selected');
// Add selected class to chosen card
if (type === 'property') {
document.getElementById('propertyInspection').classList.add('selected');
document.getElementById('inspectionTypeProperty').checked = true;
document.getElementById('schedulingSection').style.display = 'block';
} else {
document.getElementById('neighborhoodInspection').classList.add('selected');
document.getElementById('inspectionTypeNeighborhood').checked = true;
document.getElementById('schedulingSection').style.display = 'none';
}
}
// Check for source identification
document.addEventListener('DOMContentLoaded', function() {
const sourceCheckboxes = [
document.getElementById('sourceStagnantWater'),
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
if (sourceCheckboxes.some(cb => cb.checked)) {
sourceAlert.style.display = 'block';
} else {
sourceAlert.style.display = 'none';
}
});
});
});
</script>
<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;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.optional-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: normal;
margin-left: 8px;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
.source-card {
height: 100%;
transition: transform 0.3s;
}
.source-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.1);
}
.source-icon {
font-size: 2rem;
margin-bottom: 1rem;
color: #0d6efd;
}
.time-of-day-btn {
width: 100%;
margin-bottom: 10px;
display: flex;
flex-direction: column;
align-items: center;
padding: 15px 0;
}
.time-of-day-icon {
font-size: 1.5rem;
margin-bottom: 8px;
}
.time-label {
font-size: 0.9rem;
}
.severity-item {
text-align: center;
padding: 10px;
}
.severity-scale {
display: flex;
justify-content: space-between;
margin: 20px 0;
}
.btn-check:checked + .btn.time-of-day-btn {
background-color: #0d6efd;
color: white;
}
.inspection-type-card {
cursor: pointer;
border: 1px solid #dee2e6;
padding: 20px;
border-radius: 5px;
height: 100%;
transition: all 0.3s;
}
.inspection-type-card.selected {
border-color: #0d6efd;
background-color: rgba(13, 110, 253, 0.05);
}
.inspection-type-card:hover {
border-color: #0d6efd;
}
.card-highlight {
border-left: 4px solid #0d6efd;
background-color: #f8f9fa;
}
</style>
{{end}}
{{define "content"}}
<!-- Header -->
<header class="bg-light py-3">
<div class="container">
<div class="row align-items-center">
<div class="col-md-6">
<h1 class="district-name">[District Name]</h1>
</div>
<div class="col-md-6 text-md-end">
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<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>
<!-- Info Alert -->
<div class="row mb-4">
<div class="col-12">
<div class="alert alert-info" role="alert">
<h5 class="alert-heading"><i class="bi bi-info-circle me-2"></i>About Mosquito Control</h5>
<p class="mb-0">While we don't spray for adult mosquitoes based on individual requests, your reports help us identify and eliminate breeding sources. Adult mosquito control is based on trap counts and disease testing. Your detailed information helps us prioritize our work and locate potential breeding sites.</p>
</div>
</div>
</div>
<!-- Report Form -->
<form id="mosquitoNuisanceForm">
<!-- Mosquito Activity Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-bug"></i>
<h3>Mosquito Activity Information</h3>
<span class="optional-label">optional</span>
</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" 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" 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" 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" 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" id="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>
<!-- Severity -->
<div class="col-md-6">
<label for="severityRange" class="form-label">How would you rate the severity of the mosquito problem?</label>
<input type="range" class="form-range" min="1" max="5" id="severityRange" oninput="document.getElementById('severityValue').innerText = this.value">
<div class="severity-scale">
<div class="severity-item">
<div>Minor</div>
<small>Occasional mosquito</small>
</div>
<div class="severity-item">
<div>Moderate</div>
<small>Regular presence</small>
</div>
<div class="severity-item">
<div>Severe</div>
<small>Many mosquitoes</small>
</div>
</div>
<div class="text-center">
Current selection: <span id="severityValue">3</span>/5
</div>
</div>
</div>
<!-- Location -->
<div class="row">
<div class="col-md-12">
<label for="activityLocation" class="form-label">Where on your property do you notice the most mosquito activity?</label>
<select class="form-select" id="activityLocation">
<option value="">Please select</option>
<option value="front-yard">Front yard</option>
<option value="backyard">Back yard</option>
<option value="patio">Patio/deck area</option>
<option value="garden">Garden</option>
<option value="pool-area">Pool area</option>
<option value="throughout">Throughout the property</option>
<option value="indoors">Indoors</option>
<option value="other">Other area</option>
</select>
</div>
</div>
</div>
<!-- Potential Sources Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-search"></i>
<h3>Potential Mosquito Sources</h3>
<span class="optional-label">optional</span>
</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" 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" 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">Roof & Gutters</h5>
<p class="card-text">Clogged gutters, flat roofs, or AC units that collect water</p>
<div class="form-check">
<input class="form-check-input" type="checkbox" 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" rows="2" placeholder="Describe any other potential breeding sites you've noticed..."></textarea>
</div>
</div>
</div>
<!-- Inspection Request Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-clipboard-check"></i>
<h3>Inspection Request</h3>
</div>
<p class="mb-4">Would you like our technicians to inspect for potential mosquito sources?</p>
<div class="row g-4 mb-4">
<div class="col-md-6">
<div class="inspection-type-card" onclick="selectInspectionType('property')" id="propertyInspection">
<h5><i class="bi bi-house-door me-2"></i>Property Inspection</h5>
<p>Request a technician to inspect your property for mosquito sources. We'll contact you to schedule a convenient time.</p>
<div class="form-check">
<input class="form-check-input" type="radio" name="inspectionType" id="inspectionTypeProperty" value="property">
<label class="form-check-label" for="inspectionTypeProperty">
<strong>Schedule a property inspection</strong>
</label>
</div>
</div>
</div>
<div class="col-md-6">
<div class="inspection-type-card" onclick="selectInspectionType('neighborhood')" id="neighborhoodInspection">
<h5><i class="bi bi-map me-2"></i>Neighborhood Inspection</h5>
<p>Request a general inspection of your neighborhood. We'll survey the area for potential mosquito breeding sources.</p>
<div class="form-check">
<input class="form-check-input" type="radio" name="inspectionType" id="inspectionTypeNeighborhood" value="neighborhood">
<label class="form-check-label" for="inspectionTypeNeighborhood">
<strong>Request neighborhood inspection</strong>
</label>
</div>
</div>
</div>
</div>
<!-- Property Inspection Scheduling (hidden by default) -->
<div id="schedulingSection" style="display: none;">
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title">Schedule Property Inspection</h5>
<p class="card-text">Please indicate your availability for a technician visit.</p>
<div class="row mb-3">
<div class="col-md-6">
<label for="preferredDateRange" class="form-label">Preferred Date Range</label>
<select class="form-select" id="preferredDateRange">
<option value="">Select preferred dates</option>
<option value="next-week">Next week</option>
<option value="in-two-weeks">In two weeks</option>
<option value="any-time">Any time</option>
</select>
</div>
<div class="col-md-6">
<label for="preferredTime" class="form-label">Preferred Time of Day</label>
<select class="form-select" id="preferredTime">
<option value="">Select preferred time</option>
<option value="morning">Morning (8am-12pm)</option>
<option value="afternoon">Afternoon (12pm-4pm)</option>
<option value="any-time">Any time</option>
</select>
</div>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="requestCall">
<label class="form-check-label" for="requestCall">
Please call me to schedule a specific appointment time
</label>
</div>
</div>
</div>
</div>
</div>
<!-- Location & Contact Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location & Contact Information</h3>
</div>
<div class="row mb-4">
<div class="col-md-12">
<label for="address" class="form-label">Your Address</label>
<input type="text" class="form-control" id="address" placeholder="Enter your street address">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="name" class="form-label">Your Name</label>
<input type="text" class="form-control" id="name">
</div>
<div class="col-md-6 mb-3">
<label for="phone" class="form-label">Phone Number</label>
<input type="tel" class="form-control" id="phone">
</div>
<div class="col-md-12 mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control" id="email">
<div class="form-text">We'll use this to send you a confirmation and follow-up information.</div>
</div>
</div>
</div>
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<span class="optional-label">optional</span>
</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" rows="4" placeholder="Additional details about the mosquito issue..."></textarea>
</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>
</div>
</div>
</div>
</form>
<!-- Back Button -->
<div class="row mt-4">
<div class="col-12">
<a href="/" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Back to Home
</a>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
<div class="col-md-6">
<p class="mb-0">&copy; 2023 [District Name] Mosquito Management District</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
</div>
</div>
</div>
</footer>
{{end}}

View file

@ -0,0 +1,495 @@
{{template "base.html" .}}
{{define "title"}}Green Pool{{end}}
{{define "extraheader"}}
<script>
document.addEventListener('DOMContentLoaded', function() {
const photoUpload = document.getElementById('photoUpload');
const imagePreview = document.getElementById('imagePreview');
const dropArea = document.getElementById('dropArea');
// Handle file selection
photoUpload.addEventListener('change', handleFileSelect);
// Handle drag and drop
dropArea.addEventListener('dragover', function(e) {
e.preventDefault();
dropArea.style.backgroundColor = '#e9ecef';
});
dropArea.addEventListener('dragleave', function() {
dropArea.style.backgroundColor = '#f8f9fa';
});
dropArea.addEventListener('drop', function(e) {
e.preventDefault();
dropArea.style.backgroundColor = '#f8f9fa';
if (e.dataTransfer.files.length) {
handleFiles(e.dataTransfer.files);
}
});
function handleFileSelect(e) {
const files = e.target.files;
handleFiles(files);
}
function handleFiles(files) {
const maxFiles = 5;
const currentFiles = imagePreview.querySelectorAll('.preview-item').length;
for (let i = 0; i < files.length && currentFiles + i < maxFiles; i++) {
const file = files[i];
if (!file.type.match('image.*')) {
continue;
}
const reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
const previewItem = document.createElement('div');
previewItem.className = 'preview-item';
const img = document.createElement('img');
img.src = e.target.result;
const removeBtn = document.createElement('div');
removeBtn.className = 'preview-remove';
removeBtn.innerHTML = 'x';
removeBtn.addEventListener('click', function() {
imagePreview.removeChild(previewItem);
});
previewItem.appendChild(img);
previewItem.appendChild(removeBtn);
imagePreview.appendChild(previewItem);
};
})(file);
reader.readAsDataURL(file);
}
photoUpload.value = '';
}
});
</script>
<style>
.district-logo {
max-height: 80px;
width: auto;
}
.map-container {
height: 300px;
background-color: #e9ecef;
border-radius: 5px;
border: 1px solid #dee2e6;
display: flex;
align-items: center;
justify-content: center;
margin-top: 10px;
}
.file-upload-container {
border: 2px dashed #dee2e6;
border-radius: 5px;
padding: 20px;
text-align: center;
background-color: #f8f9fa;
transition: background-color 0.3s;
}
.file-upload-container:hover {
background-color: #e9ecef;
cursor: pointer;
}
.image-preview {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
.preview-item {
width: 100px;
height: 100px;
border-radius: 5px;
overflow: hidden;
position: relative;
}
.preview-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.preview-remove {
position: absolute;
top: 5px;
right: 5px;
background-color: rgba(0,0,0,0.5);
color: white;
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
cursor: pointer;
}
.form-section {
margin-bottom: 2.5rem;
padding-bottom: 2rem;
border-bottom: 1px solid #dee2e6;
}
.form-section:last-child {
border-bottom: none;
margin-bottom: 1rem;
padding-bottom: 0;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
align-items: center;
}
.section-heading i {
margin-right: 10px;
font-size: 1.5rem;
color: #0d6efd;
}
.optional-label {
font-size: 0.875rem;
color: #6c757d;
font-weight: normal;
margin-left: 8px;
}
.submit-container {
background-color: #f8f9fa;
padding: 20px;
border-radius: 5px;
margin-top: 2rem;
}
</style>
{{end}}
{{define "content"}}
<!-- Main Content -->
<main class="py-5">
<div class="container">
<!-- Page Title -->
<div class="row mb-4">
<div class="col-12">
<h2>Report a Green Pool or Mosquito Source</h2>
<p class="lead">Help us locate and treat potential mosquito breeding sources in your area</p>
</div>
</div>
<!-- Info Alert -->
<div class="row mb-4">
<div class="col-12">
<div class="alert alert-info" role="alert">
<h5 class="alert-heading"><i class="bi bi-info-circle me-2"></i>All fields are optional</h5>
<p class="mb-0">We appreciate any information you can provide. The more details you share, the better we can address the issue. Photos and location information are especially helpful.</p>
</div>
</div>
</div>
<!-- Report Form -->
<form id="greenPoolForm">
<!-- Photo Upload Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-camera"></i>
<h3>Photos</h3>
<span class="optional-label">optional</span>
</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 source.</p>
<div class="file-upload-container" id="dropArea">
<input type="file" id="photoUpload" multiple accept="image/*" class="d-none">
<div class="mb-2">
<i class="bi bi-cloud-arrow-up fs-1 text-primary"></i>
</div>
<p class="mb-1"><strong>Drag and drop photos here</strong></p>
<p class="mb-1">- or -</p>
<button type="button" class="btn btn-primary mt-2" onclick="document.getElementById('photoUpload').click()">
Select Photos
</button>
<p class="small text-muted mt-2 mb-0">You can upload multiple photos (maximum 5)</p>
</div>
<!-- Image Preview Area -->
<div class="image-preview" id="imagePreview">
<!-- Preview items will be added here dynamically -->
</div>
</div>
<!-- Location Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-geo-alt"></i>
<h3>Location</h3>
<span class="optional-label">optional</span>
</div>
<p class="mb-3">Please provide the location of the potential mosquito breeding source. We may be able to extract this information from your photos if they contain location data.</p>
<div class="row mb-3">
<div class="col-md-12">
<label for="address" class="form-label">Address or Description of Location</label>
<input type="text" class="form-control" id="address" placeholder="123 Main St, City, State or nearby landmark description">
</div>
</div>
<p class="small text-muted mb-2">You can also click on the map to mark the location precisely</p>
<div class="map-container">
<div class="text-center">
<i class="bi bi-map fs-1 text-secondary"></i>
<p class="mb-0">Interactive Map</p>
<p class="text-muted small">Click to set the location of the mosquito source</p>
</div>
</div>
</div>
<!-- Source Details Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-water"></i>
<h3>Source Details</h3>
<span class="optional-label">optional</span>
</div>
<div class="row mb-4">
<div class="col-md-6">
<label for="duration" class="form-label">How long has this source been present?</label>
<select class="form-select" id="duration">
<option value="">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">
<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">
<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="adultMosquitoes">
<label class="form-check-label" for="adultMosquitoes">
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>
<span class="optional-label">optional</span>
</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="accessInfo" class="form-label">How can the source be accessed?</label>
<textarea class="form-control" id="accessInfo" 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">
<label class="form-check-label" for="gate">Gate</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="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="lockedEntrance">
<label class="form-check-label" for="lockedEntrance">Locked entrance</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="dogs">
<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="otherObstacle">
<label class="form-check-label" for="otherObstacle">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>Contact Information</h3>
<span class="optional-label">optional</span>
</div>
<!-- Property Owner Information -->
<h5 class="mb-3">Property Owner Information (if known)</h5>
<div class="row mb-4">
<div class="col-md-6 mb-3">
<label for="ownerName" class="form-label">Owner Name</label>
<input type="text" class="form-control" id="ownerName">
</div>
<div class="col-md-6 mb-3">
<label for="ownerPhone" class="form-label">Owner Phone</label>
<input type="tel" class="form-control" id="ownerPhone">
</div>
<div class="col-md-12">
<label for="ownerEmail" class="form-label">Owner Email</label>
<input type="email" class="form-control" id="ownerEmail">
</div>
</div>
<!-- Your Contact Information -->
<h5 class="mb-3">Your Contact Information (for updates)</h5>
<div class="row mb-3">
<div class="col-md-6 mb-3">
<label for="reporterName" class="form-label">Your Name</label>
<input type="text" class="form-control" id="reporterName">
</div>
<div class="col-md-6 mb-3">
<label for="reporterPhone" class="form-label">Your Phone</label>
<input type="tel" class="form-control" id="reporterPhone">
</div>
<div class="col-md-12 mb-3">
<label for="reporterEmail" class="form-label">Your Email</label>
<input type="email" class="form-control" id="reporterEmail">
</div>
<div class="col-md-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="receiveUpdates" checked>
<label class="form-check-label" for="receiveUpdates">
I would like to receive updates on this report
</label>
</div>
</div>
</div>
</div>
<!-- Additional Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-card-text"></i>
<h3>Additional Information</h3>
<span class="optional-label">optional</span>
</div>
<p class="mb-3">Please provide any other information that might help us address this mosquito source.</p>
<div class="row">
<div class="col-md-12">
<label for="additionalInfo" class="form-label">Additional Details</label>
<textarea class="form-control" id="additionalInfo" 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>
<!-- 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>
<!-- Back Button -->
<div class="row mt-4">
<div class="col-12">
<a href="/" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Back to Home
</a>
</div>
</div>
</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}}

View file

@ -49,7 +49,7 @@
<div class="row">
<div class="col-12 text-center">
<h4 class="mb-2">On the go?</h4>
<a href="/mock/service-request-quick" class="btn btn-dark btn-lg">Make a Quick Report</a>
<a href="/quick" class="btn btn-dark btn-lg">Make a Quick Report</a>
<p class="mb-0 mt-2"><small>Report mosquito issues in under 60 seconds</small></p>
</div>
</div>
@ -72,7 +72,7 @@
</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="/mock/service-request-updates" class="btn btn-primary mt-3">Get Updates</a>
<a href="/status" class="btn btn-primary mt-3">Get Status</a>
</div>
</div>
</div>
@ -88,7 +88,7 @@
</div>
<h4 class="card-title">Report a Green Pool</h4>
<p class="card-text">Report stagnant water sources like abandoned pools that may breed mosquitoes.</p>
<a href="/mock/service-request-pool" class="btn btn-primary mt-3">Report Source</a>
<a href="/pool" class="btn btn-primary mt-3">Report Source</a>
</div>
</div>
</div>
@ -104,7 +104,7 @@
</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="/mock/service-request-mosquito" class="btn btn-primary mt-3">Report Problem</a>
<a href="/nuisance" class="btn btn-primary mt-3">Report Problem</a>
</div>
</div>
</div>
@ -121,7 +121,7 @@
<p class="mb-0">Use our streamlined form to report mosquito issues in under 60 seconds</p>
</div>
<div class="col-md-4 text-md-end mt-3 mt-md-0">
<a href="/mock/service-request-quick" class="btn btn-warning">Quick Report</a>
<a href="/quick" class="btn btn-warning">Quick Report</a>
</div>
</div>
</div>
@ -132,18 +132,4 @@
</section>
</main>
<!-- Footer -->
<footer class="bg-dark text-white py-4">
<div class="container">
<div class="row">
<div class="col-md-6">
<p class="mb-0">&copy; 2025 Gleipnir Technology</p>
</div>
<div class="col-md-6 text-md-end">
<p class="mb-0">Contact: support@mosquitoes.online</p>
</div>
</div>
</div>
</footer>
{{end}}

View file

@ -0,0 +1,133 @@
{{template "base.html" .}}
{{define "title"}}Status{{end}}
{{define "extraheader"}}
<style>
.option-card {
transition: transform 0.3s;
height: 100%;
}
.option-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}
.district-logo {
max-height: 80px;
width: auto;
}
.divider {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.divider-line {
border-left: 1px solid #dee2e6;
height: 80%;
}
@media (max-width: 767.98px) {
.divider-line {
border-left: none;
border-top: 1px solid #dee2e6;
width: 80%;
height: auto;
margin: 2rem 0;
}
}
</style>
{{end}}
{{define "content"}}
<main>
<!-- Page Title -->
<section class="py-4 bg-primary text-white">
<div class="container">
<h2 class="text-center mb-0">Check Status or Follow-up</h2>
</div>
</section>
<!-- Lookup Options -->
<section class="py-5">
<div class="container">
<div class="row">
<div class="col-12 mb-4">
<p class="lead text-center">
Choose one of the following options to check on mosquito activity or follow up on a previous report.
</p>
</div>
</div>
<div class="row g-4">
<!-- Report ID Lookup -->
<div class="col-md-5">
<div class="card option-card h-100">
<div class="card-body p-4">
<div class="text-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-file-earmark-text" viewBox="0 0 16 16">
<path d="M5.5 7a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5zM5 9.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 0 1h-5a.5.5 0 0 1-.5-.5zm0 2a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"/>
<path d="M9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.5L9.5 0zm0 1v2A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5z"/>
</svg>
</div>
<h4 class="card-title text-center mb-4">Look up by Report ID</h4>
<p class="card-text">
If you have a report ID from a previous request, enter it below to view the details and current status.
</p>
<form>
<div class="mb-3">
<label for="reportId" class="form-label">Report ID</label>
<input type="text" class="form-control" id="reportId" name="reportId" placeholder="Enter your report ID" required>
<div class="form-text">Example: MMD-2023-12345</div>
</div>
<div class="d-grid gap-2">
<a href="/service-request/abc-123" type="submit" class="btn btn-primary">View Report Details</a>
</div>
</form>
</div>
</div>
</div>
<!-- Divider for visual separation -->
<div class="col-md-2 divider">
<div class="divider-line"></div>
</div>
<!-- Location Lookup -->
<div class="col-md-5">
<div class="card option-card h-100">
<div class="card-body p-4">
<div class="text-center mb-4">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-geo-alt" 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>
</div>
<h4 class="card-title text-center mb-4">Look up by Location</h4>
<p class="card-text">
Don't have a report ID? You can check mosquito activity and reports in your area by providing your location information.
</p>
<p class="card-text mb-4">
This option will guide you through selecting your location to find relevant information about mosquito activity near you.
</p>
<div class="d-grid gap-2 mt-auto">
<a href="/service-request-location" class="btn btn-primary">Search by Location</a>
</div>
</div>
</div>
</div>
</div>
<!-- Back button -->
<div class="row mt-5">
<div class="col-12 text-center">
<a href="/" class="btn btn-outline-secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left me-2" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M15 8a.5.5 0 0 0-.5-.5H2.707l3.147-3.146a.5.5 0 1 0-.708-.708l-4 4a.5.5 0 0 0 0 .708l4 4a.5.5 0 0 0 .708-.708L2.707 8.5H14.5A.5.5 0 0 0 15 8z"/>
</svg>
Back to Home
</a>
</div>
</div>
</div>
</section>
</main>
{{end}}

View file

@ -11,6 +11,9 @@ import (
func Router() chi.Router {
r := chi.NewRouter()
r.Get("/", getRoot)
r.Get("/nuisance", getNuisance)
r.Get("/pool", getPool)
r.Get("/status", getStatus)
localFS := http.Dir("./static")
htmlpage.FileServer(r, "/static", localFS, publicreports.EmbeddedStaticFS, "static")
return r
@ -20,6 +23,28 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
publicreports.Root,
publicreports.RootContext{},
publicreports.ContextRoot{},
)
}
func getNuisance(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
publicreports.Nuisance,
publicreports.ContextNuisance{},
)
}
func getPool(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
publicreports.Pool,
publicreports.ContextPool{},
)
}
func getStatus(w http.ResponseWriter, r *http.Request) {
htmlpage.RenderOrError(
w,
publicreports.Status,
publicreports.ContextStatus{},
)
}