From a111ec84ac521bb7e5eb97e85f65b731cfa5bf87 Mon Sep 17 00:00:00 2001 From: jwnasambu Date: Fri, 13 Dec 2024 17:16:04 +0300 Subject: [PATCH] feat/O3-3846: All Calendar Date Pickers should use the same OpenmrsDatePicker component across entire EMR --- .../mark-patient-deceased-form.workspace.tsx | 26 ++++---- .../visit-attribute-type.component.tsx | 24 +++----- .../visit-form/visit-date-time.component.tsx | 24 +++----- .../conditions-widget.component.tsx | 28 +++------ .../immunizations-form.workspace.tsx | 42 ++++--------- .../drug-order-form.component.tsx | 17 ++---- .../src/notes/visit-notes-form.workspace.tsx | 18 ++---- .../orders-details-table.component.tsx | 27 ++------- .../cancel-order-form.component.tsx | 36 +++-------- .../src/programs/programs-form.workspace.tsx | 59 ++++++++----------- .../print-modal/print-modal.extension.tsx | 37 ++++-------- 11 files changed, 106 insertions(+), 232 deletions(-) diff --git a/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.workspace.tsx b/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.workspace.tsx index 382002aed0..a0ff7f09ab 100644 --- a/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.workspace.tsx +++ b/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.workspace.tsx @@ -5,8 +5,6 @@ import { useTranslation } from 'react-i18next'; import { Button, ButtonSet, - DatePicker, - DatePickerInput, DatePickerSkeleton, Form, InlineLoading, @@ -23,7 +21,14 @@ import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; import { WarningFilled } from '@carbon/react/icons'; import { EmptyState, type DefaultPatientWorkspaceProps } from '@openmrs/esm-patient-common-lib'; -import { ExtensionSlot, useLayoutType, showSnackbar, ResponsiveWrapper, useConfig } from '@openmrs/esm-framework'; +import { + ExtensionSlot, + useLayoutType, + showSnackbar, + ResponsiveWrapper, + useConfig, + OpenmrsDatePicker, +} from '@openmrs/esm-framework'; import { markPatientDeceased, useCausesOfDeath } from '../data.resource'; import { type ChartConfig } from '../config-schema'; import styles from './mark-patient-deceased-form.scss'; @@ -134,22 +139,13 @@ const MarkPatientDeceasedForm: React.FC = ({ close name="deathDate" control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} + onChange={(date) => onChange(date)} value={value} - > - - + /> )} /> {errors?.deathDate &&

{errors?.deathDate?.message}

} diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-attribute-type.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-attribute-type.component.tsx index 63d9e63885..003b388b4d 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-attribute-type.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-attribute-type.component.tsx @@ -1,8 +1,6 @@ import React, { useEffect, useId, useMemo } from 'react'; import { Checkbox, - DatePicker, - DatePickerInput, NumberInput, Select, SelectItem, @@ -14,7 +12,7 @@ import { import dayjs from 'dayjs'; import { useTranslation } from 'react-i18next'; import { Controller, type ControllerRenderProps, useFormContext } from 'react-hook-form'; -import { useConfig } from '@openmrs/esm-framework'; +import { OpenmrsDatePicker, useConfig } from '@openmrs/esm-framework'; import { type ChartConfig } from '../../config-schema'; import { useConceptAnswersForVisitAttributeType, useVisitAttributeType } from '../hooks/useVisitAttributeType'; import { type VisitFormData } from './visit-form.resource'; @@ -204,21 +202,13 @@ const AttributeTypeField: React.FC = ({ ); case 'org.openmrs.customdatatype.datatype.DateDatatype': return ( - onChange(dayjs(date).format('YYYY-MM-DD'))} - > - - + onChange={(date) => onChange(dayjs(date).format('YYYY-MM-DD'))} + labelText={labelText} + invalid={!!errors.visitAttributes?.[uuid]} + invalidText={errors.visitAttributes?.[uuid]?.message} + /> ); default: return ( diff --git a/packages/esm-patient-chart-app/src/visit/visit-form/visit-date-time.component.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-date-time.component.tsx index 01849fa3e5..63ca84d8a0 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-date-time.component.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-date-time.component.tsx @@ -1,10 +1,10 @@ import React from 'react'; import classNames from 'classnames'; import dayjs from 'dayjs'; -import { DatePicker, DatePickerInput, SelectItem, TimePicker, TimePickerSelect } from '@carbon/react'; +import { SelectItem, TimePicker, TimePickerSelect } from '@carbon/react'; import { Controller, useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { ResponsiveWrapper } from '@openmrs/esm-framework'; +import { OpenmrsDatePicker, ResponsiveWrapper } from '@openmrs/esm-framework'; import { type amPm } from '@openmrs/esm-patient-common-lib'; import { type VisitFormData } from './visit-form.resource'; import styles from './visit-form.scss'; @@ -49,25 +49,17 @@ const VisitDateTimeField: React.FC = ({ control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} + onChange={onChange} value={value ? dayjs(value).format('DD/MM/YYYY') : null} - > - - + labelText={t('date', 'Date')} + invalid={Boolean(errors[dateFieldName])} + invalidText={errors[dateFieldName]?.message} + /> )} /> diff --git a/packages/esm-patient-conditions-app/src/conditions/conditions-widget.component.tsx b/packages/esm-patient-conditions-app/src/conditions/conditions-widget.component.tsx index 7e7940d985..5c40f9cded 100644 --- a/packages/esm-patient-conditions-app/src/conditions/conditions-widget.component.tsx +++ b/packages/esm-patient-conditions-app/src/conditions/conditions-widget.component.tsx @@ -4,8 +4,6 @@ import classNames from 'classnames'; import dayjs from 'dayjs'; import 'dayjs/plugin/utc'; import { - DatePicker, - DatePickerInput, FormGroup, FormLabel, InlineLoading, @@ -18,7 +16,7 @@ import { } from '@carbon/react'; import { WarningFilled } from '@carbon/react/icons'; import { useFormContext, Controller } from 'react-hook-form'; -import { showSnackbar, useDebounce, useSession, ResponsiveWrapper } from '@openmrs/esm-framework'; +import { showSnackbar, useDebounce, useSession, ResponsiveWrapper, OpenmrsDatePicker } from '@openmrs/esm-framework'; import { type DefaultPatientWorkspaceProps } from '@openmrs/esm-patient-common-lib'; import { type CodedCondition, @@ -277,18 +275,14 @@ const ConditionsWidget: React.FC = ({ control={control} render={({ field: { onChange, onBlur, value } }) => ( - onChange(date)} + onChange={onChange} onBlur={onBlur} value={value} - > - - + labelText={t('onsetDate', 'Onset date')} + /> )} /> @@ -322,19 +316,15 @@ const ConditionsWidget: React.FC = ({ render={({ field: { onBlur, onChange, value } }) => ( <> - onChange(date)} + onChange={onChange} onBlur={onBlur} value={value} - > - - + labelText={t('endDate', 'End date')} + /> )} diff --git a/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.workspace.tsx b/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.workspace.tsx index fba58e867e..74857e29d1 100644 --- a/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.workspace.tsx +++ b/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.workspace.tsx @@ -4,8 +4,6 @@ import dayjs from 'dayjs'; import { Button, ButtonSet, - DatePicker, - DatePickerInput, Dropdown, Form, InlineNotification, @@ -24,6 +22,7 @@ import { toDateObjectStrict, showSnackbar, ResponsiveWrapper, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { useForm, Controller, FormProvider } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; @@ -229,25 +228,16 @@ const ImmunizationsForm: React.FC = ({ name="vaccinationDate" control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} - style={{ paddingBottom: '1rem' }} - > - - + onChange={(date) => onChange(date)} + style={{ paddingBottom: '1rem', width: '100%' }} + invalid={!!errors['vaccinationDate']} + invalidText={errors['vaccinationDate']?.message} + labelText={t('vaccinationDate', 'Vaccination date')} + /> )} /> @@ -380,22 +370,14 @@ const ImmunizationsForm: React.FC = ({ control={control} render={({ field: { onChange, value } }) => (
- onChange(date)} - > - - + onChange={(date) => onChange(date)} + labelText={t('expirationDate', 'Expiration date')} + />
)} /> diff --git a/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx b/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx index 3226682fb6..c5127a459f 100644 --- a/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx +++ b/packages/esm-patient-medications-app/src/add-drug-order/drug-order-form.component.tsx @@ -7,8 +7,6 @@ import { Checkbox, Column, ComboBox, - DatePicker, - DatePickerInput, IconButton, Form, FormGroup, @@ -30,6 +28,7 @@ import { ExtensionSlot, formatDate, getPatientName, + OpenmrsDatePicker, parseDate, useConfig, useLayoutType, @@ -597,21 +596,13 @@ export function DrugOrderForm({ initialOrderBasketItem, onSave, onCancel, prompt name="startDate" control={control} render={({ field: { onBlur, value, onChange, ref } }) => ( - onChange(newStartDate)} + onChange={(newStartDate) => onChange(newStartDate)} onBlur={onBlur} ref={ref} - > - - + /> )} /> diff --git a/packages/esm-patient-notes-app/src/notes/visit-notes-form.workspace.tsx b/packages/esm-patient-notes-app/src/notes/visit-notes-form.workspace.tsx index fde9147b3a..3333b8533e 100644 --- a/packages/esm-patient-notes-app/src/notes/visit-notes-form.workspace.tsx +++ b/packages/esm-patient-notes-app/src/notes/visit-notes-form.workspace.tsx @@ -11,8 +11,6 @@ import { Button, ButtonSet, Column, - DatePicker, - DatePickerInput, Form, FormGroup, InlineLoading, @@ -38,6 +36,7 @@ import { useConfig, useLayoutType, useSession, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { type DefaultPatientWorkspaceProps, useAllowedFileExtensions } from '@openmrs/esm-patient-common-lib'; import type { ConfigObject } from '../config-schema'; @@ -455,19 +454,12 @@ const VisitNotesForm: React.FC = ({ control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} - > - - + onChange={(date) => onChange(date)} + labelText={t('visitDate', 'Visit date')} + /> )} /> diff --git a/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx b/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx index 5e5edac6eb..5332166b16 100644 --- a/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx +++ b/packages/esm-patient-orders-app/src/components/orders-details-table.component.tsx @@ -6,8 +6,6 @@ import { Button, DataTable, DataTableSkeleton, - DatePicker, - DatePickerInput, Dropdown, InlineLoading, Layer, @@ -49,6 +47,7 @@ import { formatDate, getCoreTranslation, getPatientName, + OpenmrsDatePicker, PrinterIcon, useConfig, useLayoutType, @@ -361,27 +360,13 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu /> {t('dateRange', 'Date range')}: - { - handleDateFilterChange([startDate, endDate]); + onChange={(date: Date) => { + handleDateFilterChange([date, date]); }} - > - - - + labelText={t('dateRange', 'Select Date')} + /> {(() => { diff --git a/packages/esm-patient-orders-app/src/order-cancellation-form/cancel-order-form.component.tsx b/packages/esm-patient-orders-app/src/order-cancellation-form/cancel-order-form.component.tsx index 3d77d8d127..b1fee84f33 100644 --- a/packages/esm-patient-orders-app/src/order-cancellation-form/cancel-order-form.component.tsx +++ b/packages/esm-patient-orders-app/src/order-cancellation-form/cancel-order-form.component.tsx @@ -4,19 +4,8 @@ import { Controller, useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { z } from 'zod'; import { zodResolver } from '@hookform/resolvers/zod'; -import { - Button, - TextArea, - ButtonSet, - Column, - Form, - InlineNotification, - Stack, - DatePicker, - DatePickerInput, - InlineLoading, -} from '@carbon/react'; -import { showSnackbar, useLayoutType } from '@openmrs/esm-framework'; +import { Button, TextArea, ButtonSet, Column, Form, InlineNotification, Stack, InlineLoading } from '@carbon/react'; +import { OpenmrsDatePicker, showSnackbar, useLayoutType } from '@openmrs/esm-framework'; import { type DefaultPatientWorkspaceProps, usePatientOrders, type Order } from '@openmrs/esm-patient-common-lib'; import { cancelOrder } from './cancel-order.resource'; import styles from './cancel-order-form.scss'; @@ -121,24 +110,15 @@ const OrderCancellationForm: React.FC = ({ control={control} render={({ field: { onChange, value } }) => (
- onChange(date)} - autocomplete="off" - > - - + onChange={(date) => onChange(date)} + invalid={!!errors['cancellationDate']} + invalidText={errors['cancellationDate']?.message} + label={t('cancellationDate', 'Cancellation date')} + />
)} /> diff --git a/packages/esm-patient-programs-app/src/programs/programs-form.workspace.tsx b/packages/esm-patient-programs-app/src/programs/programs-form.workspace.tsx index 926f3e74c9..fbf3b4ee75 100644 --- a/packages/esm-patient-programs-app/src/programs/programs-form.workspace.tsx +++ b/packages/esm-patient-programs-app/src/programs/programs-form.workspace.tsx @@ -4,8 +4,6 @@ import dayjs from 'dayjs'; import { Button, ButtonSet, - DatePicker, - DatePickerInput, Form, FormGroup, InlineLoading, @@ -18,7 +16,15 @@ import { import { z } from 'zod'; import { useForm, Controller, useWatch } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; -import { parseDate, showSnackbar, useConfig, useLayoutType, useLocations, useSession } from '@openmrs/esm-framework'; +import { + OpenmrsDatePicker, + parseDate, + showSnackbar, + useConfig, + useLayoutType, + useLocations, + useSession, +} from '@openmrs/esm-framework'; import { type DefaultPatientWorkspaceProps } from '@openmrs/esm-patient-common-lib'; import { createProgramEnrollment, @@ -57,7 +63,6 @@ const ProgramsForm: React.FC = ({ const availableLocations = useLocations(); const { data: availablePrograms } = useAvailablePrograms(); const { data: enrollments, mutateEnrollments } = useEnrollments(patientUuid); - const [isSubmittingForm, setIsSubmittingForm] = useState(false); const { showProgramStatusField } = useConfig(); const programsFormSchema = useMemo(() => createProgramsFormSchema(t), [t]); @@ -90,7 +95,7 @@ const ProgramsForm: React.FC = ({ control, handleSubmit, watch, - formState: { isDirty }, + formState: { errors, isDirty, isSubmitting }, } = useForm({ mode: 'all', resolver: zodResolver(programsFormSchema), @@ -126,8 +131,6 @@ const ProgramsForm: React.FC = ({ }; try { - setIsSubmittingForm(true); - const abortController = new AbortController(); if (currentEnrollment) { @@ -155,8 +158,6 @@ const ProgramsForm: React.FC = ({ subtitle: error instanceof Error ? error.message : 'An unknown error occurred', }); } - - setIsSubmittingForm(false); }, [closeWorkspaceWithSavedChanges, currentEnrollment, currentState, mutateEnrollments, patientUuid, t], ); @@ -165,12 +166,13 @@ const ProgramsForm: React.FC = ({ ( + render={({ field: { onChange, value } }) => ( <> -

{fieldState?.error?.message}

)} /> @@ -194,18 +195,14 @@ const ProgramsForm: React.FC = ({ name="enrollmentDate" control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} + onChange={onChange} value={value} - > - - + labelText={t('dateEnrolled', 'Date enrolled')} + /> )} /> ); @@ -215,19 +212,15 @@ const ProgramsForm: React.FC = ({ name="completionDate" control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} + onChange={onChange} value={value} - > - - + labelText={t('dateCompleted', 'Date completed')} + /> )} /> ); @@ -267,12 +260,13 @@ const ProgramsForm: React.FC = ({ ( + render={({ field: { onChange, value } }) => ( <> -

{fieldState?.error?.message}

)} /> @@ -343,8 +336,8 @@ const ProgramsForm: React.FC = ({ -