|
1 | 1 | import { Dialog } from '@headlessui/react';
|
2 | 2 | import { QuestionMarkCircleIcon } from '@heroicons/react/20/solid';
|
3 | 3 | import { XMarkIcon } from '@heroicons/react/24/outline';
|
| 4 | +import { addMinutes, format, formatISO, parseISO } from 'date-fns'; |
4 | 5 | import { Form, Formik, useField, useFormikContext } from 'formik';
|
5 |
| -import moment from 'moment'; |
6 | 6 | import { forwardRef, useEffect, useState } from 'react';
|
7 | 7 | import { useSelector } from 'react-redux';
|
8 | 8 | import { Link } from 'react-router-dom';
|
@@ -132,40 +132,40 @@ function ConstraintValueDateTimeInput(props: ConstraintInputProps) {
|
132 | 132 |
|
133 | 133 | const [field] = useField({
|
134 | 134 | ...props,
|
135 |
| - validate: (value) => { |
136 |
| - const m = moment(value); |
137 |
| - return m.isValid() ? undefined : 'Value is not a valid datetime'; |
| 135 | + validate: (value: string) => { |
| 136 | + const m = parseISO(value); |
| 137 | + return m ? undefined : 'Value is not a valid datetime'; |
138 | 138 | }
|
139 | 139 | });
|
140 | 140 |
|
141 |
| - const [fieldDate, setFieldDate] = useState(field.value?.split('T')[0] || ''); |
142 |
| - const [fieldTime, setFieldTime] = useState(field.value?.split('T')[1] || ''); |
| 141 | + const [fieldDate, setFieldDate] = useState(''); |
| 142 | + const [fieldTime, setFieldTime] = useState(''); |
143 | 143 |
|
144 | 144 | useEffect(() => {
|
145 |
| - // if both date and time are set, then combine, parse, and set the value |
146 |
| - if ( |
147 |
| - fieldDate && |
148 |
| - fieldDate.trim() !== '' && |
149 |
| - fieldTime && |
150 |
| - fieldTime.trim() !== '' |
151 |
| - ) { |
152 |
| - if (timezone === Timezone.LOCAL) { |
153 |
| - // if local timezone, then parse as local (moment default) and convert to UTC |
154 |
| - const m = moment(`${fieldDate}T${fieldTime}`); |
155 |
| - setFieldValue(field.name, m.utc().format()); |
156 |
| - return; |
| 145 | + if (field.value) { |
| 146 | + let m = parseISO(field.value); |
| 147 | + if (timezone === Timezone.UTC) { |
| 148 | + // if utc timezone, then convert to UTC |
| 149 | + m = addMinutes(m, m.getTimezoneOffset()); |
157 | 150 | }
|
158 |
| - |
159 |
| - // otherwise, parse as UTC |
160 |
| - const m = moment.utc(`${fieldDate}T${fieldTime}`); |
161 |
| - setFieldValue(field.name, m.format()); |
162 |
| - return; |
| 151 | + setFieldDate(format(m, 'yyyy-MM-dd')); |
| 152 | + setFieldTime(format(m, 'HH:mm')); |
163 | 153 | }
|
| 154 | + }, [field.value, timezone]); |
164 | 155 |
|
165 |
| - // otherwise, if only date is set, then parse and set the value |
| 156 | + useEffect(() => { |
| 157 | + // if both date and time are set, then combine, parse, and set the value |
166 | 158 | if (fieldDate && fieldDate.trim() !== '') {
|
167 |
| - const m = moment(fieldDate); |
168 |
| - setFieldValue(field.name, m.utc().format()); |
| 159 | + let d = `${fieldDate}T00:00:00`; |
| 160 | + if (fieldTime && fieldTime.trim() !== '') { |
| 161 | + d = `${fieldDate}T${fieldTime}:00`; |
| 162 | + } |
| 163 | + let m = parseISO(d); |
| 164 | + if (timezone === Timezone.UTC) { |
| 165 | + // if utc timezone, then convert to UTC |
| 166 | + m = addMinutes(m, -m.getTimezoneOffset()); |
| 167 | + } |
| 168 | + setFieldValue(field.name, formatISO(m)); |
169 | 169 | }
|
170 | 170 | }, [timezone, field.name, fieldDate, fieldTime, setFieldValue]);
|
171 | 171 |
|
@@ -209,11 +209,7 @@ function ConstraintValueDateTimeInput(props: ConstraintInputProps) {
|
209 | 209 | type="time"
|
210 | 210 | id="valueTime"
|
211 | 211 | name="valueTime"
|
212 |
| - value={ |
213 |
| - timezone === Timezone.LOCAL |
214 |
| - ? moment(fieldTime, 'HH:mm Z').format('HH:mm') |
215 |
| - : moment.utc(fieldTime, 'HH:mm Z').format('HH:mm') |
216 |
| - } |
| 212 | + value={fieldTime} |
217 | 213 | onChange={(e) => {
|
218 | 214 | setFieldTime(e.target.value);
|
219 | 215 | }}
|
|
0 commit comments