import { addDays, addMonths, getDaysInMonth, isAfter, isBefore, isEqual, lastDayOfMonth, setDate, subDays, subMonths, } from 'date-fns'; import React, {Component} from 'react'; import DatePickerCalendar from './DatePickerCalendar'; import DatePickerNav from './DatePickerNav'; import PropTypes from 'prop-types'; export default class DatePickerDialog extends Component { static propTypes = { endDate: PropTypes.instanceOf(Date), isRange: PropTypes.bool, maxDate: PropTypes.instanceOf(Date), minDate: PropTypes.instanceOf(Date), onUpdate: PropTypes.func, resolve: PropTypes.func, startDate: PropTypes.instanceOf(Date), }; constructor(props) { super(props); this.state = { startDate: props.startDate, endDate: props.endDate, visibleDate: props.startDate, }; } onNext = () => this.setState(prevState => { const nextMonth = addMonths(prevState.visibleDate, 1); const day = Math.min( getDaysInMonth(nextMonth), prevState.visibleDate.getDate() ); if ( !this.props.maxDate || isBefore(nextMonth, this.props.maxDate) ) { const visibleDate = setDate(nextMonth, day); return { visibleDate, }; } return { visibleDate: this.props.maxDate, }; }); onPrev = () => this.setState(prevState => { const prevMonth = lastDayOfMonth( subMonths( new Date( prevState.visibleDate.getFullYear(), prevState.visibleDate.getMonth() ), 1 ) ); const day = Math.min( getDaysInMonth(prevMonth), prevState.visibleDate.getDate() ); if (!this.props.minDate || isAfter(prevMonth, this.props.minDate)) { const visibleDate = setDate(prevMonth, day); return { visibleDate, }; } return { visibleDate: this.props.minDate, }; }); onClickJump = date => { if (!this.props.isRange) { this.props.resolve({startDate: date}); } else { this.setStartAndEnd(date); } }; onClickDate = date => { if (!this.props.isRange) { this.props.resolve({startDate: date}); } else { this.setStartAndEnd(date); } }; onClickNav = date => { this.setState({visibleDate: date}); }; setStartAndEnd = date => { const {startDate, endDate} = this.state; const newDates = { startDate, endDate, }; if (isEqual(date, startDate)) { // reset start and end dates anchored to start newDates.startDate = date; newDates.endDate = addDays(date, 1); } else if (isEqual(date, endDate)) { // reset start and end dates anchored to end newDates.startDate = subDays(date, 1); newDates.endDate = date; } else if (isBefore(date, startDate)) { // extend the start date newDates.startDate = date; } else if (isAfter(date, endDate)) { // extend the end date newDates.endDate = date; } else if (isAfter(date, startDate)) { // truncate start date newDates.startDate = date; } this.setState({...newDates, visibleDate: date}); this.props.onUpdate(newDates); }; render() { const {isRange} = this.props; const {startDate, endDate, visibleDate} = this.state; return (