Fixes
This commit is contained in:
@@ -942,12 +942,19 @@
|
|||||||
<input
|
<input
|
||||||
id="guest-phone"
|
id="guest-phone"
|
||||||
type="tel"
|
type="tel"
|
||||||
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none"
|
class="flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none {guestPhoneError
|
||||||
|
? 'border-red-500'
|
||||||
|
: 'border-input'}"
|
||||||
placeholder="07700 900000"
|
placeholder="07700 900000"
|
||||||
value={guestPhone}
|
value={guestPhone}
|
||||||
oninput={(e) => { guestPhone = e.currentTarget.value; }}
|
oninput={(e) => {
|
||||||
onblur={() => { if (guestPhone && !isValidUKPhone(guestPhone)) guestPhoneError = 'Invalid UK phone number'; else guestPhoneError = ''; }}
|
guestPhone = e.currentTarget.value;
|
||||||
class={guestPhoneError ? 'border-red-500' : ''}
|
}}
|
||||||
|
onblur={() => {
|
||||||
|
if (guestPhone && !isValidUKPhone(guestPhone))
|
||||||
|
guestPhoneError = 'Invalid UK phone number';
|
||||||
|
else guestPhoneError = '';
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{#if guestPhoneError}
|
{#if guestPhoneError}
|
||||||
<p class="mt-1 text-xs text-red-600">{guestPhoneError}</p>
|
<p class="mt-1 text-xs text-red-600">{guestPhoneError}</p>
|
||||||
|
|||||||
@@ -625,12 +625,19 @@
|
|||||||
<input
|
<input
|
||||||
id="guest-phone"
|
id="guest-phone"
|
||||||
type="tel"
|
type="tel"
|
||||||
class="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none"
|
class="flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:outline-none {guestPhoneError
|
||||||
placeholder="07700 900000 (optional — helps us reach you if running late)"
|
? 'border-red-500'
|
||||||
|
: 'border-input'}"
|
||||||
|
placeholder="07700 900000"
|
||||||
value={guestPhone}
|
value={guestPhone}
|
||||||
oninput={(e) => { guestPhone = e.currentTarget.value; }}
|
oninput={(e) => {
|
||||||
onblur={() => { guestPhoneError = guestPhone && !isValidUKPhone(guestPhone) ? 'Invalid UK phone number' : ''; }}
|
guestPhone = e.currentTarget.value;
|
||||||
class={guestPhoneError ? 'border-red-500' : ''}
|
}}
|
||||||
|
onblur={() => {
|
||||||
|
if (guestPhone && !isValidUKPhone(guestPhone))
|
||||||
|
guestPhoneError = 'Invalid UK phone number';
|
||||||
|
else guestPhoneError = '';
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
{#if guestPhoneError}
|
{#if guestPhoneError}
|
||||||
<p class="mt-1 text-xs text-red-600">{guestPhoneError}</p>
|
<p class="mt-1 text-xs text-red-600">{guestPhoneError}</p>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import UserBookingModal from '$lib/components/account/UserBookingModal.svelte';
|
import UserBookingModal from '$lib/components/account/UserBookingModal.svelte';
|
||||||
import { isValidUKPhone, formatPhoneDisplay, toE164UK } from '$lib/utils/phone';
|
import { isValidUKPhone, formatPhoneDisplay, toE164UK } from '$lib/utils/phone';
|
||||||
import { savedCardsStore } from '$lib/stores/savedCards.svelte';
|
import { savedCardsStore, type SavedCard } from '$lib/stores/savedCards.svelte';
|
||||||
|
|
||||||
// zxcvbn-ts imports
|
// zxcvbn-ts imports
|
||||||
import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core';
|
import { zxcvbn, zxcvbnOptions } from '@zxcvbn-ts/core';
|
||||||
@@ -120,38 +120,8 @@
|
|||||||
|
|
||||||
let notifPrefs = $state({ emailEnabled: true, smsEnabled: true, browserPushEnabled: true });
|
let notifPrefs = $state({ emailEnabled: true, smsEnabled: true, browserPushEnabled: true });
|
||||||
|
|
||||||
type SavedCard = {
|
|
||||||
id: string;
|
|
||||||
brand: string;
|
|
||||||
last_4: string;
|
|
||||||
exp_month: number;
|
|
||||||
exp_year: number;
|
|
||||||
is_default: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
let savedCards = $state<SavedCard[]>([]);
|
|
||||||
let loadingCards = $state(false);
|
let loadingCards = $state(false);
|
||||||
|
|
||||||
async function fetchSavedCards() {
|
|
||||||
loadingCards = true;
|
|
||||||
try {
|
|
||||||
const res = await fetch('/api/user/payment-methods', {
|
|
||||||
headers: { Authorization: `Bearer ${authStore.currentToken}` }
|
|
||||||
});
|
|
||||||
if (res.ok) {
|
|
||||||
savedCards = await res.json();
|
|
||||||
if (savedCards.length > 0 && !buySelectedCard) {
|
|
||||||
const defaultCard = savedCards.find((c) => c.is_default) || savedCards[0];
|
|
||||||
buySelectedCard = defaultCard.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
toast.error('Failed to load saved cards');
|
|
||||||
} finally {
|
|
||||||
loadingCards = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cardToDelete = $state<SavedCard | null>(null);
|
let cardToDelete = $state<SavedCard | null>(null);
|
||||||
let showDeleteCardDialog = $state(false);
|
let showDeleteCardDialog = $state(false);
|
||||||
|
|
||||||
@@ -163,7 +133,7 @@
|
|||||||
});
|
});
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
toast.success('Card removed');
|
toast.success('Card removed');
|
||||||
savedCards = savedCards.filter((c) => c.id !== card.id);
|
savedCardsStore = savedCardsStore.filter((c) => c.id !== card.id);
|
||||||
} else {
|
} else {
|
||||||
toast.error('Failed to remove card');
|
toast.error('Failed to remove card');
|
||||||
}
|
}
|
||||||
@@ -444,7 +414,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (savedCards.length === 0 && buySelectedCard !== '') {
|
if (savedCardsStore.length === 0 && buySelectedCard !== '') {
|
||||||
buySelectedCard = '';
|
buySelectedCard = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1834,14 +1804,14 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if savedCards.length === 0}
|
{:else if savedCardsStore.length === 0}
|
||||||
<div class="py-8 text-center">
|
<div class="py-8 text-center">
|
||||||
<p class="text-gray-500">No saved cards yet</p>
|
<p class="text-gray-500">No saved cards yet</p>
|
||||||
<Button class="mt-4" onclick={() => (showAddCard = true)}>Add a Card</Button>
|
<Button class="mt-4" onclick={() => (showAddCard = true)}>Add a Card</Button>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
{#each savedCards as card (card.id)}
|
{#each savedCardsStore as card (card.id)}
|
||||||
<div class="flex items-center justify-between rounded-lg border p-4">
|
<div class="flex items-center justify-between rounded-lg border p-4">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<div
|
<div
|
||||||
@@ -2075,9 +2045,9 @@
|
|||||||
<span class="block text-xs font-semibold tracking-wider text-gray-500 uppercase"
|
<span class="block text-xs font-semibold tracking-wider text-gray-500 uppercase"
|
||||||
>Payment Method</span
|
>Payment Method</span
|
||||||
>
|
>
|
||||||
{#if savedCards.length > 0}
|
{#if savedCardsStore.length > 0}
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
{#each savedCards as card (card.id)}
|
{#each savedCardsStore as card (card.id)}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="flex w-full items-center justify-between rounded-lg border p-3 text-left {buySelectedCard ===
|
class="flex w-full items-center justify-between rounded-lg border p-3 text-left {buySelectedCard ===
|
||||||
|
|||||||
Reference in New Issue
Block a user