From c10c079847395adae7fb60fee52f1bee0a38aaa7 Mon Sep 17 00:00:00 2001 From: Mirus Date: Tue, 2 Apr 2024 10:45:57 +0300 Subject: [PATCH 1/3] swapRange prop was added > > The change adds an optional property to component that allows the functionality of swapping dates if we want to allow the end user to pick dates in any order. This is a real request from the end users, and it will be handy if you work with big date ranges. --- docs-site/src/components/Examples/index.js | 7 +++++ docs-site/src/examples/rangeSwapRange.js | 22 +++++++++++++ src/index.jsx | 5 +++ test/datepicker_test.test.js | 36 ++++++++++++++++++++++ 4 files changed, 70 insertions(+) create mode 100644 docs-site/src/examples/rangeSwapRange.js diff --git a/docs-site/src/components/Examples/index.js b/docs-site/src/components/Examples/index.js index fef9e6f2f..b7120c0eb 100644 --- a/docs-site/src/components/Examples/index.js +++ b/docs-site/src/components/Examples/index.js @@ -105,6 +105,7 @@ import SelectsMultiple from "../../examples/selectsMultiple"; import CalendarIconExternal from "../../examples/calendarIconExternal"; import CalendarIconSvgIcon from "../../examples/calendarIconSvgIcon"; import ToggleCalendarOnIconClick from "../../examples/toggleCalendarOnIconClick"; +import SwapRange from "../../examples/rangeSwapRange"; import "./style.scss"; import "react-datepicker/dist/react-datepicker.css"; @@ -461,6 +462,12 @@ export default class exampleComponents extends React.Component { title: "Range Quarter Picker for one quarter picker", component: RangeQuarterPickerSelectsRange, }, + { + title: "Range Swap Range", + description: + "Swap the start and end date if the end date is before the start date in a pick sequence.", + component: SwapRange, + }, { title: "Read only datepicker", component: ReadOnly, diff --git a/docs-site/src/examples/rangeSwapRange.js b/docs-site/src/examples/rangeSwapRange.js new file mode 100644 index 000000000..d78e30da3 --- /dev/null +++ b/docs-site/src/examples/rangeSwapRange.js @@ -0,0 +1,22 @@ +() => { + const [startDate, setStartDate] = useState(new Date()); + const [endDate, setEndDate] = useState(null); + const onChange = (dates) => { + const [start, end] = dates; + setStartDate(start); + setEndDate(end); + }; + return ( + + ); +}; diff --git a/src/index.jsx b/src/index.jsx index 03d84ba3f..6839710e2 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -115,6 +115,7 @@ export default class DatePicker extends React.Component { showQuarterYearPicker: false, showWeekPicker: false, strictParsing: false, + swapRange: false, timeIntervals: 30, timeCaption: "Time", previousMonthAriaLabel: "Previous Month", @@ -253,6 +254,7 @@ export default class DatePicker extends React.Component { showWeekNumbers: PropTypes.bool, showYearDropdown: PropTypes.bool, strictParsing: PropTypes.bool, + swapRange: PropTypes.bool, forceShowMonthNavigation: PropTypes.bool, showDisabledMonthNavigation: PropTypes.bool, startDate: PropTypes.instanceOf(Date), @@ -634,6 +636,7 @@ export default class DatePicker extends React.Component { selectsMultiple, selectedDates, minTime, + swapRange, } = this.props; if ( @@ -689,6 +692,8 @@ export default class DatePicker extends React.Component { } else if (hasStartRange) { if (changedDate === null) { onChange([null, null], event); + } else if (isDateBefore(changedDate, startDate) && swapRange) { + onChange([changedDate, startDate], event); } else if (isDateBefore(changedDate, startDate)) { onChange([changedDate, null], event); } else { diff --git a/test/datepicker_test.test.js b/test/datepicker_test.test.js index bd2c7b372..4737f28a4 100644 --- a/test/datepicker_test.test.js +++ b/test/datepicker_test.test.js @@ -2217,6 +2217,42 @@ describe("DatePicker", () => { ); expect(endDate).toBeNull(); }); + + it("should swap dates of range when endDate set before startDate", () => { + const selected = utils.newDate(); + const selectedPrevious = utils.subDays(utils.newDate(), 3); + let [startDate, endDate] = [selected, null]; + const onChange = (dates = []) => { + [startDate, endDate] = dates; + }; + const { container } = render( + , + ); + + let selectedDay = findSelectedDay(container, selectedPrevious); + // Ensure that we're dealing with a date at the beginning of the month + if (!selectedDay) { + // If it's the beginning of the month & if the selectedPrevious is not being displayed, navigate to the previous month and reselect the selectedPrevious + goToLastMonth(container); + selectedDay = findSelectedDay(container, selectedPrevious); + } + + fireEvent.click(selectedDay); + expect(utils.formatDate(startDate, "yyyy-MM-dd")).toBe( + utils.formatDate(selectedPrevious, "yyyy-MM-dd"), + ); + expect(utils.formatDate(endDate, "yyyy-MM-dd")).toBe( + utils.formatDate(selected, "yyyy-MM-dd"), + ); + }); }); describe("selectsRange without inline", () => { From dd7f40cff59a035dcf2c23f83b0489a082577cf0 Mon Sep 17 00:00:00 2001 From: Mirus Date: Tue, 2 Apr 2024 11:16:43 +0300 Subject: [PATCH 2/3] chore: more reliable if/else --- src/index.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/index.jsx b/src/index.jsx index 6839710e2..5168b25d3 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -692,10 +692,12 @@ export default class DatePicker extends React.Component { } else if (hasStartRange) { if (changedDate === null) { onChange([null, null], event); - } else if (isDateBefore(changedDate, startDate) && swapRange) { - onChange([changedDate, startDate], event); } else if (isDateBefore(changedDate, startDate)) { - onChange([changedDate, null], event); + if (swapRange) { + onChange([changedDate, startDate], event); + } else { + onChange([changedDate, null], event); + } } else { onChange([startDate, changedDate], event); } From 8e5dd6bf32a5d4737b7467f36789043da2967f69 Mon Sep 17 00:00:00 2001 From: Mirus Date: Wed, 3 Apr 2024 10:13:22 +0300 Subject: [PATCH 3/3] test: replace the date to static --- test/datepicker_test.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/datepicker_test.test.js b/test/datepicker_test.test.js index 4737f28a4..bc51ebcb1 100644 --- a/test/datepicker_test.test.js +++ b/test/datepicker_test.test.js @@ -2219,8 +2219,8 @@ describe("DatePicker", () => { }); it("should swap dates of range when endDate set before startDate", () => { - const selected = utils.newDate(); - const selectedPrevious = utils.subDays(utils.newDate(), 3); + const selected = utils.newDate("2024-04-03"); + const selectedPrevious = utils.subDays(selected, 3); let [startDate, endDate] = [selected, null]; const onChange = (dates = []) => { [startDate, endDate] = dates;