style: fix prettier formatting in 3 admin files
CI / Go vulnerabilities (push) Successful in 34s
CI / Tests (push) Successful in 1m34s
CI / Frontend lint & types (push) Failing after 1m52s
CI / Race detector (push) Successful in 3m33s

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-07-05 22:30:42 +01:00
co-authored by Sisyphus
parent 5f1f6c4b44
commit 9c0b189b73
3 changed files with 104 additions and 39 deletions
@@ -580,7 +580,11 @@
</select> </select>
</td> </td>
<td class="py-2"> <td class="py-2">
<select bind:value={row.end_time} disabled={!row.is_open} class="flex h-9 w-24 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"> <select
bind:value={row.end_time}
disabled={!row.is_open}
class="flex h-9 w-24 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(24) as _, hour (hour)} {#each Array(24) as _, hour (hour)}
{#each TIME15 as min (min)} {#each TIME15 as min (min)}
<option value="{String(hour).padStart(2, '0')}:{min}" <option value="{String(hour).padStart(2, '0')}:{min}"
@@ -56,7 +56,12 @@
defaultHours?: WorkingHourRow[]; defaultHours?: WorkingHourRow[];
} }
const { openUserModal, openBookingModal, rescheduleVersion = 0, defaultHours: defaultHoursProp }: Props = $props(); const {
openUserModal,
openBookingModal,
rescheduleVersion = 0,
defaultHours: defaultHoursProp
}: Props = $props();
const PAGE_SIZE = 5; const PAGE_SIZE = 5;
@@ -808,9 +813,9 @@
{:else if availableEndOptions.length === 0} {:else if availableEndOptions.length === 0}
<p class="text-sm text-gray-400">No available end time after selected start</p> <p class="text-sm text-gray-400">No available end time after selected start</p>
{:else} {:else}
<select <select
class="flex h-9 w-full rounded-md border border-input bg-background px-3 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" class="flex h-9 w-full rounded-md border border-input bg-background px-3 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"
bind:value={endSelectValue} bind:value={endSelectValue}
onchange={() => { onchange={() => {
const p = parseSelectValue(endSelectValue); const p = parseSelectValue(endSelectValue);
endHour = p.hour; endHour = p.hour;
+90 -34
View File
@@ -72,8 +72,23 @@
// =============== Lifted Data Fetching =============== // =============== Lifted Data Fetching ===============
// Fetch shared data once at page level to avoid duplicate API calls // Fetch shared data once at page level to avoid duplicate API calls
let defaultHours = $state<Array<{ weekday: number; startTime: string; endTime: string; isOpen: boolean }>>([]); let defaultHours = $state<
let services = $state<Array<{ id: string; name: string; description: string; price: number; duration_minutes: number; is_active: boolean; patch_test_duration_hours: number; minimum_age_required: number; created_at: string; created_by?: string }>>([]); Array<{ weekday: number; startTime: string; endTime: string; isOpen: boolean }>
>([]);
let services = $state<
Array<{
id: string;
name: string;
description: string;
price: number;
duration_minutes: number;
is_active: boolean;
patch_test_duration_hours: number;
minimum_age_required: number;
created_at: string;
created_by?: string;
}>
>([]);
// Responsive: reset section defaults when crossing the 768px breakpoint // Responsive: reset section defaults when crossing the 768px breakpoint
$effect(() => { $effect(() => {
@@ -268,14 +283,22 @@
<!-- 2. Customers & Bookings --> <!-- 2. Customers & Bookings -->
<div class="rounded-lg border"> <div class="rounded-lg border">
<button <button
class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.customers === 'expanded' ? 'rounded-t-lg' : 'rounded-lg'}" class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.customers ===
'expanded'
? 'rounded-t-lg'
: 'rounded-lg'}"
style="min-height: 44px;" style="min-height: 44px;"
onclick={() => sectionState.customers = sectionState.customers === 'expanded' ? 'collapsed' : 'expanded'} onclick={() =>
(sectionState.customers =
sectionState.customers === 'expanded' ? 'collapsed' : 'expanded')}
aria-expanded={sectionState.customers === 'expanded'} aria-expanded={sectionState.customers === 'expanded'}
> >
<span class="font-medium text-gray-900">Customers & Bookings</span> <span class="font-medium text-gray-900">Customers & Bookings</span>
<ChevronDownIcon <ChevronDownIcon
class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.customers === 'expanded' ? '' : '-rotate-90'}" class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.customers ===
'expanded'
? ''
: '-rotate-90'}"
/> />
</button> </button>
{#if sectionState.customers === 'expanded'} {#if sectionState.customers === 'expanded'}
@@ -291,36 +314,46 @@
<!-- 3. Services & Products --> <!-- 3. Services & Products -->
<div class="rounded-lg border"> <div class="rounded-lg border">
<button <button
class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.services === 'expanded' ? 'rounded-t-lg' : 'rounded-lg'}" class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.services ===
'expanded'
? 'rounded-t-lg'
: 'rounded-lg'}"
style="min-height: 44px;" style="min-height: 44px;"
onclick={() => sectionState.services = sectionState.services === 'expanded' ? 'collapsed' : 'expanded'} onclick={() =>
(sectionState.services = sectionState.services === 'expanded' ? 'collapsed' : 'expanded')}
aria-expanded={sectionState.services === 'expanded'} aria-expanded={sectionState.services === 'expanded'}
> >
<span class="font-medium text-gray-900">Services & Products</span> <span class="font-medium text-gray-900">Services & Products</span>
<ChevronDownIcon <ChevronDownIcon
class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.services === 'expanded' ? '' : '-rotate-90'}" class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.services ===
'expanded'
? ''
: '-rotate-90'}"
/> />
</button> </button>
{#if sectionState.services === 'expanded'} {#if sectionState.services === 'expanded'}
<div class="space-y-4 p-4"> <div class="space-y-4 p-4">
<CustomServicesManagement /> <CustomServicesManagement />
<PatchTestsManagement services={services} /> <PatchTestsManagement {services} />
<ServicesManagement services={services} onRefresh={async () => { <ServicesManagement
if (!browser) return; {services}
try { onRefresh={async () => {
const r = await fetch('/api/admin/services', { if (!browser) return;
headers: { try {
'Content-Type': 'application/json', const r = await fetch('/api/admin/services', {
Authorization: `Bearer ${authStore.currentToken}` headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${authStore.currentToken}`
}
});
if (r.ok) {
services = await r.json();
} }
}); } catch (err) {
if (r.ok) { console.error('Error refreshing services:', err);
services = await r.json();
} }
} catch (err) { }}
console.error('Error refreshing services:', err); />
}
}} />
</div> </div>
{/if} {/if}
</div> </div>
@@ -328,21 +361,29 @@
<!-- 4. Scheduling & Hours --> <!-- 4. Scheduling & Hours -->
<div class="rounded-lg border"> <div class="rounded-lg border">
<button <button
class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.scheduling === 'expanded' ? 'rounded-t-lg' : 'rounded-lg'}" class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.scheduling ===
'expanded'
? 'rounded-t-lg'
: 'rounded-lg'}"
style="min-height: 44px;" style="min-height: 44px;"
onclick={() => sectionState.scheduling = sectionState.scheduling === 'expanded' ? 'collapsed' : 'expanded'} onclick={() =>
(sectionState.scheduling =
sectionState.scheduling === 'expanded' ? 'collapsed' : 'expanded')}
aria-expanded={sectionState.scheduling === 'expanded'} aria-expanded={sectionState.scheduling === 'expanded'}
> >
<span class="font-medium text-gray-900">Scheduling & Hours</span> <span class="font-medium text-gray-900">Scheduling & Hours</span>
<ChevronDownIcon <ChevronDownIcon
class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.scheduling === 'expanded' ? '' : '-rotate-90'}" class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.scheduling ===
'expanded'
? ''
: '-rotate-90'}"
/> />
</button> </button>
{#if sectionState.scheduling === 'expanded'} {#if sectionState.scheduling === 'expanded'}
<div class="space-y-4 p-4"> <div class="space-y-4 p-4">
<TimeBlockers {openUserModal} {openBookingModal} {rescheduleVersion} defaultHours={defaultHours} /> <TimeBlockers {openUserModal} {openBookingModal} {rescheduleVersion} {defaultHours} />
<HolidayHours /> <HolidayHours />
<WeeklySchedule defaultHours={defaultHours} /> <WeeklySchedule {defaultHours} />
</div> </div>
{/if} {/if}
</div> </div>
@@ -350,14 +391,22 @@
<!-- 5. Promotions & Finance --> <!-- 5. Promotions & Finance -->
<div class="rounded-lg border"> <div class="rounded-lg border">
<button <button
class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.promotions === 'expanded' ? 'rounded-t-lg' : 'rounded-lg'}" class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.promotions ===
'expanded'
? 'rounded-t-lg'
: 'rounded-lg'}"
style="min-height: 44px;" style="min-height: 44px;"
onclick={() => sectionState.promotions = sectionState.promotions === 'expanded' ? 'collapsed' : 'expanded'} onclick={() =>
(sectionState.promotions =
sectionState.promotions === 'expanded' ? 'collapsed' : 'expanded')}
aria-expanded={sectionState.promotions === 'expanded'} aria-expanded={sectionState.promotions === 'expanded'}
> >
<span class="font-medium text-gray-900">Promotions & Finance</span> <span class="font-medium text-gray-900">Promotions & Finance</span>
<ChevronDownIcon <ChevronDownIcon
class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.promotions === 'expanded' ? '' : '-rotate-90'}" class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.promotions ===
'expanded'
? ''
: '-rotate-90'}"
/> />
</button> </button>
{#if sectionState.promotions === 'expanded'} {#if sectionState.promotions === 'expanded'}
@@ -371,14 +420,21 @@
<!-- 6. Business Settings --> <!-- 6. Business Settings -->
<div class="rounded-lg border"> <div class="rounded-lg border">
<button <button
class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.settings === 'expanded' ? 'rounded-t-lg' : 'rounded-lg'}" class="flex w-full items-center justify-between bg-gray-50 px-4 py-3 transition-colors hover:bg-gray-100 {sectionState.settings ===
'expanded'
? 'rounded-t-lg'
: 'rounded-lg'}"
style="min-height: 44px;" style="min-height: 44px;"
onclick={() => sectionState.settings = sectionState.settings === 'expanded' ? 'collapsed' : 'expanded'} onclick={() =>
(sectionState.settings = sectionState.settings === 'expanded' ? 'collapsed' : 'expanded')}
aria-expanded={sectionState.settings === 'expanded'} aria-expanded={sectionState.settings === 'expanded'}
> >
<span class="font-medium text-gray-900">Business Settings</span> <span class="font-medium text-gray-900">Business Settings</span>
<ChevronDownIcon <ChevronDownIcon
class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.settings === 'expanded' ? '' : '-rotate-90'}" class="h-4 w-4 text-gray-500 transition-transform duration-200 {sectionState.settings ===
'expanded'
? ''
: '-rotate-90'}"
/> />
</button> </button>
{#if sectionState.settings === 'expanded'} {#if sectionState.settings === 'expanded'}