From c49d5b3a998b7be712400ec3f11ecbc184383985 Mon Sep 17 00:00:00 2001 From: Lukas Tyla Date: Fri, 15 Nov 2024 12:18:47 +0200 Subject: [PATCH 1/2] [DateTimeRangePicker] Use time in `referenceDate` when selecting date (#15429) --- .../DateRangeCalendar/DateRangeCalendar.tsx | 1 + .../tests/DesktopDateTimeRangePicker.test.tsx | 16 +++++++++++++ .../utils/date-range-manager.test.ts | 22 +++++++++++++++++- .../src/internals/utils/date-range-manager.ts | 23 ++++++++++++------- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx index e41859e4304f..f4c4ba2bf64d 100644 --- a/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx +++ b/packages/x-date-pickers-pro/src/DateRangeCalendar/DateRangeCalendar.tsx @@ -258,6 +258,7 @@ const DateRangeCalendar = React.forwardRef(function DateRangeCalendar< rangePosition, allowRangeFlip, shouldMergeDateAndTime: true, + referenceDate, }); const isNextSectionAvailable = availableRangePositions.includes(nextSelection); diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx index 078ffbc61c0b..74873e20a9a1 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx @@ -39,6 +39,22 @@ describe('', () => { expect(expectFieldValueV7(startSectionsContainer, '01/11/2018 04:05 PM')); expect(expectFieldValueV7(endSectionsContainer, '01/11/2018 05:10 PM')); }); + + it('should use time from `referenceDate` when selecting the day', () => { + render( + , + ); + + openPicker({ type: 'date-time-range', variant: 'desktop', initialFocus: 'start' }); + + fireEvent.click(screen.getByRole('gridcell', { name: '11' })); + + expect(screen.getByRole('option', { name: '2 hours', selected: true })).not.to.equal(null); + expect(screen.getByRole('option', { name: '15 minutes', selected: true })).not.to.equal(null); + expect(screen.getByRole('option', { name: 'PM', selected: true })).not.to.equal(null); + const startSectionsContainer = getFieldSectionsContainer(0); + expect(expectFieldValueV7(startSectionsContainer, '04/11/2022 02:15 PM')); + }); }); describe('disabled dates', () => { diff --git a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts index 1b49f7b99c60..61f6bae9b5b8 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.test.ts @@ -17,6 +17,15 @@ describe('date-range-manager', () => { expectedRange: [start2018, null], expectedNextSelection: 'end' as const, }, + { + range: [null, null], + rangePosition: 'start' as const, + newDate: start2018, + expectedRange: [start2018At4PM, null], + expectedNextSelection: 'end' as const, + shouldMergeDateAndTime: true, + referenceDate: start2018At4PM, + }, { range: [start2018, null], rangePosition: 'start' as const, @@ -98,7 +107,16 @@ describe('date-range-manager', () => { expectedNextSelection: 'start' as const, }, ].forEach( - ({ range, rangePosition, newDate, expectedRange, allowRangeFlip, expectedNextSelection }) => { + ({ + range, + rangePosition, + newDate, + expectedRange, + allowRangeFlip, + expectedNextSelection, + shouldMergeDateAndTime, + referenceDate, + }) => { it(`calculateRangeChange should return ${expectedRange} when selecting ${rangePosition} of ${range} with user input ${newDate}`, () => { expect( calculateRangeChange({ @@ -107,6 +125,8 @@ describe('date-range-manager', () => { newDate, rangePosition, allowRangeFlip, + shouldMergeDateAndTime, + referenceDate, }), ).to.deep.equal({ nextSelection: expectedNextSelection, diff --git a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts index 94d5d02e0eb0..649273ad88f5 100644 --- a/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts +++ b/packages/x-date-pickers-pro/src/internals/utils/date-range-manager.ts @@ -14,6 +14,7 @@ interface CalculateRangeChangeOptions { */ allowRangeFlip?: boolean; shouldMergeDateAndTime?: boolean; + referenceDate?: TDate | null; } interface CalculateRangeChangeResponse { @@ -28,6 +29,7 @@ export function calculateRangeChange({ rangePosition, allowRangeFlip = false, shouldMergeDateAndTime = false, + referenceDate, }: CalculateRangeChangeOptions): CalculateRangeChangeResponse { const [start, end] = range; @@ -41,21 +43,26 @@ export function calculateRangeChange({ } } + const newSelectedDate = + referenceDate && selectedDate && shouldMergeDateAndTime + ? mergeDateAndTime(utils, selectedDate, referenceDate) + : selectedDate; + if (rangePosition === 'start') { const truthyResult: CalculateRangeChangeResponse = allowRangeFlip - ? { nextSelection: 'start', newRange: [end!, selectedDate] } - : { nextSelection: 'end', newRange: [selectedDate, null] }; - return Boolean(end) && utils.isAfter(selectedDate!, end!) + ? { nextSelection: 'start', newRange: [end!, newSelectedDate] } + : { nextSelection: 'end', newRange: [newSelectedDate, null] }; + return Boolean(end) && utils.isAfter(newSelectedDate!, end!) ? truthyResult - : { nextSelection: 'end', newRange: [selectedDate, end] }; + : { nextSelection: 'end', newRange: [newSelectedDate, end] }; } const truthyResult: CalculateRangeChangeResponse = allowRangeFlip - ? { nextSelection: 'end', newRange: [selectedDate, start!] } - : { nextSelection: 'end', newRange: [selectedDate, null] }; - return Boolean(start) && utils.isBeforeDay(selectedDate!, start!) + ? { nextSelection: 'end', newRange: [newSelectedDate, start!] } + : { nextSelection: 'end', newRange: [newSelectedDate, null] }; + return Boolean(start) && utils.isBeforeDay(newSelectedDate!, start!) ? truthyResult - : { nextSelection: 'start', newRange: [start, selectedDate] }; + : { nextSelection: 'start', newRange: [start, newSelectedDate] }; } export function calculateRangePreview( From a30f877181fc8f8882bc96ade3d82af9a435da59 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 15 Nov 2024 12:46:18 +0200 Subject: [PATCH 2/2] fix test --- .../tests/DesktopDateTimeRangePicker.test.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx index 74873e20a9a1..bce93e8e49bd 100644 --- a/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx +++ b/packages/x-date-pickers-pro/src/DesktopDateTimeRangePicker/tests/DesktopDateTimeRangePicker.test.tsx @@ -42,7 +42,10 @@ describe('', () => { it('should use time from `referenceDate` when selecting the day', () => { render( - , + , ); openPicker({ type: 'date-time-range', variant: 'desktop', initialFocus: 'start' });