diff --git a/components/TempDesignSystem/Form/Date/index.tsx b/components/TempDesignSystem/Form/Date/index.tsx index 7441ff471..8f5e7347a 100644 --- a/components/TempDesignSystem/Form/Date/index.tsx +++ b/components/TempDesignSystem/Form/Date/index.tsx @@ -28,6 +28,22 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { rules: registerOptions, }) + const dayLabel = intl.formatMessage({ id: "Day" }) + const monthLabel = intl.formatMessage({ id: "Month" }) + const yearLabel = intl.formatMessage({ id: "Year" }) + + const initialDate = dt(currentValue) + + const [selectedYear, setSelectedYear] = useState( + initialDate.isValid() ? initialDate.year() : null + ) + const [selectedMonth, setSelectedMonth] = useState( + initialDate.isValid() ? initialDate.month() : null + ) + const [selectedDay, setSelectedDay] = useState( + initialDate.isValid() ? initialDate.date() : null + ) + const currentYear = new Date().getFullYear() const months = rangeArray(1, 12).map((month) => ({ @@ -39,32 +55,60 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { .reverse() .map((year) => ({ value: year, label: year.toString() })) - // Ensure the user can't select a date that doesn't exist. - const daysInMonth = dt(currentValue).daysInMonth() + // Get max days based on selected month/year + const daysInMonth = + selectedMonth !== null && selectedYear !== null + ? dt(`${selectedYear}-${selectedMonth + 1}-01`).daysInMonth() + : 31 + const days = rangeArray(1, daysInMonth).map((day) => ({ value: day, label: `${day}`, })) - function createOnSelect(selector: DateName) { - /** - * Months are 0 index based and therefore we - * must subtract by 1 to get the selected month - */ - return (select: Key) => { - if (selector === DateName.month) { - select = Number(select) - 1 + function handleSegmentChange(selector: DateName, value: number) { + let newYear = selectedYear + let newMonth = selectedMonth + let newDay = selectedDay + + switch (selector) { + case DateName.year: + newYear = value + setSelectedYear(newYear) + break + /** + * Months are 0 index based and therefore we + * must subtract by 1 to get the selected month + */ + case DateName.month: + const monthZeroBased = value - 1 + newMonth = monthZeroBased + setSelectedMonth(newMonth) + if (selectedDay) { + const maxDays = dt(`${newYear}-${value}-01`).daysInMonth() + if (selectedDay > maxDays) { + newDay = maxDays + setSelectedDay(newDay) + } + } + break + case DateName.date: + newDay = value + setSelectedDay(newDay) + break + } + + // Check if all segments are set and update form value. + if (newYear && newMonth !== null && newDay) { + const newDate = dt().year(newYear).month(newMonth).date(newDay) + + if (newDate.isValid()) { + setValue(name, newDate.format("YYYY-MM-DD")) + trigger(name) } - const newDate = dt(currentValue).set(selector, Number(select)) - setValue(name, newDate.format("YYYY-MM-DD")) - trigger(name) } } - const dayLabel = intl.formatMessage({ id: "Day" }) - const monthLabel = intl.formatMessage({ id: "Month" }) - const yearLabel = intl.formatMessage({ id: "Year" }) - let dateValue = null try { /** @@ -98,7 +142,9 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { items={days} label={dayLabel} name={DateName.date} - onSelect={createOnSelect(DateName.date)} + onSelect={(select: Key) => + handleSegmentChange(DateName.date, Number(select)) + } placeholder="DD" required tabIndex={3} @@ -117,7 +163,9 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { items={months} label={monthLabel} name={DateName.month} - onSelect={createOnSelect(DateName.month)} + onSelect={(select: Key) => + handleSegmentChange(DateName.month, Number(select)) + } placeholder="MM" required tabIndex={2} @@ -136,7 +184,9 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) { items={years} label={yearLabel} name={DateName.year} - onSelect={createOnSelect(DateName.year)} + onSelect={(select: Key) => + handleSegmentChange(DateName.year, Number(select)) + } placeholder="YYYY" required tabIndex={1}