141 lines
4.4 KiB
TypeScript
141 lines
4.4 KiB
TypeScript
"use client"
|
|
import { type ChangeEvent, useState } from "react"
|
|
import { DayPicker } from "react-day-picker"
|
|
import { useIntl } from "react-intl"
|
|
|
|
import { Lang } from "@/constants/languages"
|
|
import { dt } from "@/lib/dt"
|
|
|
|
import { CloseLargeIcon } from "@/components/Icons"
|
|
import Button from "@/components/TempDesignSystem/Button"
|
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
|
import Subtitle from "@/components/TempDesignSystem/Text/Subtitle"
|
|
import useLang from "@/hooks/useLang"
|
|
|
|
import styles from "./mobile.module.css"
|
|
import classNames from "react-day-picker/style.module.css"
|
|
|
|
import type { DatePickerProps } from "@/types/components/datepicker"
|
|
|
|
function addOneYear(_: undefined, i: number) {
|
|
return new Date().getFullYear() + i
|
|
}
|
|
|
|
const fiftyYearsAhead = Array.from({ length: 50 }, addOneYear)
|
|
|
|
export default function DatePickerMobile({
|
|
close,
|
|
handleOnSelect,
|
|
locales,
|
|
selectedDate,
|
|
}: DatePickerProps) {
|
|
const [selectedYear, setSelectedYear] = useState(() => dt().year())
|
|
const lang = useLang()
|
|
const intl = useIntl()
|
|
|
|
function handleSelectYear(evt: ChangeEvent<HTMLSelectElement>) {
|
|
setSelectedYear(Number(evt.currentTarget.value))
|
|
}
|
|
|
|
/** English is default language and doesn't need to be imported */
|
|
const locale = lang === Lang.en ? undefined : locales[lang]
|
|
const currentDate = dt().toDate()
|
|
const startOfCurrentMonth = dt(currentDate).set("date", 1).toDate()
|
|
const yesterday = dt(currentDate).subtract(1, "day").toDate()
|
|
|
|
const startMonth = dt().set("year", selectedYear).startOf("year").toDate()
|
|
const decemberOfYear = dt().set("year", selectedYear).endOf("year").toDate()
|
|
return (
|
|
<DayPicker
|
|
classNames={{
|
|
...classNames,
|
|
caption_label: `${classNames.caption_label} ${styles.captionLabel}`,
|
|
day: `${classNames.day} ${styles.day}`,
|
|
day_button: `${classNames.day_button} ${styles.dayButton}`,
|
|
footer: styles.footer,
|
|
month: styles.month,
|
|
month_caption: `${classNames.month_caption} ${styles.monthCaption}`,
|
|
months: styles.months,
|
|
range_end: styles.rangeEnd,
|
|
range_middle: styles.rangeMiddle,
|
|
range_start: styles.rangeStart,
|
|
root: `${classNames.root} ${styles.container}`,
|
|
week: styles.week,
|
|
weekday: `${classNames.weekday} ${styles.weekDay}`,
|
|
}}
|
|
disabled={{ from: startOfCurrentMonth, to: yesterday }}
|
|
endMonth={decemberOfYear}
|
|
excludeDisabled
|
|
footer
|
|
formatters={{
|
|
formatWeekdayName(weekday) {
|
|
return dt(weekday).locale(lang).format("ddd")
|
|
},
|
|
}}
|
|
hideNavigation
|
|
lang={lang}
|
|
locale={locale}
|
|
mode="range"
|
|
/** Showing full year or what's left of it */
|
|
numberOfMonths={12}
|
|
onDayClick={handleOnSelect}
|
|
required
|
|
selected={selectedDate}
|
|
startMonth={startMonth}
|
|
weekStartsOn={1}
|
|
components={{
|
|
Footer(props) {
|
|
return (
|
|
<footer className={props.className}>
|
|
<Button
|
|
className={styles.button}
|
|
intent="tertiary"
|
|
onPress={close}
|
|
size="large"
|
|
theme="base"
|
|
>
|
|
<Body color="white" textTransform="bold">
|
|
{intl.formatMessage({ id: "Select dates" })}
|
|
</Body>
|
|
</Button>
|
|
<div className={styles.backdrop} />
|
|
</footer>
|
|
)
|
|
},
|
|
MonthCaption(props) {
|
|
return (
|
|
<div className={props.className}>
|
|
<Subtitle asChild type="two">
|
|
{props.children}
|
|
</Subtitle>
|
|
</div>
|
|
)
|
|
},
|
|
Root({ children, ...props }) {
|
|
return (
|
|
<div {...props}>
|
|
<header className={styles.header}>
|
|
<select
|
|
className={styles.select}
|
|
defaultValue={selectedYear}
|
|
onChange={handleSelectYear}
|
|
>
|
|
{fiftyYearsAhead.map((year) => (
|
|
<option key={year} value={year}>
|
|
{year}
|
|
</option>
|
|
))}
|
|
</select>
|
|
<button className={styles.close} onClick={close} type="button">
|
|
<CloseLargeIcon />
|
|
</button>
|
|
</header>
|
|
{children}
|
|
</div>
|
|
)
|
|
},
|
|
}}
|
|
/>
|
|
)
|
|
}
|