Add simple compliance landing page
This commit is contained in:
parent
4b87c74f41
commit
457f123f69
4 changed files with 181 additions and 23 deletions
144
html/template/rmo/district-compliance.html
Normal file
144
html/template/rmo/district-compliance.html
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
{{ template "rmo/layout/base.html" . }}
|
||||||
|
|
||||||
|
{{ define "title" }}Compliance Request{{ end }}
|
||||||
|
{{ define "extraheader" }}
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
}
|
||||||
|
.page-container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.content-card {
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 25px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.logo-area {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.logo {
|
||||||
|
height: 50px;
|
||||||
|
max-width: 200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
.map-container {
|
||||||
|
height: 300px;
|
||||||
|
background-color: #e9ecef;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.map-placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
background-image: url("https://placehold.co/600x300/e9ecef/adb5bd?text=Map+View");
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
|
.map-pin {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -100%);
|
||||||
|
color: #dc3545;
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
.address-container {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-left: 4px solid #0d6efd;
|
||||||
|
}
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.progress-container {
|
||||||
|
margin: 30px 0 20px;
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
height: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{{ end }}
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="page-container">
|
||||||
|
<div class="logo-area">
|
||||||
|
<img
|
||||||
|
src="{{ .District.URLLogo }}"
|
||||||
|
alt="{{ .District.Name }} Logo"
|
||||||
|
class="logo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress-container">
|
||||||
|
<div class="d-flex justify-content-between mb-1">
|
||||||
|
<span class="text-muted small">Location</span>
|
||||||
|
<span class="text-muted small">1 of 4</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress">
|
||||||
|
<div
|
||||||
|
class="progress-bar"
|
||||||
|
role="progressbar"
|
||||||
|
style="width: 25%"
|
||||||
|
aria-valuenow="25"
|
||||||
|
aria-valuemin="0"
|
||||||
|
aria-valuemax="100"
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-card">
|
||||||
|
<h1 class="h4 mb-4">Confirm Property Location</h1>
|
||||||
|
|
||||||
|
<div class="map-container">
|
||||||
|
<div class="map-placeholder"></div>
|
||||||
|
<div class="map-pin">
|
||||||
|
<i class="bi bi-geo-alt-fill"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="address-container">
|
||||||
|
<div class="mb-2"><strong>Detected Address:</strong></div>
|
||||||
|
<h5>123 Maple Street, Riverside, CA 92501</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<p>Is this the correct location of the property in question?</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="action-buttons">
|
||||||
|
<a
|
||||||
|
href="/mock/report/%7bcode%7d/evidence"
|
||||||
|
class="btn btn-success flex-grow-1"
|
||||||
|
>
|
||||||
|
<i class="bi bi-check-circle me-2"></i> Correct
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="/mock/report/%7bcode%7d/update"
|
||||||
|
class="btn btn-outline-primary flex-grow-1"
|
||||||
|
>
|
||||||
|
<i class="bi bi-geo-alt me-2"></i> Update Location
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="text-center text-muted small">
|
||||||
|
<p>
|
||||||
|
If you need assistance, please contact Vector Control at (555) 123-4567
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
23
rmo/compliance.go
Normal file
23
rmo/compliance.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
package rmo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/Gleipnir-Technology/nidus-sync/html"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getDistrictCompliance(w http.ResponseWriter, r *http.Request) {
|
||||||
|
district, err := districtBySlug(r)
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, "Failed to lookup organization", err, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
html.RenderOrError(
|
||||||
|
w,
|
||||||
|
"rmo/district-compliance.html",
|
||||||
|
ContentNuisance{
|
||||||
|
District: newContentDistrict(district),
|
||||||
|
URL: makeContentURL(nil),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ func Router(r *mux.Router) {
|
||||||
|
|
||||||
r.HandleFunc("/district", getDistrictList).Methods("GET")
|
r.HandleFunc("/district", getDistrictList).Methods("GET")
|
||||||
r.HandleFunc("/district/{slug}", getRootDistrict).Methods("GET")
|
r.HandleFunc("/district/{slug}", getRootDistrict).Methods("GET")
|
||||||
|
r.HandleFunc("/district/{slug}/compliance", getDistrictCompliance).Methods("GET")
|
||||||
r.HandleFunc("/district/{slug}/nuisance", getNuisanceDistrict).Methods("GET")
|
r.HandleFunc("/district/{slug}/nuisance", getNuisanceDistrict).Methods("GET")
|
||||||
//r.HandleFunc("/district/{slug}/nuisance-submit-complete", renderMock(mockNuisanceSubmitCompleteT)).Methods("GET")
|
//r.HandleFunc("/district/{slug}/nuisance-submit-complete", renderMock(mockNuisanceSubmitCompleteT)).Methods("GET")
|
||||||
//r.HandleFunc("/district/{slug}/status", renderMock(mockStatusT)).Methods("GET")
|
//r.HandleFunc("/district/{slug}/status", renderMock(mockStatusT)).Methods("GET")
|
||||||
|
|
|
||||||
|
|
@ -35,28 +35,18 @@ func AddStaticRoute(r *mux.Router, path string) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fileServer(r, "/static", localFS, embeddedStaticFS)
|
fileServer(r, "/static/", localFS, embeddedStaticFS)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS embed.FS) {
|
func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS embed.FS) {
|
||||||
if strings.ContainsAny(path, "{}*") {
|
log.Debug().Str("path", path).Msg("adding file server")
|
||||||
panic("FileServer does not permit any URL parameters.")
|
r.PathPrefix(path).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
|
||||||
|
|
||||||
if path != "/" && path[len(path)-1] != '/' {
|
|
||||||
r.HandleFunc(path, http.RedirectHandler(path+"/", 301).ServeHTTP)
|
|
||||||
path += "/"
|
|
||||||
}
|
|
||||||
path += "*"
|
|
||||||
|
|
||||||
r.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
//rctx := chi.RouteContext(r.Context())
|
//rctx := chi.RouteContext(r.Context())
|
||||||
|
|
||||||
//pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
|
//pathPrefix := strings.TrimSuffix(rctx.RoutePattern(), "/*")
|
||||||
pathPrefix := strings.TrimPrefix(r.URL.Path, "/static")
|
//pathPrefix := strings.TrimPrefix(r.URL.Path, "/static")
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/static/")
|
||||||
// Determine the actual file path
|
//log.Debug().Str("path", path).Msg("handling request")
|
||||||
requestedPath := strings.TrimPrefix(r.URL.Path, pathPrefix+"/")
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
var fileToServe http.File
|
var fileToServe http.File
|
||||||
|
|
@ -65,9 +55,9 @@ func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS emb
|
||||||
// For dev, try the current filesystem
|
// For dev, try the current filesystem
|
||||||
if !config.IsProductionEnvironment() {
|
if !config.IsProductionEnvironment() {
|
||||||
// Try to open from local filesystem for development
|
// Try to open from local filesystem for development
|
||||||
fileToServe, err = root.Open(requestedPath)
|
fileToServe, err = root.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn().Str("path", requestedPath).Msg("Failed to read static file for dev")
|
log.Warn().Err(err).Str("path", path).Msg("Failed to read static file for dev")
|
||||||
found = false
|
found = false
|
||||||
} else {
|
} else {
|
||||||
found = true
|
found = true
|
||||||
|
|
@ -76,10 +66,10 @@ func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS emb
|
||||||
// For production use the embedded filesystem
|
// For production use the embedded filesystem
|
||||||
if !found {
|
if !found {
|
||||||
// Requested paths start with
|
// Requested paths start with
|
||||||
embeddedFile, err := embeddedFS.Open(requestedPath)
|
embeddedFile, err := embeddedFS.Open(path)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug().Err(err).Str("requested path", requestedPath).Msg("Failed to find resource")
|
log.Debug().Err(err).Str("embedded path", path).Msg("Failed to find resource")
|
||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -93,14 +83,14 @@ func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS emb
|
||||||
|
|
||||||
// Add caching headers
|
// Add caching headers
|
||||||
if config.IsProductionEnvironment() {
|
if config.IsProductionEnvironment() {
|
||||||
ext := filepath.Ext(requestedPath)
|
ext := filepath.Ext(path)
|
||||||
switch ext {
|
switch ext {
|
||||||
case ".css", ".jpg", ".jpeg", ".png", ".gif", ".svg", ".woff", ".woff2", ".ttf":
|
case ".css", ".jpg", ".jpeg", ".png", ".gif", ".svg", ".woff", ".woff2", ".ttf":
|
||||||
// Cache for 1 week (604800 seconds)
|
// Cache for 1 week (604800 seconds)
|
||||||
crw.Header().Set("Cache-Control", "public, max-age=604800, stale-while-revalidate=86400")
|
crw.Header().Set("Cache-Control", "public, max-age=604800, stale-while-revalidate=86400")
|
||||||
default:
|
default:
|
||||||
// If it's a generated file, cache it essentially forever (1 year)
|
// If it's a generated file, cache it essentially forever (1 year)
|
||||||
if strings.HasPrefix(requestedPath, "gen/") {
|
if strings.HasPrefix(path, "/static/gen/") {
|
||||||
crw.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
|
crw.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
|
||||||
} else {
|
} else {
|
||||||
// Other files, 1 hour
|
// Other files, 1 hour
|
||||||
|
|
@ -109,7 +99,7 @@ func fileServer(r *mux.Router, path string, root http.FileSystem, embeddedFS emb
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Serve the file
|
// Serve the file
|
||||||
http.ServeContent(crw, r, requestedPath, startedTime, fileToServe)
|
http.ServeContent(crw, r, path, startedTime, fileToServe)
|
||||||
|
|
||||||
// Close the file
|
// Close the file
|
||||||
fileToServe.Close()
|
fileToServe.Close()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue