Minor changes
This commit is contained in:
@@ -4,12 +4,14 @@ import { DayPicker } from 'react-day-picker';
|
|||||||
|
|
||||||
import { buttonVariants } from '@/components/ui/button';
|
import { buttonVariants } from '@/components/ui/button';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import { es } from 'date-fns/locale';
|
||||||
|
|
||||||
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
export type CalendarProps = React.ComponentProps<typeof DayPicker>;
|
||||||
|
|
||||||
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
|
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) {
|
||||||
return (
|
return (
|
||||||
<DayPicker
|
<DayPicker
|
||||||
|
locale={es}
|
||||||
showOutsideDays={showOutsideDays}
|
showOutsideDays={showOutsideDays}
|
||||||
className={cn('p-3', className)}
|
className={cn('p-3', className)}
|
||||||
classNames={{
|
classNames={{
|
||||||
|
|||||||
@@ -277,17 +277,25 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
|
|||||||
const summary = useMemo(() => getSummary(schedules), [schedules]);
|
const summary = useMemo(() => getSummary(schedules), [schedules]);
|
||||||
const timelineHours = useMemo(() => makeTimelineHours(visibleTimeRange), [visibleTimeRange]);
|
const timelineHours = useMemo(() => makeTimelineHours(visibleTimeRange), [visibleTimeRange]);
|
||||||
|
|
||||||
const currentTime = useMemo(() => {
|
const [now, setNow] = useState(() => getNowTime());
|
||||||
if (!isTodayIso(selectedDate)) return null;
|
useEffect(() => {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setNow(getNowTime());
|
||||||
|
}, 10 * 1000);
|
||||||
|
|
||||||
const now = getNowTime();
|
return () => clearInterval(interval);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const currentTime = useMemo(() => {
|
||||||
|
|
||||||
|
if (!isTodayIso(selectedDate)) return null;
|
||||||
const nowMinutes = timeToMinutes(now);
|
const nowMinutes = timeToMinutes(now);
|
||||||
const start = timeToMinutes(visibleTimeRange.start);
|
const start = timeToMinutes(visibleTimeRange.start);
|
||||||
const end = timeToMinutes(visibleTimeRange.end);
|
const end = timeToMinutes(visibleTimeRange.end);
|
||||||
|
|
||||||
if (nowMinutes < start || nowMinutes > end) return null;
|
if (nowMinutes < start || nowMinutes > end) return null;
|
||||||
return now;
|
return now;
|
||||||
}, [selectedDate, visibleTimeRange]);
|
}, [selectedDate, visibleTimeRange, now]);
|
||||||
|
|
||||||
const createBookingMutation = useMutation({
|
const createBookingMutation = useMutation({
|
||||||
mutationFn: (payload: CreateManualBookingPayload) =>
|
mutationFn: (payload: CreateManualBookingPayload) =>
|
||||||
@@ -403,9 +411,9 @@ export function BookingProvider({ children, complex }: BookingProviderProps) {
|
|||||||
errorMessage:
|
errorMessage:
|
||||||
courtsQuery.isError || bookingsQuery.isError
|
courtsQuery.isError || bookingsQuery.isError
|
||||||
? extractMessage(
|
? extractMessage(
|
||||||
courtsQuery.error ?? bookingsQuery.error,
|
courtsQuery.error ?? bookingsQuery.error,
|
||||||
'No pudimos cargar el panel de reservas.'
|
'No pudimos cargar el panel de reservas.'
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
isCreateBookingOpen,
|
isCreateBookingOpen,
|
||||||
createBookingError: createBookingMutation.isError
|
createBookingError: createBookingMutation.isError
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ interface TimelineHeaderProps {
|
|||||||
function TimelineHeader({ timelineMarks, courtInfoWidth, gridWidth }: TimelineHeaderProps) {
|
function TimelineHeader({ timelineMarks, courtInfoWidth, gridWidth }: TimelineHeaderProps) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="sticky top-0 z-20 grid border-b bg-card/95"
|
className="sticky top-0 z-20 grid border-b bg-card/95 z-auto"
|
||||||
style={{ gridTemplateColumns: `${courtInfoWidth}px ${gridWidth}px` }}
|
style={{ gridTemplateColumns: `${courtInfoWidth}px ${gridWidth}px` }}
|
||||||
>
|
>
|
||||||
<div className="sticky left-0 z-30 border-r bg-card/95 px-4 py-3 shadow-[8px_0_18px_-18px_oklch(0_0_0/0.45)]" />
|
<div className="sticky left-0 z-30 border-r bg-card/95 px-4 py-3 shadow-[8px_0_18px_-18px_oklch(0_0_0/0.45)]" />
|
||||||
@@ -238,6 +238,9 @@ function BookingSlotBlock({ segment, schedule, rangeStart, totalMinutes }: Booki
|
|||||||
startTime: segment.startTime,
|
startTime: segment.startTime,
|
||||||
sportId: schedule.court.sportId,
|
sportId: schedule.court.sportId,
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
//console.log(JSON.stringify(segment, null, 2));
|
||||||
|
setPopoverOpen(true);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
onDoubleClick={() => {
|
onDoubleClick={() => {
|
||||||
@@ -265,6 +268,7 @@ function BookingSlotBlock({ segment, schedule, rangeStart, totalMinutes }: Booki
|
|||||||
<Users className="size-3" />
|
<Users className="size-3" />
|
||||||
{segment.booking?.customerName ?? 'Mantenimiento'}
|
{segment.booking?.customerName ?? 'Mantenimiento'}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
@@ -289,7 +293,7 @@ function CurrentTimeIndicator({
|
|||||||
const left = courtInfoWidth + ((timeToMinutes(time) - rangeStart) / totalMinutes) * gridWidth;
|
const left = courtInfoWidth + ((timeToMinutes(time) - rangeStart) / totalMinutes) * gridWidth;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="pointer-events-none absolute bottom-0 top-12 z-20" style={{ left }}>
|
<div className="pointer-events-none absolute bottom-0 top-12 z-[5]" style={{ left }}>
|
||||||
<div className="absolute left-0 top-0 -translate-x-1/2 -translate-y-1/2 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground shadow-sm">
|
<div className="absolute left-0 top-0 -translate-x-1/2 -translate-y-1/2 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground shadow-sm">
|
||||||
{time}
|
{time}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { ChevronLeft, ChevronRight, Clock, SlidersHorizontal } from 'lucide-reac
|
|||||||
import { useBooking } from '../booking-provider';
|
import { useBooking } from '../booking-provider';
|
||||||
import type { BookingStatusFilter } from '../booking.types';
|
import type { BookingStatusFilter } from '../booking.types';
|
||||||
import { fromIsoDateLocal, toIsoDateLocal } from '../lib/booking-time';
|
import { fromIsoDateLocal, toIsoDateLocal } from '../lib/booking-time';
|
||||||
|
|
||||||
const timeRangeOptions = [
|
const timeRangeOptions = [
|
||||||
{ label: '08:00 - 22:00', start: '08:00', end: '22:00' },
|
{ label: '08:00 - 22:00', start: '08:00', end: '22:00' },
|
||||||
{ label: '06:00 - 00:00', start: '06:00', end: '23:59' },
|
{ label: '06:00 - 00:00', start: '06:00', end: '23:59' },
|
||||||
|
|||||||
Reference in New Issue
Block a user