49 lines
1.2 KiB
TypeScript
49 lines
1.2 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
|
|
import { cn } from '@/lib/utils'
|
|
|
|
import type { ComponentPropsWithoutRef, FC, FocusEvent } from 'react'
|
|
|
|
|
|
const pad = (n: number): string => n.toString ().padStart (2, '0')
|
|
|
|
|
|
const toDateTimeLocalValue = (d: Date) => {
|
|
const y = d.getFullYear ()
|
|
const m = pad (d.getMonth () + 1)
|
|
const day = pad (d.getDate ())
|
|
const h = pad (d.getHours ())
|
|
const min = pad (d.getMinutes ())
|
|
return `${ y }-${ m }-${ day }T${ h }:${ min }:00`
|
|
}
|
|
|
|
|
|
type Props = Omit<ComponentPropsWithoutRef<'input'>, 'onChange'> & {
|
|
value?: string
|
|
onChange?: (isoUTC: string | null) => void
|
|
className?: string
|
|
onBlur?: (ev: FocusEvent<HTMLInputElement>) => void }
|
|
|
|
|
|
const DateTimeField: FC<Props> = ({ value, onChange, className, onBlur, ...rest }) => {
|
|
const [local, setLocal] = useState ('')
|
|
|
|
useEffect (() => {
|
|
setLocal (value ? toDateTimeLocalValue (new Date (value)) : '')
|
|
}, [value])
|
|
|
|
return (
|
|
<input
|
|
{...rest}
|
|
className={cn ('border rounded p-2', className)}
|
|
type="datetime-local"
|
|
value={local}
|
|
onChange={ev => {
|
|
const v = ev.target.value
|
|
setLocal (v)
|
|
onChange?.(v ? (new Date (v)).toISOString () : null)
|
|
}}
|
|
onBlur={onBlur}/>)
|
|
}
|
|
|
|
export default DateTimeField |