Add mock status page
This commit is contained in:
parent
54d2b26acd
commit
7919b37453
10 changed files with 301 additions and 17 deletions
|
|
@ -112,6 +112,7 @@ func makeFuncMap() template.FuncMap {
|
|||
"bigNumber": bigNumber,
|
||||
"GISStatement": gisStatement,
|
||||
"latLngDisplay": latLngDisplay,
|
||||
"publicReportID": publicReportID,
|
||||
"timeAsRelativeDate": timeAsRelativeDate,
|
||||
"timeDelta": timeDelta,
|
||||
"timeElapsed": timeElapsed,
|
||||
|
|
@ -145,6 +146,13 @@ func parseFromDisk(files []string) (*template.Template, error) {
|
|||
return templ, nil
|
||||
}
|
||||
|
||||
func publicReportID(s string) string {
|
||||
if len(s) != 12 {
|
||||
return s
|
||||
}
|
||||
return s[0:4] + "-" + s[4:8] + "-" + s[8:12]
|
||||
}
|
||||
|
||||
func timeAsRelativeDate(d time.Time) string {
|
||||
return d.Format("01-02")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,13 +29,6 @@ func getRegisterNotificationsComplete(w http.ResponseWriter, r *http.Request) {
|
|||
},
|
||||
)
|
||||
}
|
||||
func getStatus(w http.ResponseWriter, r *http.Request) {
|
||||
htmlpage.RenderOrError(
|
||||
w,
|
||||
Status,
|
||||
ContextStatus{},
|
||||
)
|
||||
}
|
||||
func postRegisterNotifications(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,10 @@ type ContextRegisterNotificationsComplete struct {
|
|||
ReportID string
|
||||
}
|
||||
type ContextRoot struct{}
|
||||
type ContextStatus struct{}
|
||||
|
||||
var (
|
||||
RegisterNotificationsComplete = buildTemplate("register-notifications-complete", "base")
|
||||
Root = buildTemplate("root", "base")
|
||||
Status = buildTemplate("status", "base")
|
||||
)
|
||||
|
||||
var components = [...]string{"footer", "location-geocode", "location-geocode-header", "photo-upload", "photo-upload-header"}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ func Router() chi.Router {
|
|||
r.Post("/register-notifications", postRegisterNotifications)
|
||||
r.Get("/register-notifications-complete", getRegisterNotificationsComplete)
|
||||
r.Get("/status", getStatus)
|
||||
r.Get("/status/{report_id}", getStatusByID)
|
||||
localFS := http.Dir("./static")
|
||||
htmlpage.FileServer(r, "/static", localFS, EmbeddedStaticFS, "static")
|
||||
return r
|
||||
|
|
|
|||
145
public-report/status.go
Normal file
145
public-report/status.go
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
package publicreport
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Gleipnir-Technology/nidus-sync/htmlpage"
|
||||
"github.com/go-chi/chi/v5"
|
||||
/*
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/Gleipnir-Technology/nidus-sync/db"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
||||
"github.com/Gleipnir-Technology/nidus-sync/h3utils"
|
||||
"github.com/aarondl/opt/omit"
|
||||
"github.com/aarondl/opt/omitnull"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/stephenafamo/bob/dialect/psql"
|
||||
"github.com/stephenafamo/bob/dialect/psql/um"
|
||||
*/)
|
||||
|
||||
type Report struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
type ContextStatus struct{}
|
||||
type ContextStatusByID struct {
|
||||
Report Report
|
||||
}
|
||||
|
||||
var (
|
||||
Status = buildTemplate("status", "base")
|
||||
StatusByID = buildTemplate("status-by-id", "base")
|
||||
)
|
||||
|
||||
func getStatus(w http.ResponseWriter, r *http.Request) {
|
||||
htmlpage.RenderOrError(
|
||||
w,
|
||||
Status,
|
||||
ContextStatus{},
|
||||
)
|
||||
}
|
||||
func getStatusByID(w http.ResponseWriter, r *http.Request) {
|
||||
report_id := chi.URLParam(r, "report_id")
|
||||
htmlpage.RenderOrError(
|
||||
w,
|
||||
StatusByID,
|
||||
ContextStatusByID{
|
||||
Report: Report{
|
||||
ID: report_id,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
func getQuick(w http.ResponseWriter, r *http.Request) {
|
||||
htmlpage.RenderOrError(
|
||||
w,
|
||||
Quick,
|
||||
ContextQuick{},
|
||||
)
|
||||
}
|
||||
func getQuickSubmitComplete(w http.ResponseWriter, r *http.Request) {
|
||||
report := r.URL.Query().Get("report")
|
||||
htmlpage.RenderOrError(
|
||||
w,
|
||||
QuickSubmitComplete,
|
||||
ContextQuickSubmitComplete{
|
||||
ReportID: report,
|
||||
},
|
||||
)
|
||||
}
|
||||
func postQuick(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseMultipartForm(32 << 10) // 32 MB buffer
|
||||
if err != nil {
|
||||
respondError(w, "Failed to parse form", err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
lat := r.FormValue("latitude")
|
||||
lng := r.FormValue("longitude")
|
||||
comments := r.FormValue("comments")
|
||||
//photos := r.FormValue("photos")
|
||||
|
||||
latitude, err := strconv.ParseFloat(lat, 64)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create parse latitude", err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
longitude, err := strconv.ParseFloat(lng, 64)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create parse longitude", err, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
u, err := GenerateReportID()
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create quick report public ID", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
c, err := h3utils.GetCell(longitude, latitude, 15)
|
||||
setter := models.PublicreportQuickSetter{
|
||||
Created: omit.From(time.Now()),
|
||||
Comments: omit.From(comments),
|
||||
//Location: omitnull.From(fmt.Sprintf("ST_GeometryFromText(Point(%s %s))", longitude, latitude)),
|
||||
H3cell: omitnull.From(c.String()),
|
||||
PublicID: omit.From(u),
|
||||
ReporterEmail: omit.From(""),
|
||||
ReporterPhone: omit.From(""),
|
||||
}
|
||||
quick, err := models.PublicreportQuicks.Insert(&setter).One(r.Context(), db.PGInstance.BobDB)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create database record", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
_, err = psql.Update(
|
||||
um.Table("publicreport.quick"),
|
||||
um.SetCol("location").To(fmt.Sprintf("ST_GeometryFromText('Point(%f %f)')", longitude, latitude)),
|
||||
um.Where(psql.Quote("id").EQ(psql.Arg(quick.ID))),
|
||||
).Exec(r.Context(), db.PGInstance.BobDB)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to insert publicreport", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Info().Float64("latitude", latitude).Float64("longitude", longitude).Msg("Got upload")
|
||||
photoSetters := make([]*models.PublicreportQuickPhotoSetter, 0)
|
||||
uploads, err := extractPhotoUploads(r)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to extract photo uploads", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
for _, u := range uploads {
|
||||
photoSetters = append(photoSetters, &models.PublicreportQuickPhotoSetter{
|
||||
Filename: omit.From(u.Filename),
|
||||
Size: omit.From(u.Size),
|
||||
UUID: omit.From(u.UUID),
|
||||
})
|
||||
}
|
||||
err = quick.InsertQuickPhotos(r.Context(), db.PGInstance.BobDB, photoSetters...)
|
||||
if err != nil {
|
||||
respondError(w, "Failed to create photo records", err, http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, fmt.Sprintf("/quick-submit-complete?report=%s", u), http.StatusFound)
|
||||
}*/
|
||||
|
|
@ -32,7 +32,7 @@
|
|||
<p class="lead">Your report has been successfully submitted.</p>
|
||||
<div class="alert alert-secondary py-3 mt-3">
|
||||
<strong>Report ID:</strong>
|
||||
<span class="fs-5">{{.ReportID}}</span>
|
||||
<span class="fs-5">{{.ReportID|publicReportID}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
<!-- Navigation Buttons -->
|
||||
<div class="mt-4">
|
||||
<a href="/check-report-status" class="btn btn-outline-primary me-2">
|
||||
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary me-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search me-1" viewBox="0 0 16 16">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<p class="lead">Your report has been successfully submitted.</p>
|
||||
<div class="alert alert-secondary py-3 mt-3">
|
||||
<strong>Report ID:</strong>
|
||||
<span class="fs-5">{{.ReportID}}</span>
|
||||
<span class="fs-5">{{.ReportID|publicReportID}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
<!-- Navigation Buttons -->
|
||||
<div class="mt-4">
|
||||
<a href="/check-report-status" class="btn btn-outline-primary me-2">
|
||||
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary me-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search me-1" viewBox="0 0 16 16">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<p class="lead">Thank you for helping us control mosquito populations in your area!</p>
|
||||
<div class="alert alert-info py-3">
|
||||
<strong>Your Report ID:</strong>
|
||||
<span class="fs-4 fw-bold">{{.ReportID}}</span>
|
||||
<span class="fs-4 fw-bold">{{.ReportID|publicReportID}}</span>
|
||||
</div>
|
||||
<p class="text-muted">Please save this ID for your reference.</p>
|
||||
</div>
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
Check Your Report Status
|
||||
</h4>
|
||||
<p>You can check the status of your report at any time using your Report ID.</p>
|
||||
<a href="/check-report-status" class="btn btn-outline-primary">
|
||||
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary">
|
||||
Check Status
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
<p class="lead">Your contact information has been successfully registered for report updates.</p>
|
||||
<div class="alert alert-secondary py-3 mt-3">
|
||||
<strong>Report ID:</strong>
|
||||
<span class="fs-5">{{.ReportID}}</span>
|
||||
<span class="fs-5">{{.ReportID|publicReportID}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
<!-- Navigation Buttons -->
|
||||
<div class="mt-4">
|
||||
<a href="/check-report-status" class="btn btn-outline-primary me-2">
|
||||
<a href="/status/{{.ReportID}}" class="btn btn-outline-primary me-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search me-1" viewBox="0 0 16 16">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
|
||||
</svg>
|
||||
|
|
|
|||
139
public-report/template/status-by-id.html
Normal file
139
public-report/template/status-by-id.html
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
{{template "base.html" .}}
|
||||
|
||||
{{define "title"}}Status of report {{.Report.ID|publicReportID}}{{end}}
|
||||
{{define "extraheader"}}
|
||||
<style>
|
||||
.timeline {
|
||||
border-left: 3px solid #dee2e6;
|
||||
padding-left: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.timeline-item {
|
||||
position: relative;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
.timeline-item:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -29px;
|
||||
top: 0;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
.timeline-date {
|
||||
font-size: 0.85rem;
|
||||
color: #6c757d;
|
||||
}
|
||||
.map-container {
|
||||
height: 300px;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.map-container {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
.status-badge {
|
||||
font-size: 1rem;
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<!-- Report ID and Status Section -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Report {{.Report.ID|publicReportID}}</h5>
|
||||
<span class="badge bg-warning text-dark status-badge">Scheduled</span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<strong><i class="fas fa-calendar-plus me-2"></i>Created:</strong>
|
||||
<span>July 15, 2023 - 9:30 AM</span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<strong><i class="fas fa-sync me-2"></i>Last Updated:</strong>
|
||||
<span>July 17, 2023 - 2:45 PM</span>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<strong><i class="fas fa-hourglass-half me-2"></i>Next Step:</strong>
|
||||
<span>July 19, 2023 (Estimated)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contact Information -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-6 mb-3 mb-md-0">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-user me-2"></i>Reporter Information</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Name:</strong> Jane Doe</p>
|
||||
<p><strong>Phone:</strong> (555) 123-4567</p>
|
||||
<p><strong>Address:</strong> 123 Main Street, Anytown, USA 12345</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="card-header bg-secondary text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-home me-2"></i>Nuisance Property Information</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Owner:</strong> John Smith</p>
|
||||
<p><strong>Address:</strong> 456 Elm Street, Anytown, USA 12345</p>
|
||||
<p><strong>Description:</strong> Standing water in abandoned pool</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Map Section -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-header bg-info text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-map-marked-alt me-2"></i>Location Map</h5>
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="map-container">
|
||||
<!-- Replace with actual map embed code -->
|
||||
<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3000!2d-122.4194!3d37.7749!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x0!2zMzfCsDQ2JzI5LjYiTiAxMjLCsDI1JzEwLjAiVw!5e0!3m2!1sen!2sus!4v1627309456789!5m2!1sen!2sus"
|
||||
width="100%" height="100%" style="border:0;" allowfullscreen="" loading="lazy"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- History Timeline -->
|
||||
<div class="card">
|
||||
<div class="card-header bg-success text-white">
|
||||
<h5 class="mb-0"><i class="fas fa-history me-2"></i>Request History</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="timeline">
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-date">July 17, 2023 - 2:45 PM</div>
|
||||
<h5 class="mb-1">Scheduled for Treatment</h5>
|
||||
<p class="mb-0">Site visit scheduled for July 19. Technician: Michael Johnson</p>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-date">July 16, 2023 - 10:30 AM</div>
|
||||
<h5 class="mb-1">Assessment Complete</h5>
|
||||
<p class="mb-0">Initial assessment completed. Property requires treatment for mosquito larvae.</p>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-date">July 15, 2023 - 1:15 PM</div>
|
||||
<h5 class="mb-1">In Review</h5>
|
||||
<p class="mb-0">Report assigned to field supervisor for initial assessment.</p>
|
||||
</div>
|
||||
<div class="timeline-item">
|
||||
<div class="timeline-date">July 15, 2023 - 9:30 AM</div>
|
||||
<h5 class="mb-1">Report Created</h5>
|
||||
<p class="mb-0">New mosquito nuisance report submitted by Jane Doe.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
Loading…
Add table
Add a link
Reference in a new issue