Skip to content

Commit

Permalink
Merge pull request #1856 from DorianDeptuch/bugfix-closing-the-datepi…
Browse files Browse the repository at this point in the history
…cker-should-cancel-the-ongoing-selection-1836

Bugfix closing the datepicker should cancel the ongoing selection 1836
  • Loading branch information
DorianDeptuch authored Nov 26, 2024
2 parents 4c9bdd7 + 14db20a commit ef620ab
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 37 deletions.
10 changes: 5 additions & 5 deletions components/DateSelector/DateSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ function DateSelector({
updateStartDate,
updateEndDate,
}) {
const [expanded, setExpanded] = useState(false);
const [expandedMenu, setExpandedMenu] = useState(false);
const classes = useStyles();

const handleOptionSelect = optionDates => {
const formattedStart = moment(optionDates[0]).format(dateFormat);
const formattedEnd = moment(optionDates[1]).format(dateFormat);
updateStartDate(formattedStart);
updateEndDate(formattedEnd);
setExpanded(false);
setExpandedMenu(false);
};

const closeOptionsOnDateToggle = useCallback(() => {
setExpanded(false);
setExpandedMenu(false);
}, []);

const {
Expand Down Expand Up @@ -64,12 +64,12 @@ function DateSelector({
</div>
</ArrowToolTip>
</Typography>
<SelectorBox onToggle={() => setExpanded(!expanded)} expanded={expanded}>
<SelectorBox onToggle={() => setExpandedMenu(!expandedMenu)} expanded={expandedMenu}>
<SelectorBox.Display>
<div className={classes.selector}>
<DatePicker
range={range}
onToggle={closeOptionsOnDateToggle}
onTogglePresets={closeOptionsOnDateToggle}
/>
<div className={classes.separator} />
</div>
Expand Down
57 changes: 48 additions & 9 deletions components/common/DatePicker/DatePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 => ({
Expand Down Expand Up @@ -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 = () => {
Expand All @@ -110,9 +137,14 @@ function DatePicker({
};

const toggleCalendar = () => {
setShowCalendar(prevState => !prevState);
if (onToggle) onToggle();
if (showCalendar) {
closeCalendar();
} else {
openCalendar();
}
if (onTogglePresets) onTogglePresets();
};

return (
<div ref={ref} className={classes.selector}>
<div onClick={toggleCalendar}>
Expand All @@ -132,6 +164,8 @@ function DatePicker({
{showCalendar ? (
<ReactDayPicker
range={range}
updateStartDate={updateStartDate}
updateEndDate={updateEndDate}
/>
) : null}
</div>
Expand All @@ -142,15 +176,15 @@ function DatePicker({
DatePicker.propTypes = {
range: PropTypes.bool,
open: PropTypes.bool,
onToggle: PropTypes.func,
onTogglePresets: PropTypes.func,
startDate: PropTypes.string,
endDate: PropTypes.string,
};

DatePicker.defaultProps = {
open: false,
range: false,
onToggle: null,
onTogglePresets: null,
startDate: null,
endDate: null,
};
Expand All @@ -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);
38 changes: 15 additions & 23 deletions components/common/ReactDayPicker/ReactDayPicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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());
Expand All @@ -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 => {
Expand Down Expand Up @@ -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);

0 comments on commit ef620ab

Please sign in to comment.