diff --git a/components/DateSelector/DateSelector.jsx b/components/DateSelector/DateSelector.jsx index 5f65a4515..a03f098af 100644 --- a/components/DateSelector/DateSelector.jsx +++ b/components/DateSelector/DateSelector.jsx @@ -21,7 +21,7 @@ function DateSelector({ updateStartDate, updateEndDate, }) { - const [expanded, setExpanded] = useState(false); + const [expandedMenu, setExpandedMenu] = useState(false); const classes = useStyles(); const handleOptionSelect = optionDates => { @@ -29,11 +29,11 @@ function DateSelector({ const formattedEnd = moment(optionDates[1]).format(dateFormat); updateStartDate(formattedStart); updateEndDate(formattedEnd); - setExpanded(false); + setExpandedMenu(false); }; const closeOptionsOnDateToggle = useCallback(() => { - setExpanded(false); + setExpandedMenu(false); }, []); const { @@ -64,12 +64,12 @@ function DateSelector({ - setExpanded(!expanded)} expanded={expanded}> + setExpandedMenu(!expandedMenu)} expanded={expandedMenu}>
diff --git a/components/common/DatePicker/DatePicker.jsx b/components/common/DatePicker/DatePicker.jsx index 813f8cc56..b7944a7b8 100644 --- a/components/common/DatePicker/DatePicker.jsx +++ b/components/common/DatePicker/DatePicker.jsx @@ -9,7 +9,10 @@ import IconButton from '@mui/material/IconButton'; import makeStyles from '@mui/styles/makeStyles'; import useOutsideClick from '@components/common/customHooks/useOutsideClick'; import ReactDayPicker from '@components/common/ReactDayPicker'; - +import { + updateEndDate as reduxUpdateEndDate, + updateStartDate as reduxUpdateStartDate, +} from '@reducers/filters'; // TODO: Apply gaps (margin, padding) from theme const useStyles = makeStyles(theme => ({ @@ -84,17 +87,41 @@ const renderSelectedDays = (dates, classes, range) => { }; function DatePicker({ - open, onToggle, range, startDate, endDate, + open, onTogglePresets, range, startDate, endDate, updateStartDate, updateEndDate, }) { const [showCalendar, setShowCalendar] = useState(() => open); + const [initialStartDate, setInitialStartDate] = useState(startDate); + const [initialEndDate, setInitialEndDate] = useState(); const classes = useStyles(); - const ref = useRef(null); - const closeCalendar = useCallback(() => setShowCalendar(false), []); + + const closeCalendar = useCallback( + () => { + if (startDate && endDate){ + setShowCalendar(false); + } else if (startDate && !endDate){ + // The calendar was closed with an incomplete date range selection so we need to restart + // startDate and endDate to their initial values + updateStartDate(initialStartDate); + updateEndDate(initialEndDate); + setShowCalendar(false); + } else { + // This should never happen. Log a warning. + console.warn('Try to set a new date selection. Dates were in an invalid state. StartDate: ', startDate, " endDate: ", endDate); + } + }, [startDate, endDate]); useOutsideClick(ref, closeCalendar); + const openCalendar = () => { + setInitialStartDate(startDate); + setInitialEndDate(endDate); + setShowCalendar(true); + } + useEffect(() => { setShowCalendar(false); + setInitialStartDate(startDate) + setInitialEndDate(endDate) }, [open]); const getCoordinates = () => { @@ -110,9 +137,14 @@ function DatePicker({ }; const toggleCalendar = () => { - setShowCalendar(prevState => !prevState); - if (onToggle) onToggle(); + if (showCalendar) { + closeCalendar(); + } else { + openCalendar(); + } + if (onTogglePresets) onTogglePresets(); }; + return (
@@ -132,6 +164,8 @@ function DatePicker({ {showCalendar ? ( ) : null}
@@ -142,7 +176,7 @@ function DatePicker({ DatePicker.propTypes = { range: PropTypes.bool, open: PropTypes.bool, - onToggle: PropTypes.func, + onTogglePresets: PropTypes.func, startDate: PropTypes.string, endDate: PropTypes.string, }; @@ -150,7 +184,7 @@ DatePicker.propTypes = { DatePicker.defaultProps = { open: false, range: false, - onToggle: null, + onTogglePresets: null, startDate: null, endDate: null, }; @@ -160,4 +194,9 @@ const mapStateToProps = state => ({ endDate: state.filters.endDate, }); -export default connect(mapStateToProps)(DatePicker); +const mapDispatchToProps = dispatch => ({ + updateStartDate: date => dispatch(reduxUpdateStartDate(date)), + updateEndDate: date => dispatch(reduxUpdateEndDate(date)), +}); + +export default connect(mapStateToProps, mapDispatchToProps)(DatePicker); diff --git a/components/common/ReactDayPicker/ReactDayPicker.jsx b/components/common/ReactDayPicker/ReactDayPicker.jsx index 6fdad9b83..b1569fcd8 100644 --- a/components/common/ReactDayPicker/ReactDayPicker.jsx +++ b/components/common/ReactDayPicker/ReactDayPicker.jsx @@ -7,11 +7,6 @@ import DayPicker from 'react-day-picker'; import { connect } from 'react-redux'; import makeStyles from '@mui/styles/makeStyles'; import clsx from 'clsx'; -import { - updateEndDate as reduxUpdateEndDate, - updateStartDate as reduxUpdateStartDate, -} from '@reducers/filters'; - import fonts from '@theme/fonts'; import colors from '@theme/colors'; import { INTERNAL_DATE_SPEC } from '../CONSTANTS'; @@ -175,13 +170,16 @@ function ReactDayPicker({ setFromDay(day); return; } - - // Our date range selection logic is very simple: the user is selecting the - // first day in their date range if from and to are set, or if they're both - // unset. Otherwise, they are selecting the last day. - if (!(startDate && endDate)) { - // If the user picks the first date then picks the second date that is before the first date - // Reassign the From and To Day + + // If both startDate and endDate were already selected. Start a new range selection. + if (startDate && endDate){ + setFromDay(day); + updateEndDate(null); + setEnteredTo(null); + // If startDate is selected and endDate is unselected, complete the range selection. + } else if (startDate && !endDate){ + // If the user selects the startDate then chooses an endDate that precedes it, + // swap the values of startDate and endDate if (moment(day).format(INTERNAL_DATE_SPEC) < startDate) { const tempDate = startDate; setToDay(moment(tempDate).toDate()); @@ -191,11 +189,10 @@ function ReactDayPicker({ } else { setToDay(day); } - return; - } - setFromDay(day); - updateEndDate(null); - setEnteredTo(null); + } else { + // This should never happen. Log a warning. + console.warn('Try to set a new date selection. Dates were in an invalid state. StartDate: ', startDate, " endDate: ", endDate); + } }; const handleDayMouseEnter = day => { @@ -248,14 +245,9 @@ ReactDayPicker.defaultProps = { endDate: null, }; -const mapDispatchToProps = dispatch => ({ - updateStartDate: date => dispatch(reduxUpdateStartDate(date)), - updateEndDate: date => dispatch(reduxUpdateEndDate(date)), -}); - const mapStateToProps = state => ({ startDate: state.filters.startDate, endDate: state.filters.endDate, }); -export default connect(mapStateToProps, mapDispatchToProps)(ReactDayPicker); +export default connect(mapStateToProps)(ReactDayPicker);