scan-flow: geolocation scan, location-aware SMS throttle (log sender), finder contact, sms_enabled toggle, branding — 19/19 phase-2 scenarios pass
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{.Title}} · WhereWoof</title>
|
||||
<title>{{.Title}} · Where Woof !</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
||||
@@ -12,7 +12,7 @@
|
||||
<body class="min-h-full bg-stone-100 text-stone-900 antialiased">
|
||||
<nav class="bg-stone-900 text-white">
|
||||
<div class="mx-auto flex max-w-4xl items-center justify-between px-4 py-3">
|
||||
<a href="/" class="text-lg font-bold tracking-tight">🐕 WhereWoof</a>
|
||||
<a href="/" class="text-lg font-bold tracking-tight">🐕 Where Woof</a>
|
||||
<div class="flex items-center gap-4 text-sm">
|
||||
{{if .CurrentUser}}
|
||||
<span class="text-stone-300">Hi, {{.CurrentUser.Name}}</span>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="mx-auto max-w-2xl text-center">
|
||||
<h1 class="text-4xl font-extrabold tracking-tight">Lost something?<br><span class="text-amber-600">The tag brings it home.</span></h1>
|
||||
<p class="mt-4 text-lg text-stone-600">
|
||||
WhereWoof tags carry the return details for your dog, baggage, skis — anything you care about.
|
||||
Where Woof tags carry the return details for your dog, baggage, skis — anything you care about.
|
||||
A finder scans the QR code or taps the NFC tag and sees exactly how to get it back to you.
|
||||
</p>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{{define "content"}}
|
||||
<div class="mx-auto max-w-md">
|
||||
<h1 class="text-2xl font-bold">Log in</h1>
|
||||
<p class="mt-1 text-sm text-stone-600">Welcome back to WhereWoof.</p>
|
||||
<p class="mt-1 text-sm text-stone-600">Welcome back to Where Woof.</p>
|
||||
|
||||
{{if .Error}}<p class="mt-4 rounded bg-red-50 px-4 py-2 text-sm text-red-700 border border-red-200">{{.Error}}</p>{{end}}
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
<button type="submit" class="w-full rounded bg-stone-900 px-4 py-2 font-semibold text-white hover:bg-stone-700">Log in</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-4 text-center text-sm text-stone-600">New to WhereWoof? <a href="/register" class="text-amber-600 hover:underline">Create an account</a></p>
|
||||
<p class="mt-4 text-center text-sm text-stone-600">New to Where Woof? <a href="/register" class="text-amber-600 hover:underline">Create an account</a></p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="mx-auto max-w-md text-center">
|
||||
<div class="text-5xl">🔎</div>
|
||||
<h1 class="mt-4 text-2xl font-bold">Tag not found</h1>
|
||||
<p class="mt-2 text-stone-600">We couldn't find a WhereWoof tag with that code. Check the code on the tag and try again.</p>
|
||||
<p class="mt-2 text-stone-600">We couldn't find a Where Woof tag with that code. Check the code on the tag and try again.</p>
|
||||
<a href="/" class="mt-6 inline-block rounded bg-stone-900 px-4 py-2 text-sm font-semibold text-white hover:bg-stone-700">Go home</a>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{{define "content"}}
|
||||
<div class="mx-auto max-w-md">
|
||||
<h1 class="text-2xl font-bold">Create your account</h1>
|
||||
<p class="mt-1 text-sm text-stone-600">Register to claim your WhereWoof tag.</p>
|
||||
<p class="mt-1 text-sm text-stone-600">Register to claim your Where Woof tag.</p>
|
||||
|
||||
{{if .Error}}<p class="mt-4 rounded bg-red-50 px-4 py-2 text-sm text-red-700 border border-red-200">{{.Error}}</p>{{end}}
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
<label class="block text-sm font-medium">Notes</label>
|
||||
<textarea name="notes" rows="2" class="mt-1 w-full rounded border border-stone-300 px-3 py-2">{{if .Data.Notes.Valid}}{{.Data.Notes.String}}{{end}}</textarea>
|
||||
</div>
|
||||
<label class="flex items-center gap-2 text-sm">
|
||||
<input type="checkbox" name="sms_enabled" value="on" {{if .Data.SmsEnabled}}checked{{end}} class="h-4 w-4">
|
||||
Send me SMS alerts when this tag is scanned
|
||||
</label>
|
||||
<div class="flex gap-3">
|
||||
<button type="submit" class="rounded bg-stone-900 px-4 py-2 font-semibold text-white hover:bg-stone-700">Save details</button>
|
||||
<a href="/account" class="rounded border border-stone-300 px-4 py-2 text-sm font-medium hover:bg-stone-50">Cancel</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="rounded-xl border border-stone-200 bg-white p-8 text-center shadow-sm">
|
||||
<div class="text-5xl">🏷️</div>
|
||||
<h1 class="mt-4 text-2xl font-bold">This tag isn't set up yet</h1>
|
||||
<p class="mt-2 text-stone-600">This WhereWoof tag hasn't been claimed. If this is your tag, log in and add it to your account to set up the return details.</p>
|
||||
<p class="mt-2 text-stone-600">This Where Woof tag hasn't been claimed. If this is your tag, log in and add it to your account to set up the return details.</p>
|
||||
<div class="mt-6 flex justify-center gap-3">
|
||||
<a href="/login" class="rounded bg-stone-900 px-4 py-2 text-sm font-semibold text-white hover:bg-stone-700">Log in</a>
|
||||
<a href="/register" class="rounded bg-amber-500 px-4 py-2 text-sm font-semibold text-stone-900 hover:bg-amber-400">Create account</a>
|
||||
@@ -22,7 +22,7 @@
|
||||
<h1 class="text-2xl font-bold">
|
||||
{{if .Data.ItemType.Valid}}{{.Data.ItemType.String | title}}{{else}}Item{{end}} — found!
|
||||
</h1>
|
||||
<p class="mt-1 text-sm text-stone-300">This item has a WhereWoof tag. Here's how to return it:</p>
|
||||
<p class="mt-1 text-sm text-stone-300">This item has a Where Woof tag. Here's how to return it:</p>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
{{if .Data.PhotoUrl.Valid}}
|
||||
@@ -37,6 +37,10 @@
|
||||
<dt class="font-medium">Call the owner</dt>
|
||||
<dd><a href="tel:{{.Data.Phone.String}}" class="font-semibold text-amber-600 hover:underline">{{.Data.Phone.String}}</a></dd>
|
||||
</div>
|
||||
<div class="flex items-center justify-between rounded bg-stone-50 px-4 py-3">
|
||||
<dt class="font-medium">Text the owner</dt>
|
||||
<dd><a href="sms:{{.Data.Phone.String}}?&body=Hi! I found your {{if .Data.ItemType.Valid}}{{.Data.ItemType.String}}{{else}}item{{end}}{{if .Data.Description.Valid}}, {{.Data.Description.String}}{{end}}. My phone number is: " class="font-semibold text-amber-600 hover:underline">Send an SMS</a></dd>
|
||||
</div>
|
||||
{{end}}
|
||||
{{if .Data.Address.Valid}}
|
||||
<div class="flex items-center justify-between rounded bg-stone-50 px-4 py-3">
|
||||
@@ -51,14 +55,51 @@
|
||||
</div>
|
||||
{{end}}
|
||||
</dl>
|
||||
<p class="mt-6 rounded bg-amber-50 px-4 py-3 text-sm text-amber-800 border border-amber-200">
|
||||
Found this item? Please contact the owner to arrange the return. Thank you for helping!
|
||||
</p>
|
||||
|
||||
<div class="mt-4 rounded border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800">
|
||||
<p><strong>Help the owner find it:</strong> sharing your location sends them a map link. No location? No problem — the page still works.</p>
|
||||
<button id="recheck-btn" type="button" class="mt-2 rounded bg-amber-500 px-3 py-1.5 text-xs font-semibold text-stone-900 hover:bg-amber-400">📍 Re-check my location</button>
|
||||
</div>
|
||||
|
||||
<div id="contact-area" class="mt-4">
|
||||
<form hx-post="/t/{{.Data.TagCode}}/contact" hx-target="#contact-area" hx-swap="innerHTML" class="flex gap-2">
|
||||
<input name="phone" type="tel" placeholder="Leave your number for the owner (optional)" class="flex-1 rounded border border-stone-300 px-3 py-2 text-sm" pattern="[0-9+ ]{8,16}">
|
||||
<button type="submit" class="rounded bg-stone-900 px-4 py-2 text-sm font-semibold text-white hover:bg-stone-700">Send number</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{if .Data.IsOwner}}
|
||||
<p class="mt-4 text-center text-sm"><a href="/account/tags/{{.Data.ID}}/edit" class="text-amber-600 hover:underline">✏️ Edit this tag's details</a></p>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var code = {{.Data.TagCode | printf "%q"}};
|
||||
var btn = document.getElementById("recheck-btn");
|
||||
function sendScan(lat, lng) {
|
||||
fetch("/t/" + code + "/scan", {
|
||||
method: "POST",
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: JSON.stringify(lat != null ? {lat: lat, lng: lng} : {})
|
||||
});
|
||||
}
|
||||
function tryLocation() {
|
||||
if (!navigator.geolocation) { sendScan(null, null); return; }
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function (pos) {
|
||||
if (btn) btn.classList.add("hidden");
|
||||
sendScan(pos.coords.latitude, pos.coords.longitude);
|
||||
},
|
||||
function () { sendScan(null, null); },
|
||||
{timeout: 8000, maximumAge: 60000}
|
||||
);
|
||||
}
|
||||
if (btn) btn.addEventListener("click", tryLocation);
|
||||
tryLocation();
|
||||
})();
|
||||
</script>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user