Populate email/phone from an unmatched kiosk search query

When the account lookup finds no match, carry the typed query into whichever
of Email/Phone it resembles (email-shaped or phone-shaped) instead of
discarding it, so the operator doesn't have to retype it. Leaves both blank
if it matches neither shape, and resets Name/notification preference for a
fresh entry.
This commit is contained in:
2026-07-28 16:05:41 +02:00
parent b4cd140168
commit 21176e1e0b
+23 -1
View File
@@ -85,6 +85,13 @@ function fmtCurrency(val: number) {
return val === 0 ? "Free" : `R${val.toFixed(2)}`; 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 ─────────────────────────────────────────────────────────────── // ─── Kiosk Page ───────────────────────────────────────────────────────────────
export default function SelfServicePage() { export default function SelfServicePage() {
const [screen, setScreen] = useState<Screen>("setup"); const [screen, setScreen] = useState<Screen>("setup");
@@ -450,8 +457,9 @@ export default function SelfServicePage() {
// Classify the query as email- or phone-shaped and send it as only that param — // 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 // 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. // (e.g. a numeric local-part) get misread as an unrelated phone number.
const isEmailLike = q.includes("@");
const params = new URLSearchParams(); const params = new URLSearchParams();
if (q.includes("@")) params.set("email", q); if (isEmailLike) params.set("email", q);
else params.set("phone", q); else params.set("phone", q);
const data = await apiFetch<{ const data = await apiFetch<{
exists: boolean; exists: boolean;
@@ -466,7 +474,21 @@ export default function SelfServicePage() {
setAccountExists(true); setAccountExists(true);
setLookupMessage("Account found — details filled in below."); setLookupMessage("Account found — details filled in below.");
} else { } 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); 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."); setLookupMessage("No matching account found.");
} }
} catch { } catch {