import React, { useContext } from 'react' import classnames from 'classnames' import { isPast, isSameDay, isAfter, isWithinInterval } from 'date-fns' import useSWR from 'swr' import Calendar from 'react-calendar' import { dateFormatBackend } from '../../helpers/date' import { getNextBigger, getNextSmaller } from '../../helpers/array' import { WizardContext } from './context/wizardStore' const fetcher = (path: string) => fetch(path).then((r) => r.json()) export default function MyCalendar() { const { onChange, state } = useContext(WizardContext) const { startDate: start, endDate: end } = state.formData const startDate = (start && new Date(start)) || null const endDate = (end && new Date(end)) || null const { data: daysBooked, error: fetchBookedOnError } = useSWR( '/api/daysbooked', fetcher ) const inSelection = !!start && !end const prevBooked = inSelection && getNextSmaller(daysBooked, start) const nextBooked = inSelection && getNextBigger(daysBooked, start) function isSelected(date: Date) { if (!startDate) { return false } // if end is before start, it is not within if (endDate && !isAfter(endDate, startDate)) { return false } return isWithinInterval(date, { start: startDate, end: endDate || startDate, }) } function tileClassName({ date, view }) { const isMonthView = view === 'month' const isDaysBookedLoaded = !!daysBooked const isInPast = isPast(date) const isBooked = daysBooked?.includes(dateFormatBackend(date)) return classnames({ 'react-calendar__tile--past': isMonthView && isInPast, 'react-calendar__tile--booked': isMonthView && isDaysBookedLoaded && isBooked && !isInPast, 'react-calendar__tile--free': isMonthView && isDaysBookedLoaded && !isBooked && !isInPast, 'react-calendar__tile--selected-start': isMonthView && isSameDay(date, startDate), 'react-calendar__tile--selected-end': isMonthView && isSameDay(date, endDate), 'react-calendar__tile--selected': isSelected(date) || isSameDay(date, startDate), 'react-calendar__tile--unselectable': inSelection && ((prevBooked && date < new Date(prevBooked)) || (nextBooked && date > new Date(nextBooked))), }) } if (fetchBookedOnError) { return (