diff --git a/frontend/src/app/self-service/page.tsx b/frontend/src/app/self-service/page.tsx index 45af3c9..db16625 100644 --- a/frontend/src/app/self-service/page.tsx +++ b/frontend/src/app/self-service/page.tsx @@ -85,6 +85,13 @@ function fmtCurrency(val: number) { return val === 0 ? "Free" : `R${val.toFixed(2)}`; } +// Loose "does this look like a mobile number" check — covers 0821234567 (10, leading 0), +// 821234567 (9, no leading 0), and 27821234567 / +27821234567 (11 digits, country code). +function looksLikePhone(s: string): boolean { + const digits = s.replace(/\D/g, ""); + return digits.length >= 9 && digits.length <= 11; +} + // ─── Kiosk Page ─────────────────────────────────────────────────────────────── export default function SelfServicePage() { const [screen, setScreen] = useState("setup"); @@ -450,8 +457,9 @@ export default function SelfServicePage() { // Classify the query as email- or phone-shaped and send it as only that param — // sending the same raw string as both could let digits embedded in an email // (e.g. a numeric local-part) get misread as an unrelated phone number. + const isEmailLike = q.includes("@"); const params = new URLSearchParams(); - if (q.includes("@")) params.set("email", q); + if (isEmailLike) params.set("email", q); else params.set("phone", q); const data = await apiFetch<{ exists: boolean; @@ -466,7 +474,21 @@ export default function SelfServicePage() { setAccountExists(true); setLookupMessage("Account found — details filled in below."); } else { + // No match — still save the retype: carry the query into whichever field it + // resembles, and leave everything else blank for a fresh entry. setAccountExists(false); + setVisitorName(""); + setNotificationPref("email"); + if (isEmailLike) { + setVisitorEmail(q); + setVisitorPhone(""); + } else if (looksLikePhone(q)) { + setVisitorPhone(q); + setVisitorEmail(""); + } else { + setVisitorEmail(""); + setVisitorPhone(""); + } setLookupMessage("No matching account found."); } } catch {