fix: booking duration calculation, tip page auth, and UI polish across frontend

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-25 18:04:43 +01:00
co-authored by Sisyphus
parent 2a8f04e7b3
commit f553ebad99
14 changed files with 468 additions and 225 deletions
@@ -18,8 +18,11 @@
let showApprovalModal = $state(false);
// Calculate total duration from services
// IMPORTANT: Use override_duration_minutes when present — services may have been
// customised at booking time (discounts, extended sessions). Showing base values
// misleads admins about what was actually booked.
let totalDuration = $derived(
selectedBooking?.services?.reduce((sum, service) => sum + (service.duration_minutes || 0), 0) ||
selectedBooking?.services?.reduce((sum, service) => sum + (service.override_duration_minutes ?? service.duration_minutes ?? 0), 0) ||
0
);
@@ -278,8 +281,8 @@
<div class="mt-1 text-sm text-gray-600">{service.service_description}</div>
{/if}
<div class="mt-2 flex items-center justify-between text-sm">
<span class="text-gray-600">{service.duration_minutes} min</span>
<span class="font-semibold">£{service.price?.toFixed(2) || '0.00'}</span>
<span class="text-gray-600">{service.override_duration_minutes ?? service.duration_minutes} min</span>
<span class="font-semibold">£{(service.override_price ?? service.price ?? 0).toFixed(2)}</span>
</div>
</div>
{/each}
@@ -410,9 +413,15 @@
<div class="flex items-start justify-between">
<div class="flex-1">
<div class="flex items-center gap-2">
<span class="font-medium capitalize"
>{payment.payment_method.replace('_', ' ')}</span
>
<span class="font-medium">
{#if payment.payment_method === 'online_square'}Online
{:else if payment.payment_method === 'in_person_card'}Card Machine
{:else if payment.payment_method === 'cash'}Cash
{:else if payment.payment_method === 'giftcard'}Gift Card
{:else if payment.payment_method === 'discount'}Discount
{:else}{payment.payment_method.replace('_', ' ')}
{/if}
</span>
<span
class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium
{payment.status === 'completed'
@@ -428,7 +437,10 @@
</div>
<div class="mt-1 text-xs text-gray-500">
{payment.payment_type.charAt(0).toUpperCase() +
payment.payment_type.slice(1)}
payment.payment_type.slice(1)} payment
{#if payment.card_last4}
, Card ending in {payment.card_last4}
{/if}
</div>
{#if payment.vendor_code || payment.invoice_number}
<div class="mt-1 text-xs text-gray-500">
@@ -7,6 +7,7 @@
import { Button } from '$lib/components/ui/button';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Checkbox } from '$lib/components/ui/checkbox';
import { Separator } from '$lib/components/ui/separator';
import * as Modal from '$lib/components/ui/dialog';
import * as AlertDialog from '$lib/components/ui/alert-dialog';
@@ -523,11 +524,7 @@
<tr class="border-t">
<td class="py-2">{weekdayLabel(row.weekday)}</td>
<td class="py-2">
<input
type="checkbox"
bind:checked={row.is_open}
class="h-4 w-4 rounded border-gray-300 bg-gray-100"
/>
<Checkbox bind:checked={row.is_open} />
</td>
<td class="py-2">
<Input
@@ -7,6 +7,7 @@
import { Button } from '$lib/components/ui/button';
import * as Card from '$lib/components/ui/card';
import { Input } from '$lib/components/ui/input';
import { Checkbox } from '$lib/components/ui/checkbox';
import * as Modal from '$lib/components/ui/dialog';
import * as AlertDialog from '$lib/components/ui/alert-dialog';
import { Skeleton } from '$lib/components/ui/skeleton';
@@ -475,11 +476,7 @@
<tr class="border-t">
<td class="py-2 text-sm">{weekdayLabel(row.weekday)}</td>
<td class="py-2">
<input
type="checkbox"
bind:checked={row.is_open}
class="h-4 w-4 rounded border-gray-300 bg-gray-100 text-primary focus:ring-primary"
/>
<Checkbox bind:checked={row.is_open} />
</td>
<td class="py-2">
<Input