diff --git a/frontend/src/lib/components/admin/GiftCardsManagement.svelte b/frontend/src/lib/components/admin/GiftCardsManagement.svelte index 9c87380..f839115 100644 --- a/frontend/src/lib/components/admin/GiftCardsManagement.svelte +++ b/frontend/src/lib/components/admin/GiftCardsManagement.svelte @@ -4,6 +4,7 @@ import { Button } from '$lib/components/ui/button'; import * as Card from '$lib/components/ui/card'; import { Input } from '$lib/components/ui/input'; + import { EmailInput } from '$lib/components/ui/email-input'; import * as Modal from '$lib/components/ui/dialog'; import { Skeleton } from '$lib/components/ui/skeleton'; @@ -1765,11 +1766,10 @@ Recipient Email Address (Optional) {/if} - {#if selectedCustomer?.email && !generateEmail.trim()}

Defaults to: {selectedCustomer.email}

diff --git a/frontend/src/lib/components/booking/BookingFlow.svelte b/frontend/src/lib/components/booking/BookingFlow.svelte index cedfe1e..b5f45dd 100644 --- a/frontend/src/lib/components/booking/BookingFlow.svelte +++ b/frontend/src/lib/components/booking/BookingFlow.svelte @@ -2,6 +2,7 @@ import { Button } from '$lib/components/ui/button/index.js'; import * as Card from '$lib/components/ui/card/index.js'; import { Input } from '$lib/components/ui/input/index.js'; + import { EmailInput } from '$lib/components/ui/email-input/index.js'; import { Label } from '$lib/components/ui/label/index.js'; import { Textarea } from '$lib/components/ui/textarea/index.js'; import CharCounter from '$lib/components/ui/CharCounter.svelte'; @@ -106,18 +107,6 @@ isValidUKPhone(customerInfo.phone) ); - function validateEmailFormat(email: string) { - if (!email) { - emailError = ''; - return; - } - if (!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) { - emailError = 'Please enter a valid email address'; - } else { - emailError = ''; - } - } - async function checkEmailExists(email: string) { if (!email || !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)) { emailSuggestion = null; @@ -1713,18 +1702,17 @@
- { - validateEmailFormat(customerInfo.email); + required + onvaluechange={() => { + emailSuggestion = null; debouncedEmailCheck(); }} - oninput={() => { - emailSuggestion = null; - emailError = ''; + onerrorchange={(err) => { emailError = err; }} + onblur={() => { debouncedEmailCheck(); }} /> diff --git a/frontend/src/routes/account/+page.svelte b/frontend/src/routes/account/+page.svelte index daa43c1..ab834f7 100644 --- a/frontend/src/routes/account/+page.svelte +++ b/frontend/src/routes/account/+page.svelte @@ -28,6 +28,7 @@ import { Checkbox } from '$lib/components/ui/checkbox'; import * as Card from '$lib/components/ui/card'; import { Input } from '$lib/components/ui/input'; + import { EmailInput } from '$lib/components/ui/email-input/index.js'; import { PhoneInput } from '$lib/components/ui/phone-input/index.js'; import { Separator } from '$lib/components/ui/separator'; import * as AlertDialog from '$lib/components/ui/alert-dialog'; @@ -2095,18 +2096,17 @@
{#if buyRecipientType === 'friend'} -
- - -
+
+ + +
{/if}
diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index 3b19bb3..5ed0ca8 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -2,6 +2,7 @@ import { resolve } from '$app/paths'; import { Button } from '$lib/components/ui/button/index.js'; import { Input } from '$lib/components/ui/input/index.js'; + import { EmailInput } from '$lib/components/ui/email-input/index.js'; import { PhoneInput } from '$lib/components/ui/phone-input/index.js'; import { Label } from '$lib/components/ui/label/index.js'; import { Separator } from '$lib/components/ui/separator/index.js'; @@ -67,37 +68,6 @@ }; } - // Email validation - function validateEmail(email: string): boolean { - // ASCII-only email regex (safe with most providers) - const asciiRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; - - // Unicode-friendly regex (valid per RFC 6531) - const unicodeRegex = /^[\p{L}\p{M}0-9._%+-]+@[\p{L}\p{M}0-9.-]+\.[\p{L}\p{M}]{2,}$/u; - - if (!email) { - validationErrors.email = ''; - return true; - } - - if (asciiRegex.test(email)) { - // OK: standard ASCII address - validationErrors.email = ''; - return true; - } else if (unicodeRegex.test(email)) { - // Looks like a valid internationalised address, but unsupported - validationErrors.email = - 'This looks like a valid international email address, ' + - 'but our providers only supports standard (A-Z, 0-9) email addresses. ' + - 'We are sorry. Please use an ASCII-compatible email.'; - return false; - } else { - // Not even valid under the Unicode spec - validationErrors.email = 'Invalid email format'; - return false; - } - } - function validatePhone(phone: string): boolean { const valid = isValidUKPhone(phone); validationErrors.phone = valid ? '' : 'Please enter a valid UK phone number'; @@ -217,7 +187,7 @@ } // Validate before submitting - const isEmailValid = validateEmail(formData.email); + const isEmailValid = !validationErrors.email && formData.email.trim().length > 0; const isPhoneValid = validatePhone(formData.phone); const isAgeValid = validateAge(formData.dateOfBirth); @@ -380,23 +350,18 @@ {#if !isLogin}
-

What we need to log you in

+

What we need to log you in

-
- - validateEmail(formData.email)} - required - /> - {#if validationErrors.email} -

{validationErrors.email}

- {/if} -
+
+ + +
@@ -540,25 +505,20 @@
{:else} -
-
- - validateEmail(formData.email)} - required - /> - {#if validationErrors.email} -

{validationErrors.email}

- {/if} -
+
+
+ + +
-
- +
+