Files
web/components/TempDesignSystem/Form/Date/index.tsx
2024-04-16 13:28:28 +02:00

125 lines
3.7 KiB
TypeScript

"use client"
import { parseDate } from "@internationalized/date"
import { useController, useFormContext, useWatch } from "react-hook-form"
import { _ } from "@/lib/translation"
import { dt } from "@/lib/dt"
import { rangeArray } from "@/utils/rangeArray"
import {
DateInput,
DatePicker,
DateSegment,
Group,
} from "react-aria-components"
import Select from "./Select"
import styles from "./date.module.css"
import { DateName } from "./Select/select"
import type { DateProps } from "./date"
import type { Key } from "react-aria-components"
/** TODO: Get selecting with Enter-key to work */
export default function DateSelect({
control,
name,
registerOptions,
}: DateProps) {
const d = useWatch({ name })
const { setValue } = useFormContext()
const { field } = useController({
control,
name,
rules: registerOptions,
})
const currentYear = new Date().getFullYear()
const months = rangeArray(1, 12)
const years = rangeArray(1900, currentYear).reverse()
function handleOnSelect(select: Key, selector: DateName) {
/**
* Months are 0 index based and therefore we
* must subtract by 1 to get the selected month
*/
if (selector === DateName.month) {
select = Number(select) - 1
}
const newDate = dt(d).set(selector, Number(select))
setValue(name, newDate.format("YYYY-MM-DD"))
}
return (
<DatePicker
aria-label="Select date of birth"
granularity="day"
isRequired={!!registerOptions.required}
name={name}
ref={field.ref}
value={parseDate(d)}
>
<Group>
<DateInput className={styles.container}>
{(segment) => {
switch (segment.type) {
case "day":
let days = []
if (segment.maxValue && segment.minValue) {
days = rangeArray(segment.minValue, segment.maxValue)
} else {
days = Array.from(Array(segment.maxValue).keys()).map(
(i) => i + 1
)
}
return (
<DateSegment className={styles.day} segment={segment}>
<Select
aria-label={_("Day")}
items={days}
label={_("Day")}
name={DateName.date}
onSelect={handleOnSelect}
placeholder={_("DD")}
value={segment.value}
/>
</DateSegment>
)
case "month":
return (
<DateSegment className={styles.month} segment={segment}>
<Select
aria-label={_("Month")}
items={months}
label={_("Month")}
name={DateName.month}
onSelect={handleOnSelect}
placeholder={_("MM")}
value={segment.value}
/>
</DateSegment>
)
case "year":
return (
<DateSegment className={styles.year} segment={segment}>
<Select
aria-label={_("Year")}
items={years}
label={_("Year")}
name={DateName.year}
onSelect={handleOnSelect}
placeholder={_("YYYY")}
value={segment.value}
/>
</DateSegment>
)
default:
/** DateInput forces return of ReactElement */
return <></>
}
}}
</DateInput>
</Group>
</DatePicker>
)
}