From 9158681001bf8c96f03b5f2ff23e84a44f0561c6 Mon Sep 17 00:00:00 2001 From: Sam Rolfe Date: Mon, 10 Aug 2026 12:27:20 +1000 Subject: [PATCH] fix batch: admin login rehash->password_hash mapping (500); geolocation timeout 20s + hide button on approval + 'location shared' notice; sms: link includes typed number (Alpine); location page = found-dog + map + finder number + tag details; nicer closed page; password visibility toggles; product photos; templates use x-text (no {{}} in Alpine) --- db/schema.sql | 3 +++ frontend/internal/handlers/location.go | 26 ++++++++++++++--------- frontend/templates/location.html | 24 ++++++++++++++++----- frontend/templates/login.html | 7 +++++-- frontend/templates/register.html | 7 +++++-- frontend/templates/tag-public.html | 29 +++++++++++++++++++------- 6 files changed, 70 insertions(+), 26 deletions(-) diff --git a/db/schema.sql b/db/schema.sql index b58bcd9..4b440a5 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -97,3 +97,6 @@ ALTER TABLE orders ADD COLUMN IF NOT EXISTS renews_at TIMESTAMPTZ; -- Tag lifecycle: closed state (owner close / moved-from). Idempotent. ALTER TABLE tags DROP CONSTRAINT IF EXISTS tags_status_check; ALTER TABLE tags ADD CONSTRAINT tags_status_check CHECK (status IN ('unset','active','suspended','closed')); + +-- Product photos (admin). +ALTER TABLE products ADD COLUMN IF NOT EXISTS photo_url TEXT; diff --git a/frontend/internal/handlers/location.go b/frontend/internal/handlers/location.go index e3cc4fd..e675274 100644 --- a/frontend/internal/handlers/location.go +++ b/frontend/internal/handlers/location.go @@ -1,11 +1,8 @@ package handlers import ( - "errors" "net/http" - "github.com/jackc/pgx/v5" - "wherewoof/frontend/internal/db" ) @@ -16,10 +13,16 @@ type locationData struct { FinderPhone string TagCode string ScannedAt string + ItemType string + Name string + PhotoURL string + Phone string + Address string } // ServeShort resolves a short code to its scan and renders the owner's -// location page (map embed + finder details). +// location page: "your item was found here" — map embed + finder details + +// the tag's return details. func (a *App) ServeShort(w http.ResponseWriter, r *http.Request) { code := r.PathValue("code") sc, err := a.Queries.GetShortCode(r.Context(), code) @@ -36,11 +39,7 @@ func (a *App) ServeShort(w http.ResponseWriter, r *http.Request) { tag, err := a.Queries.GetTagByID(r.Context(), scan.TagID) if err != nil { - if errors.Is(err, pgx.ErrNoRows) { - http.NotFound(w, r) - return - } - http.Error(w, "internal error", http.StatusInternalServerError) + http.NotFound(w, r) return } @@ -50,8 +49,15 @@ func (a *App) ServeShort(w http.ResponseWriter, r *http.Request) { FinderPhone: scan.ScannerPhone.String, TagCode: tag.TagCode, ScannedAt: scan.ScannedAt.Time.Local().Format("Mon 2 Jan, 3:04 pm"), + Name: tag.Description.String, + PhotoURL: tag.PhotoUrl.String, + Phone: tag.Phone.String, + Address: tag.Address.String, } - a.render(w, r, "location", "Location found", data, "") + if tag.ItemType.Valid { + data.ItemType = titleCase(tag.ItemType.String) + } + a.render(w, r, "location", "Found", data, "") } // keep the db import referenced (Tag lookup above uses a.Queries only; this diff --git a/frontend/templates/location.html b/frontend/templates/location.html index 141cffc..1521b20 100644 --- a/frontend/templates/location.html +++ b/frontend/templates/location.html @@ -2,8 +2,8 @@
-

📍 Location found

-

Your Where Woof tag was scanned at {{.Data.ScannedAt}}. This is where it was reported:

+

🎉 Your {{if .Data.ItemType}}{{.Data.ItemType}}{{else}}item{{end}} was found!

+

It was reported at {{.Data.ScannedAt}}. Here's where it was seen:

@@ -16,9 +16,23 @@
{{if .Data.FinderPhone}} -
-
The finder left their number
-
{{.Data.FinderPhone}}
+
+ The finder left their number + {{.Data.FinderPhone}} +
+ {{end}} + + {{if or .Data.PhotoURL .Data.Name .Data.Address .Data.Phone}} +
+

About your {{if .Data.ItemType}}{{.Data.ItemType}}{{else}}item{{end}}

+
+ {{if .Data.PhotoURL}}Your item{{end}} +
+ {{if .Data.Name}}

{{.Data.Name}}

{{end}} + {{if .Data.Address}}

{{.Data.Address}}

{{end}} + {{if .Data.Phone}}

Contact: {{.Data.Phone}}

{{end}} +
+
{{end}} diff --git a/frontend/templates/login.html b/frontend/templates/login.html index 86c329c..3374d01 100644 --- a/frontend/templates/login.html +++ b/frontend/templates/login.html @@ -10,9 +10,12 @@
-
+
- +
+ + +
diff --git a/frontend/templates/register.html b/frontend/templates/register.html index ab9dc49..616af5a 100644 --- a/frontend/templates/register.html +++ b/frontend/templates/register.html @@ -18,9 +18,12 @@
-
+
- +
+ + +
diff --git a/frontend/templates/tag-public.html b/frontend/templates/tag-public.html index f365a75..3276867 100644 --- a/frontend/templates/tag-public.html +++ b/frontend/templates/tag-public.html @@ -17,10 +17,15 @@

The owner has disabled this tag. Please try another way to return the item.

{{else if eq .Data.Status "closed"}} -
+
🔒

This tag has been closed

-

This tag is no longer active. If you found this item, please try to return it another way.

+

This Where Woof tag is no longer active — its owner has retired it (maybe a broken tag, a new tag, or the item was found and the tag removed).

+

If you found this item, please try to return it another way (ask around, check lost & found, or contact local authorities).

+
{{else}}
@@ -43,9 +48,13 @@
Call the owner
{{.Data.Phone.String}}
-
+
Text the owner
-
Send an SMS
+
+ Send an SMS + +
{{end}} {{if .Data.Address.Valid}} @@ -65,6 +74,7 @@

Help the owner find it: sharing your location sends them a map link. No location? No problem — the page still works.

+
@@ -111,11 +121,16 @@ if (!navigator.geolocation) { sendScan(null, null); return; } navigator.geolocation.getCurrentPosition( function (pos) { - if (btn) btn.classList.add("hidden"); + // Location approved: hide the button permanently and send coords. + if (btn) { btn.classList.add("hidden"); btn.disabled = true; } + var shared = document.getElementById("location-shared"); + if (shared) shared.classList.remove("hidden"); sendScan(pos.coords.latitude, pos.coords.longitude); }, - function () { sendScan(null, null); }, - {timeout: 8000, maximumAge: 60000} + function () { + sendScan(null, null); // no location — page still works, button stays + }, + {timeout: 20000, maximumAge: 0} ); } if (btn) btn.addEventListener("click", tryLocation);