siakad-itm/resources/js/components/datetime-field.tsx
2026-08-30 16:06:05 +07:00

78 lines
2.1 KiB
TypeScript

import { format, isSameDay } from 'date-fns';
import { useState } from 'react';
import { DatePicker } from '@/components/date-picker';
import InputError from '@/components/input-error';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
type DateTimeFieldProps = {
label: string;
name: string;
required?: boolean;
defaultValue?: string | null;
error?: string;
placeholder?: string;
maxNow?: boolean;
};
function parseDefault(value?: string | null): Date | undefined {
if (!value) {
return undefined;
}
const date = new Date(value);
return Number.isNaN(date.getTime()) ? undefined : date;
}
export function DateTimeField({
label,
name,
required,
defaultValue,
error,
placeholder = 'Pilih tanggal',
maxNow,
}: DateTimeFieldProps) {
const initial = parseDefault(defaultValue);
const [date, setDate] = useState<Date | undefined>(initial);
const [time, setTime] = useState(initial ? format(initial, 'HH:mm') : '');
const combined = date
? `${format(date, 'yyyy-MM-dd')} ${time || '00:00'}:00`
: '';
const now = new Date();
const maxTime =
maxNow && date && isSameDay(date, now)
? format(now, 'HH:mm')
: undefined;
return (
<div className="grid gap-2">
<Label>
{label}{' '}
{required && <span className="text-destructive">*</span>}
</Label>
<input type="hidden" name={name} value={combined} />
<div className="flex gap-2">
<DatePicker
value={date}
onChange={setDate}
placeholder={placeholder}
className="flex-1"
maxDate={maxNow ? now : undefined}
/>
<Input
type="time"
value={time}
onChange={(e) => setTime(e.target.value)}
max={maxTime}
className="w-28"
/>
</div>
<InputError message={error} />
</div>
);
}