import React, { ReactElement, MouseEvent, useState, useCallback, useEffect, } from 'react'; import getDate from 'date-fns/fp/getDate'; import getMonth from 'date-fns/fp/getMonth'; import getYear from 'date-fns/fp/getYear'; import addYears from 'date-fns/fp/addYears'; import subYears from 'date-fns/fp/subYears'; import setMonth from 'date-fns/fp/setMonth'; import setYear from 'date-fns/fp/setYear'; import Select from '../../Select'; import { Container, Navigation, CalendarWrapper, CalendarRow, DayWrapper, Day, } from './StyledCalendar'; import { DAYS, getMonthMatrix, getSingleCalendarDayState, generateYearOptions, generateMonthOptions, } from './utils'; import DoubleCalendar from './DoubleCalendar'; import MonthCalendar from './MonthCalendar'; import WeekCalendar from './WeekCalendar'; interface CalendarProps { maxDate?: Date; minDate?: Date; onSelectDate?: (date: Date) => void; selectedDate?: Date; } const Calendar = ({ selectedDate, onSelectDate, minDate, maxDate, }: CalendarProps): ReactElement => { const currentDate = new Date(); const initialDate = selectedDate !== undefined ? selectedDate : currentDate; const [date, setDate] = useState(initialDate); const month = getMonth(date); const year = getYear(date); const caldendarMinDate = minDate !== undefined ? minDate : subYears(100, currentDate); const calendarMaxDate = maxDate !== undefined ? maxDate : addYears(100, currentDate); const yearOptions = generateYearOptions({ minDate: caldendarMinDate, maxDate: calendarMaxDate, }); const monthOptions = generateMonthOptions({ minDate: caldendarMinDate, maxDate: calendarMaxDate, year, }); const onChangeMonth = useCallback( newMonth => { setDate(setMonth(newMonth, date)); }, [date, setDate] ); const onChangeYear = useCallback( newYear => { setDate(setYear(newYear, date)); }, [date, setDate] ); useEffect(() => { setDate(selectedDate !== undefined ? selectedDate : new Date()); }, [selectedDate, setDate]); const monthMatrix = getMonthMatrix({ month, year, minDate, maxDate }); return ( {DAYS.map(day => ( {day} ))} {monthMatrix.map((week, weekNumber) => ( // eslint-disable-next-line react/no-array-index-key {week.map(dateOfWeek => { const day = getDate(dateOfWeek.date); const onDateClick = (e: MouseEvent, clickedDate: Date): void => { if (onSelectDate !== undefined) { onSelectDate(clickedDate); } e.preventDefault(); }; const dateState = getSingleCalendarDayState({ dateOfWeek, selectedDate, }); return ( // eslint-disable-next-line react/no-array-index-key onDateClick(e, dateOfWeek.date) : undefined } > {day} ); })} ))} ); }; Calendar.Double = DoubleCalendar; Calendar.Month = MonthCalendar; Calendar.Week = WeekCalendar; export default Calendar;