import React, { 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 from './Button';
import useLocale from 'hooks/useLocale';
import { dateFormat } from 'lib/date';
import { chunk } from 'lib/array';
import { dateLocales } from 'lib/lang';
import Chevron from 'assets/chevron-down.svg';
import Cross from 'assets/times.svg';
import styles from './Calendar.module.css';
import Icon from './Icon';
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}
: } size="small" />
{year}
: } size="small" />
{!selectMonth && !selectYear && (
)}
{selectMonth && (
)}
{selectYear && (
)}
);
}
const DaySelector = ({ date, minDate, maxDate, locale, onSelect }) => {
const startWeek = startOfWeek(date, { locale: dateLocales[locale] });
const startMonth = startOfMonth(date, { locale: dateLocales[locale] });
const startDay = subDays(startMonth, startMonth.getDay());
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) => (
{dateFormat(day, 'EEE', locale)}
|
))}
{chunk(days, 7).map((week, i) => (
{week.map((day, j) => {
const disabled = isBefore(day, minDate) || isAfter(day, maxDate);
return (
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 (
{chunk(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 (
}
size="small"
onClick={handlePrevClick}
disabled={years[0] <= minYear}
variant="light"
/>
{chunk(years, 5).map((row, i) => (
{row.map((n, j) => (
maxYear,
})}
onClick={() => (n < minYear || n > maxYear ? null : handleSelect(n))}
>
{n}
|
))}
))}
}
size="small"
onClick={handleNextClick}
disabled={years[years.length - 1] > maxYear}
variant="light"
/>
);
};