fix: match date/time picker style, fix two-row footer layout

- Replace Modal.Footer with plain div to avoid bits-ui class merging (sm:flex-row override)
- DatePicker wrapped in flex items-center justify-center matching BookingCreateModal
- Time picker uses Button elements with fuchsia selection (hover:bg-fuchsia-50, bg-fuchsia-100)
- Generate 30-min time slots from 08:00-18:00 matching salon hours
- Reschedule form container uses bg-gray-50 matching other sections
- Footer: two rows with flex-1 buttons for equal width
This commit is contained in:
2026-05-08 22:27:40 +01:00
parent 8b539afccc
commit 6d95eb6dcf
@@ -146,6 +146,30 @@
return jsDate < todayStart;
}
function formatTime(time: string): string {
const parts = time.split(':').map(Number);
const hours = parts[0];
const minutes = parts.length > 1 ? parts[1] : 0;
if (hours === 12 && minutes === 0) return 'Noon';
if (hours === 0 && minutes === 0) return 'Midnight';
const period = hours >= 12 ? 'PM' : 'AM';
const displayHours = hours % 12 || 12;
return `${displayHours}:${minutes.toString().padStart(2, '0')} ${period}`;
}
function generateTimeSlots(): string[] {
const slots: string[] = [];
for (let h = 8; h <= 18; h++) {
for (let m = 0; m < 60; m += 30) {
if (h === 18 && m > 0) break;
slots.push(`${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`);
}
}
return slots;
}
const timeSlots = generateTimeSlots();
async function submitReschedule() {
if (!selectedBooking || !rescheduleDate || !rescheduleTime) return;
rescheduleSubmitting = true;
@@ -427,70 +451,79 @@
{/if}
{#if showRescheduleForm}
<div class="rounded-lg border border-amber-200 bg-amber-50 p-4">
<h3 class="mb-3 text-sm font-semibold tracking-wide text-amber-700 uppercase">
<div class="rounded-lg border border-gray-200 bg-gray-50 p-4">
<h3 class="mb-3 text-sm font-semibold tracking-wide text-gray-600 uppercase">
Request Reschedule
</h3>
<div class="space-y-4">
<div class="flex items-center justify-center">
<DatePicker
date={rescheduleDate}
placeholder={reschedulePlaceholder}
minValue={minDate}
maxValue={maxCalendarDate}
isDateUnavailable={isDateUnavailable}
onchange={(d) => { rescheduleDate = d; }}
onchange={(d) => { rescheduleDate = d; rescheduleTime = ''; }}
onPlaceholderChange={(p) => { reschedulePlaceholder = p; }}
/>
</div>
<div class="space-y-2">
<Label.Root for="reschedule-time">Preferred Time *</Label.Root>
<input
id="reschedule-time"
type="time"
bind:value={rescheduleTime}
class="flex h-9 w-full rounded-md border border-gray-300 bg-transparent px-3 py-1 text-sm shadow-sm"
/>
<p class="text-xs text-gray-500">We'll confirm the exact time based on availability</p>
{#if rescheduleDate}
<div class="no-scrollbar mt-2 flex max-h-40 w-full scroll-pb-6 flex-col gap-4 overflow-y-auto border-t pt-4">
<div class="grid justify-center gap-2 text-sm text-gray-600">
{rescheduleDate.toDate(getLocalTimeZone()).toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'short' })}
</div>
<div class="grid gap-2">
{#each timeSlots as slot (slot)}
<Button
variant="outline"
onclick={() => { rescheduleTime = slot; }}
class="w-full hover:bg-fuchsia-50 {rescheduleTime === slot ? 'bg-fuchsia-100' : ''}"
>
{formatTime(slot)}
</Button>
{/each}
</div>
</div>
{/if}
<div class="space-y-2">
<Label.Root for="reschedule-notes">Reason (optional)</Label.Root>
<Textarea.Root
id="reschedule-notes"
bind:value={rescheduleNotes}
placeholder="Tell us why you need to reschedule"
rows={2}
/>
</div>
<div class="mt-4 space-y-2">
<Label.Root for="reschedule-notes">Reason (optional)</Label.Root>
<Textarea.Root
id="reschedule-notes"
bind:value={rescheduleNotes}
placeholder="Tell us why you need to reschedule"
rows={2}
/>
</div>
<div class="flex gap-2">
<Button
size="sm"
onclick={submitReschedule}
disabled={!isRescheduleValid || rescheduleSubmitting}
>
{rescheduleSubmitting ? 'Submitting...' : 'Submit Request'}
</Button>
<Button
size="sm"
variant="outline"
onclick={() => {
showRescheduleForm = false;
rescheduleDate = undefined;
rescheduleTime = '';
rescheduleNotes = '';
}}
>
Cancel
</Button>
</div>
<div class="mt-4 flex gap-2">
<Button
size="sm"
onclick={submitReschedule}
disabled={!isRescheduleValid || rescheduleSubmitting}
>
{rescheduleSubmitting ? 'Submitting...' : 'Submit Request'}
</Button>
<Button
size="sm"
variant="outline"
onclick={() => {
showRescheduleForm = false;
rescheduleDate = undefined;
rescheduleTime = '';
rescheduleNotes = '';
}}
>
Cancel
</Button>
</div>
</div>
{/if}
</div>
{/if}
<Modal.Footer class="flex flex-col gap-2">
<div class="flex flex-col gap-2 border-t px-4 py-3">
<div class="flex gap-2">
{#if isCancellable}
<Button
@@ -535,7 +568,7 @@
{/if}
<Button size="sm" class="flex-1" onclick={() => (open = false)}>Close</Button>
</div>
</Modal.Footer>
</div>
</Modal.Content>
</Modal.Root>