import { useState } from 'react'; import classNames from 'classnames'; import { startOfWeek, startOfMonth, startOfYear, endOfMonth, addDays, subDays, addYears, subYears, addMonths, setMonth, setYear, isSameDay, isBefore, isAfter, } from 'date-fns'; import { Button, Icon } from 'react-basics'; import { chunkArray } from 'next-basics'; import useLocale from 'hooks/useLocale'; import { dateFormat } from 'lib/date'; import { getDateLocale } from 'lib/lang'; import Chevron from 'assets/chevron-down.svg'; import Cross from 'assets/times.svg'; import styles from './Calendar.module.css'; export default function Calendar({ date, minDate, maxDate, onChange }) { const { locale } = useLocale(); const [selectMonth, setSelectMonth] = useState(false); const [selectYear, setSelectYear] = useState(false); const month = dateFormat(date, 'MMMM', locale); const year = date.getFullYear(); function toggleMonthSelect() { setSelectYear(false); setSelectMonth(state => !state); } function toggleYearSelect() { setSelectMonth(false); setSelectYear(state => !state); } function handleChange(value) { setSelectMonth(false); setSelectYear(false); if (value) { onChange(value); } } return (
{date.getDate()}
{month} {selectMonth ? : }
{year} {selectMonth ? : }
{!selectMonth && !selectYear && ( )} {selectMonth && ( )} {selectYear && ( )}
); } const DaySelector = ({ date, minDate, maxDate, locale, onSelect }) => { const dateLocale = getDateLocale(locale); const weekStartsOn = dateLocale?.options?.weekStartsOn || 0; const startWeek = startOfWeek(date, { locale: dateLocale, weekStartsOn, }); const startMonth = startOfMonth(date); const startDay = subDays(startMonth, startMonth.getDay() - weekStartsOn); const month = date.getMonth(); const year = date.getFullYear(); const daysOfWeek = []; for (let i = 0; i < 7; i++) { daysOfWeek.push(addDays(startWeek, i)); } const days = []; for (let i = 0; i < 35; i++) { days.push(addDays(startDay, i)); } return ( {daysOfWeek.map((day, i) => ( ))} {chunkArray(days, 7).map((week, i) => ( {week.map((day, j) => { const disabled = isBefore(day, minDate) || isAfter(day, maxDate); return ( ); })} ))}
{dateFormat(day, 'EEE', locale)}
onSelect(day) : null} > {day.getDate()}
); }; const MonthSelector = ({ date, minDate, maxDate, locale, onSelect }) => { const start = startOfYear(date); const months = []; for (let i = 0; i < 12; i++) { months.push(addMonths(start, i)); } function handleSelect(value) { onSelect(setMonth(date, value)); } return ( {chunkArray(months, 3).map((row, i) => ( {row.map((month, j) => { const disabled = isBefore(endOfMonth(month), minDate) || isAfter(startOfMonth(month), maxDate); return ( ); })} ))}
handleSelect(month.getMonth()) : null} > {dateFormat(month, 'MMMM', locale)}
); }; const YearSelector = ({ date, minDate, maxDate, onSelect }) => { const [currentDate, setCurrentDate] = useState(date); const year = date.getFullYear(); const currentYear = currentDate.getFullYear(); const minYear = minDate.getFullYear(); const maxYear = maxDate.getFullYear(); const years = []; for (let i = 0; i < 15; i++) { years.push(currentYear - 7 + i); } function handleSelect(value) { onSelect(setYear(date, value)); } function handlePrevClick() { setCurrentDate(state => subYears(state, 15)); } function handleNextClick() { setCurrentDate(state => addYears(state, 15)); } return (
{chunkArray(years, 5).map((row, i) => ( {row.map((n, j) => ( ))} ))}
maxYear, })} onClick={() => (n < minYear || n > maxYear ? null : handleSelect(n))} > {n}
); };