New booking panel
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { DatePicker } from '@/components/ui/date-picker';
|
||||
import { Field, FieldLabel } from '@/components/ui/field';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import { ChevronLeft, ChevronRight, Clock, SlidersHorizontal } from 'lucide-react';
|
||||
import { useBooking } from '../booking-provider';
|
||||
import type { BookingStatusFilter } from '../booking.types';
|
||||
import { fromIsoDateLocal, toIsoDateLocal } from '../lib/booking-time';
|
||||
|
||||
const timeRangeOptions = [
|
||||
{ label: '08:00 - 22:00', start: '08:00', end: '22:00' },
|
||||
{ label: '06:00 - 00:00', start: '06:00', end: '23:59' },
|
||||
{ label: '08:00 - 14:00', start: '08:00', end: '14:00' },
|
||||
{ label: '14:00 - 22:00', start: '14:00', end: '22:00' },
|
||||
];
|
||||
|
||||
const statusOptions: Array<{ value: BookingStatusFilter; label: string }> = [
|
||||
{ value: 'all', label: 'Todos' },
|
||||
{ value: 'free', label: 'Libre' },
|
||||
{ value: 'reserved', label: 'Reservado' },
|
||||
{ value: 'maintenance', label: 'Mantenimiento' },
|
||||
];
|
||||
|
||||
export function BookingToolbar() {
|
||||
const {
|
||||
courts,
|
||||
selectedDate,
|
||||
selectedSportId,
|
||||
selectedStatus,
|
||||
visibleTimeRange,
|
||||
setSelectedDate,
|
||||
moveSelectedDate,
|
||||
setSelectedSportId,
|
||||
setSelectedStatus,
|
||||
setVisibleTimeRange,
|
||||
} = useBooking();
|
||||
|
||||
const sports = [...new Map(courts.map((court) => [court.sport.id, court.sport])).values()];
|
||||
const activeRangeValue = `${visibleTimeRange.start}-${visibleTimeRange.end}`;
|
||||
|
||||
return (
|
||||
<section className="rounded-lg border bg-card/85 p-4 shadow-sm">
|
||||
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-[1fr_1fr_1.6fr_1.1fr_auto] xl:items-end">
|
||||
<Field>
|
||||
<FieldLabel>Deporte</FieldLabel>
|
||||
<Select value={selectedSportId} onValueChange={setSelectedSportId}>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="all">Todos</SelectItem>
|
||||
{sports.map((sport) => (
|
||||
<SelectItem key={sport.id} value={sport.id}>
|
||||
{sport.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<FieldLabel>Estado</FieldLabel>
|
||||
<Select
|
||||
value={selectedStatus}
|
||||
onValueChange={(value) => setSelectedStatus(value as BookingStatusFilter)}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{statusOptions.map((option) => (
|
||||
<SelectItem key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<FieldLabel>Fecha</FieldLabel>
|
||||
<div className="grid grid-cols-[auto_1fr_auto] gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => moveSelectedDate(-1)}
|
||||
>
|
||||
<ChevronLeft className="size-4" />
|
||||
</Button>
|
||||
<DatePicker
|
||||
value={fromIsoDateLocal(selectedDate)}
|
||||
onChange={(date) =>
|
||||
setSelectedDate(date ? toIsoDateLocal(date) : toIsoDateLocal(new Date()))
|
||||
}
|
||||
/>
|
||||
<Button type="button" variant="outline" size="icon" onClick={() => moveSelectedDate(1)}>
|
||||
<ChevronRight className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</Field>
|
||||
|
||||
<Field>
|
||||
<FieldLabel>Hora</FieldLabel>
|
||||
<Select
|
||||
value={activeRangeValue}
|
||||
onValueChange={(value) => {
|
||||
const option = timeRangeOptions.find((item) => `${item.start}-${item.end}` === value);
|
||||
if (option) {
|
||||
setVisibleTimeRange({ start: option.start, end: option.end });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<Clock className="mr-2 size-4 text-muted-foreground" />
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{timeRangeOptions.map((option) => (
|
||||
<SelectItem
|
||||
key={`${option.start}-${option.end}`}
|
||||
value={`${option.start}-${option.end}`}
|
||||
>
|
||||
{option.label}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
|
||||
<Button variant="outline" className="xl:self-end">
|
||||
<SlidersHorizontal className="size-4" />
|
||||
Filtros avanzados
|
||||
</Button>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user