import { useEffect, useState } from 'react'; import DatePicker, { DatePickerProps, } from 'react-date-picker/dist/entry.nostyle'; import classnames from 'classnames'; import parseISO from 'date-fns/parseISO'; import { InjectedFieldProps } from '../Field/InjectedFieldProps'; import { FormDefaults } from '../FormDefaults'; import Group, { GroupProps } from '../Group'; export interface DatePickerGroupProps extends InjectedFieldProps, Omit< DatePickerProps, keyof InjectedFieldProps | 'name' | 'value' | 'className' >, Omit | 'children'> { convert: (arg: Date) => T; } /** * Field for inputting dates. Uses `` and ``. * * Uses [react-date-picker](https://www.npmjs.com/package/react-date-picker) */ export default function DatePickerGroup({ input, meta, label, helpText, className, required, disabled, convert, maxDate = new Date(9999, 11, 31), minDate = new Date(1000, 0, 1), ...rest }: DatePickerGroupProps) { const [displayDate, setDisplayDate] = useState(null); useEffect(() => { if (!input.value) { setDisplayDate(null); } else if (typeof input.value === 'string') { if (input.value.indexOf('T') === -1) { setDisplayDate(new Date(`${input.value}T00:00:00.000`)); } else { setDisplayDate(new Date(input.value)); } } }, [setDisplayDate, input.value]); return (
{ // Manually trigger Formik's onBlur when the user clicks away from the date picker input.onBlur(); }}>
); function handleChange(e: Date | Date[] | string | undefined) { const { onChange } = input; if (onChange === null) { return; } if (!e) { onChange(undefined); setDisplayDate(null); return; } else if (typeof e === 'string') { const parsedValue = parseISO(e.toString().split('T')[0]); setDisplayDate(parsedValue); onChange(convert(parsedValue)); } else if (e instanceof Date) { const parsedValue = parseISO( convertToTimeZoneInsensitiveISOString(e).split('T')[0] ); setDisplayDate(parsedValue); onChange(convert(parsedValue)); } else { // e is instanceof Date[] const parsedValue = parseISO( convertToTimeZoneInsensitiveISOString(e[0]).split('T')[0] ); setDisplayDate(parsedValue); onChange(convert(parsedValue)); } } } export function convertToTimeZoneInsensitiveISOString(date: Date): string { const year = new Intl.DateTimeFormat('en', { year: 'numeric' }) .format(date) .substring(0, 4) .padStart(4, '0'); const month = new Intl.DateTimeFormat('en', { month: '2-digit' }).format( date ); const day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date); return `${year}-${month}-${day}T00:00:00.000Z`; }