Add rendering of district-specific standing water report

This commit is contained in:
Eli Ribble 2026-02-01 03:24:50 +00:00
parent 2066840a40
commit c15d1b1e22
No known key found for this signature in database
5 changed files with 194 additions and 220 deletions

View file

@ -38,11 +38,11 @@ func addMockRoutes(r chi.Router) {
func makeContentURLMock(slug string) ContentURL {
return ContentURL{
Nuisance: makeURLMock(slug, "nuisance"),
NuisanceSubmitComplete: makeURLMock(slug, "nuisance-submit-complete"),
Status: makeURLMock(slug, "status"),
Tegola: config.MakeURLTegola("/"),
Water: makeURLMock(slug, "water"),
Nuisance: makeURLMock(slug, "nuisance"),
Status: makeURLMock(slug, "status"),
SubmitComplete: makeURLMock(slug, "nuisance-submit-complete"),
Tegola: config.MakeURLTegola("/"),
Water: makeURLMock(slug, "water"),
}
}
func makeURLMock(slug, p string) string {

View file

@ -21,12 +21,12 @@ type ContentRoot struct {
URL ContentURL
}
type ContentURL struct {
Nuisance string
NuisanceSubmit string
NuisanceSubmitComplete string
Status string
Tegola string
Water string
Nuisance string
NuisanceSubmit string
SubmitComplete string
Status string
Tegola string
Water string
}
var (

View file

@ -11,19 +11,19 @@ func Router() chi.Router {
r.Get("/nuisance", getNuisance)
r.Post("/nuisance", postNuisance)
r.Get("/submit-complete", getSubmitComplete)
r.Get("/water", getWater)
r.Get("/district/{slug}", getRootDistrict)
r.Get("/district/{slug}/nuisance", getNuisanceDistrict)
//r.Get("/district/{slug}/nuisance-submit-complete", renderMock(mockNuisanceSubmitCompleteT))
//r.Get("/district/{slug}/status", renderMock(mockStatusT))
//r.Get("/district/{slug}/water", renderMock(mockWaterT))
r.Get("/district/{slug}/water", getWaterDistrict)
r.Get("/privacy", getPrivacy)
r.Get("/robots.txt", getRobots)
r.Get("/email", getEmailByCode)
r.Get("/image/{uuid}", getImageByUUID)
r.Route("/mock", addMockRoutes)
r.Get("/pool", getPool)
r.Post("/pool-submit", postPool)
r.Get("/pool-submit-complete", getPoolSubmitComplete)
r.Get("/quick", getQuick)

View file

@ -8,6 +8,7 @@
<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>
{{template "photo-upload-header"}}
<style>
.district-logo {
@ -24,28 +25,7 @@
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 img {
width: 80px;
height: 80px;
object-fit: cover;
border-radius: 4px;
}
.section-heading {
margin-bottom: 1.5rem;
display: flex;
@ -56,12 +36,6 @@
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;
@ -251,50 +225,65 @@ function displaySelectedCoordinates(lngLat) {
</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 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>
<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="greenPoolForm" action="/pool-submit" method="POST" enctype="multipart/form-data">
<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>
<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>
<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"}}
<photo-upload/>
</div>
</div>
<!-- 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>
<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>
<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 -->
@ -315,9 +304,6 @@ function displaySelectedCoordinates(lngLat) {
</address-input>
</div>
</div>
<div class="col-md-6">
<address-display></address-display>
</div>
</div>
<p class="small text-muted mb-2">You can also click on the map to mark the location precisely</p>
@ -325,166 +311,146 @@ function displaySelectedCoordinates(lngLat) {
<input type="hidden" id="map-zoom" name="map-zoom"/>
</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" 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>
<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="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 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="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 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>
</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="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>
<!-- Access Information Section -->
<div class="form-section">
<div class="section-heading">
<i class="bi bi-unlock"></i>
<h3>Access Information</h3>
</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>
<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="form-check">
<input class="form-check-input" type="checkbox" id="fence" name="access-fence">
<label class="form-check-label" for="fence">Fence</label>
<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>
<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 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>
</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="owner-name" class="form-label">Owner Name</label>
<input type="text" class="form-control" id="owner-name" name="owner-name">
<!-- 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="col-md-6 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-12">
<label for="owner-email" class="form-label">Owner Email</label>
<input type="email" class="form-control" id="owner-email" name="owner-email">
</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="reporter-name" class="form-label">Your Name</label>
<input type="text" class="form-control" id="reporter-name" name="reporter-name">
</div>
<div class="col-md-6 mb-3">
<label for="reporter-phone" class="form-label">Your Phone</label>
<input type="tel" class="form-control" id="reporter-phone" name="reporter-phone">
</div>
<div class="col-md-12 mb-3">
<label for="reporter-email" class="form-label">Your Email</label>
<input type="email" class="form-control" id="reporter-email" name="reporter-email">
</div>
<div class="col-md-12">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="subscribe" name="subscribe" checked>
<label class="form-check-label" for="subscribe">
I would like to receive updates on this report
</label>
<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>
</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="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="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>
@ -497,22 +463,13 @@ function displaySelectedCoordinates(lngLat) {
<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">
<a class="btn btn-primary btn-lg" href="{{.URL.SubmitComplete}}">
Submit Report
</button>
</a>
</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>

View file

@ -19,23 +19,40 @@ import (
"github.com/rs/zerolog/log"
)
type ContextPool struct {
type ContentPool struct {
District *ContentDistrict
MapboxToken string
URL ContentURL
}
type ContextPoolSubmitComplete struct {
type ContentPoolSubmitComplete struct {
ReportID string
}
var (
Pool = buildTemplate("pool", "base")
PoolSubmitComplete = buildTemplate("pool-submit-complete", "base")
WaterT = buildTemplate("water", "base")
)
func getPool(w http.ResponseWriter, r *http.Request) {
func getWater(w http.ResponseWriter, r *http.Request) {
html.RenderOrError(
w,
Pool,
ContextPool{
WaterT,
ContentPool{
MapboxToken: config.MapboxToken,
},
)
}
func getWaterDistrict(w http.ResponseWriter, r *http.Request) {
district, err := districtBySlug(r)
if err != nil {
respondError(w, "Failed to lookup organization", err, http.StatusBadRequest)
return
}
html.RenderOrError(
w,
WaterT,
ContentPool{
District: newContentDistrict(district),
MapboxToken: config.MapboxToken,
},
)
@ -45,7 +62,7 @@ func getPoolSubmitComplete(w http.ResponseWriter, r *http.Request) {
html.RenderOrError(
w,
PoolSubmitComplete,
ContextPoolSubmitComplete{
ContentPoolSubmitComplete{
ReportID: report,
},
)