{#if pageState === 'loading'}
{#each range(5) as i (i)} {/each}
{:else if pageState === 'authorized'}

My Account

Manage your profile, bookings, and settings

{#if authStore.currentUser?.role !== 'admin'} {/if} {#if authStore.currentUser?.role !== 'admin'} {/if} {#if canSaveCards} {/if}
{#if activeTab === 'general'} Profile Information Your personal details and account information {#if userData} {@const initials = userData.firstName && userData.lastName ? userData.firstName .split(' ') .map((n) => n[0]) .join('') + userData.lastName .split(' ') .map((n) => n[0]) .join('') : ''} {@const hasImage = !!userData.profilePicUrl || !!previewUrl} {@const displayUrl = previewUrl || userData.profilePicUrl || ''}
{#if hasImage || initials} {#if hasImage} Profile {:else}
{initials}
{/if} {:else}
{/if}
{/if} Crop Profile Picture
{#if cropImageUrl} { cropArea = e.pixels; }} /> {/if}
{#if loadingUser} {#each range(6) as i (i)} {/each} {:else if userData}
First Name {#if editingFirstName}
{#if firstNameError}

{firstNameError}

{/if}
{:else}
{userData.firstName}
{/if}
Last Name {#if editingLastName}
{#if lastNameError}

{lastNameError}

{/if}
{:else}
{userData.lastName}
{/if}
Email
{userData.email}
Phone {#if editingPhone}
{:else}
{userData.phone || '—'}
{/if}
{#if authStore.currentUser?.role !== 'admin'} {#if stamps >= 10}

Card Completed — 10% Off Your Next Booking!

{/if}
{#if userData}

Loyalty Stamp Card

{stamps < 10 ? `Collect ${10 - stamps} more stamp${10 - stamps === 1 ? '' : 's'} to get 10% off your next booking.` : (() => { const fc = Math.floor(stamps / 10); return `You have ${fc === 1 ? 'a' : fc} full stampcard${fc === 1 ? '' : 's'} ready to take advantage of at your next booking!`; })()}

{#each range(10) as i (i)} {@const slotNum = i + 1} {@const rot = ((slotNum * 37 + 13) % 7) - 3} {#if slotNum <= (stamps > 0 ? stamps % 10 || 10 : 0)}
{:else}
{slotNum}
{/if} {/each}
{/if}
{/if} {/if}
{:else if activeTab === 'history'} {#if upcomingBookings.length > 0} Upcoming Appointments Next {upcomingBookings.length < 3 ? upcomingBookings.length : 3} upcoming bookings {#if loadingUpcoming} {#each range(3) as i (i)} {/each} {:else} {#each upcomingBookings as b (b.id)}
{formatDateTime(b.start_time)}
{b.status} {#if b.services && b.services.length > 0} - {(() => { const services = b.services.map( (s) => s.service_name || 'Unknown Service' ); if (services.length === 1) return services[0]; if (services.length === 2) return services.join(' and '); return `${services[0]} and ${services.length - 1} other${services.length - 1 > 1 ? 's' : ''}`; })()} {/if}
{/each} {/if}
{/if} Past Appointments Previous bookings {#if loadingPast} {#each range(5) as i (i)} {/each} {:else if pastBookings.length === 0}
No past bookings
{:else} {#each pastBookings as b (b.id)}
{formatDateTime(b.start_time)}
{#if (b.amount_due || 0) > 0} Unpaid {/if} {#if b.services && b.services.length > 0} - {(() => { const services = b.services.map( (s) => s.service_name || 'Unknown Service' ); if (services.length === 1) return services[0]; if (services.length === 2) return services.join(' and '); return `${services[0]} and ${services.length - 1} other${services.length - 1 > 1 ? 's' : ''}`; })()} {/if} {#if b.total_amount} — £{b.total_amount.toFixed(2)} {/if}
{/each} {/if} {#if pastTotalPages > 1}
{pastPage} / {pastTotalPages}
{/if}
{:else if activeTab === 'referral'} Referral Program Share your code and earn rewards {#if loadingUser} {:else if userData?.referralCode}
Your Referral Code
{#each userData.referralCode.match(/.{1,4}/g) as part, i (i)}{part}{#if i < 2}{/if}{/each}
{userData.referralCodeUses || 0}
Friends Referred
£{(userData.referralSavings || 0).toFixed(2)}
Total Saved

How it works:

  • • Share your referral code with friends
  • • They get 10% off their first booking
  • • You get 10% off your next booking after they claim
  • • You earn 3 loyalty stamp for each use to keep the savings going
{:else}
No referral code available
{/if}
{:else if activeTab === 'cards'} Saved Cards Manage your saved payment methods {#if loadingCards}
{:else if savedCardsStore.cards.length === 0}

No saved cards yet

{:else}
{#each savedCardsStore.cards as card (card.id)}
**** {card.last_4}
Expires {String(card.exp_month).padStart(2, '0')}/{card.exp_year}
{/each}
{/if}
Redeem Gift Card Redeem a gift card directly to your account balance.
Your Balance
{loadingBalance ? '...' : formatCurrency(giftCardBalance)}
Redeem Gift Card Claiming this gift card will add its remaining balance directly to your account balance, which can be used toward future bookings.

What happens when I claim?

  • The gift card value is added to your account balance.
  • Account balances do not expire, but gift card codes become invalid once redeemed.
  • This action is final and cannot be reversed.

Legal & GDPR Information

  • Your personal data (name, email, transaction history) is processed in accordance with UK data protection law.
  • Financial records are retained for 7 years as required by HMRC, after which personally identifiable information is anonymised.
  • You can request a full copy of your data or deletion of your account at any time via your account settings.

By redeeming this gift card, you agree to our Terms & Conditions. Link T&Cs here once available.

Cancel Confirm & Redeem
Buy a Gift Card Purchase a gift card online for yourself or a friend. {#if purchaseResultCode}
Purchase Successful!
{#if buyRecipientType === 'self'}

Your purchase of {formatCurrency(buyAmount)} has been automatically added to your account balance!

{:else}

Here is your gift card code:

{formatCardCode(purchaseResultCode)}

⚠️ Please save this code and send it to your friend — no email was sent.

{/if}
{:else}
Select Value
{#each [10, 20, 50] as amount (amount)} {/each}
Recipient
{#if buyRecipientType === 'friend'}
{/if}
Payment Method {#if savedCardsStore.cards.length > 0}
{#each savedCardsStore.cards as card (card.id)} {/each}
{:else} {/if}
{/if}
{:else if activeTab === 'admin'} Account Settings Manage your security and account preferences

Password

Update your password to keep your account secure

Session

Log out of this account on this device.

Data Privacy

View and export all personal data we hold about you

{#if gdprCountdown}

{gdprCountdown}

{/if}
{#if authStore.currentUser?.role !== 'admin'}

Notifications

Choose how you receive booking reminders and updates

Email
Booking confirmations and reminders
SMS
Text message reminders
Browser
In-browser notifications
{/if}

Policies

View our cancellation, deposit, and no-show policies

{#snippet trigger()} {/snippet}
{#if authStore.currentUser?.role !== 'admin'}

Danger Zone

Once you delete your account, there is no going back. Please be certain.

{/if}
{/if}
{#if authStore.currentUser?.role !== 'admin'} {/if} {#if authStore.currentUser?.role !== 'admin'} {/if} {#if canSaveCards} {/if}
{#if showPasswordModal}
Change Password Enter your current and new password
{#if passwordData.new && newPasswordStrength}

{newPasswordStrength.feedback.warning ? newPasswordStrength.feedback.warning : `Strength: ${['Very weak', 'Weak', 'Fair', 'Strong', 'Very strong'][newPasswordStrength.score]}`}

{#if newPasswordStrength.feedback.suggestions.length > 0}

{newPasswordStrength.feedback.suggestions[0]}

{/if}
{/if}
{#if !passwordsMatch}

Passwords do not match

{/if}
{/if} Delete Account? This action cannot be undone. This will permanently delete your account and remove all your data from our servers.
{ deleteConfirmText = ''; }} > Cancel
{ if (!open) cardToDelete = null; }} > Remove saved card? {#if cardToDelete} Remove {cardToDelete.brand} card ending in {cardToDelete.last_4}? {/if} You can add it again later. (cardToDelete = null)}>Cancel cardToDelete && deleteCard(cardToDelete)} class="bg-red-600 hover:bg-red-700" > Remove {/if}