Add mocks for service request, sync information to dashboard

Should have been split, but I had commit challenges
This commit is contained in:
Eli Ribble 2025-11-08 00:04:44 +00:00
parent eb52b36f45
commit 31ca1a2f45
No known key found for this signature in database
13 changed files with 2145 additions and 20 deletions

View file

@ -358,6 +358,7 @@ func periodicallyExportFieldseeker(ctx context.Context, org *models.Organization
if err != nil { if err != nil {
return fmt.Errorf("Failed to export Fieldseeker data: %v", err) return fmt.Errorf("Failed to export Fieldseeker data: %v", err)
} }
slog.Info("Completed exporting data, waiting 15 minutes to go agoin.")
pollTicker = time.NewTicker(15 * time.Minute) pollTicker = time.NewTicker(15 * time.Minute)
} }
} }
@ -400,7 +401,9 @@ func exportFieldseekerData(ctx context.Context, org *models.Organization, oauth
RecordsUnchanged: omit.From(int32(stats.Unchanged)), RecordsUnchanged: omit.From(int32(stats.Unchanged)),
} }
err = org.InsertFieldseekerSyncs(ctx, PGInstance.BobDB, &setter) err = org.InsertFieldseekerSyncs(ctx, PGInstance.BobDB, &setter)
//err = user.InsertUserOauthTokens(ctx, PGInstance.BobDB, &setter) if err != nil {
return fmt.Errorf("Failed to insert sync: %v", err)
}
return nil return nil
} }

View file

@ -182,6 +182,50 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
respondError(w, "Failed to render root", err, http.StatusInternalServerError) respondError(w, "Failed to render root", err, http.StatusInternalServerError)
} }
} }
func getServiceRequest(w http.ResponseWriter, r *http.Request) {
err := htmlServiceRequest(w)
if err != nil {
respondError(w, "Failed to generate service request page", err, http.StatusInternalServerError)
}
}
func getServiceRequestDetail(w http.ResponseWriter, r *http.Request) {
code := chi.URLParam(r, "code")
err := htmlServiceRequestDetail(w, code)
if err != nil {
respondError(w, "Failed to generate service request page", err, http.StatusInternalServerError)
}
}
func getServiceRequestLocation(w http.ResponseWriter, r *http.Request) {
err := htmlServiceRequestLocation(w)
if err != nil {
respondError(w, "Failed to generate service request location page", err, http.StatusInternalServerError)
}
}
func getServiceRequestMosquito(w http.ResponseWriter, r *http.Request) {
err := htmlServiceRequestMosquito(w)
if err != nil {
respondError(w, "Failed to generate service request mosquito page", err, http.StatusInternalServerError)
}
}
func getServiceRequestPool(w http.ResponseWriter, r *http.Request) {
err := htmlServiceRequestPool(w)
if err != nil {
respondError(w, "Failed to generate service request pool page", err, http.StatusInternalServerError)
}
}
func getServiceRequestUpdates(w http.ResponseWriter, r *http.Request) {
err := htmlServiceRequestUpdates(w)
if err != nil {
respondError(w, "Failed to generate service request updates page", err, http.StatusInternalServerError)
}
}
func getSignup(w http.ResponseWriter, r *http.Request) { func getSignup(w http.ResponseWriter, r *http.Request) {
err := htmlSignup(w, r.URL.Path) err := htmlSignup(w, r.URL.Path)
if err != nil { if err != nil {

70
html.go
View file

@ -18,17 +18,23 @@ import (
) )
var ( var (
dashboard = newBuiltTemplate("dashboard", "authenticated") dashboard = newBuiltTemplate("dashboard", "authenticated")
oauthPrompt = newBuiltTemplate("oauth-prompt", "authenticated") oauthPrompt = newBuiltTemplate("oauth-prompt", "authenticated")
report = newBuiltTemplate("report", "base") report = newBuiltTemplate("report", "base")
reportConfirmation = newBuiltTemplate("report-confirmation", "base") reportConfirmation = newBuiltTemplate("report-confirmation", "base")
reportContribute = newBuiltTemplate("report-contribute", "base") reportContribute = newBuiltTemplate("report-contribute", "base")
reportDetail = newBuiltTemplate("report-detail", "base") reportDetail = newBuiltTemplate("report-detail", "base")
reportEvidence = newBuiltTemplate("report-evidence", "base") reportEvidence = newBuiltTemplate("report-evidence", "base")
reportSchedule = newBuiltTemplate("report-schedule", "base") reportSchedule = newBuiltTemplate("report-schedule", "base")
reportUpdate = newBuiltTemplate("report-update", "base") reportUpdate = newBuiltTemplate("report-update", "base")
signin = newBuiltTemplate("signin", "base") serviceRequest = newBuiltTemplate("service-request", "base")
signup = newBuiltTemplate("signup", "base") serviceRequestDetail = newBuiltTemplate("service-request-detail", "base")
serviceRequestLocation = newBuiltTemplate("service-request-location", "base")
serviceRequestMosquito = newBuiltTemplate("service-request-mosquito", "base")
serviceRequestPool = newBuiltTemplate("service-request-pool", "base")
serviceRequestUpdates = newBuiltTemplate("service-request-updates", "base")
signin = newBuiltTemplate("signin", "base")
signup = newBuiltTemplate("signup", "base")
) )
var components = [...]string{"header"} var components = [...]string{"header"}
@ -52,7 +58,7 @@ type ContentDashboard struct {
CountInspections int CountInspections int
CountMosquitoSources int CountMosquitoSources int
CountServiceRequests int CountServiceRequests int
LastSync string LastSync time.Time
Org string Org string
RecentRequests []ServiceRequestSummary RecentRequests []ServiceRequestSummary
User User User User
@ -109,13 +115,12 @@ func htmlDashboard(ctx context.Context, w io.Writer, user *models.User) error {
if err != nil { if err != nil {
return fmt.Errorf("Failed to get org: %v", err) return fmt.Errorf("Failed to get org: %v", err)
} }
var syncString string var lastSync time.Time
sync, err := org.FieldseekerSyncs(sm.OrderBy("created")).One(ctx, PGInstance.BobDB) sync, err := org.FieldseekerSyncs(sm.OrderBy("created")).One(ctx, PGInstance.BobDB)
if err != nil { if err != nil {
//return fmt.Errorf("Failed to get sync: %v", err) return fmt.Errorf("Failed to get sync: %v", err)
syncString = "never"
} else { } else {
syncString = sync.Created.String() lastSync = sync.Created
} }
inspectionCount, err := org.FSMosquitoinspections().Count(ctx, PGInstance.BobDB) inspectionCount, err := org.FSMosquitoinspections().Count(ctx, PGInstance.BobDB)
if err != nil { if err != nil {
@ -146,7 +151,7 @@ func htmlDashboard(ctx context.Context, w io.Writer, user *models.User) error {
CountInspections: int(inspectionCount), CountInspections: int(inspectionCount),
CountMosquitoSources: int(sourceCount), CountMosquitoSources: int(sourceCount),
CountServiceRequests: int(serviceCount), CountServiceRequests: int(serviceCount),
LastSync: syncString, LastSync: lastSync,
Org: org.Name.MustGet(), Org: org.Name.MustGet(),
RecentRequests: requests, RecentRequests: requests,
User: User{ User: User{
@ -226,6 +231,36 @@ func htmlReportUpdate(w io.Writer, code string) error {
return reportUpdate.ExecuteTemplate(w, data) return reportUpdate.ExecuteTemplate(w, data)
} }
func htmlServiceRequest(w io.Writer) error {
data := ContentPlaceholder{}
return serviceRequest.ExecuteTemplate(w, data)
}
func htmlServiceRequestDetail(w io.Writer, code string) error {
data := ContentPlaceholder{}
return serviceRequestDetail.ExecuteTemplate(w, data)
}
func htmlServiceRequestLocation(w io.Writer) error {
data := ContentPlaceholder{}
return serviceRequestLocation.ExecuteTemplate(w, data)
}
func htmlServiceRequestMosquito(w io.Writer) error {
data := ContentPlaceholder{}
return serviceRequestMosquito.ExecuteTemplate(w, data)
}
func htmlServiceRequestPool(w io.Writer) error {
data := ContentPlaceholder{}
return serviceRequestPool.ExecuteTemplate(w, data)
}
func htmlServiceRequestUpdates(w io.Writer) error {
data := ContentPlaceholder{}
return serviceRequestUpdates.ExecuteTemplate(w, data)
}
func htmlSignin(w io.Writer, errorCode string) error { func htmlSignin(w io.Writer, errorCode string) error {
data := ContentSignin{ data := ContentSignin{
InvalidCredentials: errorCode == "invalid-credentials", InvalidCredentials: errorCode == "invalid-credentials",
@ -311,6 +346,7 @@ func timeSince(t time.Time) string {
diff := now.Sub(t) diff := now.Sub(t)
hours := diff.Hours() hours := diff.Hours()
slog.Info("time since", slog.String("t", t.String()), slog.Float64("hours", hours))
if hours < 1 { if hours < 1 {
minutes := diff.Minutes() minutes := diff.Minutes()
return fmt.Sprintf("%d minutes ago", int(minutes)) return fmt.Sprintf("%d minutes ago", int(minutes))

View file

@ -71,6 +71,12 @@ func main() {
r.Get("/report/{code}/evidence", getReportEvidence) r.Get("/report/{code}/evidence", getReportEvidence)
r.Get("/report/{code}/schedule", getReportSchedule) r.Get("/report/{code}/schedule", getReportSchedule)
r.Get("/report/{code}/update", getReportUpdate) r.Get("/report/{code}/update", getReportUpdate)
r.Get("/service-request", getServiceRequest)
r.Get("/service-request/{code}", getServiceRequestDetail)
r.Get("/service-request-location", getServiceRequestLocation)
r.Get("/service-request-mosquito", getServiceRequestMosquito)
r.Get("/service-request-pool", getServiceRequestPool)
r.Get("/service-request-updates", getServiceRequestUpdates)
r.Post("/signin", postSignin) r.Post("/signin", postSignin)
r.Get("/signup", getSignup) r.Get("/signup", getSignup)
r.Post("/signup", postSignup) r.Post("/signup", postSignup)

View file

@ -3,8 +3,14 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap CSS -->
<title>{{template "title" .}} - Nidus Sync</title> <title>{{template "title" .}} - Nidus Sync</title>
<link href="/static/vendor/css/bootstrap.min.css" rel="stylesheet"> <link href="/static/vendor/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<script>
{{block "script" .}} {{end}}
</script>
<style> <style>
{{template "style" .}} {{template "style" .}}
</style> </style>

View file

@ -69,7 +69,7 @@ body {
</div> </div>
<div class="col-md-6 text-md-end d-flex align-items-center justify-content-md-end"> <div class="col-md-6 text-md-end d-flex align-items-center justify-content-md-end">
<p class="last-refreshed mb-0"> <p class="last-refreshed mb-0">
<i class="fas fa-sync-alt me-2"></i>Last updated: <span id="last-refreshed-time">{{ .LastSync }}</span> <i class="fas fa-sync-alt me-2"></i>Last updated: <span id="last-refreshed-time">{{ .LastSync | timeSince }}</span>
<button class="btn btn-sm btn-outline-primary ms-3">Refresh Data</button> <button class="btn btn-sm btn-outline-primary ms-3">Refresh Data</button>
</p> </p>
</div> </div>
@ -85,7 +85,7 @@ body {
<i class="fas fa-clock"></i> <i class="fas fa-clock"></i>
</div> </div>
<h5 class="card-title">Last Data Refresh</h5> <h5 class="card-title">Last Data Refresh</h5>
<p class="metric-value">{{ .LastSync }}</p> <p class="metric-value">{{ .LastSync | timeSince }}</p>
<p class="card-text text-muted">Last sync: 12:45 PM</p> <p class="card-text text-muted">Last sync: 12:45 PM</p>
</div> </div>
</div> </div>

7
templates/empty.html Normal file
View file

@ -0,0 +1,7 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "style"}}
{{end}}
{{define "content"}}
{{end}}

View file

@ -0,0 +1,316 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "style"}}
.district-logo {
max-height: 80px;
width: auto;
}
.map-container {
height: 300px;
background-color: #e9ecef;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
border: 1px solid #dee2e6;
}
.progress-tracker {
display: flex;
justify-content: space-between;
margin: 20px 0;
position: relative;
}
.progress-tracker::before {
content: '';
position: absolute;
top: 25px;
left: 0;
width: 100%;
height: 2px;
background-color: #dee2e6;
z-index: 1;
}
.progress-step {
position: relative;
z-index: 2;
text-align: center;
width: 60px;
}
.progress-icon {
height: 50px;
width: 50px;
background-color: #fff;
border-radius: 50%;
border: 2px solid #dee2e6;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8px;
}
.progress-icon.active {
border-color: #0d6efd;
background-color: #0d6efd;
color: white;
}
.progress-icon.completed {
border-color: #198754;
background-color: #198754;
color: white;
}
.progress-label {
font-size: 0.8rem;
font-weight: 500;
}
.type-badge {
display: flex;
align-items: center;
font-size: 1.1rem;
}
.type-badge i {
margin-right: 8px;
}
.coordinates {
font-size: 0.85rem;
color: #6c757d;
}
.note-item {
border-left: 3px solid #0d6efd;
padding: 10px 15px;
background-color: rgba(13, 110, 253, 0.05);
margin-bottom: 10px;
}
.note-date {
font-size: 0.8rem;
color: #6c757d;
margin-bottom: 2px;
}
{{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">
<!-- Report Header -->
<div class="row mb-4">
<div class="col-md-8">
<h2>Report #MMD-2023-12345</h2>
</div>
<div class="col-md-4 text-md-end">
<span class="badge bg-primary type-badge">
<i class="bi bi-water"></i> Green Pool
</span>
</div>
</div>
<!-- Progress Tracker -->
<div class="progress-tracker mb-5">
<div class="progress-step">
<div class="progress-icon completed">
<i class="bi bi-check-lg"></i>
</div>
<div class="progress-label">Submitted</div>
</div>
<div class="progress-step">
<div class="progress-icon completed">
<i class="bi bi-check-lg"></i>
</div>
<div class="progress-label">Accepted</div>
</div>
<div class="progress-step">
<div class="progress-icon active">
<i class="bi bi-clock"></i>
</div>
<div class="progress-label">Scheduled</div>
</div>
<div class="progress-step">
<div class="progress-icon">
<i class="bi bi-flag"></i>
</div>
<div class="progress-label">Complete</div>
</div>
</div>
<div class="row">
<!-- Map and Location Information -->
<div class="col-lg-5 mb-4">
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Location</h5>
</div>
<div class="card-body">
<!-- Map Placeholder -->
<div class="map-container mb-3">
<div class="text-center">
<i class="bi bi-map fs-1 text-secondary"></i>
<p class="mb-0">Map of Report Location</p>
</div>
</div>
<!-- Address Information -->
<div>
<h6>Address</h6>
<p class="mb-2">123 Mosquito Ave, Lakeside, CA 92040</p>
<p class="coordinates mb-0">
<i class="bi bi-geo-alt"></i> 32.8573° N, 116.9222° W
</p>
</div>
</div>
</div>
</div>
<!-- Report Details -->
<div class="col-lg-7 mb-4">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Report Details</h5>
</div>
<div class="card-body">
<div class="row mb-4">
<div class="col-md-6">
<h6>Report Source</h6>
<p><i class="bi bi-phone"></i> Phone Call</p>
</div>
<div class="col-md-6">
<h6>Report Date</h6>
<p>October 15, 2023 at 2:45 PM</p>
</div>
</div>
<div class="mb-4">
<h6>Description</h6>
<p>I noticed my neighbor's backyard pool has turned green and there's nobody living in the house currently. I'm concerned it might be breeding mosquitoes as I've noticed more of them in my yard recently. The house seems to be vacant for about 3 months now.</p>
</div>
<div class="row mb-4">
<div class="col-md-6">
<h6>Pool Status</h6>
<p><span class="badge bg-warning text-dark"><i class="bi bi-exclamation-triangle"></i> Stagnant/Green</span></p>
</div>
<div class="col-md-6">
<h6>Scheduled Appointment</h6>
<p>October 20, 2023, 9:00 AM - 11:00 AM</p>
</div>
</div>
<div class="mb-4">
<h6>Contact Information</h6>
<div class="row">
<div class="col-md-6">
<p class="mb-1"><strong>Reported By:</strong> John Smith</p>
<p class="mb-1"><strong>Phone:</strong> (555) 123-4567</p>
</div>
<div class="col-md-6">
<p class="mb-1"><strong>Email:</strong> john.smith@example.com</p>
<p class="mb-1"><strong>Preferred Contact:</strong> Phone</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Technician Notes -->
<div class="row">
<div class="col-12 mb-4">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Notes & Updates</h5>
<span class="badge bg-info">3 Notes</span>
</div>
<div class="card-body">
<div class="note-item">
<div class="note-date">Added by System on Oct 15, 2023, 2:45 PM</div>
<div class="note-content">Report created via phone call to district office.</div>
</div>
<div class="note-item">
<div class="note-date">Added by Sarah Johnson (Office Staff) on Oct 16, 2023, 9:30 AM</div>
<div class="note-content">Verified location information. Property appears to be vacant according to county records. Left voicemail with property management company listed in county database.</div>
</div>
<div class="note-item">
<div class="note-date">Added by Mike Davis (Technician) on Oct 18, 2023, 11:15 AM</div>
<div class="note-content">Scheduled inspection for Oct 20. Will need access to backyard. Contacted reporter to confirm they'll be available to provide access information on day of service.</div>
</div>
</div>
</div>
</div>
</div>
<!-- Next Steps -->
<div class="row">
<div class="col-12 mb-4">
<div class="card bg-light">
<div class="card-body">
<h5><i class="bi bi-arrow-right-circle"></i> Next Steps</h5>
<p>Technician scheduled to inspect the property on October 20, 2023, between 9:00 AM - 11:00 AM. If access to the property is not possible, treatment may be conducted from outside the property or additional follow-up may be required.</p>
<p class="mb-0"><strong>Note:</strong> You will receive a notification when the status of this report changes.</p>
</div>
</div>
</div>
</div>
<!-- Update Form -->
<div class="row mt-3">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Add Information</h5>
</div>
<div class="card-body">
<p>Do you have additional information about this report? Add it below to update the technician.</p>
<form>
<div class="mb-3">
<label for="updateMessage" class="form-label">Message</label>
<textarea class="form-control" id="updateMessage" rows="3" placeholder="Enter additional information here..."></textarea>
</div>
<div class="mb-3">
<label for="contactPhone" class="form-label">Phone Number (optional)</label>
<input type="tel" class="form-control" id="contactPhone" placeholder="(555) 123-4567">
<div class="form-text">Provide your phone number if you'd like to be contacted about this update.</div>
</div>
<button type="submit" class="btn btn-primary">Submit Update</button>
</form>
</div>
</div>
</div>
</div>
<!-- Back Button -->
<div class="row mt-4">
<div class="col-12">
<a href="/check-status" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Back to Status Check
</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,365 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "style"}}
.district-logo {
max-height: 80px;
width: auto;
}
.map-container {
height: 400px;
background-color: #e9ecef;
border-radius: 5px;
border: 1px solid #dee2e6;
position: relative;
}
.map-placeholder {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
flex-direction: column;
}
.map-overlay {
position: absolute;
bottom: 20px;
right: 20px;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px;
border-radius: 5px;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
max-width: 250px;
}
.map-controls {
position: absolute;
top: 10px;
right: 10px;
display: flex;
flex-direction: column;
gap: 5px;
}
.map-control-btn {
width: 40px;
height: 40px;
background-color: white;
border: 1px solid #dee2e6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}
.report-type-icon {
font-size: 1.2rem;
}
.days-ago {
font-size: 0.85rem;
color: #6c757d;
}
.status-badge {
font-size: 0.85rem;
font-weight: normal;
padding: 6px 10px;
}
.report-row:hover {
background-color: rgba(13, 110, 253, 0.05);
cursor: pointer;
}
.instruction-card {
border-left: 4px solid #0d6efd;
}
{{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>Lookup Reports by Location</h2>
<p class="lead">Find reports and mosquito activity in your area</p>
</div>
</div>
<!-- Instructions Card -->
<div class="row mb-4">
<div class="col-12">
<div class="card instruction-card">
<div class="card-body">
<h5><i class="bi bi-info-circle me-2"></i>How to use this tool</h5>
<p class="mb-0">You can either <strong>enter an address</strong> in the search box or <strong>navigate the map</strong> by dragging and zooming to find reports in your area. The table below will update automatically to show reports within the current map view.</p>
</div>
</div>
</div>
</div>
<!-- Search and Map Section -->
<div class="row mb-4">
<div class="col-md-4 mb-3 mb-md-0">
<!-- Address Search -->
<div class="card h-100">
<div class="card-header">
<h5 class="mb-0">Search by Address</h5>
</div>
<div class="card-body">
<form id="addressSearchForm">
<div class="mb-3">
<label for="addressInput" class="form-label">Enter an address or location</label>
<div class="input-group">
<input type="text" class="form-control" id="addressInput" placeholder="123 Main St, City, State">
<button class="btn btn-primary" type="submit">
<i class="bi bi-search"></i>
</button>
</div>
</div>
<div class="mb-3">
<label class="form-label">Search radius</label>
<select class="form-select" id="searchRadius">
<option value="0.5">0.5 miles</option>
<option value="1" selected>1 mile</option>
<option value="2">2 miles</option>
<option value="5">5 miles</option>
</select>
</div>
</form>
<div class="alert alert-info mt-4">
<small><i class="bi bi-eye me-1"></i> Currently showing reports within <strong>1 mile</strong> of map center</small>
</div>
</div>
</div>
</div>
<div class="col-md-8">
<!-- Map Area -->
<div class="map-container">
<div class="map-placeholder">
<i class="bi bi-map fs-1 text-secondary mb-2"></i>
<p class="mb-1 fw-bold">Interactive Map Area</p>
<p class="text-muted small mb-0">The map will display here and allow you to navigate the area</p>
</div>
<!-- Simulated map controls -->
<div class="map-controls">
<button class="map-control-btn">
<i class="bi bi-plus"></i>
</button>
<button class="map-control-btn">
<i class="bi bi-dash"></i>
</button>
<button class="map-control-btn">
<i class="bi bi-house"></i>
</button>
</div>
<!-- Map overlay showing current view -->
<div class="map-overlay">
<div class="small fw-bold mb-1">Current View</div>
<div class="small">Lakeside, CA</div>
<div class="small text-muted">32.857° N, 116.922° W</div>
</div>
</div>
</div>
</div>
<!-- Results Section -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Reports in This Area</h5>
<span class="badge bg-secondary">Showing 12 of 37 total reports</span>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th>Type</th>
<th>Location</th>
<th>Submitted</th>
<th>Status</th>
<th>Report ID</th>
</tr>
</thead>
<tbody>
<!-- Report Row 1 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-primary me-1">
<i class="bi bi-water"></i>
</span>
Green Pool
</td>
<td>123 Mosquito Ave</td>
<td>
Oct 15, 2023
<div class="days-ago">5 days ago</div>
</td>
<td>
<span class="badge bg-primary status-badge">Scheduled</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12345">MMD-2023-12345</a>
</td>
</tr>
<!-- Report Row 2 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-danger me-1">
<i class="bi bi-bug"></i>
</span>
Mosquito Nuisance
</td>
<td>456 Lake Dr</td>
<td>
Oct 12, 2023
<div class="days-ago">8 days ago</div>
</td>
<td>
<span class="badge bg-success status-badge">Complete</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12341">MMD-2023-12341</a>
</td>
</tr>
<!-- Report Row 3 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-success me-1">
<i class="bi bi-droplet"></i>
</span>
Fish Request
</td>
<td>789 Creek Rd</td>
<td>
Oct 18, 2023
<div class="days-ago">2 days ago</div>
</td>
<td>
<span class="badge bg-warning text-dark status-badge">Acknowledged</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12350">MMD-2023-12350</a>
</td>
</tr>
<!-- Report Row 4 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-danger me-1">
<i class="bi bi-bug"></i>
</span>
Mosquito Nuisance
</td>
<td>101 Pond Ln</td>
<td>
Sep 25, 2023
<div class="days-ago">25 days ago</div>
</td>
<td>
<span class="badge bg-success status-badge">Complete</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12289">MMD-2023-12289</a>
</td>
</tr>
<!-- Report Row 5 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-primary me-1">
<i class="bi bi-water"></i>
</span>
Green Pool
</td>
<td>202 Highland Ave</td>
<td>
Oct 19, 2023
<div class="days-ago">1 day ago</div>
</td>
<td>
<span class="badge bg-secondary status-badge">Submitted</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12356">MMD-2023-12356</a>
</td>
</tr>
<!-- Report Row 6 -->
<tr class="report-row">
<td>
<span class="report-type-icon text-primary me-1">
<i class="bi bi-water"></i>
</span>
Green Pool
</td>
<td>303 Marsh Way</td>
<td>
Aug 15, 2023
<div class="days-ago">2 months ago</div>
</td>
<td>
<span class="badge bg-success status-badge">Complete</span>
</td>
<td>
<a href="/report-details?id=MMD-2023-12056">MMD-2023-12056</a>
</td>
</tr>
<!-- More rows would go here -->
</tbody>
</table>
</div>
</div>
<div class="card-footer text-center">
<p class="mb-0 small text-muted">
Showing reports submitted within the last 6 months. The table displays up to 20 reports at a time.
</p>
</div>
</div>
</div>
</div>
<!-- Back Button -->
<div class="row mt-4">
<div class="col-12">
<a href="/check-status" class="btn btn-outline-secondary">
<i class="bi bi-arrow-left"></i> Back to Status Check
</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,539 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "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';
}
});
});
});
{{end}}
{{define "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;
}
{{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,522 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "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 = '';
}
});
{{end}}
{{define "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;
}
{{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 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>
<!-- 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,160 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "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;
}
}
{{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>
<!-- 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>
<!-- 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,121 @@
{{template "base.html" .}}
{{define "title"}}Dash{{end}}
{{define "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);
}
.district-logo {
max-height: 80px;
width: auto;
}
{{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>
<!-- 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">Welcome to Our Mosquito Management Services</h2>
<p class="lead text-center">
We are dedicated to protecting public health and improving quality of life by reducing
mosquito populations and the diseases they can carry. Our district provides comprehensive
mosquito surveillance, control, and education services to our community.
</p>
</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">
<!-- Service Option 1 -->
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-search" 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>
</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="/service-request-updates" class="btn btn-primary mt-3">Get Updates</a>
</div>
</div>
</div>
<!-- Service Option 2 -->
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-water" viewBox="0 0 16 16">
<path d="M.036 3.314a.5.5 0 0 1 .65-.278l1.757.703a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.757-.703a.5.5 0 1 1 .372.928l-1.758.703a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0L.664 3.964a.5.5 0 0 1-.278-.65zm0 3a.5.5 0 0 1 .65-.278l1.757.703a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.757-.703a.5.5 0 1 1 .372.928l-1.758.703a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0L.664 6.964a.5.5 0 0 1-.278-.65zm0 3a.5.5 0 0 1 .65-.278l1.757.703a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.014-.406a2.5 2.5 0 0 1 1.857 0l1.015.406a1.5 1.5 0 0 0 1.114 0l1.757-.703a.5.5 0 1 1 .372.928l-1.758.703a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0l-1.014-.406a1.5 1.5 0 0 0-1.114 0l-1.015.406a2.5 2.5 0 0 1-1.857 0L.664 9.964a.5.5 0 0 1-.278-.65z"/>
</svg>
</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="/service-request-pool" class="btn btn-primary mt-3">Report Source</a>
</div>
</div>
</div>
<!-- Service Option 3 -->
<div class="col-md-4">
<div class="card service-card h-100">
<div class="card-body text-center">
<div class="mb-3">
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" class="bi bi-bug" viewBox="0 0 16 16">
<path d="M4.355.522a.5.5 0 0 1 .623.333l.291.956A4.979 4.979 0 0 1 8 1c1.007 0 1.946.298 2.731.811l.29-.956a.5.5 0 1 1 .957.29l-.41 1.352A4.985 4.985 0 0 1 13 6h.5a.5.5 0 0 0 .5-.5V5a.5.5 0 0 1 1 0v.5A1.5 1.5 0 0 1 13.5 7H13v1h1.5a.5.5 0 0 1 0 1H13v1h.5a1.5 1.5 0 0 1 1.5 1.5v.5a.5.5 0 1 1-1 0v-.5a.5.5 0 0 0-.5-.5H13a5 5 0 0 1-10 0h-.5a.5.5 0 0 0-.5.5v.5a.5.5 0 1 1-1 0v-.5A1.5 1.5 0 0 1 2.5 10H3V9H1.5a.5.5 0 0 1 0-1H3V7h-.5A1.5 1.5 0 0 1 1 5.5V5a.5.5 0 0 1 1 0v.5a.5.5 0 0 0 .5.5H3c0-1.364.547-2.601 1.432-3.503l-.41-1.352a.5.5 0 0 1 .333-.623zM4 7v4a4 4 0 0 0 3.5 3.97V7H4zm4.5 0v7.97A4 4 0 0 0 12 11V7H8.5zM12 6a3.989 3.989 0 0 0-1.334-2.982A3.983 3.983 0 0 0 8 2a3.983 3.983 0 0 0-2.667 1.018A3.989 3.989 0 0 0 4 6h8z"/>
</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="/service-request-mosquito" class="btn btn-primary mt-3">Report Problem</a>
</div>
</div>
</div>
</div>
</div>
</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; 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}}