diff --git a/endpoint.go b/endpoint.go index aab2269a..9a680303 100644 --- a/endpoint.go +++ b/endpoint.go @@ -4,7 +4,11 @@ import ( "errors" "log/slog" "net/http" + "strconv" "strings" + + "github.com/go-chi/chi/v5" + "github.com/skip2/go-qrcode" ) func getFavicon(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-type", "image/x-icon") @@ -12,6 +16,65 @@ func getFavicon(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "static/favicon.ico") } +func getQRCodeReport(w http.ResponseWriter, r *http.Request) { + code := chi.URLParam(r, "code") + if code == "" { + respondError(w, "There should always be a code", nil, http.StatusBadRequest) + } + content := BaseURL + "/report/" + code + // Get optional size parameter (default to 256) + size := 256 + if sizeStr := r.URL.Query().Get("size"); sizeStr != "" { + var err error + size, err = strconv.Atoi(sizeStr) + if err != nil { + http.Error(w, "Invalid 'size' parameter, must be an integer", http.StatusBadRequest) + return + } + } + + // Get optional error correction level (default to Medium) + level := qrcode.Medium + if levelStr := r.URL.Query().Get("level"); levelStr != "" { + switch levelStr { + case "L", "l": + level = qrcode.Low + case "M", "m": + level = qrcode.Medium + case "Q", "q": + level = qrcode.High + case "H", "h": + level = qrcode.Highest + default: + respondError(w, "Invalid 'level' parameter, must be L, M, Q, or H", nil, http.StatusBadRequest) + return + } + } + + // Generate the QR code + var qr *qrcode.QRCode + var err error + qr, err = qrcode.New(content, level) + if err != nil { + respondError(w, "Error generating QR code", err, http.StatusInternalServerError) + return + } + + // Set the appropriate content type + w.Header().Set("Content-Type", "image/png") + + // Generate PNG and write directly to the response writer + png, err := qr.PNG(size) + if err != nil { + respondError(w, "Error encoding QR code to PNG", err, http.StatusInternalServerError) + return + } + + _, err = w.Write(png) + if err != nil { + respondError(w, "Error writing response", err, http.StatusInternalServerError) + } +} func getReport(w http.ResponseWriter, r *http.Request) { //org := r.URL.Query().Get("org") err := htmlReport(w) diff --git a/go.mod b/go.mod index a6169970..d7d0869a 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/lib/pq v1.10.9 github.com/pressly/goose/v3 v3.26.0 github.com/riverqueue/river/rivershared v0.26.0 + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/stephenafamo/bob v0.41.1 github.com/stephenafamo/scan v0.7.0 github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 diff --git a/go.sum b/go.sum index 3d1b3e63..ecc55c09 100644 --- a/go.sum +++ b/go.sum @@ -144,6 +144,8 @@ github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQU github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= github.com/stephenafamo/bob v0.41.1 h1:xcRPuRMCwtZZ9tS4JIVbZ5Erdm5Dy5dIvbS5kivwPpA= github.com/stephenafamo/bob v0.41.1/go.mod h1:8l55917DM36gF518Iz1MHjLds7KGAfkitJfxISYlth8= github.com/stephenafamo/fakedb v0.0.0-20221230081958-0b86f816ed97 h1:XItoZNmhOih06TC02jK7l3wlpZ0XT/sPQYutDcGOQjg= diff --git a/html.go b/html.go index 8d76a510..3d0921b5 100644 --- a/html.go +++ b/html.go @@ -30,6 +30,9 @@ type Link struct { Href string Title string } +type ContentReportDiagnostic struct { + URL string +} type ContentDashboard struct { User User } @@ -87,7 +90,10 @@ func htmlDashboard(w io.Writer, user *models.User) error { } func htmlReport(w io.Writer) error { - data := ContentPlaceholder{} + url := BaseURL + "/report/t78fd3" + data := ContentReportDiagnostic{ + URL: url, + } return report.ExecuteTemplate(w, data) } diff --git a/main.go b/main.go index d70a59a0..59ed3a5a 100644 --- a/main.go +++ b/main.go @@ -58,6 +58,7 @@ func main() { r.Use(sessionManager.LoadAndSave) r.Get("/", getRoot) + r.Get("/qr-code/report/{code}", getQRCodeReport) r.Get("/report", getReport) r.Post("/signin", postSignin) r.Get("/signup", getSignup) diff --git a/templates/report.html b/templates/report.html index 1cbd0cee..ef5dd202 100644 --- a/templates/report.html +++ b/templates/report.html @@ -102,49 +102,6 @@ } {{end}} {{define "content"}} - -
@@ -168,7 +125,7 @@

Customers will receive the following text message with a link to begin the reporting process:

- Vector Control: We noticed a potential green pool at your property. Please tap the link to report status or schedule inspection: https://sync.nidus.cloud/report/t78fd3 + Vector Control: We noticed a potential green pool at your property. Please tap the link to report status or schedule inspection: {{ .URL }}
@@ -197,7 +154,7 @@

Scan this code with your phone camera to report your pool status or schedule an inspection.

-

Or visit: https://sync.nidus.cloud/report/t78fd3

+

Or visit: {{ .URL }}

-

Please click the button above or visit https://sync.nidus.cloud/report/t78fd3 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.

+

Please click the button above or visit {{ .URL }} 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.

Thank you for helping keep our community safe and healthy.