From a24ececd67cc3f50e801ae88456118136247b944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stanis=C5=82aw=20Zakrzewski?= <41862803+stanislaw-zakrzewski@users.noreply.github.com> Date: Tue, 6 Aug 2024 11:47:22 +0200 Subject: [PATCH] [115] Update formik datepicker date parsing method to avoid timezone issues (#133) * Fix parsing date, that is passed to the formik date picker * Update date parsing for multiple timezones --- .../ui/src/api/models/Day0Case.ts | 30 ++++++------ .../ui/src/components/CaseForm.tsx | 46 +++++++------------ .../common-form-fields/FormikFields.tsx | 4 +- .../new-case-form-fields/TravelHistory.tsx | 2 +- .../new-case-form-fields/Vaccines.tsx | 2 +- .../ui/src/components/util/date.tsx | 19 +++++--- 6 files changed, 48 insertions(+), 55 deletions(-) diff --git a/verification/curator-service/ui/src/api/models/Day0Case.ts b/verification/curator-service/ui/src/api/models/Day0Case.ts index 19d03d7b..434a47f3 100644 --- a/verification/curator-service/ui/src/api/models/Day0Case.ts +++ b/verification/curator-service/ui/src/api/models/Day0Case.ts @@ -94,26 +94,26 @@ export interface Location { } export interface Events { - dateEntry: string | null; - dateReported: string | null; - dateLastModified: string | null; - dateOnset?: string | null; - dateConfirmation?: string | null; + dateEntry: Date | string | null; + dateReported: Date | string | null; + dateLastModified: Date | string | null; + dateOnset?: Date | string | null; + dateConfirmation?: Date | string | null; confirmationMethod?: string; - dateOfFirstConsult?: string | null; + dateOfFirstConsult?: Date | string | null; hospitalized?: YesNo | ''; reasonForHospitalization?: HospitalizationReason | ''; - dateHospitalization?: string | null; - dateDischargeHospital?: string | null; + dateHospitalization?: Date | string | null; + dateDischargeHospital?: Date | string | null; intensiveCare?: YesNo | ''; - dateAdmissionICU?: string | null; - dateDischargeICU?: string | null; + dateAdmissionICU?: Date | string | null; + dateDischargeICU?: Date | string | null; homeMonitoring?: YesNo | ''; isolated?: YesNo | ''; - dateIsolation?: string | null; + dateIsolation?: Date | string | null; outcome?: Outcome | ''; - dateDeath?: string | null; - dateRecovered?: string | null; + dateDeath?: Date | string | null; + dateRecovered?: Date | string | null; } export interface PreexistingConditions { @@ -134,7 +134,7 @@ export interface Transmission { export interface TravelHistory { travelHistory?: YesNo | ''; - travelHistoryEntry?: string | null; + travelHistoryEntry?: Date | string | null; travelHistoryStart?: string; travelHistoryLocation?: string; travelHistoryCountry?: string; @@ -237,7 +237,7 @@ interface PreexistingConditionsFormValues { interface VaccinationFormValues { vaccination?: YesNo | ''; vaccineName?: string; - vaccineDate?: string | null; + vaccineDate?: Date | string | null; vaccineSideEffects?: string[]; } diff --git a/verification/curator-service/ui/src/components/CaseForm.tsx b/verification/curator-service/ui/src/components/CaseForm.tsx index c8b80586..f9e9a18d 100644 --- a/verification/curator-service/ui/src/components/CaseForm.tsx +++ b/verification/curator-service/ui/src/components/CaseForm.tsx @@ -225,6 +225,8 @@ const initialValuesFromCase = ( }, events: { ...c.events, + dateEntry: toLocalDate(c.events.dateEntry), + dateReported: toLocalDate(c.events.dateReported), dateOnset: toLocalDate(c.events.dateOnset), dateConfirmation: toLocalDate(c.events.dateConfirmation), dateOfFirstConsult: toLocalDate(c.events.dateOfFirstConsult), @@ -438,45 +440,31 @@ export default function CaseForm(props: Props): JSX.Element { }, events: { ...values.events, - dateEntry: - toUTCDate(values.events.dateEntry || undefined) || null, - dateReported: - toUTCDate(values.events.dateReported || undefined) || null, - dateOnset: toUTCDate(values.events.dateOnset || undefined), - dateConfirmation: toUTCDate( - values.events.dateConfirmation || undefined, - ), + dateEntry: toUTCDate(values.events.dateEntry) || null, + dateReported: toUTCDate(values.events.dateReported) || null, + dateOnset: toUTCDate(values.events.dateOnset), + dateConfirmation: toUTCDate(values.events.dateConfirmation), confirmationMethod: values.events.confirmationMethod || undefined, - dateOfFirstConsult: toUTCDate( - values.events.dateOfFirstConsult || undefined, - ), + dateOfFirstConsult: toUTCDate(values.events.dateOfFirstConsult), hospitalized: values.events.hospitalized || undefined, reasonForHospitalization: values.events.reasonForHospitalization || undefined, dateHospitalization: toUTCDate( - values.events.dateHospitalization || undefined, + values.events.dateHospitalization, ), dateDischargeHospital: toUTCDate( - values.events.dateDischargeHospital || undefined, + values.events.dateDischargeHospital, ), intensiveCare: values.events.intensiveCare || undefined, - dateAdmissionICU: toUTCDate( - values.events.dateAdmissionICU || undefined, - ), - dateDischargeICU: toUTCDate( - values.events.dateDischargeICU || undefined, - ), + dateAdmissionICU: toUTCDate(values.events.dateAdmissionICU), + dateDischargeICU: toUTCDate(values.events.dateDischargeICU), homeMonitoring: values.events.homeMonitoring || undefined, isolated: values.events.isolated || undefined, - dateIsolation: toUTCDate( - values.events.dateIsolation || undefined, - ), + dateIsolation: toUTCDate(values.events.dateIsolation), outcome: values.events.outcome || undefined, - dateDeath: toUTCDate(values.events.dateDeath || undefined), - dateRecovered: toUTCDate( - values.events.dateRecovered || undefined, - ), + dateDeath: toUTCDate(values.events.dateDeath), + dateRecovered: toUTCDate(values.events.dateRecovered), }, preexistingConditions: { ...values.preexistingConditions, @@ -490,9 +478,7 @@ export default function CaseForm(props: Props): JSX.Element { ...values.vaccination, vaccineSideEffects: vaccineSideEffects.join(', '), vaccination: values.vaccination.vaccination || undefined, - vaccineDate: toUTCDate( - values.vaccination.vaccineDate || undefined, - ), + vaccineDate: toUTCDate(values.vaccination.vaccineDate), }, transmission: { ...values.transmission, @@ -504,7 +490,7 @@ export default function CaseForm(props: Props): JSX.Element { ...values.travelHistory, travelHistory: values.travelHistory.travelHistory || undefined, travelHistoryEntry: toUTCDate( - values.travelHistory.travelHistoryEntry || undefined, + values.travelHistory.travelHistoryEntry, ), }, location: { diff --git a/verification/curator-service/ui/src/components/common-form-fields/FormikFields.tsx b/verification/curator-service/ui/src/components/common-form-fields/FormikFields.tsx index fe1add23..783ff5bc 100644 --- a/verification/curator-service/ui/src/components/common-form-fields/FormikFields.tsx +++ b/verification/curator-service/ui/src/components/common-form-fields/FormikFields.tsx @@ -2,6 +2,7 @@ import axios from 'axios'; import { FastField, Field, useFormikContext } from 'formik'; import { Select, TextField } from 'formik-mui'; import { get } from 'lodash'; +import dayjs from 'dayjs'; import { Autocomplete, FormControl, @@ -196,7 +197,8 @@ export function DateField(props: DateFieldProps): JSX.Element { const { classes } = useStyles(); const dateValue = - typeof props.value === 'string' ? new Date(props.value) : props.value; + // We cut the time part of the date string to avoid timezone issues + typeof props.value === 'string' ? dayjs(props.value?.split('T')[0]).toDate() : props.value; return (
diff --git a/verification/curator-service/ui/src/components/new-case-form-fields/TravelHistory.tsx b/verification/curator-service/ui/src/components/new-case-form-fields/TravelHistory.tsx index 33cfdec3..225d00e0 100644 --- a/verification/curator-service/ui/src/components/new-case-form-fields/TravelHistory.tsx +++ b/verification/curator-service/ui/src/components/new-case-form-fields/TravelHistory.tsx @@ -73,7 +73,7 @@ export default function TravelHistory(): JSX.Element { travelHistory: { ...values.travelHistory, travelHistoryEntry: - newValue?.toDateString() || undefined, + newValue || null, }, }); }} diff --git a/verification/curator-service/ui/src/components/new-case-form-fields/Vaccines.tsx b/verification/curator-service/ui/src/components/new-case-form-fields/Vaccines.tsx index 978b8ec7..d0411569 100644 --- a/verification/curator-service/ui/src/components/new-case-form-fields/Vaccines.tsx +++ b/verification/curator-service/ui/src/components/new-case-form-fields/Vaccines.tsx @@ -70,7 +70,7 @@ export default function Vaccines(): JSX.Element { vaccination: { ...values.vaccination, vaccineDate: - newValue?.toDateString() || undefined, + newValue || null, }, }); }} diff --git a/verification/curator-service/ui/src/components/util/date.tsx b/verification/curator-service/ui/src/components/util/date.tsx index 5fe225e8..785ffbf8 100644 --- a/verification/curator-service/ui/src/components/util/date.tsx +++ b/verification/curator-service/ui/src/components/util/date.tsx @@ -1,4 +1,5 @@ import { parse } from 'date-fns'; +import dayjs from "dayjs"; export default function renderDate( date: string | Date | undefined | null, @@ -14,8 +15,13 @@ export default function renderDate( } // Changes the date to be in UTC while maintaining the current date values -export function toUTCDate(dateString: string | undefined): string | undefined { +export function toUTCDate(dateString: Date | string | undefined | null): string | undefined { if (!dateString) return undefined; + if (dateString instanceof Date) { + return new Date( + Date.UTC(dateString.getFullYear(), dateString.getMonth(), dateString.getDate()), + ).toString(); + } const date = new Date(dateString); // The datepicker sometimes returns the date at the @@ -29,14 +35,13 @@ export function toUTCDate(dateString: string | undefined): string | undefined { } export function toLocalDate( - dateString: string | null | undefined, -): string | undefined { - if (!dateString) return undefined; + dateString: Date | string | null | undefined, +): Date | null { + if (!dateString) return null; + if (dateString instanceof Date) return dateString; // Parse date as local timezone to properly display it - const date = parse(dateString.slice(0, 10), 'yyyy-MM-dd', new Date()); - - return date.toString(); + return dayjs(dateString.split('T')[0]).toDate() } export function renderDateRange(range?: {