Add navigation for previous and next days in public booking
This commit is contained in:
@@ -108,6 +108,8 @@ type BookingShellProps = {
|
||||
onSelectDate: (date: string) => void;
|
||||
onPreviousDays: () => void;
|
||||
onNextDays: () => void;
|
||||
onPreviousDay: () => void;
|
||||
onNextDay: () => void;
|
||||
onSelectSport: (sportId: string) => void;
|
||||
onSelectCourt: (courtId: string) => void;
|
||||
onSelectSlot: (slot: SelectedSlot) => void;
|
||||
@@ -527,9 +529,6 @@ function PublicBookingDesktop(props: BookingShellProps) {
|
||||
sportSelectionRequired,
|
||||
errorMessage,
|
||||
autoAdjustedDateNotice,
|
||||
onPreviousDays,
|
||||
onNextDays,
|
||||
onSelectDate,
|
||||
onSelectSport,
|
||||
onSelectCourt,
|
||||
onSelectSlot,
|
||||
@@ -538,6 +537,8 @@ function PublicBookingDesktop(props: BookingShellProps) {
|
||||
const currentStep = getStep(selectedSlot, props.form.formState.isValid);
|
||||
const completedSteps = getCompletedSteps(selectedSlot, props.form.formState.isValid);
|
||||
const selectedDay = dayOptions.find((option) => option.value === selectedDate);
|
||||
const currentDayIndex = dayOptions.findIndex((option) => option.value === selectedDate);
|
||||
const canGoBackButton = canGoBack || currentDayIndex > 0;
|
||||
|
||||
return (
|
||||
<PublicBookingPageChrome
|
||||
@@ -635,9 +636,9 @@ function PublicBookingDesktop(props: BookingShellProps) {
|
||||
<button
|
||||
type="button"
|
||||
className="flex size-11 items-center justify-center border-r border-white/10 transition hover:bg-white/[0.06]"
|
||||
onClick={onPreviousDays}
|
||||
disabled={!canGoBack}
|
||||
aria-label="Mostrar días anteriores"
|
||||
onClick={props.onPreviousDay}
|
||||
disabled={!canGoBackButton}
|
||||
aria-label="Día anterior"
|
||||
>
|
||||
<ChevronLeft className="size-5" />
|
||||
</button>
|
||||
@@ -648,8 +649,8 @@ function PublicBookingDesktop(props: BookingShellProps) {
|
||||
<button
|
||||
type="button"
|
||||
className="flex size-11 items-center justify-center border-l border-white/10 transition hover:bg-white/[0.06]"
|
||||
onClick={onNextDays}
|
||||
aria-label="Mostrar próximos días"
|
||||
onClick={props.onNextDay}
|
||||
aria-label="Día siguiente"
|
||||
>
|
||||
<ChevronRight className="size-5" />
|
||||
</button>
|
||||
@@ -670,44 +671,6 @@ function PublicBookingDesktop(props: BookingShellProps) {
|
||||
<CourtDetails court={selectedCourt} />
|
||||
<SelectedSlotCard {...props} />
|
||||
</div>
|
||||
|
||||
<Panel className="p-5">
|
||||
<h3 className="font-semibold">Cambiá de día</h3>
|
||||
<div className="mt-4 grid grid-cols-[36px_repeat(7,minmax(0,1fr))_36px] items-stretch gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onPreviousDays}
|
||||
disabled={!canGoBack}
|
||||
className="flex items-center justify-center rounded-md bg-white/[0.04] text-white transition hover:bg-white/[0.08] disabled:opacity-35"
|
||||
aria-label="Mostrar días anteriores"
|
||||
>
|
||||
<ChevronLeft className="size-5" />
|
||||
</button>
|
||||
{dayOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
onClick={() => onSelectDate(option.value)}
|
||||
className={`rounded-md border px-3 py-3 text-center transition ${
|
||||
selectedDate === option.value
|
||||
? 'border-emerald-500 bg-emerald-500/18 text-white'
|
||||
: 'border-white/10 bg-white/[0.035] text-white/76 hover:bg-white/[0.06]'
|
||||
}`}
|
||||
>
|
||||
<span className="block text-base font-semibold capitalize">{option.weekday}</span>
|
||||
<span className="mt-1 block text-sm">{option.dayMonth}</span>
|
||||
</button>
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
onClick={onNextDays}
|
||||
className="flex items-center justify-center rounded-md bg-white/[0.04] text-white transition hover:bg-white/[0.08]"
|
||||
aria-label="Mostrar próximos días"
|
||||
>
|
||||
<ChevronRight className="size-5" />
|
||||
</button>
|
||||
</div>
|
||||
</Panel>
|
||||
</section>
|
||||
</div>
|
||||
</PublicBookingPageChrome>
|
||||
@@ -757,10 +720,10 @@ function PublicBookingMobile(props: BookingShellProps) {
|
||||
<span className="px-2 text-sm text-white/76">Fecha</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={props.onPreviousDays}
|
||||
onClick={props.onPreviousDay}
|
||||
disabled={!props.canGoBack}
|
||||
className="flex size-9 items-center justify-center rounded-md border border-white/10 bg-white/[0.035] disabled:opacity-35"
|
||||
aria-label="Mostrar días anteriores"
|
||||
aria-label="Día anterior"
|
||||
>
|
||||
<ChevronLeft className="size-4" />
|
||||
</button>
|
||||
@@ -770,9 +733,9 @@ function PublicBookingMobile(props: BookingShellProps) {
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={props.onNextDays}
|
||||
onClick={props.onNextDay}
|
||||
className="flex size-9 items-center justify-center rounded-md border border-white/10 bg-white/[0.035]"
|
||||
aria-label="Mostrar próximos días"
|
||||
aria-label="Día siguiente"
|
||||
>
|
||||
<ChevronRight className="size-4" />
|
||||
</button>
|
||||
@@ -804,43 +767,6 @@ function PublicBookingMobile(props: BookingShellProps) {
|
||||
<SelectedSlotCard {...props} compact />
|
||||
</div>
|
||||
</Panel>
|
||||
|
||||
<Panel className="p-3">
|
||||
<div className="grid grid-cols-[32px_repeat(5,minmax(0,1fr))_32px] gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={props.onPreviousDays}
|
||||
disabled={!props.canGoBack}
|
||||
className="flex items-center justify-center rounded-md bg-white/[0.04] disabled:opacity-35"
|
||||
aria-label="Mostrar días anteriores"
|
||||
>
|
||||
<ChevronLeft className="size-4" />
|
||||
</button>
|
||||
{props.dayOptions.map((option) => (
|
||||
<button
|
||||
key={option.value}
|
||||
type="button"
|
||||
onClick={() => props.onSelectDate(option.value)}
|
||||
className={`rounded-md border px-1 py-2 text-center transition ${
|
||||
props.selectedDate === option.value
|
||||
? 'border-emerald-500 bg-emerald-500/18 text-white'
|
||||
: 'border-white/10 bg-white/[0.035] text-white/70'
|
||||
}`}
|
||||
>
|
||||
<span className="block text-xs font-semibold capitalize">{option.weekday}</span>
|
||||
<span className="block text-[11px]">{option.shortDay}</span>
|
||||
</button>
|
||||
))}
|
||||
<button
|
||||
type="button"
|
||||
onClick={props.onNextDays}
|
||||
className="flex items-center justify-center rounded-md bg-white/[0.04]"
|
||||
aria-label="Mostrar próximos días"
|
||||
>
|
||||
<ChevronRight className="size-4" />
|
||||
</button>
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
</PublicBookingPageChrome>
|
||||
);
|
||||
@@ -1298,6 +1224,7 @@ export function PublicBookingPage({ complexSlug }: PublicBookingPageProps) {
|
||||
const availabilityQuery = useQuery({
|
||||
queryKey: ['public-booking-availability', complexSlug, selectedDate, selectedSportId],
|
||||
enabled: Boolean(selectedDate),
|
||||
placeholderData: (previousData) => previousData,
|
||||
queryFn: () =>
|
||||
apiClient.publicBookings.getAvailability(complexSlug, {
|
||||
date: selectedDate,
|
||||
@@ -1516,6 +1443,42 @@ export function PublicBookingPage({ complexSlug }: PublicBookingPageProps) {
|
||||
});
|
||||
};
|
||||
|
||||
const goToPreviousDay = () => {
|
||||
const currentIndex = dayOptions.findIndex((o) => o.value === selectedDate);
|
||||
if (currentIndex > 0) {
|
||||
const prevDate = dayOptions[currentIndex - 1].value;
|
||||
setSelectedDate(prevDate);
|
||||
setSelectedSlot(null);
|
||||
setAutoAdjustedDateNotice(null);
|
||||
return;
|
||||
}
|
||||
if (windowStartOffset > 0) {
|
||||
const newOffset = windowStartOffset - 1;
|
||||
const newStartDate = toIsoDateLocal(addDays(today, newOffset));
|
||||
setWindowStartOffset(newOffset);
|
||||
setSelectedDate(newStartDate);
|
||||
setSelectedSlot(null);
|
||||
setAutoAdjustedDateNotice(null);
|
||||
}
|
||||
};
|
||||
|
||||
const goToNextDay = () => {
|
||||
const currentIndex = dayOptions.findIndex((o) => o.value === selectedDate);
|
||||
if (currentIndex < dayOptions.length - 1) {
|
||||
const nextDate = dayOptions[currentIndex + 1].value;
|
||||
setSelectedDate(nextDate);
|
||||
setSelectedSlot(null);
|
||||
setAutoAdjustedDateNotice(null);
|
||||
return;
|
||||
}
|
||||
const newOffset = windowStartOffset + 1;
|
||||
const nextDate = toIsoDateLocal(addDays(today, newOffset));
|
||||
setWindowStartOffset(newOffset);
|
||||
setSelectedDate(nextDate);
|
||||
setSelectedSlot(null);
|
||||
setAutoAdjustedDateNotice(null);
|
||||
};
|
||||
|
||||
const shellProps: BookingShellProps = {
|
||||
complexName: availabilityQuery.data?.complexName,
|
||||
complexAddress: availabilityQuery.data?.complexAddress,
|
||||
@@ -1543,6 +1506,8 @@ export function PublicBookingPage({ complexSlug }: PublicBookingPageProps) {
|
||||
onSelectDate: selectDate,
|
||||
onPreviousDays: goToPreviousDays,
|
||||
onNextDays: goToNextDays,
|
||||
onPreviousDay: goToPreviousDay,
|
||||
onNextDay: goToNextDay,
|
||||
onSelectSport: (sportId) => {
|
||||
setSelectedSportId(sportId);
|
||||
setSelectedCourtId(undefined);
|
||||
|
||||
Reference in New Issue
Block a user