Skip to content

Commit f2e9d6e

Browse files
authored
Fix end time selection before selecting date (#6858)
1 parent 8329a32 commit f2e9d6e

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
type: fix
2+
fix:
3+
description: Fix `DateRangePicker` end time selection before selecting end date
4+
links:
5+
- https://github.com/palantir/blueprint/pull/6858

packages/datetime2/src/components/date-range-picker3/dateRangePicker3.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import classNames from "classnames";
18-
import { format } from "date-fns";
18+
import { addDays, format } from "date-fns";
1919
import * as React from "react";
2020
import type { DateFormatter, DayModifiers, DayMouseEventHandler, ModifiersClassNames } from "react-day-picker";
2121

@@ -265,17 +265,38 @@ export class DateRangePicker3 extends DateFnsLocalizedComponent<DateRangePicker3
265265

266266
const { value, time } = this.state;
267267
const newValue = DateUtils.getDateTime(
268-
value[dateIndex] != null ? DateUtils.clone(value[dateIndex]!) : new Date(),
268+
value[dateIndex] != null ? DateUtils.clone(value[dateIndex]!) : this.getDefaultDate(dateIndex),
269269
newTime,
270270
);
271271
const newDateRange: DateRange = [value[0], value[1]];
272272
newDateRange[dateIndex] = newValue;
273273
const newTimeRange: DateRange = [time[0], time[1]];
274274
newTimeRange[dateIndex] = newTime;
275+
275276
this.props.onChange?.(newDateRange);
276277
this.setState({ value: newDateRange, time: newTimeRange });
277278
};
278279

280+
// When a user sets the time value before choosing a date, we need to pick a date for them
281+
// The default depends on the value of the other date since there's an invariant
282+
// that the left/0 date is always less than the right/1 date
283+
private getDefaultDate = (dateIndex: number) => {
284+
const { value } = this.state;
285+
const otherIndex = dateIndex === 0 ? 1 : 0;
286+
const otherDate = value[otherIndex];
287+
if (otherDate == null) {
288+
return new Date();
289+
}
290+
291+
const { allowSingleDayRange } = this.props;
292+
if (!allowSingleDayRange) {
293+
const dateDiff = dateIndex === 0 ? -1 : 1;
294+
return addDays(otherDate, dateDiff);
295+
}
296+
297+
return otherDate;
298+
};
299+
279300
private handleTimeChangeLeftCalendar = (time: Date) => {
280301
this.handleTimeChange(time, 0);
281302
};

packages/datetime2/test/components/dateRangePicker3Tests.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import { assert } from "chai";
18-
import { format, parse } from "date-fns";
18+
import { addDays, format, parse } from "date-fns";
1919
import enUSLocale from "date-fns/locale/en-US";
2020
import { mount, type ReactWrapper } from "enzyme";
2121
import * as React from "react";
@@ -1293,11 +1293,35 @@ describe("<DateRangePicker3>", () => {
12931293
assert.equal(parseInt(minuteInputText, 10), newLeftMinute);
12941294
});
12951295

1296-
it("changing time without date uses today", () => {
1296+
it("changing time without date uses today, when other date not selected", () => {
12971297
render({ timePrecision: "minute" }).setTimeInput("minute", "left", 45);
12981298
assert.isTrue(DateUtils.isSameDay(onChangeSpy.firstCall.args[0][0] as Date, new Date()));
12991299
});
13001300

1301+
it("changing time without date uses other date if selected and `allowSingleDayRange` is true", () => {
1302+
const dateRange = render({ timePrecision: "minute", allowSingleDayRange: true });
1303+
1304+
dateRange.left.clickDay(10);
1305+
dateRange.setTimeInput("minute", "right", 45);
1306+
const [start, end] = dateRange.wrapper.state("value");
1307+
1308+
assert.isNotNull(start);
1309+
assert.isNotNull(end);
1310+
assert.isTrue(DateUtils.isSameDay(start!, end!));
1311+
});
1312+
1313+
it("changing time without date uses 1 day offset from other date if selected and `allowSingleDayRange` is false", () => {
1314+
const dateRange = render({ timePrecision: "minute", allowSingleDayRange: false });
1315+
1316+
dateRange.left.clickDay(10);
1317+
dateRange.setTimeInput("minute", "right", 45);
1318+
const [start, end] = dateRange.wrapper.state("value");
1319+
1320+
assert.isNotNull(start);
1321+
assert.isNotNull(end);
1322+
assert.isTrue(DateUtils.isSameDay(end!, addDays(start!, 1)));
1323+
});
1324+
13011325
it("clicking a shortcut with includeTime=false doesn't change time", () => {
13021326
render({ timePrecision: "minute", defaultValue: defaultRange }).clickShortcut();
13031327
assert.isTrue(DateUtils.isSameTime(onChangeSpy.firstCall.args[0][0] as Date, defaultRange[0]));

0 commit comments

Comments
 (0)