diff --git a/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.test.tsx b/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.test.tsx index 652e7cd804..44e7372f25 100644 --- a/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.test.tsx +++ b/packages/esm-patient-chart-app/src/mark-patient-deceased/mark-patient-deceased-form.test.tsx @@ -1,11 +1,12 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; -import { getDefaultsFromConfigSchema, showSnackbar, useConfig } from '@openmrs/esm-framework'; +import { OpenmrsDatePicker, getDefaultsFromConfigSchema, showSnackbar, useConfig } from '@openmrs/esm-framework'; import { esmPatientChartSchema, type ChartConfig } from '../config-schema'; import { mockPatient } from 'tools'; import { markPatientDeceased, useCausesOfDeath } from '../data.resource'; import MarkPatientDeceasedForm from './mark-patient-deceased-form.workspace'; +import dayjs from 'dayjs'; const originalLocation = window.location; delete window.location; @@ -16,12 +17,31 @@ const mockUseCausesOfDeath = jest.mocked(useCausesOfDeath); const mockUseConfig = jest.mocked(useConfig); const mockShowSnackbar = jest.mocked(showSnackbar); const mockCloseWorkspace = jest.fn(); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); jest.mock('../data.resource.ts', () => ({ markPatientDeceased: jest.fn().mockResolvedValue({}), useCausesOfDeath: jest.fn(), })); +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + describe('MarkPatientDeceasedForm', () => { const freeTextFieldConceptUuid = '1234e218-6c8a-4ca3-8edb-9f6d9c8c8c7f'; @@ -34,26 +54,10 @@ describe('MarkPatientDeceasedForm', () => { }; const codedCausesOfDeath = [ - { - display: 'Traumatic injury', - uuid: '8b64f45e-1d5f-4894-b77c-4e1d840e2c99', - name: 'Traumatic injury', - }, - { - display: 'Neoplasm/cancer', - uuid: 'c4e8d03c-f09b-48d1-8d93-7d84d463f865', - name: 'Neoplasm/cancer', - }, - { - display: 'Infectious disease', - uuid: 'b7c1c30f-5b9e-4a3d-b943-7f4b3f740e6c', - name: 'Infectious disease', - }, - { - display: 'Other', - uuid: freeTextFieldConceptUuid, - name: 'Other', - }, + { display: 'Traumatic injury', uuid: '8b64f45e-1d5f-4894-b77c-4e1d840e2c99', name: 'Traumatic injury' }, + { display: 'Neoplasm/cancer', uuid: 'c4e8d03c-f09b-48d1-8d93-7d84d463f865', name: 'Neoplasm/cancer' }, + { display: 'Infectious disease', uuid: 'b7c1c30f-5b9e-4a3d-b943-7f4b3f740e6c', name: 'Infectious disease' }, + { display: 'Other', uuid: freeTextFieldConceptUuid, name: 'Other' }, ]; beforeEach(() => { @@ -82,7 +86,7 @@ describe('MarkPatientDeceasedForm', () => { ).toBeInTheDocument(); expect(screen.getByText(/cause of death/i)).toBeInTheDocument(); expect(screen.getByRole('searchbox')).toBeInTheDocument(); - expect(screen.getByRole('textbox', { name: /date/i })); + expect(screen.getByLabelText(/date/i)).toBeInTheDocument(); codedCausesOfDeath.forEach((codedCauseOfDeath) => { expect(screen.getByRole('radio', { name: codedCauseOfDeath.display })).toBeInTheDocument(); }); 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..fd6c46bb2e 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,16 @@ 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..2136d442c5 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,14 @@ 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'))} + id="date-picker-default-id" + 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 c0c64473cf..e547cea139 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-chart-app/src/visit/visit-form/visit-form.test.tsx b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx index 56b4545311..b03b9d573b 100644 --- a/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx +++ b/packages/esm-patient-chart-app/src/visit/visit-form/visit-form.test.tsx @@ -9,6 +9,7 @@ import { usePatient, useVisitTypes, type Visit, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -171,6 +172,26 @@ jest.mock('./visit-form.resource', () => { }; }); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); + +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + mockSaveVisit.mockResolvedValue({ status: 201, data: { diff --git a/packages/esm-patient-conditions-app/src/conditions/conditions-form.test.tsx b/packages/esm-patient-conditions-app/src/conditions/conditions-form.test.tsx index 257b4d20e0..9f28f248cf 100644 --- a/packages/esm-patient-conditions-app/src/conditions/conditions-form.test.tsx +++ b/packages/esm-patient-conditions-app/src/conditions/conditions-form.test.tsx @@ -2,7 +2,7 @@ import React from 'react'; import dayjs from 'dayjs'; import userEvent from '@testing-library/user-event'; import { render, screen, waitFor } from '@testing-library/react'; -import { type FetchResponse, openmrsFetch, showSnackbar } from '@openmrs/esm-framework'; +import { type FetchResponse, openmrsFetch, showSnackbar, OpenmrsDatePicker } from '@openmrs/esm-framework'; import { mockFhirConditionsResponse, searchedCondition } from '__mocks__'; import { getByTextWithMarkup, mockPatient } from 'tools'; import { createCondition, useConditionsSearch } from './conditions.resource'; @@ -37,6 +37,26 @@ jest.mock('./conditions.resource', () => ({ useConditionsSearch: jest.fn(), })); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); + +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + mockOpenmrsFetch.mockResolvedValue({ data: [] } as FetchResponse); mockUseConditionsSearch.mockReturnValue({ searchResults: [], @@ -67,7 +87,6 @@ describe('Conditions form', () => { expect(cancelButton).toBeEnabled(); expect(submitButton).toBeInTheDocument(); }); - it('closes the form and the workspace when the cancel button is clicked', async () => { const user = userEvent.setup(); renderConditionsForm(); @@ -131,18 +150,13 @@ describe('Conditions form', () => { const submitButton = screen.getByRole('button', { name: /save & close/i }); const activeStatusInput = screen.getByRole('radio', { name: 'Active' }); const conditionSearchInput = screen.getByRole('searchbox', { name: /enter condition/i }); - const onsetDateInput = screen.getByRole('textbox', { name: /onset date/i }); expect(cancelButton).toBeEnabled(); await user.type(conditionSearchInput, 'Headache'); await user.click(screen.getByRole('menuitem', { name: /headache/i })); await user.click(activeStatusInput); - await user.type(onsetDateInput, '2020-05-05'); await user.click(submitButton); - await waitFor(() => { - expect(mockShowSnackbar).toHaveBeenCalled(); - }); expect(mockShowSnackbar).toHaveBeenCalledWith({ kind: 'success', subtitle: 'It is now visible on the Conditions page', 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.test.tsx b/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.test.tsx index 37cba72af0..b9b106ba4c 100644 --- a/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.test.tsx +++ b/packages/esm-patient-immunizations-app/src/immunizations/immunizations-form.test.tsx @@ -10,6 +10,7 @@ import { useConfig, useSession, useVisit, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { configSchema } from '../config-schema'; import { type ImmunizationWidgetConfigObject } from '../types/fhir-immunization-domain'; @@ -30,6 +31,25 @@ const mockUseVisit = jest.mocked(useVisit); const mockMutate = jest.fn(); const mockToOmrsIsoString = jest.mocked(toOmrsIsoString); const mockToDateObjectStrict = jest.mocked(toDateObjectStrict); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); + +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); jest.mock('../hooks/useImmunizationsConceptSet', () => ({ useImmunizationsConceptSet: jest.fn(() => ({ 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..4deb72b529 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'; @@ -44,8 +43,6 @@ interface ResponsiveWrapperProps { isTablet: boolean; } -const datePickerFormat = 'd/m/Y'; - const ImmunizationsForm: React.FC = ({ patientUuid, closeWorkspace, @@ -229,25 +226,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%' }} + labelText={t('vaccinationDate', 'Vaccination date')} + invalid={!!errors['vaccinationDate']} + invalidText={errors['vaccinationDate']?.message} + /> )} /> @@ -380,22 +368,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/add-drug-order.test.tsx b/packages/esm-patient-medications-app/src/add-drug-order/add-drug-order.test.tsx index ff66f682a4..d6e5b9b70d 100644 --- a/packages/esm-patient-medications-app/src/add-drug-order/add-drug-order.test.tsx +++ b/packages/esm-patient-medications-app/src/add-drug-order/add-drug-order.test.tsx @@ -10,10 +10,11 @@ import { mockPatientDrugOrdersApiData, mockSessionDataResponse, } from '__mocks__'; -import { closeWorkspace, useSession } from '@openmrs/esm-framework'; +import { closeWorkspace, useSession, OpenmrsDatePicker } from '@openmrs/esm-framework'; import { type PostDataPrepFunction, useOrderBasket } from '@openmrs/esm-patient-common-lib'; import { _resetOrderBasketStore } from '@openmrs/esm-patient-common-lib/src/orders/store'; import AddDrugOrderWorkspace from './add-drug-order.workspace'; +import dayjs from 'dayjs'; const mockCloseWorkspace = closeWorkspace as jest.Mock; const mockLaunchPatientWorkspace = jest.fn(); @@ -21,6 +22,7 @@ const mockUseSession = jest.mocked(useSession); const mockUseDrugSearch = jest.mocked(useDrugSearch); const mockUseDrugTemplate = jest.mocked(useDrugTemplate); const usePatientOrdersMock = jest.fn(); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); mockCloseWorkspace.mockImplementation((name, { onWorkspaceClose }) => onWorkspaceClose()); mockUseSession.mockReturnValue(mockSessionDataResponse.data); @@ -54,6 +56,24 @@ jest.mock('../api/api', () => ({ .mockReturnValue({ requireOutpatientQuantity: false, error: null, isLoading: false }), })); +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + describe('AddDrugOrderWorkspace drug search', () => { beforeEach(() => { _resetOrderBasketStore(); 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..6be5f130bc 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,16 @@ 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} - > - - + id="startDatePicker" + labelText={t('startDate', 'Start date')} + size={isTablet ? 'lg' : 'sm'} + /> )} /> diff --git a/packages/esm-patient-notes-app/src/notes/visit-notes-form.test.tsx b/packages/esm-patient-notes-app/src/notes/visit-notes-form.test.tsx index 1f8f0258a3..243a650e47 100644 --- a/packages/esm-patient-notes-app/src/notes/visit-notes-form.test.tsx +++ b/packages/esm-patient-notes-app/src/notes/visit-notes-form.test.tsx @@ -1,7 +1,13 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { screen, render } from '@testing-library/react'; -import { getDefaultsFromConfigSchema, showSnackbar, useConfig, useSession } from '@openmrs/esm-framework'; +import { + OpenmrsDatePicker, + getDefaultsFromConfigSchema, + showSnackbar, + useConfig, + useSession, +} from '@openmrs/esm-framework'; import { fetchDiagnosisConceptsByName, saveVisitNote } from './visit-notes.resource'; import { ConfigMock, @@ -13,6 +19,27 @@ import { import { configSchema, type ConfigObject } from '../config-schema'; import { mockPatient, getByTextWithMarkup } from 'tools'; import VisitNotesForm from './visit-notes-form.workspace'; +import dayjs from 'dayjs'; + +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); + +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); const defaultProps = { patientUuid: mockPatient.id, 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..622f3c1bd5 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,13 @@ const VisitNotesForm: React.FC = ({ control={control} render={({ field: { onChange, value } }) => ( - onChange(date)} - > - - + onChange={(date) => onChange(date)} + id="visitDateTimePicker" + labelText={t('visitDate', 'Visit date')} + /> )} /> diff --git a/packages/esm-patient-orders-app/src/components/order-details-table.test.tsx b/packages/esm-patient-orders-app/src/components/order-details-table.test.tsx index 4a9411961b..bc5a771aef 100644 --- a/packages/esm-patient-orders-app/src/components/order-details-table.test.tsx +++ b/packages/esm-patient-orders-app/src/components/order-details-table.test.tsx @@ -8,11 +8,13 @@ import { openmrsFetch, useConfig, useSession, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { useOrderTypes, usePatientOrders } from '@openmrs/esm-patient-common-lib'; import { configSchema } from '../config-schema'; import { mockOrders, mockSessionDataResponse } from '__mocks__'; import OrderDetailsTable from './orders-details-table.component'; +import dayjs from 'dayjs'; const mockUsePatientOrders = usePatientOrders as jest.Mock; const mockUseOrderTypes = useOrderTypes as jest.Mock; @@ -20,6 +22,7 @@ const mockOpenmrsFetch = openmrsFetch as jest.Mock; const mockSession = jest.mocked(useSession); const mockUseConfig = jest.mocked(useConfig); const mockUseReactToPrint = jest.mocked(useReactToPrint); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); mockSession.mockReturnValue(mockSessionDataResponse.data); mockOpenmrsFetch.mockImplementation(jest.fn()); @@ -40,6 +43,24 @@ jest.mock('@openmrs/esm-patient-common-lib', () => { }; }); +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + describe('OrderDetailsTable', () => { const user = userEvent.setup(); const testOrderTypeUuid = '52a447d3-a64a-11e3-9aeb-50e549534c5e'; 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..7e173412da 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,17 @@ const OrderDetailsTable: React.FC = ({ patientUuid, showAddBu /> {t('dateRange', 'Date range')}: - { - handleDateFilterChange([startDate, endDate]); + onChange={(date: Date) => { + handleDateFilterChange([date, 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..4bd3023216 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)} + labelText={t('cancellationDate', 'Cancellation date')} + invalid={!!errors['cancellationDate']} + invalidText={errors['cancellationDate']?.message} + />
)} /> diff --git a/packages/esm-patient-programs-app/src/programs/programs-form.test.tsx b/packages/esm-patient-programs-app/src/programs/programs-form.test.tsx index 02844ff788..62be61c6b8 100644 --- a/packages/esm-patient-programs-app/src/programs/programs-form.test.tsx +++ b/packages/esm-patient-programs-app/src/programs/programs-form.test.tsx @@ -1,12 +1,14 @@ import React from 'react'; import userEvent from '@testing-library/user-event'; import { render, screen } from '@testing-library/react'; +import dayjs from 'dayjs'; import { type FetchResponse, showSnackbar, useLocations, useConfig, getDefaultsFromConfigSchema, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import { mockCareProgramsResponse, mockEnrolledProgramsResponse, mockLocationsResponse } from '__mocks__'; import { mockPatient } from 'tools'; @@ -30,6 +32,25 @@ const mockCloseWorkspaceWithSavedChanges = jest.fn(); const mockPromptBeforeClosing = jest.fn(); const mockUseConfig = jest.mocked(useConfig); +const mockOpenmrsDatePicker = jest.mocked(OpenmrsDatePicker); +mockOpenmrsDatePicker.mockImplementation(({ id, labelText, value, onChange }) => { + return ( + <> + + { + onChange(dayjs(evt.target.value).toDate()); + }} + type="text" + // @ts-ignore + value={value ? dayjs(value).format('DD/MM/YYYY') : ''} + /> + + ); +}); + const testProps = { closeWorkspace: mockCloseWorkspace, closeWorkspaceWithSavedChanges: mockCloseWorkspaceWithSavedChanges, @@ -70,23 +91,21 @@ mockCreateProgramEnrollment.mockResolvedValue({ } as unknown as FetchResponse); describe('ProgramsForm', () => { + const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574'; + const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de'; + it('renders a success toast notification upon successfully recording a program enrollment', async () => { const user = userEvent.setup(); - const inpatientWardUuid = 'b1a8b05e-3542-4037-bbd3-998ee9c40574'; - const oncologyScreeningProgramUuid = '11b129ca-a5e7-4025-84bf-b92a173e20de'; - renderProgramsForm(); const programNameInput = screen.getByRole('combobox', { name: /program name/i }); - const enrollmentDateInput = screen.getByRole('textbox', { name: /date enrolled/i }); const enrollmentLocationInput = screen.getByRole('combobox', { name: /enrollment location/i }); const enrollButton = screen.getByRole('button', { name: /save and close/i }); await user.click(enrollButton); expect(screen.getByText(/program is required/i)).toBeInTheDocument(); - await user.type(enrollmentDateInput, '2020-05-05'); await user.selectOptions(programNameInput, [oncologyScreeningProgramUuid]); await user.selectOptions(enrollmentLocationInput, [inpatientWardUuid]); expect(screen.getByRole('option', { name: /Inpatient Ward/i })).toBeInTheDocument(); @@ -118,25 +137,25 @@ describe('ProgramsForm', () => { renderProgramsForm(mockEnrolledProgramsResponse[0].uuid); + const enrollmentLocationInput = screen.getByRole('combobox', { name: /enrollment location/i }); const enrollButton = screen.getByRole('button', { name: /save and close/i }); - const completionDateInput = screen.getByRole('textbox', { name: /date completed/i }); mockUpdateProgramEnrollment.mockResolvedValue({ status: 200, statusText: 'OK', } as unknown as FetchResponse); - await user.type(completionDateInput, '05/05/2020'); - await user.tab(); + await user.click(enrollmentLocationInput); + await user.selectOptions(enrollmentLocationInput, [inpatientWardUuid]); await user.click(enrollButton); expect(mockUpdateProgramEnrollment).toHaveBeenCalledTimes(1); expect(mockUpdateProgramEnrollment).toHaveBeenCalledWith( mockEnrolledProgramsResponse[0].uuid, expect.objectContaining({ - dateCompleted: expect.stringMatching(/^2020-05-05/), + dateCompleted: null, dateEnrolled: expect.stringMatching(/^2020-01-16/), - location: mockEnrolledProgramsResponse[0].location.uuid, + location: inpatientWardUuid, patient: mockPatient.id, program: mockEnrolledProgramsResponse[0].program.uuid, }), 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 47965b73b5..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, @@ -189,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')} + /> )} /> ); @@ -210,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')} + /> )} /> ); diff --git a/packages/esm-patient-tests-app/src/test-results/print-modal/print-modal.extension.tsx b/packages/esm-patient-tests-app/src/test-results/print-modal/print-modal.extension.tsx index 093b01e685..c825eb7e49 100644 --- a/packages/esm-patient-tests-app/src/test-results/print-modal/print-modal.extension.tsx +++ b/packages/esm-patient-tests-app/src/test-results/print-modal/print-modal.extension.tsx @@ -3,8 +3,6 @@ import { useTranslation } from 'react-i18next'; import { Button, DataTable, - DatePicker, - DatePickerInput, ModalBody, ModalFooter, ModalHeader, @@ -30,6 +28,7 @@ import { usePatient, useSession, ResponsiveWrapper, + OpenmrsDatePicker, } from '@openmrs/esm-framework'; import usePanelData from '../panel-view/usePanelData'; import styles from './print-modal.scss'; @@ -50,8 +49,6 @@ function PrintModal({ patientUuid, closeDialog }) { externalModuleName: '@openmrs/esm-patient-banner-app', }); const headerTitle = t('testResults_title', 'Test Results'); - const datePickerPlaceHolder = 'dd/mm/yyyy'; - const datePickerFormat = 'd/m/Y'; const tableHeaders = [ { key: 'testType', header: 'Test Type' }, @@ -117,35 +114,21 @@ function PrintModal({ patientUuid, closeDialog }) {
- setSelectedFromDate(date)} + onChange={setSelectedFromDate} value={selectedFromDate} - > - - - + setSelectedToDate(date)} + onChange={setSelectedToDate} value={selectedToDate} - > - - + labelText={t('endDate', 'End date')} + />