Gift Card Management Create, top-up, and track gift cards. Unclaimed cards can be topped up or transferred.
Total Unclaimed
{loading ? '...' : formatCurrency(summary.total_unclaimed)}
User Account Balances
{loading ? '...' : formatCurrency(summary.total_user_balances)}
Combined Liability
{loading ? '...' : formatCurrency(summary.total_unclaimed + summary.total_user_balances)}
{#if activeSection === 'cards' || activeSection === 'expired_cards'}
{ if (e.key === 'Enter') searchCards(); }} />
{#if sortedCards.length === 0 && !loading && !loadingSearch}
{activeSection === 'expired_cards' ? 'No expired gift cards found.' : 'No gift cards generated yet.'}
{:else if sortedCards.length > 0}
{#each sortedCards as gc (gc.id)}
{formatCardCode(gc.id)} {#if gc.redeemed_by} Claimed {:else if gc.is_inventory} Inventory {:else if isExpired(gc.last_used_at)} Expired {:else if gc.amount_remaining === 0} Spent {:else} Active {/if}
Total Added: {formatCurrency(gc.total_funds_added)}
Remaining: {formatCurrency(gc.amount_remaining)}
Created: {formatDate(gc.created_at)}
{#if gc.last_used_at}
Expires: {formatDate(getExpiryDate(gc.last_used_at)!.toISOString())}
{/if}
{#if !gc.redeemed_by} {/if}
{/each}
{/if}
{#if totalPages > 1}
Page {currentPage} of {totalPages}
{/if} {:else if activeSection === 'balances'}
{#if loading} {#each range(2) as i (i)}
{/each} {:else if balances.length === 0}
No customers have redeemed gift cards yet.
{:else} {#each sortedBalances as ub (ub.user_id)}
{ub.name}
Email: {ub.email}
Balance: {formatCurrency(ub.balance)}
Updated: {formatDate(ub.updated_at)}
{/each} {/if}
{:else if activeSection === 'expired'}
{#if loadingExpired} {#each range(2) as i (i)}
{/each} {:else if expiredBalances.length === 0}
No expired balances found.
{:else} {#each expiredBalances as eb (eb.id)}
{eb.account_id || 'N/A'} {#if eb.claimed_at} Claimed {:else} Unclaimed {/if}
Balance: {formatCurrency(eb.original_balance)}
Expired: {formatDate(eb.expired_at)}
{#if eb.claimed_at}
Claimed: {formatDate(eb.claimed_at)}
{/if}
{#if !eb.claimed_at} {/if}
{/each} {/if}
{/if}
Generate Gift Card {#if generateStep === 'type'} Select how the gift card will be issued and redeemed. {:else if generateStep === 'customer'} Select the customer for this gift card. {:else if generateStep === 'amount_email'} Enter the starting amount and delivery details. {:else if generateStep === 'payment'} Select the payment method. {:else if generateStep === 'cash_entry'} Enter cash amount received. {/if} {#if generateStep === 'type'}

How would you like to issue this gift card?

{:else if generateStep === 'customer'}
{#if generateType === 'code'} {/if}
{#if generateCustomerTab === 'current'}
{#if loadingCurrentCustomer}
{:else if currentCustomerInfo} {:else}
No current or next appointment found today.
{/if}
{:else if generateCustomerTab === 'member'}
{ if (e.key === 'Enter') { e.preventDefault(); searchGenerateCustomers(); } }} />
{#if generateUsers.length === 0 && !generateLoadingUsers}
{generateUserQuery ? 'No members found.' : 'Search for a member above.'}
{:else if generateUsers.length > 0}
    {#each generateUsers.slice(0, 5) as user (user.id)}
  • {/each}
{/if}
{:else if generateCustomerTab === 'guest'}
{/if}
{:else if generateStep === 'amount_email'}
{#if generateType === 'stock'}

£0 — Blank Card for Stock

Creates an empty gift card. No delivery details needed.

{:else}
Customer

{#if selectedCustomer} {formatUserName( selectedCustomer.name, selectedCustomer.previousFirstName, selectedCustomer.previousLastName )} (Member) {:else if isGuestSelected} Walk-in Guest {/if}

{#if generateError} {generateError} {/if}
{#if generateType === 'code'}
{#if selectedCustomer?.email && !generateEmail.trim()}

Defaults to: {selectedCustomer.email}

{/if}
{/if} {/if}
{#if generateType === 'stock'} {:else} {/if} {:else if generateStep === 'payment'}
Total Amount {formatCurrency(Number(generateAmount))}
{#if isSquareConfigured()} {/if}
{#if onlineSquareAction === 'create'}
(onlineSquareCardReady = r)} />
{/if}
{:else if generateStep === 'cash_entry'}
Total Amount {formatCurrency(Number(generateAmount))}
(cashAmount = e.currentTarget.value)} />
{#if Number(cashAmount) > Number(generateAmount)}
Change due: {formatCurrency(Number(cashAmount) - Number(generateAmount))}
{/if}
{:else if generateStep === 'processing'}

{processingMessage}

{:else if generateStep === 'success'}

Payment Successful

{#if generateType === 'code'}

A copy of the code has been emailed.

{formatCardCode(paymentResult?.giftcard_code || paymentResult?.item_id || '')}

Write down or print this code for the customer.

{:else if generateType === 'account'}

✓ Gift card added to {selectedCustomer?.name || 'account'}

Balance is available immediately.

{/if}
{:else if generateStep === 'error'}

Payment Failed

{paymentError || 'An error occurred during transaction.'}

{/if}
Top Up Gift Card {#if topUpStep === 'choice'} Select how you would like to add funds to this card. {:else if topUpStep === 'amount'} Enter the amount to add to this card. {:else if topUpStep === 'payment'} Select the payment method. {:else if topUpStep === 'cash_entry'} Enter cash amount received. {/if} {#if topUpStep === 'choice'}

How would you like to add funds?

{:else if topUpStep === 'amount'}
{#if topUpError} {topUpError} {/if}
{:else if topUpStep === 'payment'}
Total Top Up {formatCurrency(Number(topUpAmount))}
{#if isSquareConfigured()} {/if}
{#if onlineSquareAction === 'topup'}
(onlineSquareCardReady = r)} />
{/if}
{:else if topUpStep === 'cash_entry'}
Total Top Up {formatCurrency(Number(topUpAmount))}
(cashAmount = e.currentTarget.value)} />
{#if Number(cashAmount) > Number(topUpAmount)}
Change due: {formatCurrency(Number(cashAmount) - Number(topUpAmount))}
{/if}
{:else if topUpStep === 'processing'}

{processingMessage}

{:else if topUpStep === 'success'}

Top Up Successful

✓ Gift card topped up successfully!

New balance is available immediately.

{:else if topUpStep === 'error'}

Top Up Failed

{paymentError || 'An error occurred during transaction.'}

{/if}
Transfer Balance Transfer funds from {formatCardCode(selectedCardId ?? '')} directly to another card.
{#if transferCodeError} {transferCodeError} {/if}
{#if transferAmountError} {transferAmountError} {/if}