feat(booking-ui): add confirmation dialog for cancelling bookings and improve mobile UI

This commit is contained in:
Jose Selesan
2026-06-04 16:39:45 -03:00
parent 7ca784d5f5
commit 1210854c22

View File

@@ -24,6 +24,7 @@ import {
Wrench,
XCircle,
} from 'lucide-react';
import { useState } from 'react';
import { useBooking } from '../booking-provider';
function formatDate(date: string | undefined) {
@@ -70,6 +71,7 @@ export function BookingToolsDialog() {
useBooking();
const isMobile = useIsMobile();
const booking = selectedSegment?.booking;
const [confirmCancelOpen, setConfirmCancelOpen] = useState(false);
const status = statusConfig[booking?.status ?? 'CONFIRMED'] ?? {
label: booking?.status,
@@ -93,8 +95,62 @@ export function BookingToolsDialog() {
closeBookingTools();
};
const cancelConfirmDialog = (
<ResponsiveDialog
open={confirmCancelOpen}
onOpenChange={(open) => !open && setConfirmCancelOpen(false)}
>
<ResponsiveDialogContent>
<ResponsiveDialogHeader>
<ResponsiveDialogTitle>¿Cancelar reserva?</ResponsiveDialogTitle>
<ResponsiveDialogDescription>
Esta acción no se puede deshacer. Se eliminará la reserva y la cancha volverá a estar
disponible.
</ResponsiveDialogDescription>
</ResponsiveDialogHeader>
<div className="space-y-2 rounded-lg border bg-card p-4">
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Cliente</span>
<span className="text-sm font-medium">{booking?.customerName ?? '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Cancha</span>
<span className="text-sm font-medium">{booking?.courtName ?? '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Fecha</span>
<span className="text-sm font-medium">{formatDate(booking?.date) || '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-muted-foreground">Horario</span>
<span className="text-sm font-medium">
{booking?.startTime ?? '--:--'} a {booking?.endTime ?? '--:--'}
</span>
</div>
</div>
<ResponsiveDialogFooter>
<ResponsiveDialogClose asChild>
<Button variant="outline">Volver</Button>
</ResponsiveDialogClose>
<Button
variant="destructive"
onClick={() => {
setConfirmCancelOpen(false);
updateStatus('CANCELLED');
}}
>
, cancelar reserva
</Button>
</ResponsiveDialogFooter>
</ResponsiveDialogContent>
</ResponsiveDialog>
);
if (isMobile) {
return (
<>
<ResponsiveDialog
open={bookingToolsOpen}
onOpenChange={(open) => !open && closeBookingTools()}
@@ -106,17 +162,23 @@ export function BookingToolsDialog() {
<MobileBookingToolsSheet
status={status}
onComplete={() => updateStatus('COMPLETED')}
onCancel={() => updateStatus('CANCELLED')}
onCancel={() => setConfirmCancelOpen(true)}
onReminder={sendWhatsappReminder}
onNoShow={() => updateStatus('NOSHOW')}
/>
</ResponsiveDialogContent>
</ResponsiveDialog>
{cancelConfirmDialog}
</>
);
}
return (
<ResponsiveDialog open={bookingToolsOpen} onOpenChange={(open) => !open && closeBookingTools()}>
<>
<ResponsiveDialog
open={bookingToolsOpen}
onOpenChange={(open) => !open && closeBookingTools()}
>
<ResponsiveDialogContent
className="data-[variant=dialog]:max-w-5xl data-[variant=drawer]:max-h-[92dvh] data-[variant=drawer]:overflow-y-auto data-[variant=drawer]:px-4 data-[variant=drawer]:pb-5"
onOpenAutoFocus={(event) => event.preventDefault()}
@@ -203,9 +265,7 @@ export function BookingToolsDialog() {
title="Cancelar reserva"
description="El cliente avisó que no va a venir. La cancha vuelve a estar disponible."
className="border-red-500/40 bg-red-500/10 text-lg text-red-600 hover:bg-red-500/15 hover:text-red-800"
onClick={() => {
updateStatus('CANCELLED');
}}
onClick={() => setConfirmCancelOpen(true)}
/>
<ActionButton
@@ -238,6 +298,8 @@ export function BookingToolsDialog() {
</ResponsiveDialogFooter>
</ResponsiveDialogContent>
</ResponsiveDialog>
{cancelConfirmDialog}
</>
);
}