From 7856d8c1f540bad5387bde5b275d53fe1aca95fe Mon Sep 17 00:00:00 2001 From: Pontus Dreij Date: Fri, 28 Mar 2025 13:07:49 +0000 Subject: [PATCH] Merged in fix(SW-1796)-issues-with-datepicker (pull request #1631) Fix(SW-1796) issues with datepicker * feat(SW-1796) Refactor DatePicker for Range * feat(SW-1796) cleanup * feat(SW-1796) added const for dateClicked and now Approved-by: Michael Zetterberg Approved-by: Niclas Edenvin --- .../components/DatePicker/Range/Desktop.tsx | 6 +- .../components/DatePicker/Range/Mobile.tsx | 6 +- .../components/DatePicker/index.tsx | 66 +++++++++++-------- .../types/components/datepicker.ts | 6 +- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/apps/scandic-web/components/DatePicker/Range/Desktop.tsx b/apps/scandic-web/components/DatePicker/Range/Desktop.tsx index ca4d1c0b3..f90ead47b 100644 --- a/apps/scandic-web/components/DatePicker/Range/Desktop.tsx +++ b/apps/scandic-web/components/DatePicker/Range/Desktop.tsx @@ -24,7 +24,7 @@ export default function DatePickerRangeDesktop({ close, handleOnSelect, locales, - selectedDate, + selectedRange, }: DatePickerRangeProps) { const lang = useLang() const intl = useIntl() @@ -79,10 +79,10 @@ export default function DatePickerRangeDesktop({ mode="range" month={month} numberOfMonths={2} - onDayClick={handleOnSelect} + onSelect={handleOnSelect} onMonthChange={handleMonthChange} required={false} - selected={selectedDate} + selected={selectedRange} startMonth={currentDate} endMonth={endDate} weekStartsOn={1} diff --git a/apps/scandic-web/components/DatePicker/Range/Mobile.tsx b/apps/scandic-web/components/DatePicker/Range/Mobile.tsx index d562049e4..8da35a856 100644 --- a/apps/scandic-web/components/DatePicker/Range/Mobile.tsx +++ b/apps/scandic-web/components/DatePicker/Range/Mobile.tsx @@ -21,7 +21,7 @@ export default function DatePickerRangeMobile({ close, handleOnSelect, locales, - selectedDate, + selectedRange, }: DatePickerRangeProps) { const lang = useLang() const intl = useIntl() @@ -75,9 +75,9 @@ export default function DatePickerRangeMobile({ mode="range" /** Showing full year or what's left of it */ numberOfMonths={13} - onDayClick={handleOnSelect} + onSelect={handleOnSelect} required - selected={selectedDate} + selected={selectedRange} startMonth={currentDate} weekStartsOn={1} components={{ diff --git a/apps/scandic-web/components/DatePicker/index.tsx b/apps/scandic-web/components/DatePicker/index.tsx index e39e55fc9..b9a56cd0e 100644 --- a/apps/scandic-web/components/DatePicker/index.tsx +++ b/apps/scandic-web/components/DatePicker/index.tsx @@ -16,6 +16,8 @@ import DatePickerRangeMobile from "./Range/Mobile" import styles from "./date-picker.module.css" +import type { DateRange } from "react-day-picker" + import type { DatePickerFormProps } from "@/types/components/datepicker" const locales = { @@ -35,16 +37,12 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) { const { register, setValue } = useFormContext() const ref = useRef(null) - const [isSelectingFrom, setIsSelectingFrom] = useState(true) - const close = useCallback(() => { if (!selectedDate.toDate) { setValue(name, { fromDate: selectedDate.fromDate, toDate: dt(selectedDate.fromDate).add(1, "day").format("YYYY-MM-DD"), }) - - setIsSelectingFrom(true) } setIsOpen(false) @@ -54,34 +52,46 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) { setIsOpen(true) } - function handleSelectDate(selected: Date) { + function handleSelectDate( + _nextRange: DateRange | undefined, + selectedDay: Date + ) { + const now = dt() + const dateClicked = dt(selectedDay) + const dateClickedFormatted = dateClicked.format("YYYY-MM-DD") /* check if selected date is not before todays date, which happens when "Enter" key is pressed in any other input field of the form */ - if (!dt(selected).isBefore(dt(), "day")) { - if (isSelectingFrom) { + if (!dateClicked.isBefore(now, "day")) { + // Handle form value updates based on the requirements + if (selectedDate.fromDate && selectedDate.toDate) { + // Both dates were previously selected, starting fresh with new date setValue(name, { - fromDate: dt(selected).format("YYYY-MM-DD"), + fromDate: dateClickedFormatted, toDate: undefined, }) - setIsSelectingFrom(false) - } else if (!dt(selectedDate.fromDate).isSame(dt(selected))) { - const fromDate = dt(selectedDate.fromDate) - const toDate = dt(selected) - if (toDate.isAfter(fromDate)) { + } else if (selectedDate.fromDate && !selectedDate.toDate) { + // If the selected day is the same as the first date, we don't need to update the form value + if (dateClicked.isSame(selectedDate.fromDate)) { + return + } + // We're selecting the second date + if (dateClicked.isBefore(selectedDate.fromDate)) { + // If second selected date is before first date, swap them setValue(name, { - fromDate: selectedDate.fromDate, - toDate: toDate.format("YYYY-MM-DD"), - }) - } else { - setValue(name, { - fromDate: toDate.format("YYYY-MM-DD"), + fromDate: dateClickedFormatted, toDate: selectedDate.fromDate, }) + } else { + // If second selected date is after first date, keep order + setValue(name, { + fromDate: selectedDate.fromDate, + toDate: dateClickedFormatted, + }) } - setIsSelectingFrom(true) } } } + const closeIfOutside = useCallback( (target: HTMLElement) => { if (ref.current && target && !ref.current.contains(target)) { @@ -153,9 +163,11 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) { handleOnSelect={handleSelectDate} locales={locales} // DayPicker lib needs Daterange in form as below to show appropriate UI - selectedDate={{ - from: selectedDate.fromDate, - to: selectedDate.toDate, + selectedRange={{ + from: dt(selectedDate.fromDate).toDate(), + to: selectedDate.toDate + ? dt(selectedDate.toDate).toDate() + : undefined, }} /> diff --git a/apps/scandic-web/types/components/datepicker.ts b/apps/scandic-web/types/components/datepicker.ts index c67abf918..60d5f03a7 100644 --- a/apps/scandic-web/types/components/datepicker.ts +++ b/apps/scandic-web/types/components/datepicker.ts @@ -11,17 +11,17 @@ type LangWithoutEn = Lang.da | Lang.de | Lang.fi | Lang.no | Lang.sv interface DatePickerProps { close: () => void - handleOnSelect: (selected: Date) => void locales: Record - selectedDate: DateRange | Date startMonth?: Date hideHeader?: boolean } export interface DatePickerRangeProps extends DatePickerProps { - selectedDate: DateRange + selectedRange: DateRange | undefined + handleOnSelect: (nextRange: DateRange | undefined, selectedDay: Date) => void } export interface DatePickerSingleProps extends DatePickerProps { selectedDate: Date + handleOnSelect: (selected: Date) => void }