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
This commit is contained in:
Pontus Dreij
2025-03-28 13:07:49 +00:00
parent a4df9596e0
commit 7856d8c1f5
4 changed files with 49 additions and 35 deletions

View File

@@ -24,7 +24,7 @@ export default function DatePickerRangeDesktop({
close, close,
handleOnSelect, handleOnSelect,
locales, locales,
selectedDate, selectedRange,
}: DatePickerRangeProps) { }: DatePickerRangeProps) {
const lang = useLang() const lang = useLang()
const intl = useIntl() const intl = useIntl()
@@ -79,10 +79,10 @@ export default function DatePickerRangeDesktop({
mode="range" mode="range"
month={month} month={month}
numberOfMonths={2} numberOfMonths={2}
onDayClick={handleOnSelect} onSelect={handleOnSelect}
onMonthChange={handleMonthChange} onMonthChange={handleMonthChange}
required={false} required={false}
selected={selectedDate} selected={selectedRange}
startMonth={currentDate} startMonth={currentDate}
endMonth={endDate} endMonth={endDate}
weekStartsOn={1} weekStartsOn={1}

View File

@@ -21,7 +21,7 @@ export default function DatePickerRangeMobile({
close, close,
handleOnSelect, handleOnSelect,
locales, locales,
selectedDate, selectedRange,
}: DatePickerRangeProps) { }: DatePickerRangeProps) {
const lang = useLang() const lang = useLang()
const intl = useIntl() const intl = useIntl()
@@ -75,9 +75,9 @@ export default function DatePickerRangeMobile({
mode="range" mode="range"
/** Showing full year or what's left of it */ /** Showing full year or what's left of it */
numberOfMonths={13} numberOfMonths={13}
onDayClick={handleOnSelect} onSelect={handleOnSelect}
required required
selected={selectedDate} selected={selectedRange}
startMonth={currentDate} startMonth={currentDate}
weekStartsOn={1} weekStartsOn={1}
components={{ components={{

View File

@@ -16,6 +16,8 @@ import DatePickerRangeMobile from "./Range/Mobile"
import styles from "./date-picker.module.css" import styles from "./date-picker.module.css"
import type { DateRange } from "react-day-picker"
import type { DatePickerFormProps } from "@/types/components/datepicker" import type { DatePickerFormProps } from "@/types/components/datepicker"
const locales = { const locales = {
@@ -35,16 +37,12 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
const { register, setValue } = useFormContext() const { register, setValue } = useFormContext()
const ref = useRef<HTMLDivElement | null>(null) const ref = useRef<HTMLDivElement | null>(null)
const [isSelectingFrom, setIsSelectingFrom] = useState(true)
const close = useCallback(() => { const close = useCallback(() => {
if (!selectedDate.toDate) { if (!selectedDate.toDate) {
setValue(name, { setValue(name, {
fromDate: selectedDate.fromDate, fromDate: selectedDate.fromDate,
toDate: dt(selectedDate.fromDate).add(1, "day").format("YYYY-MM-DD"), toDate: dt(selectedDate.fromDate).add(1, "day").format("YYYY-MM-DD"),
}) })
setIsSelectingFrom(true)
} }
setIsOpen(false) setIsOpen(false)
@@ -54,34 +52,46 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
setIsOpen(true) 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, /* check if selected date is not before todays date,
which happens when "Enter" key is pressed in any other input field of the form */ which happens when "Enter" key is pressed in any other input field of the form */
if (!dt(selected).isBefore(dt(), "day")) { if (!dateClicked.isBefore(now, "day")) {
if (isSelectingFrom) { // 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, { setValue(name, {
fromDate: dt(selected).format("YYYY-MM-DD"), fromDate: dateClickedFormatted,
toDate: undefined, toDate: undefined,
}) })
setIsSelectingFrom(false) } else if (selectedDate.fromDate && !selectedDate.toDate) {
} else if (!dt(selectedDate.fromDate).isSame(dt(selected))) { // If the selected day is the same as the first date, we don't need to update the form value
const fromDate = dt(selectedDate.fromDate) if (dateClicked.isSame(selectedDate.fromDate)) {
const toDate = dt(selected) return
if (toDate.isAfter(fromDate)) { }
// We're selecting the second date
if (dateClicked.isBefore(selectedDate.fromDate)) {
// If second selected date is before first date, swap them
setValue(name, { setValue(name, {
fromDate: selectedDate.fromDate, fromDate: dateClickedFormatted,
toDate: toDate.format("YYYY-MM-DD"),
})
} else {
setValue(name, {
fromDate: toDate.format("YYYY-MM-DD"),
toDate: selectedDate.fromDate, 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( const closeIfOutside = useCallback(
(target: HTMLElement) => { (target: HTMLElement) => {
if (ref.current && target && !ref.current.contains(target)) { if (ref.current && target && !ref.current.contains(target)) {
@@ -153,9 +163,11 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
handleOnSelect={handleSelectDate} handleOnSelect={handleSelectDate}
locales={locales} locales={locales}
// DayPicker lib needs Daterange in form as below to show appropriate UI // DayPicker lib needs Daterange in form as below to show appropriate UI
selectedDate={{ selectedRange={{
from: selectedDate.fromDate, from: dt(selectedDate.fromDate).toDate(),
to: selectedDate.toDate, to: selectedDate.toDate
? dt(selectedDate.toDate).toDate()
: undefined,
}} }}
/> />
<DatePickerRangeMobile <DatePickerRangeMobile
@@ -163,9 +175,11 @@ export default function DatePickerForm({ name = "date" }: DatePickerFormProps) {
handleOnSelect={handleSelectDate} handleOnSelect={handleSelectDate}
locales={locales} locales={locales}
// DayPicker lib needs Daterange in form as below to show appropriate UI // DayPicker lib needs Daterange in form as below to show appropriate UI
selectedDate={{ selectedRange={{
from: selectedDate.fromDate, from: dt(selectedDate.fromDate).toDate(),
to: selectedDate.toDate, to: selectedDate.toDate
? dt(selectedDate.toDate).toDate()
: undefined,
}} }}
/> />
</div> </div>

View File

@@ -11,17 +11,17 @@ type LangWithoutEn = Lang.da | Lang.de | Lang.fi | Lang.no | Lang.sv
interface DatePickerProps { interface DatePickerProps {
close: () => void close: () => void
handleOnSelect: (selected: Date) => void
locales: Record<LangWithoutEn, Locale> locales: Record<LangWithoutEn, Locale>
selectedDate: DateRange | Date
startMonth?: Date startMonth?: Date
hideHeader?: boolean hideHeader?: boolean
} }
export interface DatePickerRangeProps extends DatePickerProps { export interface DatePickerRangeProps extends DatePickerProps {
selectedDate: DateRange selectedRange: DateRange | undefined
handleOnSelect: (nextRange: DateRange | undefined, selectedDay: Date) => void
} }
export interface DatePickerSingleProps extends DatePickerProps { export interface DatePickerSingleProps extends DatePickerProps {
selectedDate: Date selectedDate: Date
handleOnSelect: (selected: Date) => void
} }