Use common logic in mocks, add dispatch mock
This commit is contained in:
parent
62dbfb3ebc
commit
3a8d6395d7
31 changed files with 671 additions and 291 deletions
90
endpoint.go
90
endpoint.go
|
|
@ -66,19 +66,6 @@ func getOAuthRefresh(w http.ResponseWriter, r *http.Request) {
|
||||||
htmlOauthPrompt(w, user)
|
htmlOauthPrompt(w, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPhoneCall(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlPhoneCall(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDataEntry(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlDataEntry(w)
|
|
||||||
}
|
|
||||||
func getDataEntryBad(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlDataEntryBad(w)
|
|
||||||
}
|
|
||||||
func getDataEntryGood(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlDataEntryGood(w)
|
|
||||||
}
|
|
||||||
func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
|
func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
|
||||||
code := chi.URLParam(r, "code")
|
code := chi.URLParam(r, "code")
|
||||||
if code == "" {
|
if code == "" {
|
||||||
|
|
@ -138,40 +125,6 @@ func getQRCodeReport(w http.ResponseWriter, r *http.Request) {
|
||||||
respondError(w, "Error writing response", err, http.StatusInternalServerError)
|
respondError(w, "Error writing response", err, http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func getReport(w http.ResponseWriter, r *http.Request) {
|
|
||||||
//org := r.URL.Query().Get("org")
|
|
||||||
htmlReport(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportConfirmation(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportConfirmation(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportContribute(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportContribute(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportDetail(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportDetail(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportEvidence(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportEvidence(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportSchedule(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportSchedule(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getReportUpdate(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlReportUpdate(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRoot(w http.ResponseWriter, r *http.Request) {
|
func getRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
user, err := getAuthenticatedUser(r)
|
user, err := getAuthenticatedUser(r)
|
||||||
|
|
@ -202,39 +155,6 @@ func getRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getServiceRequest(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequest(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestDetail(w http.ResponseWriter, r *http.Request) {
|
|
||||||
code := chi.URLParam(r, "code")
|
|
||||||
htmlServiceRequestDetail(w, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestLocation(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestLocation(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestMosquito(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestMosquito(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestPool(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestPool(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestQuick(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestQuick(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestQuickConfirmation(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestQuickConfirmation(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getServiceRequestUpdates(w http.ResponseWriter, r *http.Request) {
|
|
||||||
htmlServiceRequestUpdates(w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getSettings(w http.ResponseWriter, r *http.Request, u *models.User) {
|
func getSettings(w http.ResponseWriter, r *http.Request, u *models.User) {
|
||||||
htmlSettings(w, r, u)
|
htmlSettings(w, r, u)
|
||||||
}
|
}
|
||||||
|
|
@ -326,3 +246,13 @@ func postSignup(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
http.Redirect(w, r, "/", http.StatusFound)
|
http.Redirect(w, r, "/", http.StatusFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderMock(templateName string) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
code := chi.URLParam(r, "code")
|
||||||
|
if code == "" {
|
||||||
|
code = "abc-123"
|
||||||
|
}
|
||||||
|
htmlMock(templateName, w, code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
187
html.go
187
html.go
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"log/slog"
|
|
||||||
"math"
|
"math"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -41,10 +40,13 @@ var (
|
||||||
|
|
||||||
// Unauthenticated pages
|
// Unauthenticated pages
|
||||||
var (
|
var (
|
||||||
|
admin = newBuiltTemplate("admin", "base")
|
||||||
dataEntry = newBuiltTemplate("data-entry", "base")
|
dataEntry = newBuiltTemplate("data-entry", "base")
|
||||||
dataEntryGood = newBuiltTemplate("data-entry-good", "base")
|
dataEntryGood = newBuiltTemplate("data-entry-good", "base")
|
||||||
dataEntryBad = newBuiltTemplate("data-entry-bad", "base")
|
dataEntryBad = newBuiltTemplate("data-entry-bad", "base")
|
||||||
phoneCall = newBuiltTemplate("phone-call", "base")
|
dispatch = newBuiltTemplate("dispatch", "base")
|
||||||
|
dispatchResults = newBuiltTemplate("dispatch-results", "base")
|
||||||
|
mockRoot = newBuiltTemplate("mock-root", "base")
|
||||||
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")
|
||||||
|
|
@ -64,6 +66,7 @@ var (
|
||||||
signup = newBuiltTemplate("signup", "base")
|
signup = newBuiltTemplate("signup", "base")
|
||||||
)
|
)
|
||||||
var components = [...]string{"header", "map"}
|
var components = [...]string{"header", "map"}
|
||||||
|
var templatesByFilename = make(map[string]BuiltTemplate, 0)
|
||||||
|
|
||||||
type BreedingSourceSummary struct {
|
type BreedingSourceSummary struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
@ -99,15 +102,26 @@ type ContentCell struct {
|
||||||
Treatments []Treatment
|
Treatments []Treatment
|
||||||
User User
|
User User
|
||||||
}
|
}
|
||||||
type ContentPhoneCall struct {
|
type ContentMockURLs struct {
|
||||||
|
Dispatch string
|
||||||
|
DispatchResults string
|
||||||
|
ReportConfirmation string
|
||||||
|
ReportDetail string
|
||||||
|
ReportContribute string
|
||||||
|
ReportEvidence string
|
||||||
|
ReportSchedule string
|
||||||
|
ReportUpdate string
|
||||||
|
Root string
|
||||||
|
}
|
||||||
|
type ContentMock struct {
|
||||||
DistrictName string
|
DistrictName string
|
||||||
|
URLs ContentMockURLs
|
||||||
}
|
}
|
||||||
type ContentReportDetail struct {
|
type ContentReportDetail struct {
|
||||||
NextURL string
|
NextURL string
|
||||||
UpdateURL string
|
UpdateURL string
|
||||||
}
|
}
|
||||||
type ContentReportDiagnostic struct {
|
type ContentReportDiagnostic struct {
|
||||||
URL string
|
|
||||||
}
|
}
|
||||||
type ContentDashboard struct {
|
type ContentDashboard struct {
|
||||||
CountInspections int
|
CountInspections int
|
||||||
|
|
@ -279,21 +293,6 @@ func htmlCell(ctx context.Context, w http.ResponseWriter, user *models.User, c i
|
||||||
renderOrError(w, cell, &data)
|
renderOrError(w, cell, &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func htmlDataEntry(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, dataEntry, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlDataEntryBad(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, dataEntryBad, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlDataEntryGood(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, dataEntryGood, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User) {
|
func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User) {
|
||||||
org, err := user.Organization().One(ctx, db.PGInstance.BobDB)
|
org, err := user.Organization().One(ctx, db.PGInstance.BobDB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -355,6 +354,30 @@ func htmlDashboard(ctx context.Context, w http.ResponseWriter, user *models.User
|
||||||
renderOrError(w, dashboard, data)
|
renderOrError(w, dashboard, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func htmlMock(t string, w http.ResponseWriter, code string) {
|
||||||
|
data := ContentMock{
|
||||||
|
DistrictName: "Delta MVCD",
|
||||||
|
URLs: ContentMockURLs{
|
||||||
|
Dispatch: "/mock/dispatch",
|
||||||
|
DispatchResults: "/mock/dispatch-results",
|
||||||
|
ReportConfirmation: fmt.Sprintf("/mock/report/%s/confirm", code),
|
||||||
|
ReportDetail: fmt.Sprintf("/mock/report/%s", code),
|
||||||
|
ReportContribute: fmt.Sprintf("/mock/report/%s/contribute", code),
|
||||||
|
ReportEvidence: fmt.Sprintf("/mock/report/%s/evidence", code),
|
||||||
|
ReportSchedule: fmt.Sprintf("/mock/report/%s/schedule", code),
|
||||||
|
ReportUpdate: fmt.Sprintf("/mock/report/%s/update", code),
|
||||||
|
Root: "/mock",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
template, ok := templatesByFilename[t]
|
||||||
|
if !ok {
|
||||||
|
log.Error().Str("template", t).Msg("Failed to find template")
|
||||||
|
respondError(w, "Failed to render template", nil, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
renderOrError(w, &template, data)
|
||||||
|
}
|
||||||
|
|
||||||
func htmlOauthPrompt(w http.ResponseWriter, user *models.User) {
|
func htmlOauthPrompt(w http.ResponseWriter, user *models.User) {
|
||||||
dp := user.DisplayName
|
dp := user.DisplayName
|
||||||
data := ContentDashboard{
|
data := ContentDashboard{
|
||||||
|
|
@ -367,110 +390,6 @@ func htmlOauthPrompt(w http.ResponseWriter, user *models.User) {
|
||||||
renderOrError(w, oauthPrompt, data)
|
renderOrError(w, oauthPrompt, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func htmlPhoneCall(w http.ResponseWriter) {
|
|
||||||
data := ContentPhoneCall{
|
|
||||||
DistrictName: "[District Name]",
|
|
||||||
}
|
|
||||||
renderOrError(w, phoneCall, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReport(w http.ResponseWriter) {
|
|
||||||
url := BaseURL + "/report/t78fd3"
|
|
||||||
data := ContentReportDiagnostic{
|
|
||||||
URL: url,
|
|
||||||
}
|
|
||||||
renderOrError(w, report, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportConfirmation(w http.ResponseWriter, code string) {
|
|
||||||
url := BaseURL + "/report/" + code + "/history"
|
|
||||||
data := ContentReportDiagnostic{
|
|
||||||
URL: url,
|
|
||||||
}
|
|
||||||
renderOrError(w, reportConfirmation, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportContribute(w http.ResponseWriter, code string) {
|
|
||||||
nextURL := BaseURL + "/report/" + code + "/schedule"
|
|
||||||
data := ContentReportDetail{
|
|
||||||
NextURL: nextURL,
|
|
||||||
}
|
|
||||||
renderOrError(w, reportContribute, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportDetail(w http.ResponseWriter, code string) {
|
|
||||||
nextURL := BaseURL + "/report/" + code + "/evidence"
|
|
||||||
data := ContentReportDetail{
|
|
||||||
NextURL: nextURL,
|
|
||||||
UpdateURL: BaseURL + "/report/" + code + "/update",
|
|
||||||
}
|
|
||||||
renderOrError(w, reportDetail, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportEvidence(w http.ResponseWriter, code string) {
|
|
||||||
nextURL := BaseURL + "/report/" + code + "/contribute"
|
|
||||||
data := ContentReportDetail{
|
|
||||||
NextURL: nextURL,
|
|
||||||
}
|
|
||||||
renderOrError(w, reportEvidence, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportSchedule(w http.ResponseWriter, code string) {
|
|
||||||
nextURL := BaseURL + "/report/" + code + "/confirm"
|
|
||||||
data := ContentReportDetail{
|
|
||||||
NextURL: nextURL,
|
|
||||||
}
|
|
||||||
renderOrError(w, reportSchedule, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlReportUpdate(w http.ResponseWriter, code string) {
|
|
||||||
nextURL := BaseURL + "/report/" + code + "/evidence"
|
|
||||||
data := ContentReportDetail{
|
|
||||||
NextURL: nextURL,
|
|
||||||
}
|
|
||||||
renderOrError(w, reportUpdate, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequest(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequest, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestDetail(w http.ResponseWriter, code string) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestDetail, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestLocation(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestLocation, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestMosquito(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestMosquito, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestPool(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestPool, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestQuick(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestQuick, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestQuickConfirmation(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestQuickConfirmation, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlServiceRequestUpdates(w http.ResponseWriter) {
|
|
||||||
data := ContentPlaceholder{}
|
|
||||||
renderOrError(w, serviceRequestUpdates, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func htmlSettings(w http.ResponseWriter, r *http.Request, user *models.User) {
|
func htmlSettings(w http.ResponseWriter, r *http.Request, user *models.User) {
|
||||||
userContent, err := contentForUser(r.Context(), user)
|
userContent, err := contentForUser(r.Context(), user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -596,7 +515,7 @@ func makeFuncMap() template.FuncMap {
|
||||||
}
|
}
|
||||||
return funcMap
|
return funcMap
|
||||||
}
|
}
|
||||||
func newBuiltTemplate(name string, files ...string) BuiltTemplate {
|
func newBuiltTemplate(name string, files ...string) *BuiltTemplate {
|
||||||
files_on_disk := true
|
files_on_disk := true
|
||||||
all_files := append([]string{name}, files...)
|
all_files := append([]string{name}, files...)
|
||||||
for _, f := range all_files {
|
for _, f := range all_files {
|
||||||
|
|
@ -607,18 +526,22 @@ func newBuiltTemplate(name string, files ...string) BuiltTemplate {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var result BuiltTemplate
|
||||||
if files_on_disk {
|
if files_on_disk {
|
||||||
return BuiltTemplate{
|
result = BuiltTemplate{
|
||||||
files: all_files,
|
files: all_files,
|
||||||
name: name,
|
name: name,
|
||||||
template: nil,
|
template: nil,
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
result = BuiltTemplate{
|
||||||
|
files: all_files,
|
||||||
|
name: name,
|
||||||
|
template: parseEmbedded(all_files),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return BuiltTemplate{
|
templatesByFilename[name] = result
|
||||||
files: all_files,
|
return &result
|
||||||
name: name,
|
|
||||||
template: parseEmbedded(all_files),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEmbedded(files []string) *template.Template {
|
func parseEmbedded(files []string) *template.Template {
|
||||||
|
|
@ -867,11 +790,11 @@ func trapsBySource(ctx context.Context, org *models.Organization, sourceID strin
|
||||||
return traps, nil
|
return traps, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderOrError(w http.ResponseWriter, template BuiltTemplate, context interface{}) {
|
func renderOrError(w http.ResponseWriter, template *BuiltTemplate, context interface{}) {
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
err := template.ExecuteTemplate(buf, context)
|
err := template.ExecuteTemplate(buf, context)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Failed to render template", slog.String("err", err.Error()), slog.String("template", template.name))
|
log.Error().Err(err).Str("template", template.name).Msg("Failed to render template")
|
||||||
respondError(w, "Failed to render template", err, http.StatusInternalServerError)
|
respondError(w, "Failed to render template", err, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
main.go
42
main.go
|
|
@ -94,29 +94,33 @@ func main() {
|
||||||
r.Get("/arcgis/oauth/callback", getArcgisOauthCallback)
|
r.Get("/arcgis/oauth/callback", getArcgisOauthCallback)
|
||||||
r.Get("/favicon.ico", getFavicon)
|
r.Get("/favicon.ico", getFavicon)
|
||||||
|
|
||||||
r.Get("/mock/data-entry", getDataEntry)
|
r.Get("/mock", renderMock("mock-root"))
|
||||||
r.Get("/mock/data-entry/bad", getDataEntryBad)
|
r.Get("/mock/admin", renderMock("admin"))
|
||||||
r.Get("/mock/data-entry/good", getDataEntryGood)
|
r.Get("/mock/admin/service-request", renderMock("admin-service-request"))
|
||||||
|
r.Get("/mock/data-entry", renderMock("data-entry"))
|
||||||
|
r.Get("/mock/data-entry/bad", renderMock("data-entry-bad"))
|
||||||
|
r.Get("/mock/data-entry/good", renderMock("data-entry-good"))
|
||||||
|
r.Get("/mock/dispatch", renderMock("dispatch"))
|
||||||
|
r.Get("/mock/dispatch-results", renderMock("dispatch-results"))
|
||||||
|
r.Get("/mock/report", renderMock("report"))
|
||||||
|
r.Get("/mock/report/{code}", renderMock("report-detail"))
|
||||||
|
r.Get("/mock/report/{code}/confirm", renderMock("report-confirmation"))
|
||||||
|
r.Get("/mock/report/{code}/contribute", renderMock("report-contribute"))
|
||||||
|
r.Get("/mock/report/{code}/evidence", renderMock("report-evidence"))
|
||||||
|
r.Get("/mock/report/{code}/schedule", renderMock("report-schedule"))
|
||||||
|
r.Get("/mock/report/{code}/update", renderMock("report-update"))
|
||||||
|
r.Get("/mock/service-request", renderMock("service-request"))
|
||||||
|
r.Get("/mock/service-request/{code}", renderMock("service-request-detail"))
|
||||||
|
r.Get("/mock/service-request-location", renderMock("service-request-location"))
|
||||||
|
r.Get("/mock/service-request-mosquito", renderMock("service-request-mosquito"))
|
||||||
|
r.Get("/mock/service-request-pool", renderMock("service-request-pool"))
|
||||||
|
r.Get("/mock/service-request-quick", renderMock("service-request-quick"))
|
||||||
|
r.Get("/mock/service-request-quick-confirmation", renderMock("service-request-quick-confirmation"))
|
||||||
|
r.Get("/mock/service-request-updates", renderMock("service-request-updates"))
|
||||||
|
|
||||||
r.Get("/oauth/refresh", getOAuthRefresh)
|
r.Get("/oauth/refresh", getOAuthRefresh)
|
||||||
|
|
||||||
r.Get("/phone-call", getPhoneCall)
|
|
||||||
r.Get("/qr-code/report/{code}", getQRCodeReport)
|
r.Get("/qr-code/report/{code}", getQRCodeReport)
|
||||||
r.Get("/report", getReport)
|
|
||||||
r.Get("/report/{code}", getReportDetail)
|
|
||||||
r.Get("/report/{code}/confirm", getReportConfirmation)
|
|
||||||
r.Get("/report/{code}/contribute", getReportContribute)
|
|
||||||
r.Get("/report/{code}/evidence", getReportEvidence)
|
|
||||||
r.Get("/report/{code}/schedule", getReportSchedule)
|
|
||||||
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-quick", getServiceRequestQuick)
|
|
||||||
r.Get("/service-request-quick-confirmation", getServiceRequestQuickConfirmation)
|
|
||||||
r.Get("/service-request-updates", getServiceRequestUpdates)
|
|
||||||
r.Get("/signin", getSignin)
|
r.Get("/signin", getSignin)
|
||||||
r.Post("/signin", postSignin)
|
r.Post("/signin", postSignin)
|
||||||
r.Get("/signup", getSignup)
|
r.Get("/signup", getSignup)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
@ -63,6 +64,7 @@ body {
|
||||||
.tech-table tr td {
|
.tech-table tr td {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
@ -75,6 +77,7 @@ body {
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
<!--
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
|
@ -90,7 +93,7 @@ body {
|
||||||
<a class="nav-link" href="#"><i class="bi bi-gear"></i> Settings</a>
|
<a class="nav-link" href="#"><i class="bi bi-gear"></i> Settings</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>-->
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
@ -117,7 +120,7 @@ body {
|
||||||
<div class="card shadow-sm h-100">
|
<div class="card shadow-sm h-100">
|
||||||
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center py-2">
|
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center py-2">
|
||||||
<h5 class="mb-0">Mosquito Activity & Relief</h5>
|
<h5 class="mb-0">Mosquito Activity & Relief</h5>
|
||||||
<a href="/phone-call/service-request" class="btn btn-light btn-sm"><i class="bi bi-plus-circle"></i> New Service Request</a>
|
<a href="/mock/admin/service-request" class="btn btn-light btn-sm"><i class="bi bi-plus-circle"></i> New Service Request</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
|
|
@ -10,12 +10,7 @@
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||||
<!-- Fontawesome Icons -->
|
<!-- Fontawesome Icons -->
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||||
<script>
|
{{block "extraheader" .}} {{end}}
|
||||||
{{block "script" .}} {{end}}
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
{{template "style" .}}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
{{template "content" .}}
|
{{template "content" .}}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Data Entry{{end}}
|
{{define "title"}}Data Entry{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.results-container {
|
.results-container {
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
.table-header-line {
|
.table-header-line {
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container mt-4 results-container mb-5">
|
<div class="container mt-4 results-container mb-5">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Data Entry{{end}}
|
{{define "title"}}Data Entry{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.results-container {
|
.results-container {
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -18,6 +19,7 @@
|
||||||
.status-badge {
|
.status-badge {
|
||||||
font-size: 0.85rem;
|
font-size: 0.85rem;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container mt-4 results-container">
|
<div class="container mt-4 results-container">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Data Entry{{end}}
|
{{define "title"}}Data Entry{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.upload-container {
|
.upload-container {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -22,6 +23,7 @@
|
||||||
color: red;
|
color: red;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container mt-4 upload-container">
|
<div class="container mt-4 upload-container">
|
||||||
|
|
|
||||||
260
templates/dispatch-results.html
Normal file
260
templates/dispatch-results.html
Normal file
|
|
@ -0,0 +1,260 @@
|
||||||
|
{{template "base.html" .}}
|
||||||
|
|
||||||
|
{{define "title"}}Data Entry{{end}}
|
||||||
|
{{define "extraheader"}}
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const checkboxes = document.querySelectorAll('.route-select');
|
||||||
|
const switchBtn = document.getElementById('switchRoutesBtn');
|
||||||
|
|
||||||
|
// Enable/disable switch button based on selection
|
||||||
|
checkboxes.forEach(checkbox => {
|
||||||
|
checkbox.addEventListener('change', () => {
|
||||||
|
const checkedBoxes = document.querySelectorAll('.route-select:checked');
|
||||||
|
switchBtn.disabled = checkedBoxes.length !== 2;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// For demonstration purposes
|
||||||
|
switchBtn.addEventListener('click', function() {
|
||||||
|
const selectedRoutes = Array.from(document.querySelectorAll('.route-select:checked')).map(cb => cb.value);
|
||||||
|
alert(`Switching routes ${selectedRoutes[0]} and ${selectedRoutes[1]}`);
|
||||||
|
// In a real application, this would trigger the route switching logic
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.main-container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.map-container {
|
||||||
|
height: 400px;
|
||||||
|
background-color: #e9ecef;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
border-radius: 5px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.route-badge {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.tech-photo {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.action-button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
.completion-alert {
|
||||||
|
border-left: 5px solid #0d6efd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{end}}
|
||||||
|
{{define "content"}}
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h1>Route Calculation Results</h1>
|
||||||
|
<a href="{{ .URLs.Dispatch }}" class="btn btn-outline-primary">
|
||||||
|
<i class="bi bi-pencil-square me-1"></i> Edit Parameters
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Map View -->
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header bg-primary text-white">
|
||||||
|
<h2 class="h4 mb-0">Route Map</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-2">
|
||||||
|
<div class="map-container d-flex align-items-center justify-content-center">
|
||||||
|
<div class="text-center">
|
||||||
|
<i class="bi bi-map fs-1 text-muted"></i>
|
||||||
|
<h3 class="text-muted">Interactive Map View</h3>
|
||||||
|
<p class="text-muted">Routes are color-coded by technician assignment</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Completion Projection -->
|
||||||
|
<div class="alert alert-info mb-4 completion-alert">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<i class="bi bi-calendar-check fs-4 me-3"></i>
|
||||||
|
<div>
|
||||||
|
<h4 class="h5 mb-1">Coverage Projection</h4>
|
||||||
|
<p class="mb-0">If every day were like today, all pools would be complete on <strong>October 27, 2023</strong></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Route Summary Table -->
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
||||||
|
<h2 class="h4 mb-0">Route Summary</h2>
|
||||||
|
<button class="btn btn-sm btn-light" id="switchRoutesBtn" disabled>
|
||||||
|
<i class="bi bi-arrow-left-right me-1"></i> Switch Selected Routes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th width="40">Select</th>
|
||||||
|
<th width="50">Route</th>
|
||||||
|
<th>Technician</th>
|
||||||
|
<th>Cold Call Pools</th>
|
||||||
|
<th>Drone Inspections</th>
|
||||||
|
<th>Service Calls</th>
|
||||||
|
<th>Warrants</th>
|
||||||
|
<th>Est. Time</th>
|
||||||
|
<th>Actions</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input route-select" type="checkbox" value="A" id="routeA">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="route-badge bg-primary text-white">A</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="John Davis" class="tech-photo me-2">
|
||||||
|
<span>John Davis</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>12</td>
|
||||||
|
<td>0</td>
|
||||||
|
<td>5</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>6h 15m</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input route-select" type="checkbox" value="B" id="routeB">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="route-badge bg-success text-white">B</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/women/65.jpg" alt="Sarah Johnson" class="tech-photo me-2">
|
||||||
|
<span>Sarah Johnson</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>8</td>
|
||||||
|
<td>3</td>
|
||||||
|
<td>4</td>
|
||||||
|
<td>1</td>
|
||||||
|
<td>7h 30m</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input route-select" type="checkbox" value="C" id="routeC">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="route-badge bg-danger text-white">C</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/men/44.jpg" alt="Michael Chen" class="tech-photo me-2">
|
||||||
|
<span>Michael Chen</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>10</td>
|
||||||
|
<td>4</td>
|
||||||
|
<td>3</td>
|
||||||
|
<td>0</td>
|
||||||
|
<td>7h 45m</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input route-select" type="checkbox" value="D" id="routeD">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="route-badge bg-warning text-dark">D</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/women/22.jpg" alt="Jessica Martinez" class="tech-photo me-2">
|
||||||
|
<span>Jessica Martinez</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>14</td>
|
||||||
|
<td>2</td>
|
||||||
|
<td>6</td>
|
||||||
|
<td>3</td>
|
||||||
|
<td>8h 00m</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-secondary">
|
||||||
|
<i class="bi bi-eye"></i>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<a href="{{ .URLs.Dispatch }}" class="btn btn-outline-secondary action-button">
|
||||||
|
<i class="bi bi-arrow-left me-2"></i>Back to Parameters
|
||||||
|
</a>
|
||||||
|
<a href="{{ .URLs.Root }}" class="btn btn-success action-button">
|
||||||
|
<i class="bi bi-check-circle me-2"></i>Approve & Dispatch
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal for Route Details -->
|
||||||
|
<div class="modal fade" id="routeDetailsModal" tabindex="-1" aria-labelledby="routeDetailsModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="routeDetailsModalLabel">Route A Details</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<!-- Route details would go here -->
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
172
templates/dispatch.html
Normal file
172
templates/dispatch.html
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
{{template "base.html" .}}
|
||||||
|
|
||||||
|
{{define "title"}}Data Entry{{end}}
|
||||||
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
|
.tech-photo {
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.main-container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.action-button {
|
||||||
|
padding: 15px 30px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{end}}
|
||||||
|
{{define "content"}}
|
||||||
|
<div class="container-fluid p-4 main-container">
|
||||||
|
<h1 class="mb-4">Technician Routing & Dispatch</h1>
|
||||||
|
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-header bg-primary text-white">
|
||||||
|
<h2 class="h4 mb-0">Technician Roster</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Technician</th>
|
||||||
|
<th>Working Hours</th>
|
||||||
|
<th>Truck Assignment</th>
|
||||||
|
<th>Warrant Service</th>
|
||||||
|
<th>Drone Certified</th>
|
||||||
|
<th>Routing Options</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/men/32.jpg" alt="John Davis" class="tech-photo me-3">
|
||||||
|
<div>
|
||||||
|
<div class="fw-bold">John Davis</div>
|
||||||
|
<div class="small text-muted">ID: T-1001</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>7:00 AM - 3:30 PM</td>
|
||||||
|
<td>Truck #103</td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td><span class="badge bg-danger">No</span></td>
|
||||||
|
<td>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="warrant-partner1" data-bs-toggle="tooltip" data-bs-placement="left" title="Require second person for warrant service">
|
||||||
|
<label class="form-check-label" for="warrant-partner1">Warrant Partner</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="resident-history1" data-bs-toggle="tooltip" data-bs-placement="left" title="Route to previously visited residents">
|
||||||
|
<label class="form-check-label" for="resident-history1">Prior Interactions</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="include-route1" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Include in route calculations">
|
||||||
|
<label class="form-check-label" for="include-route1">Include in Routes</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/women/65.jpg" alt="Sarah Johnson" class="tech-photo me-3">
|
||||||
|
<div>
|
||||||
|
<div class="fw-bold">Sarah Johnson</div>
|
||||||
|
<div class="small text-muted">ID: T-1042</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>8:00 AM - 4:30 PM</td>
|
||||||
|
<td>Truck #118</td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="warrant-partner2" data-bs-toggle="tooltip" data-bs-placement="left" title="Require second person for warrant service">
|
||||||
|
<label class="form-check-label" for="warrant-partner2">Warrant Partner</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="resident-history2" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Route to previously visited residents">
|
||||||
|
<label class="form-check-label" for="resident-history2">Prior Interactions</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="include-route2" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Include in route calculations">
|
||||||
|
<label class="form-check-label" for="include-route2">Include in Routes</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/men/44.jpg" alt="Michael Chen" class="tech-photo me-3">
|
||||||
|
<div>
|
||||||
|
<div class="fw-bold">Michael Chen</div>
|
||||||
|
<div class="small text-muted">ID: T-1019</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>6:30 AM - 3:00 PM</td>
|
||||||
|
<td>Truck #107</td>
|
||||||
|
<td><span class="badge bg-danger">No</span></td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="warrant-partner3" disabled data-bs-toggle="tooltip" data-bs-placement="left" title="Require second person for warrant service">
|
||||||
|
<label class="form-check-label" for="warrant-partner3">Warrant Partner</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="resident-history3" data-bs-toggle="tooltip" data-bs-placement="left" title="Route to previously visited residents">
|
||||||
|
<label class="form-check-label" for="resident-history3">Prior Interactions</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="include-route3" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Include in route calculations">
|
||||||
|
<label class="form-check-label" for="include-route3">Include in Routes</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<img src="https://randomuser.me/api/portraits/women/22.jpg" alt="Jessica Martinez" class="tech-photo me-3">
|
||||||
|
<div>
|
||||||
|
<div class="fw-bold">Jessica Martinez</div>
|
||||||
|
<div class="small text-muted">ID: T-1055</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>7:30 AM - 4:00 PM</td>
|
||||||
|
<td>Truck #112</td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td><span class="badge bg-success">Yes</span></td>
|
||||||
|
<td>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="warrant-partner4" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Require second person for warrant service">
|
||||||
|
<label class="form-check-label" for="warrant-partner4">Warrant Partner</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check mb-2">
|
||||||
|
<input class="form-check-input" type="checkbox" id="resident-history4" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Route to previously visited residents">
|
||||||
|
<label class="form-check-label" for="resident-history4">Prior Interactions</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="include-route4" checked data-bs-toggle="tooltip" data-bs-placement="left" title="Include in route calculations">
|
||||||
|
<label class="form-check-label" for="include-route4">Include in Routes</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid gap-2 col-md-6 mx-auto">
|
||||||
|
<a href="{{ .URLs.DispatchResults }}" class="btn btn-primary btn-lg action-button" type="button">
|
||||||
|
<i class="bi bi-calculator me-2"></i>Calculate Routes
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
||||||
51
templates/mock-root.html
Normal file
51
templates/mock-root.html
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{{template "base.html" .}}
|
||||||
|
|
||||||
|
{{define "title"}}Data Entry{{end}}
|
||||||
|
{{define "extraheader"}}
|
||||||
|
{{end}}
|
||||||
|
{{define "content"}}
|
||||||
|
<div class="container">
|
||||||
|
<h1>Mock Listing</h1>
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" style="min-width: 20vw">Link</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/admin">/mock/admin</a></td>
|
||||||
|
<td>Admin</td>
|
||||||
|
<td>Used by office admins to handle phone calls and other public-facing responsibilities</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/data-entry">/mock/flyover-data-entry</a></td>
|
||||||
|
<td>Flyover Data Entry</td>
|
||||||
|
<td>Used to upload CSV files with information about problematic pools</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/dispatch">/mock/dispatch</a></td>
|
||||||
|
<td>Dispatch</td>
|
||||||
|
<td>Used each day to calculate the working routes for technicians</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/report">/mock/report</a></td>
|
||||||
|
<td>Reporting Overview</td>
|
||||||
|
<td>Shows examples of text message contents, printable QR codes, and email bodies for sending to the public to help them self-report</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/report/abc-123">/mock/report/abc-123</a></td>
|
||||||
|
<td>Self-Report</td>
|
||||||
|
<td>A page for members of the public to report a green pool.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="/mock/service-request">/mock/service-request</a></td>
|
||||||
|
<td>Service Request</td>
|
||||||
|
<td>A page for members of the public to make a direct service request</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "authenticated.html" .}}
|
{{template "authenticated.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.connect-container {
|
.connect-container {
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -42,6 +43,7 @@
|
||||||
.connect-btn {
|
.connect-btn {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -114,6 +115,7 @@
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +126,7 @@
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
@ -220,10 +222,10 @@
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="d-flex justify-content-between mt-4">
|
<div class="d-flex justify-content-between mt-4">
|
||||||
<button type="button" class="btn btn-outline-secondary">
|
<a href="{{ .URLs.ReportEvidence }}" class="btn btn-outline-secondary">
|
||||||
<i class="bi bi-arrow-left me-2"></i> Back
|
<i class="bi bi-arrow-left me-2"></i> Back
|
||||||
</button>
|
</a>
|
||||||
<a href="{{ .NextURL }}" class="btn btn-primary">
|
<a href="{{ .URLs.ReportSchedule }}" class="btn btn-primary">
|
||||||
Next Step <i class="bi bi-arrow-right ms-2"></i>
|
Next Step <i class="bi bi-arrow-right ms-2"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +71,7 @@ body {
|
||||||
.progress {
|
.progress {
|
||||||
height: 8px;
|
height: 8px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
@ -113,10 +115,10 @@ body {
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
<a href="{{ .NextURL }}" class="btn btn-success flex-grow-1">
|
<a href="{{ .URLs.ReportEvidence }}" class="btn btn-success flex-grow-1">
|
||||||
<i class="bi bi-check-circle me-2"></i> Correct
|
<i class="bi bi-check-circle me-2"></i> Correct
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ .UpdateURL }}" class="btn btn-outline-primary flex-grow-1">
|
<a href="{{ .URLs.ReportUpdate }}" class="btn btn-outline-primary flex-grow-1">
|
||||||
<i class="bi bi-geo-alt me-2"></i> Update Location
|
<i class="bi bi-geo-alt me-2"></i> Update Location
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -84,6 +85,7 @@
|
||||||
.trap-low {
|
.trap-low {
|
||||||
color: #198754;
|
color: #198754;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
@ -227,7 +229,7 @@
|
||||||
|
|
||||||
<!-- Action Button -->
|
<!-- Action Button -->
|
||||||
<div class="d-grid gap-2 mt-4">
|
<div class="d-grid gap-2 mt-4">
|
||||||
<a href="{{ .NextURL }}" class="btn btn-primary btn-lg">
|
<a href="{{ .URLs.ReportContribute }}" class="btn btn-primary btn-lg">
|
||||||
<i class="bi bi-arrow-right-circle me-2"></i> Next Step: Upload Current Photos
|
<i class="bi bi-arrow-right-circle me-2"></i> Next Step: Upload Current Photos
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -125,6 +126,7 @@
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
@ -298,10 +300,10 @@
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="d-flex justify-content-between mt-4">
|
<div class="d-flex justify-content-between mt-4">
|
||||||
<button type="button" class="btn btn-outline-secondary">
|
<a href="{{ .URLs.ReportContribute }}" class="btn btn-outline-secondary">
|
||||||
<i class="bi bi-arrow-left me-2"></i> Back
|
<i class="bi bi-arrow-left me-2"></i> Back
|
||||||
</button>
|
</a>
|
||||||
<a href="{{ .NextURL }}" class="btn btn-success">
|
<a href="{{ .URLs.ReportConfirmation }}" class="btn btn-success">
|
||||||
<i class="bi bi-calendar-check me-2"></i> Confirm Appointment
|
<i class="bi bi-calendar-check me-2"></i> Confirm Appointment
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
|
@ -98,6 +99,7 @@ body {
|
||||||
.form-section {
|
.form-section {
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="page-container">
|
<div class="page-container">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.entry-container {
|
.entry-container {
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -100,6 +101,7 @@
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-radius: 20px 20px 0 0;
|
border-radius: 20px 20px 0 0;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container py-5">
|
<div class="container py-5">
|
||||||
|
|
@ -125,7 +127,7 @@
|
||||||
<p>Customers will receive the following text message with a link to begin the reporting process:</p>
|
<p>Customers will receive the following text message with a link to begin the reporting process:</p>
|
||||||
|
|
||||||
<div class="sms-mockup">
|
<div class="sms-mockup">
|
||||||
<strong>Vector Control:</strong> We noticed a potential green pool at your property. Please tap the link to report status or schedule inspection: <a href="{{ .URL }}">{{ .URL }}</a>
|
<strong>Vector Control:</strong> We noticed a potential green pool at your property. Please tap the link to report status or schedule inspection: <a href="{{ .URLs.ReportDetail }}">{{ .URLs.ReportDetail }}</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
|
|
@ -154,7 +156,7 @@
|
||||||
<img src="/qr-code/report/t78fd3" width="256" height="256"/>
|
<img src="/qr-code/report/t78fd3" width="256" height="256"/>
|
||||||
|
|
||||||
<p><strong>Scan this code</strong> with your phone camera to report your pool status or schedule an inspection.</p>
|
<p><strong>Scan this code</strong> with your phone camera to report your pool status or schedule an inspection.</p>
|
||||||
<p class="small text-muted">Or visit: {{ .URL }}</p>
|
<p class="small text-muted">Or visit: {{ .URLs.ReportDetail }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
|
|
@ -192,7 +194,7 @@
|
||||||
<a href="/report/t78fd3" class="btn btn-primary">Report Pool Status or Schedule Inspection</a>
|
<a href="/report/t78fd3" class="btn btn-primary">Report Pool Status or Schedule Inspection</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Please click the button above or visit <a href="{{ .URL }}">{{ .URL }}</a> to complete a brief questionnaire about your pool status. This will help us determine if an inspection is needed or if you've already addressed the issue.</p>
|
<p>Please click the button above or visit <a href="{{ .URLs.ReportDetail }}">{{ .URLs.ReportDetail }}</a> to complete a brief questionnaire about your pool status. This will help us determine if an inspection is needed or if you've already addressed the issue.</p>
|
||||||
|
|
||||||
<p>Thank you for helping keep our community safe and healthy.</p>
|
<p>Thank you for helping keep our community safe and healthy.</p>
|
||||||
|
|
||||||
|
|
@ -214,7 +216,7 @@
|
||||||
|
|
||||||
<div class="d-flex justify-content-between mt-4">
|
<div class="d-flex justify-content-between mt-4">
|
||||||
<a href="/" class="btn btn-outline-primary">Back to Dashboard</a>
|
<a href="/" class="btn btn-outline-primary">Back to Dashboard</a>
|
||||||
<a href="{{ .URL }}" class="btn btn-success">Test Reporting Flow</a>
|
<a href="{{ .URLs.ReportDetail }}" class="btn btn-success">Test Reporting Flow</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -85,6 +86,7 @@
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -69,6 +70,7 @@
|
||||||
.instruction-card {
|
.instruction-card {
|
||||||
border-left: 4px solid #0d6efd;
|
border-left: 4px solid #0d6efd;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "script"}}
|
{{define "extraheader"}}
|
||||||
|
<script>
|
||||||
// Handle inspection type selection
|
// Handle inspection type selection
|
||||||
function selectInspectionType(type) {
|
function selectInspectionType(type) {
|
||||||
// Remove selected class from both cards
|
// Remove selected class from both cards
|
||||||
|
|
@ -41,8 +42,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
{{end}}
|
</script>
|
||||||
{{define "style"}}
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -139,6 +140,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
border-left: 4px solid #0d6efd;
|
border-left: 4px solid #0d6efd;
|
||||||
background-color: #f8f9fa;
|
background-color: #f8f9fa;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "script"}}
|
{{define "extraheader"}}
|
||||||
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const photoUpload = document.getElementById('photoUpload');
|
const photoUpload = document.getElementById('photoUpload');
|
||||||
const imagePreview = document.getElementById('imagePreview');
|
const imagePreview = document.getElementById('imagePreview');
|
||||||
|
|
@ -74,8 +75,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
photoUpload.value = '';
|
photoUpload.value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
{{end}}
|
</script>
|
||||||
{{define "style"}}
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -167,6 +168,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-top: 2rem;
|
margin-top: 2rem;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
@ -174,7 +176,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h1 class="district-name">[District Name]</h1>
|
<h1 class="district-name">{{ .DistrictName }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
||||||
|
|
@ -510,7 +512,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p class="mb-0">© 2023 [District Name] Mosquito Management District</p>
|
<p class="mb-0">© 2023 {{ .DistrictName }} Mosquito Management District</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -41,6 +42,7 @@
|
||||||
height: 80px;
|
height: 80px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.district-logo {
|
.district-logo {
|
||||||
max-height: 60px;
|
max-height: 60px;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|
@ -49,6 +50,7 @@
|
||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.option-card {
|
.option-card {
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -33,6 +34,7 @@
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
@ -40,7 +42,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h1 class="district-name">[District Name]</h1>
|
<h1 class="district-name">{{ .DistrictName }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
||||||
|
|
@ -149,7 +151,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p class="mb-0">© 2023 [District Name] Mosquito Management District</p>
|
<p class="mb-0">© 2023 {{ .DistrictName }} Mosquito Management District</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.service-card {
|
.service-card {
|
||||||
transition: transform 0.3s;
|
transition: transform 0.3s;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
@ -21,6 +22,7 @@
|
||||||
background-color: #ffefd5;
|
background-color: #ffefd5;
|
||||||
border-left: 4px solid #ff9800;
|
border-left: 4px solid #ff9800;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
|
|
@ -28,7 +30,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h1 class="district-name">[District Name]</h1>
|
<h1 class="district-name">{{ .DistrictName }}</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
<img src="placeholder-logo.png" alt="District Logo" class="district-logo">
|
||||||
|
|
@ -61,7 +63,7 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 text-center">
|
<div class="col-12 text-center">
|
||||||
<h4 class="mb-2">On the go?</h4>
|
<h4 class="mb-2">On the go?</h4>
|
||||||
<a href="/service-request-quick" class="btn btn-dark btn-lg">Make a Quick Report</a>
|
<a href="/mock/service-request-quick" class="btn btn-dark btn-lg">Make a Quick Report</a>
|
||||||
<p class="mb-0 mt-2"><small>Report mosquito issues in under 60 seconds</small></p>
|
<p class="mb-0 mt-2"><small>Report mosquito issues in under 60 seconds</small></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -84,7 +86,7 @@
|
||||||
</div>
|
</div>
|
||||||
<h4 class="card-title">Follow-up or Check Status</h4>
|
<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>
|
<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>
|
<a href="/mock/service-request-updates" class="btn btn-primary mt-3">Get Updates</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -100,7 +102,7 @@
|
||||||
</div>
|
</div>
|
||||||
<h4 class="card-title">Report a Green Pool</h4>
|
<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>
|
<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>
|
<a href="/mock/service-request-pool" class="btn btn-primary mt-3">Report Source</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -116,7 +118,7 @@
|
||||||
</div>
|
</div>
|
||||||
<h4 class="card-title">Report Mosquito Nuisance</h4>
|
<h4 class="card-title">Report Mosquito Nuisance</h4>
|
||||||
<p class="card-text">Report areas with high adult mosquito activity causing discomfort or concern.</p>
|
<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>
|
<a href="/mock/service-request-mosquito" class="btn btn-primary mt-3">Report Problem</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -133,7 +135,7 @@
|
||||||
<p class="mb-0">Use our streamlined form to report mosquito issues in under 60 seconds</p>
|
<p class="mb-0">Use our streamlined form to report mosquito issues in under 60 seconds</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 text-md-end mt-3 mt-md-0">
|
<div class="col-md-4 text-md-end mt-3 mt-md-0">
|
||||||
<a href="/service-request-quick" class="btn btn-warning">Quick Report</a>
|
<a href="/mock/service-request-quick" class="btn btn-warning">Quick Report</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -149,7 +151,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<p class="mb-0">© 2023 [District Name] Mosquito Management District</p>
|
<p class="mb-0">© 2023 {{.DistrictName}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-md-end">
|
<div class="col-md-6 text-md-end">
|
||||||
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
<p class="mb-0">Contact: (555) 123-4567 | info@mosquitodistrict.gov</p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "authenticated.html" .}}
|
{{template "authenticated.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Dash{{end}}
|
{{define "title"}}Dash{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<p>Imagine settings here</p>
|
<p>Imagine settings here</p>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.login-container {
|
.login-container {
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -21,6 +22,7 @@
|
||||||
.login-header {
|
.login-header {
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
{{template "base.html" .}}
|
{{template "base.html" .}}
|
||||||
|
|
||||||
{{define "title"}}Login{{end}}
|
{{define "title"}}Login{{end}}
|
||||||
{{define "style"}}
|
{{define "extraheader"}}
|
||||||
|
<style>
|
||||||
.register-container {
|
.register-container {
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
|
@ -35,6 +36,7 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{define "content"}}
|
{{define "content"}}
|
||||||
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
<div class="container min-vh-100 d-flex align-items-center justify-content-center py-5">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue