diff --git a/src/components/DatePicker/DatePicker.jsx b/src/components/DatePicker/DatePicker.jsx index b809345d7..750a3bea0 100644 --- a/src/components/DatePicker/DatePicker.jsx +++ b/src/components/DatePicker/DatePicker.jsx @@ -40,16 +40,27 @@ export const DatePicker = ({ timezoneName = null, // seller timezone (e.g. "America/Los_Angeles") to return correct today date ...rest }) => { - const initialValue = variant === variants.single ? value : value?.from; - const [currentMonth, setCurrentMonth] = useState(initialValue); - const [startMonth, setStartMonth] = useState(value?.from); - const [endMonth, setEndMonth] = useState( - dayjs(value?.to).isSame(dayjs(value?.from), "month") - ? dayjs(value?.from).add(1, "month").toDate() - : value?.to ?? dayjs(value?.from).add(1, "month").toDate(), - ); + const initialValue = value ? (variant === variants.single ? value : value.from) : null; + const [currentMonth, setCurrentMonth] = useState(initialValue ?? dayjs().toDate()); + const [startMonth, setStartMonth] = useState(() => { + if (!value || !value.from) { + return new Date(); + } + + return value.from; + }); + const [endMonth, setEndMonth] = useState(() => { + if (!value || !value.to || !value.from) { + return dayjs(new Date()).add(1, "month").toDate(); + } + + return dayjs(value.to).isSame(dayjs(value.from), "month") + ? dayjs(value.from).add(1, "month").toDate() + : value.to; + }); const [rangeName, setRangeName] = useState(""); const isRangeVariant = variant === variants.range; + const isValidValue = value && value.from && value.to; // Sync internal month state with outside. useEffect(() => { @@ -115,11 +126,11 @@ export const DatePicker = ({ setRangeName(""); if (isRangeVariant) { - if (value?.from && value.to) { + if (isValidValue) { // This allows us to easily select another date range, // if both dates are selected. onChange({ from: day, to: null }, options, event); - } else if ((value?.from || value.to).getTime() === day.getTime()) { + } else if (value && (value.from || value.to) && (value.from || value.to).getTime() === day.getTime()) { const from = dayjs(day).startOf("day").toDate(); const to = dayjs(day).endOf("day").toDate(); @@ -132,9 +143,10 @@ export const DatePicker = ({ } }; - const CaptionElement = shouldShowYearPicker - ? ({ date }) => - : undefined; + const CaptionElement = + shouldShowYearPicker && currentMonth + ? ({ date }) => + : undefined; const renderDay = (date) => { const tooltipContent = getTooltip?.(date); @@ -161,10 +173,9 @@ export const DatePicker = ({ ); }; - const rangeModifier = isRangeVariant ? { start: value?.from, end: value.to } : null; - + const rangeModifier = isRangeVariant && isValidValue ? { start: value.from, end: value.to } : null; // Comparing `from` and `to` dates hides a weird CSS style when you select the same date twice in a date range. - const useDateRangeStyle = isRangeVariant && value?.from?.getTime() !== value.to?.getTime(); + const useDateRangeStyle = isRangeVariant && isValidValue && value.from?.getTime() !== value.to?.getTime(); // Return the same value if it is already dayjs object or has range variant otherwise format it to dayJs object const selectedDays = value && (dayjs.isDayjs(value) || isRangeVariant ? value : dayjs(value).toDate()); @@ -225,7 +236,7 @@ export const DatePicker = ({ {components.Footer ? : null} {useDateRangeStyle && shouldShowRelativeRanges && ( -
+
{ const isStartDateIsTheSameMonth = dayjs(value?.from).isSame(dayjs(value?.to), "month"); - const CaptionStartElement = shouldShowYearPicker - ? ({ date }) => - : undefined; - - const CaptionEndElement = shouldShowYearPicker - ? ({ date }) => - : undefined; + const CaptionStartElement = + shouldShowYearPicker && startMonth + ? ({ date }) => ( + + ) + : undefined; + + const CaptionEndElement = + shouldShowYearPicker && endMonth + ? ({ date }) => + : undefined; const isDisabledStartDays = (date) => { if (isFunction(disabledDays)) { @@ -133,7 +137,7 @@ const RangeDatePicker = ({ disabledDays={isDisabledStartDays} navbarElement={NavbarElement} captionElement={CaptionStartElement} - selectedDays={selectedDays} + selectedDays={[selectedDays?.from, selectedDays]} renderDay={renderStartDay} getTooltip={getTooltip} onDayClick={(day, options, event) => handleDayClick(day, options, event, true)} diff --git a/src/stories/DataDisplay/DateRangePicker.stories.js b/src/stories/DataDisplay/DateRangePicker.stories.js index 47c79657c..7017e8558 100644 --- a/src/stories/DataDisplay/DateRangePicker.stories.js +++ b/src/stories/DataDisplay/DateRangePicker.stories.js @@ -63,11 +63,9 @@ export const RelativeDateRanges = () => { export const DateRangeWithInput = ({ shouldShowRelativeRanges, ranges }) => { const defaultValue = { from: today, to: dayjs(today).add(7, "days").toDate() }; const [value, setValue] = useState(defaultValue); - const [displayValue, setDisplayValue] = useState(defaultValue); - const handleChange = (newValue, displayValue) => { + const handleChange = (newValue) => { setValue(newValue); - setDisplayValue(displayValue ?? newValue); }; return ( @@ -81,9 +79,9 @@ export const DateRangeWithInput = ({ shouldShowRelativeRanges, ranges }) => { onChange={handleChange} >
- {dayjs(displayValue.from).format("LL")} + {value.from ? dayjs(value.from).format("LL") : "Pending"}  to  - {displayValue.to ? dayjs(displayValue.to).format("LL") : "Pending"} + {value.to ? dayjs(value.to).format("LL") : "Pending"}