import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { ArrowLeft, CalendarDays, Clock, MapPin, Phone, ShieldCheck, User, UserX, } from 'lucide-react'; import { useMemo } from 'react'; import { useBooking } from '../booking-provider'; import type { BookingTimelineSegment } from '../booking.types'; import { formatBookingDate } from '../lib/booking-time'; const statusConfig: Record = { CONFIRMED: { label: 'Reservada', className: 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400 border-emerald-500/30', }, COMPLETED: { label: 'Completada', className: 'bg-sky-500/15 text-sky-600 dark:text-sky-400 border-sky-500/30', }, CANCELLED: { label: 'Cancelada', className: 'bg-red-500/15 text-red-600 dark:text-red-400 border-red-500/30', }, NOSHOW: { label: 'No show', className: 'bg-amber-500/15 text-amber-600 dark:text-amber-400 border-amber-500/30', }, }; const statusIconConfig: Record = { CONFIRMED: ShieldCheck, COMPLETED: ShieldCheck, CANCELLED: UserX, NOSHOW: UserX, }; export function BookingListView() { const { selectedDate, setViewMode, schedules, openBookingTools, isLoading, isError, errorMessage, } = useBooking(); const reservedSegments = useMemo(() => { return schedules .flatMap((schedule) => schedule.segments .filter((segment) => segment.booking) .map((segment) => ({ schedule, segment })) ) .sort((a, b) => { const timeDiff = a.segment.startMinutes - b.segment.startMinutes; if (timeDiff !== 0) return timeDiff; return a.schedule.court.name.localeCompare(b.schedule.court.name); }); }, [schedules]); return (

Reservas del día

{formatBookingDate(selectedDate, { year: 'numeric' })}

{reservedSegments.length} {reservedSegments.length === 1 ? 'reserva' : 'reservas'}
{isLoading && (
Cargando reservas...
)} {isError && !isLoading && (
{errorMessage}
)} {!isLoading && !isError && reservedSegments.length === 0 && (

No hay reservas para este día.

)} {!isLoading && !isError && reservedSegments.length > 0 && (
{/* Desktop table */} {reservedSegments.map(({ schedule, segment }) => ( openBookingTools(segment)} /> ))}
Horario Cancha Cliente Teléfono Estado
{/* Mobile cards */}
{reservedSegments.map(({ schedule, segment }) => ( ))}
)}
); } interface BookingRowProps { segment: BookingTimelineSegment; courtName: string; sportName: string; onClick: () => void; } function BookingRow({ segment, courtName, sportName, onClick }: BookingRowProps) { const booking = segment.booking; return ( { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onClick(); } }} tabIndex={0} role="button" >
{segment.startTime} - {segment.endTime}

{courtName}

{sportName}

{booking?.customerName ?? 'Sin información'}
{booking?.customerPhone ?? '-'}
); } function StatusBadge({ status }: { status: string }) { const config = statusConfig[status] ?? { label: status, className: 'bg-slate-500/15 text-slate-600 dark:text-slate-400 border-slate-500/30', }; const Icon = statusIconConfig[status] ?? ShieldCheck; return ( {config.label} ); }