diff --git a/src/frontend/src/components/forms/DateTimeField.tsx b/src/frontend/src/components/forms/DateTimeField.tsx new file mode 100644 index 0000000000..7c888f72af --- /dev/null +++ b/src/frontend/src/components/forms/DateTimeField.tsx @@ -0,0 +1,75 @@ +import type { ApiFormFieldType } from '@lib/types/Forms'; +import { t } from '@lingui/core/macro'; +import { DateTimePicker } from '@mantine/dates'; +import dayjs from 'dayjs'; +import customParseFormat from 'dayjs/plugin/customParseFormat'; +import { useCallback, useId, useMemo } from 'react'; +import type { FieldValues, UseControllerReturn } from 'react-hook-form'; + +dayjs.extend(customParseFormat); + +export default function DateTimeField({ + controller, + definition +}: Readonly<{ + controller: UseControllerReturn; + definition: ApiFormFieldType; +}>) { + const fieldId = useId(); + + const { + field, + fieldState: { error } + } = controller; + + const valueFormat = 'YYYY-MM-DD HH:mm:ss'; + + const onChange = useCallback( + (value: any) => { + // Convert the returned date object to a string + if (value) { + value = value.toString(); + value = dayjs(value).format(valueFormat); + } + + field.onChange(value); + definition.onValueChange?.(value); + }, + [field.onChange, definition, valueFormat] + ); + + const dateTimeValue: Date | null = useMemo(() => { + let dv: Date | null = null; + + if (field.value) { + dv = dayjs(field.value).toDate(); + } + + // Ensure that the date is valid + if (dv instanceof Date && !Number.isNaN(dv.getTime())) { + return dv; + } else { + return null; + } + }, [field.value]); + + return ( + + ); +} diff --git a/src/frontend/src/components/forms/fields/ApiFormField.tsx b/src/frontend/src/components/forms/fields/ApiFormField.tsx index cc6f12e710..1bbc8f932c 100644 --- a/src/frontend/src/components/forms/fields/ApiFormField.tsx +++ b/src/frontend/src/components/forms/fields/ApiFormField.tsx @@ -6,6 +6,7 @@ import { type Control, type FieldValues, useController } from 'react-hook-form'; import type { ApiFormFieldSet, ApiFormFieldType } from '@lib/types/Forms'; import { IconFileUpload } from '@tabler/icons-react'; +import DateTimeField from '../DateTimeField'; import { BooleanField } from './BooleanField'; import { ChoiceField } from './ChoiceField'; import DateField from './DateField'; @@ -161,10 +162,13 @@ export function ApiFormField({ /> ); case 'date': - case 'datetime': return ( ); + case 'datetime': + return ( + + ); case 'integer': case 'decimal': case 'float': diff --git a/src/frontend/src/components/forms/fields/DateField.tsx b/src/frontend/src/components/forms/fields/DateField.tsx index 56e5eb0a45..c1fc187d8a 100644 --- a/src/frontend/src/components/forms/fields/DateField.tsx +++ b/src/frontend/src/components/forms/fields/DateField.tsx @@ -22,12 +22,7 @@ export default function DateField({ fieldState: { error } } = controller; - const valueFormat = useMemo(() => { - // Determine the format based on the field type - return definition.field_type == 'date' - ? 'YYYY-MM-DD' - : 'YYYY-MM-DD HH:mm:ss'; - }, [definition.field_type]); + const valueFormat = 'YYYY-MM-DD'; const onChange = useCallback( (value: any) => { @@ -35,6 +30,8 @@ export default function DateField({ if (value) { value = value.toString(); value = dayjs(value).format(valueFormat); + + // Strip the time portion from the date input value = value.toString().split('T')[0]; }