fix: correct prop names in Svelte templates after a11y cleanup

This commit is contained in:
2026-07-10 12:27:08 +01:00
parent bee2ce81e6
commit 19d1d8dd47
20 changed files with 274 additions and 328 deletions
+1 -41
View File
@@ -22,7 +22,6 @@ import (
)
func TestSPV_VATAppliedAtTillSale(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -91,7 +90,6 @@ func TestSPV_VATAppliedAtTillSale(t *testing.T) {
}
func TestMPV_NoVATAtTillSale(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -154,7 +152,6 @@ func TestMPV_NoVATAtTillSale(t *testing.T) {
}
func TestMPV_VATAppliedAtRedemption(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -239,7 +236,6 @@ func TestMPV_VATAppliedAtRedemption(t *testing.T) {
}
func TestSPV_NoVATAtRedemption(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -315,7 +311,6 @@ func TestSPV_NoVATAtRedemption(t *testing.T) {
}
}
func TestVAT_SkippedWhenNotRegistered(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = FALSE, voucher_type = 'SPV'`)
@@ -378,7 +373,6 @@ func TestVAT_SkippedWhenNotRegistered(t *testing.T) {
}
func TestEnableVATRegistration(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = FALSE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -469,7 +463,6 @@ func TestEnableVATRegistration(t *testing.T) {
}
func TestCashBookingPayment_VATApplied(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -542,7 +535,6 @@ func TestCashBookingPayment_VATApplied(t *testing.T) {
}
func TestCashBookingPayment_NoVATWhenNotRegistered(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
// Explicitly not registered (default)
@@ -600,7 +592,6 @@ func TestCashBookingPayment_NoVATWhenNotRegistered(t *testing.T) {
}
func TestOnTheHouseTillSale_NoVATEvenIfRegistered(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -658,7 +649,6 @@ func TestOnTheHouseTillSale_NoVATEvenIfRegistered(t *testing.T) {
}
func TestGetVATConfig(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 5.00, voucher_type = 'MPV'`)
@@ -693,7 +683,6 @@ func TestGetVATConfig(t *testing.T) {
}
func TestApplyVATToBookingPayment_Direct(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -754,7 +743,6 @@ func TestApplyVATToBookingPayment_Direct(t *testing.T) {
}
func TestApplyVATToTillSale_Direct(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -806,7 +794,6 @@ func TestApplyVATToTillSale_Direct(t *testing.T) {
}
func TestVAT_Idempotency_ApplyTwice(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -875,7 +862,6 @@ func TestVAT_Idempotency_ApplyTwice(t *testing.T) {
}
func TestVAT_DifferentRates(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
// Test with 5% reduced VAT rate
@@ -938,7 +924,6 @@ func TestVAT_DifferentRates(t *testing.T) {
}
func TestPaymentSummary_VATAggregates(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -1033,7 +1018,6 @@ func TestPaymentSummary_VATAggregates(t *testing.T) {
}
func TestBuyGiftCard_SPV_VATApplied(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -1112,7 +1096,6 @@ func TestBuyGiftCard_SPV_VATApplied(t *testing.T) {
}
func TestVAT_ToggleLifecycle(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = FALSE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -1252,7 +1235,6 @@ func TestVAT_ToggleLifecycle(t *testing.T) {
}
func TestVAT_Refund_VATInclusiveCashPayment(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -1339,7 +1321,6 @@ func TestVAT_Refund_VATInclusiveCashPayment(t *testing.T) {
}
func TestSPV_FullLifecycle_BuyAndRedeem(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -1451,7 +1432,6 @@ func TestSPV_FullLifecycle_BuyAndRedeem(t *testing.T) {
}
func TestMPV_FullLifecycle_BuyAndRedeem(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -1564,7 +1544,6 @@ func TestMPV_FullLifecycle_BuyAndRedeem(t *testing.T) {
}
func TestVAT_TopupGiftCard_NoVATOnTopup(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -1638,7 +1617,6 @@ func TestVAT_TopupGiftCard_NoVATOnTopup(t *testing.T) {
}
func TestVAT_RemainingBalanceWithVAT(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -1756,7 +1734,6 @@ func TestVAT_RemainingBalanceWithVAT(t *testing.T) {
}
func TestVAT_GiftCardCRUD_DoesNotInterfere(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -1845,7 +1822,6 @@ func TestVAT_GiftCardCRUD_DoesNotInterfere(t *testing.T) {
// TestMPV_Topup_NoVAT verifies a gift card topup with voucher_type=MPV does not
// apply VAT at sale.
func TestMPV_Topup_NoVAT(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -1919,7 +1895,6 @@ func TestMPV_Topup_NoVAT(t *testing.T) {
// Uses a booking that has already started so buildSplitRecords returns a
// single payment record, making VAT assertion straightforward.
func TestCreateBookingPayment_VATApplied(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -1989,7 +1964,6 @@ func TestCreateBookingPayment_VATApplied(t *testing.T) {
// TestTillSale_SavedCard_SPV_VATApplied verifies that a till sale with
// saved_card payment method applies VAT for SPV.
func TestTillSale_SavedCard_SPV_VATApplied(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -2068,7 +2042,6 @@ func TestTillSale_SavedCard_SPV_VATApplied(t *testing.T) {
// get double-taxed. The voucher_type_at_purchase stored on the card at
// creation time is used at redemption, not the current business_settings.
func TestVoucherToggle_SPVPurchase_MPVRedeem(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'SPV'`)
@@ -2182,7 +2155,6 @@ func TestVoucherToggle_SPVPurchase_MPVRedeem(t *testing.T) {
// TestApplyVATToTillSale_MPV verifies ApplyVATToTillSale has no effect when
// voucher_type is MPV.
func TestApplyVATToTillSale_MPV(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -2229,7 +2201,6 @@ func TestApplyVATToTillSale_MPV(t *testing.T) {
// switching to SPV still gets VAT at redemption — because the stored
// voucher_type_at_purchase is MPV, overriding the current business_settings.
func TestVoucherToggle_MPVPurchase_SPVRedeem(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -2342,7 +2313,6 @@ func TestVoucherToggle_MPVPurchase_SPVRedeem(t *testing.T) {
// TestLegacyGiftCard_NullVoucherType defaults NULL voucher_type_at_purchase
// to SPV behavior — no VAT at redemption.
func TestLegacyGiftCard_NullVoucherType(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00, voucher_type = 'MPV'`)
@@ -2415,7 +2385,6 @@ func TestLegacyGiftCard_NullVoucherType(t *testing.T) {
// user's account balance (usedBalance=true), no VAT is ever applied —
// it was already paid when the card was originally purchased.
func TestUsedBalance_NoVATRegardless(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
// Set MPV — even with MPV, usedBalance should NOT have VAT
@@ -2495,7 +2464,6 @@ func TestUsedBalance_NoVATRegardless(t *testing.T) {
// TestVAT_DiscountPayment_NoVAT verifies that discount payments never get VAT
// applied, even when the business is VAT-registered.
func TestVAT_DiscountPayment_NoVAT(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -2603,7 +2571,6 @@ func TestVAT_DiscountPayment_NoVAT(t *testing.T) {
// TestVAT_SplitPayments verifies VAT is correctly partitioned across split
// records when a single Square payment is split into deposit + balance.
func TestVAT_SplitPayments(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -2712,7 +2679,6 @@ func TestVAT_SplitPayments(t *testing.T) {
// TestEnableVATRegistration_TillSales verifies that enable_vat_registration
// also retroactively applies VAT to completed till_sales records.
func TestEnableVATRegistration_TillSales(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
adminID, err := fixtures.CreateTestAdminUser(tx)
@@ -2775,7 +2741,6 @@ func TestEnableVATRegistration_TillSales(t *testing.T) {
}
func TestGetVATConfig_WithTxQuerier(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 5.00, voucher_type = 'MPV'`)
@@ -2800,7 +2765,6 @@ func TestGetVATConfig_WithTxQuerier(t *testing.T) {
}
func TestGetVATConfig_DbConnQuerier(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 8.00, voucher_type = 'SPV'`)
@@ -2826,7 +2790,6 @@ func TestGetVATConfig_DbConnQuerier(t *testing.T) {
}
func TestApplyVATToBookingPayment_DefensiveCheck(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -2878,7 +2841,6 @@ func TestApplyVATToBookingPayment_DefensiveCheck(t *testing.T) {
}
func TestApplyVATToBookingPayment_OnTheHouse_Skip(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -3302,8 +3264,7 @@ func TestVAT_RoundingConsistency(t *testing.T) {
for _, tt := range edgeCases {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
if err != nil {
@@ -3406,7 +3367,6 @@ func TestVAT_RoundingConsistency(t *testing.T) {
// including purchase, redemption, and toggle scenarios.
func TestVAT_DiscountAndCashPayment_RemainingBalance(t *testing.T) {
t.Parallel()
ctx, tx := testutils.SetupTestTx(t)
_, err := tx.Exec(ctx, `UPDATE business_settings SET is_vat_registered = TRUE, default_vat_rate = 20.00`)
@@ -570,7 +570,7 @@
workingHours = { ...workingHours, ...whMap };
availableHours = { ...availableHours, ...ahMap };
}
} catch {
} catch {
toast.error('Failed to load availability');
} finally {
loadingAvailableHours = false;
@@ -1144,7 +1144,7 @@
{#if loadingUsers}
<div class="space-y-2 p-2">
{#each Array(3) as __, i (i)}
{__}
{__}
<Skeleton class="h-10 w-full" />
{__}
{/each}
@@ -1258,7 +1258,7 @@
{#if loadingServices}
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
{#each Array(4) as __, i (i)}
{__}
{__}
<Skeleton class="h-28 w-full" />
{__}
{/each}
@@ -1290,10 +1290,10 @@
/>
<Button variant="outline" size="sm" onclick={fetchCustomServices}>Search</Button>
</div>
{#if loadingCustomServices}
{#if loadingCustomServices}
<div class="space-y-2">
{#each Array(3) as __, i (i)}
{__}
{__}
<Skeleton class="h-10 w-full" />
{__}
{/each}
@@ -251,7 +251,7 @@
summary.total_user_balances = data.total_user_balances;
cards = data.gift_cards;
balances = data.user_balances;
totalBalanceRecords = data.ub_total ?? data.user_balances?.length ?? 0;
totalBalanceRecords = data.ub_total ?? data.user_balances?.length ?? 0;
currentPage = data.page;
totalPages = data.totalPages;
} else {
@@ -1253,12 +1253,12 @@
</thead>
<tbody>
{#if loading}
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-36" /></td>
<td class="py-3"><Skeleton class="h-4 w-44" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-36" /></td>
<td class="py-3"><Skeleton class="h-4 w-44" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
</tr>
{:else if balances.length === 0}
<tr>
<td colspan="4" class="py-8 text-center text-gray-500">
@@ -1285,7 +1285,7 @@
<div class="grid gap-4 md:hidden">
{#if loading}
{#each Array(2) as __, i (i)}
{__}
{__}
<div class="space-y-3 rounded-lg border p-4">
<Skeleton class="h-4 w-36" />
<Skeleton class="h-4 w-full" />
@@ -1337,28 +1337,27 @@
</thead>
<tbody>
{#if loadingExpired}
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-16" /></td>
<td class="py-3"><Skeleton class="h-4 w-24" /></td>
<td class="py-3"><Skeleton class="h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-24" /></td>
</tr>
{:else if expiredBalances.length === 0}
<tr>
<td colspan="5" class="py-8 text-center text-gray-500">
@@ -1414,7 +1413,7 @@
<div class="grid gap-4 md:hidden">
{#if loadingExpired}
{#each Array(2) as __, i (i)}
{__}
{__}
<div class="space-y-3 rounded-lg border p-4">
<Skeleton class="h-4 w-36" />
<Skeleton class="h-4 w-full" />
@@ -297,31 +297,30 @@
</thead>
<tbody>
{#if loading}
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3"><Skeleton class="mx-auto h-4 w-12" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
{:else}
{#each patchTests as pt (pt.id)}
<tr class="border-b hover:bg-gray-50">
@@ -366,46 +366,45 @@
</thead>
<tbody>
{#if servicesLoading}
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
<tr class="border-b">
<td class="py-3"><Skeleton class="h-4 w-32" /></td>
<td class="py-3"><Skeleton class="h-4 w-48" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-16" /></td>
<td class="py-3 text-right"><Skeleton class="ml-auto h-4 w-20" /></td>
<td class="py-3 text-center"><Skeleton class="mx-auto h-4 w-16" /></td>
<td class="py-3 text-center">
<div class="flex justify-center gap-2">
<Skeleton class="h-8 w-16" />
<Skeleton class="h-8 w-16" />
</div>
</td>
</tr>
{:else}
{#each services as service (service.id)}
<tr class="border-b hover:bg-gray-50">
@@ -667,7 +667,7 @@
Prev
</Button>
{#each Array(totalPages) as __, i (i)}
{__}
{__}
<Button
variant={currentPage === i + 1 ? 'default' : 'outline'}
size="sm"
@@ -508,7 +508,7 @@
</h3>
<div class="space-y-2">
{#each Array(5) as __, i (i)}
{__}
{__}
<div class="h-10 animate-pulse rounded-md bg-gray-200"></div>
{/each}
</div>
@@ -177,7 +177,7 @@
<div class="mt-3 max-h-60 space-y-2 overflow-y-auto">
{#if initialLoad}
{#each Array(3) as __, i (i)}
{__}
{__}
<div class="rounded bg-gray-50 p-2">
<Skeleton class="mb-1 h-4 w-32" />
<Skeleton class="h-3 w-48" />
@@ -207,10 +207,7 @@
const dayEndTimeVal = minutesToTime(dayEndMinutesVal);
if (shouldApplyLunchProtection(dayStartTimeVal, dayEndTimeVal)) {
const { windowStart } = calculateMiddleWindow(
dayStartTimeVal,
dayEndTimeVal
);
const { windowStart } = calculateMiddleWindow(dayStartTimeVal, dayEndTimeVal);
const lunchWalkerBlocker = {
startTime: minutesToTime(windowStart),
endTime: minutesToTime(windowStart + 60)
@@ -468,6 +465,5 @@
maxSlotDuration={reservedDuration}
availableStartTime={reservedStartTime ?? undefined}
{reservationExpiresAt}
_onclose={handleModalClose}
/>
{/if}
@@ -39,7 +39,7 @@
maxSlotDuration = 0,
availableStartTime,
reservationExpiresAt,
onBookingCreated,
onBookingCreated
}: Props = $props();
// =============== State ===============
@@ -722,7 +722,7 @@
{#if loadingUsers}
<div class="space-y-2 p-2">
{#each Array(3) as __, i (i)}
{__}
{__}
<Skeleton class="h-10 w-full" />
{/each}
</div>
@@ -804,7 +804,6 @@
bind:value={guestPhone}
bind:error={guestPhoneError}
placeholder="07700 900000"
_required={false}
/>
</div>
<p class="rounded-lg bg-yellow-50 p-3 text-sm text-yellow-800">
@@ -836,7 +835,7 @@
{#if loadingServices}
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
{#each Array(4) as __, i (i)}
{__}
{__}
<Skeleton class="h-28 w-full" />
{/each}
</div>
@@ -870,7 +869,7 @@
{#if loadingCustomServices}
<div class="space-y-2">
{#each Array(3) as __, i (i)}
{__}
{__}
<Skeleton class="h-10 w-full" />
{/each}
</div>
@@ -423,147 +423,146 @@
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
<tr>
<td class="px-4 py-4">
<div class="flex items-center gap-2">
<Skeleton class="h-8 w-8 rounded-full" />
<Skeleton class="h-4 w-20" />
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
</div>
</td>
<td class="px-4 py-4 text-center">
<Skeleton class="mx-auto h-6 w-16 rounded-full" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4">
<Skeleton class="h-4 w-20" />
</td>
<td class="px-4 py-4 text-right">
<Skeleton class="ml-auto h-4 w-12" />
</td>
</tr>
</tbody>
</table>
</div>
@@ -620,34 +619,34 @@
<Checkbox bind:checked={row.is_open} />
</td>
<td class="py-2">
<select
bind:value={row.start_time}
disabled={!row.is_open}
class="flex h-9 max-w-[70px] rounded-md border border-input bg-background px-2 py-1 text-sm shadow-xs ring-offset-background transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
>
{#each Array.from({ length: 24 }, (_, hour) => hour) as hour (hour)}
{#each TIME15 as min (min)}
<option value="{String(hour).padStart(2, '0')}:{min}"
>{String(hour).padStart(2, '0')}:{min}</option
>
{/each}
<select
bind:value={row.start_time}
disabled={!row.is_open}
class="flex h-9 max-w-[70px] rounded-md border border-input bg-background px-2 py-1 text-sm shadow-xs ring-offset-background transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
>
{#each Array.from({ length: 24 }, (_, hour) => hour) as hour (hour)}
{#each TIME15 as min (min)}
<option value="{String(hour).padStart(2, '0')}:{min}"
>{String(hour).padStart(2, '0')}:{min}</option
>
{/each}
</select>
{/each}
</select>
</td>
<td class="py-2">
<select
bind:value={row.end_time}
disabled={!row.is_open}
class="flex h-9 max-w-[70px] rounded-md border border-input bg-background px-2 py-1 text-sm shadow-xs ring-offset-background transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
>
{#each Array.from({ length: 24 }, (_, hour) => hour) as hour (hour)}
{#each TIME15 as min (min)}
<option value="{String(hour).padStart(2, '0')}:{min}"
>{String(hour).padStart(2, '0')}:{min}</option
>
{/each}
<select
bind:value={row.end_time}
disabled={!row.is_open}
class="flex h-9 max-w-[70px] rounded-md border border-input bg-background px-2 py-1 text-sm shadow-xs ring-offset-background transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
>
{#each Array.from({ length: 24 }, (_, hour) => hour) as hour (hour)}
{#each TIME15 as min (min)}
<option value="{String(hour).padStart(2, '0')}:{min}"
>{String(hour).padStart(2, '0')}:{min}</option
>
{/each}
</select>
{/each}
</select>
</td>
</tr>
{/each}
@@ -219,15 +219,14 @@
return;
}
try {
// Check for pending bookings
const pendingResp = await apiFetch('/api/bookings?status=pending&perPage=1');
if (pendingResp.ok) {
const data = await pendingResp.json();
if (data.bookings && data.bookings.length > 0) {
hasActiveBooking = true;
return;
hasActiveBooking = true;
return;
}
}
@@ -75,7 +75,7 @@
async function fetchCustomerGiftCardBalance() {
const targetUserId = booking.user_id ?? booking.user?.id;
if (!targetUserId) return;
try {
try {
const res = await apiFetch(`/api/admin/users/${targetUserId}/giftcard-balance`);
if (res.ok) {
const data = await res.json();
@@ -61,8 +61,6 @@
let newCardCVC = $state('');
let saveCardForFuture = $state(false);
function parseExpiryParts(value: string): { month: number; year: number } | null {
if (!/^\d{2}\/\d{2}$/.test(value)) return null;
const [monthStr, yearStr] = value.split('/');
@@ -688,7 +688,7 @@
{#if loading}
<div class="space-y-3">
{#each Array(5) as __, i (i)}
{__}
{__}
<div class="flex items-center gap-3 rounded-lg border p-3 sm:gap-4">
<Skeleton class="h-4 w-[45px] sm:w-[60px] lg:w-[80px]" />
<Skeleton class="h-10 w-1 shrink-0" />
+4 -4
View File
@@ -1519,7 +1519,7 @@
{#if loadingUser}
{#each Array(6) as __, i (i)}
{__}
{__}
<Skeleton class="h-12 w-full" />
{/each}
{:else if userData}
@@ -1719,7 +1719,7 @@
<div class="grid grid-cols-5 gap-3 sm:grid-cols-10">
{#each Array(10) as __, i (i)}
{__}
{__}
{@const slotNum = i + 1}
{@const rot = ((slotNum * 37 + 13) % 7) - 3}
{#if slotNum <= (stamps > 0 ? stamps % 10 || 10 : 0)}
@@ -1793,7 +1793,7 @@
<Card.Content class="space-y-2">
{#if loadingUpcoming}
{#each Array(3) as __, i (i)}
{__}
{__}
<Skeleton class="h-16 w-full" />
{/each}
{:else}
@@ -1848,7 +1848,7 @@
<Card.Content class="space-y-2">
{#if loadingPast}
{#each Array(5) as __, i (i)}
{__}
{__}
<Skeleton class="h-16 w-full" />
{/each}
{:else if pastBookings.length === 0}
@@ -368,7 +368,7 @@
<div class="mx-auto max-w-3xl space-y-4 p-6 pt-24">
<Skeleton class="h-8 w-48" />
{#each Array(5) as __, i (i)}
{__}
{__}
<Skeleton class="h-24 w-full" />
{/each}
</div>
-1
View File
@@ -486,7 +486,6 @@
bind:value={formData.phone}
bind:error={validationErrors.phone}
placeholder="07123 456789 or +44 7123 456789"
_required
/>
</div>
+1 -1
View File
@@ -63,7 +63,7 @@
{#if servicesLoading}
<div class="space-y-4">
{#each Array(5) as __, i (i)}
{__}
{__}
<Card.Root class="shadow-sm">
<Card.Content>
<div class="flex items-start justify-between">
-1
View File
@@ -147,7 +147,6 @@
<!-- Current/Next Appointment Card (Full Width) -->
<CurrentAppointment
_openBookingModal={openBookingModal}
{openEditBookingModal}
{openUserModal}
/>