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}
-
+