Files
guilan-ace-frontend/src/components/AdminDateTimeField.tsx

97 lines
3.0 KiB
TypeScript

"use client";
import * as React from "react";
import DateObject from "react-date-object";
import persian from "react-date-object/calendars/persian";
import persian_fa from "react-date-object/locales/persian_fa";
import DatePicker from "react-multi-date-picker";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
type AdminDateTimeFieldProps = {
label: string;
value?: string | null;
onChange: (value: string | null) => void;
required?: boolean;
disabled?: boolean;
};
function splitDateTime(value?: string | null) {
if (!value) {
return { date: null as DateObject | null, time: "" };
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return { date: null, time: "" };
}
return {
date: new DateObject({ date, calendar: persian, locale: persian_fa }),
time: `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`,
};
}
function combineDateTime(date: DateObject | null, time: string) {
if (!date || !time || !/^\d{2}:\d{2}$/.test(time)) return null;
const gregorian = date.toDate();
const [hours, minutes] = time.split(":").map(Number);
gregorian.setHours(hours, minutes, 0, 0);
return gregorian.toISOString();
}
export default function AdminDateTimeField({
label,
value,
onChange,
required,
disabled,
}: AdminDateTimeFieldProps) {
const initial = React.useMemo(() => splitDateTime(value), [value]);
const [date, setDate] = React.useState<DateObject | null>(initial.date);
const [time, setTime] = React.useState(initial.time);
React.useEffect(() => {
setDate(initial.date);
setTime(initial.time);
}, [initial.date, initial.time]);
const emitChange = (nextDate: DateObject | null, nextTime: string) => {
onChange(combineDateTime(nextDate, nextTime));
};
return (
<div className="space-y-2">
<Label>
{label}
{required ? <span className="text-destructive"> *</span> : null}
</Label>
<div className="grid gap-2 sm:grid-cols-[1fr_120px]">
<DatePicker
value={date}
onChange={(next) => {
const nextDate = next instanceof DateObject ? next : null;
setDate(nextDate);
emitChange(nextDate, time);
}}
calendar={persian}
locale={persian_fa}
calendarPosition="bottom-right"
disabled={disabled}
inputClass="h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-right ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50"
placeholder="تاریخ"
containerClassName="w-full"
/>
<Input
dir="ltr"
type="time"
value={time}
disabled={disabled}
onChange={(event) => {
setTime(event.target.value);
emitChange(date, event.target.value);
}}
/>
</div>
</div>
);
}