refactor: admin edit and approval modals

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-29 16:08:05 +01:00
co-authored by Sisyphus
parent b2788b2269
commit a44972fbc6
4 changed files with 22 additions and 19 deletions
@@ -1,4 +1,5 @@
<script lang="ts">
import { SvelteDate } from 'svelte/reactivity';
import { authStore } from '$lib/stores/auth.svelte';
import { toast } from 'svelte-sonner';
import * as Modal from '$lib/components/ui/dialog';
@@ -64,7 +65,7 @@
function getBookingDateTime(): string {
if (!booking?.start_time) return '';
const d = new Date(booking.start_time);
const d = new SvelteDate(booking.start_time);
return d.toLocaleDateString('en-GB', {
weekday: 'long',
day: 'numeric',
@@ -147,12 +148,12 @@
function findOldestBooking(): { id: string; isCurrent: boolean } | null {
if (overlappingBookings.length === 0) return null;
const currentCreatedAt = new Date(booking.created_at).getTime();
const currentCreatedAt = new SvelteDate(booking.created_at).getTime();
let oldestId = booking.id;
let oldestTime = currentCreatedAt;
for (const ob of overlappingBookings) {
const obTime = new Date(ob.created_at).getTime();
const obTime = new SvelteDate(ob.created_at).getTime();
if (obTime < oldestTime) {
oldestTime = obTime;
oldestId = ob.id;
@@ -402,7 +403,7 @@
{ob.user?.full_name || 'Unknown'}
</div>
<div class="text-xs text-gray-500">
{new Date(ob.start_time).toLocaleDateString('en-GB', {
{new SvelteDate(ob.start_time).toLocaleDateString('en-GB', {
weekday: 'short',
day: 'numeric',
month: 'short',
@@ -430,7 +431,7 @@
{ob.status}
</span>
<div class="mt-1 text-xs text-gray-400">
{new Date(ob.created_at).toLocaleDateString('en-GB', {
{new SvelteDate(ob.created_at).toLocaleDateString('en-GB', {
day: 'numeric',
month: 'short',
hour: 'numeric',
@@ -2,6 +2,7 @@
import { authStore } from '$lib/stores/auth.svelte';
import { SvelteDate } from 'svelte/reactivity';
import { toast } from 'svelte-sonner';
import { formatDuration } from '$lib/utils/format';
import * as Modal from '$lib/components/ui/dialog';
import * as AlertDialog from '$lib/components/ui/alert-dialog';
import { Button } from '$lib/components/ui/button';
@@ -274,10 +275,10 @@
let maxAvailableDuration = $derived.by(() => {
if (!booking?.start_time || !nextAppointmentStart) return null;
const bookingStart = new Date(booking.start_time).getTime();
const bookingStart = new SvelteDate(booking.start_time).getTime();
const currentDurationMs = totalDuration * 60 * 1000;
const bookingEnd = bookingStart + currentDurationMs;
const nextStart = new Date(nextAppointmentStart).getTime();
const nextStart = new SvelteDate(nextAppointmentStart).getTime();
const availableMs = nextStart - bookingEnd;
return Math.max(0, Math.floor(availableMs / (60 * 1000)));
@@ -474,7 +475,7 @@
<div class="flex-1">
<div class="font-medium">{service.service_name}</div>
<div class="mt-1 text-sm text-gray-600">
{service.override_duration_minutes ?? service.duration_minutes} min • £{(service.override_price ?? service.price ?? 0).toFixed(2)}
{formatDuration(service.override_duration_minutes ?? service.duration_minutes ?? 0)} • £{(service.override_price ?? service.price ?? 0).toFixed(2)}
</div>
{#if service.override_price !== undefined || service.override_duration_minutes !== undefined}
<div class="text-xs text-amber-600">Modified</div>
@@ -523,7 +524,7 @@
</div>
<div class="mt-3 flex items-center justify-between border-t border-gray-200 pt-3 text-sm">
<span class="text-gray-600">Total: {totalDuration} min</span>
<span class="text-gray-600">Total: {formatDuration(totalDuration)}</span>
<span class="font-semibold">£{totalPrice.toFixed(2)}</span>
</div>
{/if}
@@ -536,7 +537,7 @@
Payments ({booking.payments.length})
</h3>
<div class="space-y-2">
{#each booking.payments as payment (payment.id)}
{#each booking.payments as payment, index (index)}
<div class="flex items-center justify-between rounded-md border border-gray-300 bg-white p-3">
<div class="flex-1">
<div class="font-medium">
@@ -561,7 +562,7 @@
{/if}
</div>
<div class="mt-1 text-xs text-gray-400">
{new Date(payment.created_at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })}
{new SvelteDate(payment.created_at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })}
</div>
</div>
{#if payment.status === 'completed'}
@@ -1,4 +1,5 @@
<script lang="ts">
import { SvelteDate } from 'svelte/reactivity';
import { authStore } from '$lib/stores/auth.svelte';
import { toast } from 'svelte-sonner';
import * as Modal from '$lib/components/ui/dialog';
@@ -51,7 +52,7 @@
let showDenyConfirm = $state(false);
function formatDateLine1(dateTimeString: string): string {
const d = new Date(dateTimeString);
const d = new SvelteDate(dateTimeString);
const dateStr = d.toLocaleDateString('en-GB', {
weekday: 'long',
day: 'numeric',
@@ -67,7 +68,7 @@
}
function formatDateLine2(dateTimeString: string, durationMinutes: number): string {
const d = new Date(dateTimeString);
const d = new SvelteDate(dateTimeString);
const endMinutes = d.getHours() * 60 + d.getMinutes() + durationMinutes;
const endH = Math.floor(endMinutes / 60);
const endM = endMinutes % 60;
@@ -248,7 +249,7 @@
<div>
<div class="mb-1 text-xs text-gray-500">Original</div>
<div class="space-y-2">
{#each editRequest.original.services as service}
{#each editRequest.original.services as service (service.id)}
{#if serviceDiff.removed.some((s) => s.id === service.id)}
<div class="flex items-start gap-2 rounded border border-red-200 bg-red-50 p-2">
<span class="mt-0.5 text-red-600 font-mono text-sm"></span>
@@ -278,7 +279,7 @@
<div>
<div class="mb-1 text-xs text-gray-500">Proposed</div>
<div class="space-y-2">
{#each editRequest.proposed.services as service}
{#each editRequest.proposed.services as service (service.id)}
{#if serviceDiff.added.some((s) => s.id === service.id)}
<div class="flex items-start gap-2 rounded border border-emerald-200 bg-emerald-50 p-2">
<span class="mt-0.5 text-emerald-600 font-mono text-sm">+</span>
@@ -33,7 +33,7 @@
let saving = $state(false);
let placeholder = $state<CalendarDate>(
new CalendarDate(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate())
new CalendarDate(new SvelteDate().getFullYear(), new SvelteDate().getMonth() + 1, new SvelteDate().getDate())
);
let selectedDate = $state<CalendarDate | undefined>(undefined);
let selectedTime = $state<string | null>(null);
@@ -237,7 +237,7 @@
loadingMonths = {};
loadingMonthKeys = new Set();
rescheduleAutoSelectDone = false;
placeholder = new CalendarDate(new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate());
placeholder = new CalendarDate(new SvelteDate().getFullYear(), new SvelteDate().getMonth() + 1, new SvelteDate().getDate());
}
async function reschedule() {