import startOfMonth from 'date-fns/fp/startOfMonth'; import endOfMonth from 'date-fns/fp/endOfMonth'; import startOfWeek from 'date-fns/fp/startOfWeek'; import endOfWeek from 'date-fns/fp/endOfWeek'; import eachWeekOfInterval from 'date-fns/fp/eachWeekOfInterval'; import eachDayOfInterval from 'date-fns/fp/eachDayOfInterval'; import addDays from 'date-fns/fp/addDays'; import addWeeks from 'date-fns/fp/addWeeks'; import subDays from 'date-fns/fp/subDays'; import getMonth from 'date-fns/fp/getMonth'; import getYear from 'date-fns/fp/getYear'; import isSameDay from 'date-fns/fp/isSameDay'; import isBefore from 'date-fns/fp/isBefore'; import isAfter from 'date-fns/fp/isAfter'; import eachYearOfInterval from 'date-fns/fp/eachYearOfInterval'; const MONTHS = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; const DAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']; const getMonthMatrix = ({ month, year, minDate, maxDate, }: { maxDate?: Date; minDate?: Date; month: number; year: number; }): { date: Date; disabled: boolean }[][] => { const date = new Date(year, month); const weekStartDates = eachWeekOfInterval({ start: startOfMonth(date), end: addWeeks(1, endOfMonth(date)), }); const monthMatrix = weekStartDates .filter((_date, index) => index < 6) .map(weekStartDate => eachDayOfInterval({ start: startOfWeek(weekStartDate), end: endOfWeek(weekStartDate), }).map(dateOfWeek => ({ date: dateOfWeek, disabled: getMonth(dateOfWeek) !== month || (minDate !== undefined && isBefore(minDate, dateOfWeek)) || (maxDate !== undefined && isAfter(maxDate, dateOfWeek)), })) ); return monthMatrix; }; const getSingleCalendarDayState = ({ dateOfWeek, selectedDate, }: { dateOfWeek: { date: Date; disabled: boolean }; selectedDate?: Date; }): 'enabled' | 'disabled' | 'selected' | 'today' => { if (dateOfWeek.disabled === true) { return 'disabled'; } if (selectedDate !== undefined && isSameDay(dateOfWeek.date, selectedDate)) { return 'selected'; } if (isSameDay(dateOfWeek.date, new Date())) { return 'today'; } return 'enabled'; }; const getWeekCalendarState = ({ dateOfWeek, selectedDate, tempDate, }: { dateOfWeek: { date: Date; disabled: boolean }; selectedDate?: Date; tempDate?: Date; }): 'enabled' | 'disabled' | 'selected' | 'inHoveringWeek' => { if (selectedDate !== undefined) { const firstDateOfWeek = startOfWeek(selectedDate); if (isSameDay(firstDateOfWeek, dateOfWeek.date)) { return 'selected'; } } if (tempDate !== undefined) { const firstDateOfWeek = startOfWeek(tempDate); const lastDateOfWeek = endOfWeek(tempDate); if ( (isAfter(firstDateOfWeek, dateOfWeek.date) && isBefore(lastDateOfWeek, dateOfWeek.date)) || isSameDay(firstDateOfWeek, dateOfWeek.date) || isSameDay(lastDateOfWeek, dateOfWeek.date) ) { return 'inHoveringWeek'; } } if (dateOfWeek.disabled === true) { return 'disabled'; } return 'enabled'; }; const getWeekCalendarDayState = ({ dateOfWeek, selectedDate, tempDate, }: { dateOfWeek: { date: Date; disabled: boolean }; selectedDate?: Date; tempDate?: Date; }): | 'enabled' | 'disabled' | 'today' | 'inHoveringWeekDate' | 'selectedWeekDate' | 'selectedFirstDateOfWeek' | 'selectedLastDateOfWeek' | 'inHoveringFirstDateOfWeek' | 'inHoveringLastDateOfWeek' => { if (selectedDate !== undefined) { const firstDateOfWeek = startOfWeek(selectedDate); const lastDateOfWeek = endOfWeek(selectedDate); if (isSameDay(firstDateOfWeek, dateOfWeek.date)) { return 'selectedFirstDateOfWeek'; } if (isSameDay(lastDateOfWeek, dateOfWeek.date)) { return 'selectedLastDateOfWeek'; } if ( isAfter(firstDateOfWeek, dateOfWeek.date) && isBefore(lastDateOfWeek, dateOfWeek.date) ) { return 'selectedWeekDate'; } } if (tempDate !== undefined) { const firstDateOfWeek = startOfWeek(tempDate); const lastDateOfWeek = endOfWeek(tempDate); if (isSameDay(lastDateOfWeek, dateOfWeek.date)) { return 'inHoveringLastDateOfWeek'; } if ( isAfter(firstDateOfWeek, dateOfWeek.date) && isBefore(lastDateOfWeek, dateOfWeek.date) ) { return 'inHoveringWeekDate'; } if (isSameDay(firstDateOfWeek, dateOfWeek.date)) { return 'inHoveringFirstDateOfWeek'; } } if (isSameDay(dateOfWeek.date, new Date())) { return 'today'; } if (dateOfWeek.disabled === true) { return 'disabled'; } return 'enabled'; }; const getDoubleCalendarDayState = ({ dateOfWeek, isSettingStartDate, isSettingEndDate, dateClickCount, startDate, endDate, tempDate, }: { dateClickCount: number; dateOfWeek: { date: Date; disabled: boolean }; endDate?: Date; isSettingEndDate: boolean; isSettingStartDate: boolean; startDate?: Date; tempDate?: Date; }): | 'enabled' | 'disabled' | 'selectedRangeDate' | 'selectedStartDate' | 'selectedEndDate' | 'today' | 'inRange' | 'inHoveringRange' => { if ( dateOfWeek.disabled === true || (startDate !== undefined && isSettingEndDate === true && dateClickCount === 1 && isBefore(startDate, dateOfWeek.date)) || (endDate !== undefined && isSettingStartDate === true && dateClickCount === 1 && isAfter(endDate, dateOfWeek.date)) ) { return 'disabled'; } if ( startDate !== undefined && endDate !== undefined && isSameDay(startDate, endDate) && isSameDay(dateOfWeek.date, startDate) ) { return 'selectedRangeDate'; } if (startDate !== undefined && isSameDay(dateOfWeek.date, startDate)) { return 'selectedStartDate'; } if (endDate !== undefined && isSameDay(dateOfWeek.date, endDate)) { return 'selectedEndDate'; } if ( startDate !== undefined && endDate !== undefined && isAfter(startDate, dateOfWeek.date) && isBefore(endDate, dateOfWeek.date) ) { return 'inRange'; } if ( (endDate !== undefined && tempDate !== undefined && isSettingStartDate === true && isAfter(subDays(1, tempDate), dateOfWeek.date) && isBefore(endDate, dateOfWeek.date)) || (startDate !== undefined && tempDate !== undefined && isSettingEndDate === true && isAfter(startDate, dateOfWeek.date) && isBefore(addDays(1, tempDate), dateOfWeek.date)) ) { return 'inHoveringRange'; } if (isSameDay(dateOfWeek.date, new Date())) { return 'today'; } return 'enabled'; }; const generateYearOptions = ({ maxDate, minDate, }: { maxDate: Date; minDate: Date; }): { text: string; value: number }[] => { return eachYearOfInterval({ start: minDate, end: maxDate }).map( dateOfYear => { const year = getYear(dateOfYear); return { value: year, text: year.toString(), }; } ); }; const generateMonthOptions = ({ maxDate, minDate, year, }: { maxDate: Date; minDate: Date; year: number; }): { text: string; value: number }[] => { const monthOptions = MONTHS.map((month, index) => ({ value: index, text: month, })); if (year > getYear(minDate) && year < getYear(maxDate)) return monthOptions; if (year <= getYear(minDate)) return monthOptions.map(monthOpt => monthOpt.value < getMonth(minDate) ? { ...monthOpt, disabled: true } : monthOpt ); return monthOptions.map(monthOpt => monthOpt.value > getMonth(maxDate) ? { ...monthOpt, disabled: true } : monthOpt ); }; const getMonthPickerOptions = ({ maxDate, minDate, year, }: { maxDate?: Date; minDate?: Date; year: number; }): { date: Date; disabled: boolean; text: string; }[] => { const result = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(monthIndex => { const monthStartDate = startOfMonth(new Date(year, monthIndex)); const disabled = (minDate !== undefined && isBefore(minDate, monthStartDate)) || (maxDate !== undefined && isAfter(maxDate, monthStartDate)); const text = MONTHS[monthIndex]; return { date: monthStartDate, disabled, text: text !== undefined ? text : '', }; }); return result; }; export { MONTHS, DAYS, getMonthMatrix, getSingleCalendarDayState, getDoubleCalendarDayState, generateYearOptions, generateMonthOptions, getMonthPickerOptions, getWeekCalendarDayState, getWeekCalendarState, };