@ampath/esm-patient-registration-app 6.0.1-pre.98 → 9.2.0-next.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/1119.js +1 -0
- package/dist/1197.js +1 -0
- package/dist/21.js +1 -0
- package/dist/21.js.map +1 -0
- package/dist/2146.js +1 -0
- package/dist/2372.js +1 -0
- package/dist/2372.js.map +1 -0
- package/dist/2470.js +1 -0
- package/dist/2470.js.map +1 -0
- package/dist/2690.js +1 -0
- package/dist/2913.js +2 -0
- package/dist/{913.js.LICENSE.txt → 2913.js.LICENSE.txt} +3 -23
- package/dist/2913.js.map +1 -0
- package/dist/3093.js +1 -0
- package/dist/3093.js.map +1 -0
- package/dist/3099.js +1 -0
- package/dist/3144.js +2 -0
- package/dist/3144.js.LICENSE.txt +19 -0
- package/dist/3144.js.map +1 -0
- package/dist/320.js +2 -0
- package/dist/{876.js.LICENSE.txt → 320.js.LICENSE.txt} +2 -3
- package/dist/320.js.map +1 -0
- package/dist/3464.js +1 -0
- package/dist/3464.js.map +1 -0
- package/dist/3474.js +2 -0
- package/dist/3474.js.LICENSE.txt +8 -0
- package/dist/3474.js.map +1 -0
- package/dist/3584.js +1 -0
- package/dist/4041.js +2 -0
- package/dist/4041.js.map +1 -0
- package/dist/4055.js +1 -0
- package/dist/4132.js +1 -0
- package/dist/4300.js +1 -0
- package/dist/4335.js +1 -0
- package/dist/4463.js +1 -0
- package/dist/4463.js.map +1 -0
- package/dist/4618.js +1 -0
- package/dist/4652.js +1 -0
- package/dist/4944.js +1 -0
- package/dist/5173.js +1 -0
- package/dist/5220.js +2 -0
- package/dist/5220.js.LICENSE.txt +29 -0
- package/dist/5220.js.map +1 -0
- package/dist/5241.js +1 -0
- package/dist/5442.js +1 -0
- package/dist/5661.js +1 -0
- package/dist/6022.js +1 -0
- package/dist/6078.js +2 -0
- package/dist/6078.js.LICENSE.txt +9 -0
- package/dist/6078.js.map +1 -0
- package/dist/627.js +1 -0
- package/dist/627.js.map +1 -0
- package/dist/6276.js +1 -0
- package/dist/6276.js.map +1 -0
- package/dist/6468.js +1 -0
- package/dist/6679.js +1 -0
- package/dist/6737.js +2 -0
- package/dist/6737.js.LICENSE.txt +9 -0
- package/dist/6737.js.map +1 -0
- package/dist/6840.js +1 -0
- package/dist/6859.js +1 -0
- package/dist/7092.js +1 -0
- package/dist/7092.js.map +1 -0
- package/dist/7097.js +1 -0
- package/dist/7159.js +1 -0
- package/dist/723.js +1 -0
- package/dist/7495.js +2 -0
- package/dist/7495.js.LICENSE.txt +9 -0
- package/dist/7495.js.map +1 -0
- package/dist/7617.js +1 -0
- package/dist/795.js +1 -0
- package/dist/8163.js +1 -0
- package/dist/8349.js +1 -0
- package/dist/8404.js +2 -0
- package/dist/{629.js.LICENSE.txt → 8404.js.LICENSE.txt} +9 -3
- package/dist/8404.js.map +1 -0
- package/dist/8434.js +1 -0
- package/dist/8434.js.map +1 -0
- package/dist/8618.js +1 -0
- package/dist/89.js +2 -0
- package/dist/89.js.LICENSE.txt +9 -0
- package/dist/89.js.map +1 -0
- package/dist/890.js +1 -0
- package/dist/9214.js +1 -0
- package/dist/9538.js +1 -0
- package/dist/9569.js +1 -0
- package/dist/986.js +1 -0
- package/dist/9876.js +1 -0
- package/dist/9876.js.map +1 -0
- package/dist/9879.js +1 -0
- package/dist/9895.js +1 -0
- package/dist/9900.js +1 -0
- package/dist/9913.js +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +36 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-registration-app.js +1 -0
- package/dist/openmrs-esm-patient-registration-app.js.buildmanifest.json +1576 -0
- package/dist/openmrs-esm-patient-registration-app.js.map +1 -0
- package/dist/routes.json +1 -1
- package/package.json +16 -15
- package/src/{add-patient-link.tsx → add-patient-link.extension.tsx} +4 -2
- package/src/add-patient-link.test.tsx +6 -10
- package/src/config-schema.ts +109 -55
- package/src/constants.ts +1 -1
- package/src/declarations.d.ts +5 -4
- package/src/index.ts +10 -29
- package/src/nav-link.test.tsx +3 -3
- package/src/offline.resources.ts +26 -18
- package/src/patient-photo.extension.tsx +3 -1
- package/src/patient-registration/field/address/address-field.component.tsx +58 -37
- package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +16 -18
- package/src/patient-registration/field/address/address-hierarchy.resource.tsx +3 -3
- package/src/patient-registration/field/address/address-hierarchy.test.tsx +290 -0
- package/src/patient-registration/field/address/address-search.component.tsx +7 -5
- package/src/patient-registration/field/address/address-search.scss +5 -5
- package/src/patient-registration/field/address/address-search.test.tsx +140 -0
- package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +98 -0
- package/src/patient-registration/field/custom-field.component.tsx +3 -9
- package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +84 -0
- package/src/patient-registration/field/dob/dob.component.tsx +55 -50
- package/src/patient-registration/field/dob/dob.test.tsx +90 -0
- package/src/patient-registration/field/field.component.tsx +12 -6
- package/src/patient-registration/field/field.resource.ts +11 -4
- package/src/patient-registration/field/field.scss +69 -25
- package/src/patient-registration/field/field.test.tsx +329 -0
- package/src/patient-registration/field/gender/gender-field.component.tsx +14 -9
- package/src/patient-registration/field/gender/gender-field.test.tsx +73 -33
- package/src/patient-registration/field/id/id-field.component.tsx +24 -23
- package/src/patient-registration/field/id/id-field.test.tsx +147 -0
- package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +12 -10
- package/src/patient-registration/field/id/identifier-selection.scss +12 -8
- package/src/patient-registration/field/name/name-field.component.tsx +10 -5
- package/src/patient-registration/field/obs/obs-field.component.tsx +59 -2
- package/src/patient-registration/field/obs/obs-field.test.tsx +133 -39
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +3 -3
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx +141 -0
- package/src/patient-registration/field/person-attributes/location-person-attribute-field.component.tsx +105 -0
- package/src/patient-registration/field/person-attributes/location-person-attribute-field.resource.tsx +48 -0
- package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx +19 -22
- package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +193 -0
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +90 -0
- package/src/patient-registration/form-manager.test.ts +91 -0
- package/src/patient-registration/form-manager.ts +49 -23
- package/src/patient-registration/input/basic-input/input/input.component.tsx +6 -2
- package/src/patient-registration/input/basic-input/select/select-input.test.tsx +49 -0
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.scss +5 -5
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.test.tsx +164 -0
- package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +73 -36
- package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +335 -0
- package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +3 -0
- package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +2 -11
- package/src/patient-registration/input/input.scss +17 -13
- package/src/patient-registration/patient-registration-context.ts +22 -11
- package/src/patient-registration/patient-registration-hooks.ts +158 -193
- package/src/patient-registration/patient-registration-utils.test.ts +33 -0
- package/src/patient-registration/patient-registration-utils.ts +11 -13
- package/src/patient-registration/patient-registration.component.tsx +87 -103
- package/src/patient-registration/{patient-registration.resource.testt.tsx → patient-registration.resource.test.tsx} +0 -4
- package/src/patient-registration/patient-registration.resource.ts +27 -3
- package/src/patient-registration/patient-registration.scss +27 -38
- package/src/patient-registration/patient-registration.test.tsx +579 -0
- package/src/patient-registration/patient-registration.types.ts +23 -25
- package/src/patient-registration/section/death-info/death-info-section.component.tsx +22 -17
- package/src/patient-registration/section/death-info/death-info-section.test.tsx +47 -0
- package/src/patient-registration/section/demographics/demographics-section.component.tsx +5 -5
- package/src/patient-registration/section/demographics/demographics-section.test.tsx +98 -0
- package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +8 -7
- package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +113 -0
- package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +28 -28
- package/src/patient-registration/section/patient-relationships/relationships.scss +4 -4
- package/src/patient-registration/section/section-wrapper.component.tsx +1 -1
- package/src/patient-registration/section/section.component.tsx +1 -1
- package/src/patient-registration/section/section.scss +21 -1
- package/src/patient-registration/ui-components/overlay/overlay.scss +8 -8
- package/src/patient-registration/validation/{patient-registration-validation.test.tsx → patient-registration-validation.test.ts} +71 -23
- package/src/patient-registration/validation/patient-registration-validation.ts +123 -0
- package/src/resources-context.ts +14 -0
- package/src/root.component.tsx +3 -3
- package/src/routes.json +10 -24
- package/src/widgets/cancel-patient-edit.modal.tsx +33 -0
- package/src/widgets/cancel-patient-edit.test.tsx +22 -0
- package/src/widgets/delete-identifier-confirmation.modal.tsx +48 -0
- package/src/widgets/{delete-identifier-confirmation-modal.testt.tsx → delete-identifier-confirmation.test.tsx} +5 -7
- package/src/widgets/edit-patient-details-button.component.tsx +0 -1
- package/src/widgets/edit-patient-details-button.test.tsx +35 -0
- package/translations/am.json +43 -35
- package/translations/ar.json +41 -33
- package/translations/ar_SY.json +119 -0
- package/translations/bn.json +119 -0
- package/translations/de.json +119 -0
- package/translations/en.json +44 -42
- package/translations/en_US.json +119 -0
- package/translations/es.json +69 -57
- package/translations/es_MX.json +119 -0
- package/translations/fr.json +74 -58
- package/translations/he.json +44 -40
- package/translations/hi.json +119 -0
- package/translations/hi_IN.json +119 -0
- package/translations/id.json +119 -0
- package/translations/it.json +119 -0
- package/translations/ka.json +119 -0
- package/translations/km.json +44 -40
- package/translations/ku.json +119 -0
- package/translations/ky.json +119 -0
- package/translations/lg.json +119 -0
- package/translations/ne.json +119 -0
- package/translations/pl.json +119 -0
- package/translations/pt.json +119 -0
- package/translations/pt_BR.json +119 -0
- package/translations/qu.json +119 -0
- package/translations/ro_RO.json +119 -0
- package/translations/ru_RU.json +119 -0
- package/translations/si.json +119 -0
- package/translations/sw.json +119 -0
- package/translations/sw_KE.json +119 -0
- package/translations/tr.json +119 -0
- package/translations/tr_TR.json +119 -0
- package/translations/uk.json +119 -0
- package/translations/uz.json +119 -0
- package/translations/uz@Latn.json +119 -0
- package/translations/uz_UZ.json +119 -0
- package/translations/vi.json +119 -0
- package/translations/zh.json +45 -23
- package/translations/zh_CN.json +39 -17
- package/.turbo/turbo-build.log +0 -40
- package/dist/132.js +0 -1
- package/dist/197.js +0 -1
- package/dist/236.js +0 -1
- package/dist/236.js.map +0 -1
- package/dist/300.js +0 -1
- package/dist/335.js +0 -1
- package/dist/372.js +0 -1
- package/dist/372.js.map +0 -1
- package/dist/41.js +0 -2
- package/dist/41.js.map +0 -1
- package/dist/449.js +0 -1
- package/dist/449.js.map +0 -1
- package/dist/464.js +0 -1
- package/dist/464.js.map +0 -1
- package/dist/495.js +0 -1
- package/dist/495.js.map +0 -1
- package/dist/55.js +0 -1
- package/dist/56.js +0 -1
- package/dist/56.js.map +0 -1
- package/dist/621.js +0 -1
- package/dist/621.js.map +0 -1
- package/dist/629.js +0 -2
- package/dist/629.js.map +0 -1
- package/dist/652.js +0 -1
- package/dist/661.js +0 -1
- package/dist/757.js +0 -1
- package/dist/757.js.map +0 -1
- package/dist/828.js +0 -1
- package/dist/828.js.map +0 -1
- package/dist/830.js +0 -1
- package/dist/830.js.map +0 -1
- package/dist/831.js +0 -2
- package/dist/831.js.LICENSE.txt +0 -3
- package/dist/831.js.map +0 -1
- package/dist/876.js +0 -2
- package/dist/876.js.map +0 -1
- package/dist/879.js +0 -1
- package/dist/913.js +0 -2
- package/dist/913.js.map +0 -1
- package/dist/927.js +0 -1
- package/dist/927.js.map +0 -1
- package/dist/99.js +0 -1
- package/dist/ampath-esm-patient-registration-app.js +0 -1
- package/dist/ampath-esm-patient-registration-app.js.buildmanifest.json +0 -694
- package/dist/ampath-esm-patient-registration-app.js.map +0 -1
- package/src/patient-registration/date-util.ts +0 -52
- package/src/patient-registration/field/person-attributes/custom-person-attribute-field.component.tsx +0 -56
- package/src/patient-registration/validation/patient-registration-validation.tsx +0 -60
- package/src/patient-verification/assets/counties.json +0 -236
- package/src/patient-verification/assets/verification-assets.ts +0 -11
- package/src/patient-verification/patient-verification-hook.tsx +0 -176
- package/src/patient-verification/patient-verification-utils.ts +0 -179
- package/src/patient-verification/patient-verification.component.tsx +0 -124
- package/src/patient-verification/patient-verification.scss +0 -25
- package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +0 -72
- package/src/patient-verification/verification-modal/empty-prompt.component.tsx +0 -35
- package/src/patient-verification/verification-types.ts +0 -50
- package/src/widgets/cancel-patient-edit.component.tsx +0 -37
- package/src/widgets/delete-identifier-confirmation-modal.tsx +0 -41
- package/src/widgets/delete-identifier-modal.scss +0 -34
- /package/dist/{41.js.LICENSE.txt → 4041.js.LICENSE.txt} +0 -0
- /package/src/patient-registration/input/custom-input/identifier/{utils.testt.ts → utils.test.ts} +0 -0
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
2
|
import userEvent from '@testing-library/user-event';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
5
|
+
import { esmPatientRegistrationSchema, type FieldDefinition, type RegistrationConfig } from '../../../config-schema';
|
|
6
6
|
import { useConcept, useConceptAnswers } from '../field.resource';
|
|
7
7
|
import { ObsField } from './obs-field.component';
|
|
8
|
+
import {
|
|
9
|
+
PatientRegistrationContextProvider,
|
|
10
|
+
type PatientRegistrationContextProps,
|
|
11
|
+
} from '../../patient-registration-context';
|
|
12
|
+
import { mockOpenmrsId, mockPatient } from '__mocks__';
|
|
8
13
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
jest.
|
|
14
|
+
const mockUseConcept = jest.mocked(useConcept);
|
|
15
|
+
const mockUseConceptAnswers = jest.mocked(useConceptAnswers);
|
|
16
|
+
const mockUseConfig = jest.mocked(useConfig<RegistrationConfig>);
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
const mockedUseConceptAnswers = useConceptAnswers as jest.Mock;
|
|
18
|
+
jest.mock('../field.resource');
|
|
15
19
|
|
|
16
20
|
const useConceptMockImpl = (uuid: string) => {
|
|
17
21
|
let data;
|
|
@@ -42,6 +46,14 @@ const useConceptMockImpl = (uuid: string) => {
|
|
|
42
46
|
],
|
|
43
47
|
setMembers: [],
|
|
44
48
|
};
|
|
49
|
+
} else if (uuid == 'vaccination-date-uuid') {
|
|
50
|
+
data = {
|
|
51
|
+
uuid: 'vaccination-date-uuid',
|
|
52
|
+
display: 'Vaccination Date',
|
|
53
|
+
datatype: { display: 'Date', uuid: 'date' },
|
|
54
|
+
answers: [],
|
|
55
|
+
setMembers: [],
|
|
56
|
+
};
|
|
45
57
|
} else {
|
|
46
58
|
throw Error(`Programming error, you probably didn't mean to do this: unknown concept uuid '${uuid}'`);
|
|
47
59
|
}
|
|
@@ -59,6 +71,7 @@ const useConceptAnswersMockImpl = (uuid: string) => {
|
|
|
59
71
|
{ display: 'Mexico', uuid: 'mex' },
|
|
60
72
|
],
|
|
61
73
|
isLoading: false,
|
|
74
|
+
error: null,
|
|
62
75
|
};
|
|
63
76
|
} else if (uuid == 'other-countries-uuid') {
|
|
64
77
|
return {
|
|
@@ -67,11 +80,13 @@ const useConceptAnswersMockImpl = (uuid: string) => {
|
|
|
67
80
|
{ display: 'Uganda', uuid: 'ug' },
|
|
68
81
|
],
|
|
69
82
|
isLoading: false,
|
|
83
|
+
error: null,
|
|
70
84
|
};
|
|
71
85
|
} else if (uuid == '') {
|
|
72
86
|
return {
|
|
73
87
|
data: [],
|
|
74
88
|
isLoading: false,
|
|
89
|
+
error: null,
|
|
75
90
|
};
|
|
76
91
|
} else {
|
|
77
92
|
throw Error(`Programming error, you probably didn't mean to do this: unknown concept answer set uuid '${uuid}'`);
|
|
@@ -79,19 +94,21 @@ const useConceptAnswersMockImpl = (uuid: string) => {
|
|
|
79
94
|
};
|
|
80
95
|
|
|
81
96
|
type FieldProps = {
|
|
82
|
-
children: ({ field, form: { touched, errors } }) => React.ReactNode;
|
|
97
|
+
children: ({ field, form: { touched, errors }, meta }) => React.ReactNode;
|
|
83
98
|
};
|
|
84
99
|
|
|
85
100
|
jest.mock('formik', () => ({
|
|
86
101
|
...(jest.requireActual('formik') as object),
|
|
87
|
-
Field: jest.fn(({ children }: FieldProps) =>
|
|
102
|
+
Field: jest.fn(({ children }: FieldProps) => (
|
|
103
|
+
<>{children({ field: {}, form: { touched: {}, errors: {} }, meta: { error: undefined } })}</>
|
|
104
|
+
)),
|
|
88
105
|
useField: jest.fn(() => [{ value: null }, {}]),
|
|
89
106
|
}));
|
|
90
107
|
|
|
91
108
|
const textFieldDef: FieldDefinition = {
|
|
92
109
|
id: 'chief-complaint',
|
|
93
110
|
type: 'obs',
|
|
94
|
-
label: '',
|
|
111
|
+
label: 'Chief complaint',
|
|
95
112
|
placeholder: '',
|
|
96
113
|
showHeading: false,
|
|
97
114
|
uuid: 'chief-complaint-uuid',
|
|
@@ -106,7 +123,7 @@ const textFieldDef: FieldDefinition = {
|
|
|
106
123
|
const numberFieldDef: FieldDefinition = {
|
|
107
124
|
id: 'weight',
|
|
108
125
|
type: 'obs',
|
|
109
|
-
label: '',
|
|
126
|
+
label: 'Weight',
|
|
110
127
|
placeholder: '',
|
|
111
128
|
showHeading: false,
|
|
112
129
|
uuid: 'weight-uuid',
|
|
@@ -118,10 +135,25 @@ const numberFieldDef: FieldDefinition = {
|
|
|
118
135
|
customConceptAnswers: [],
|
|
119
136
|
};
|
|
120
137
|
|
|
138
|
+
const dateFieldDef: FieldDefinition = {
|
|
139
|
+
id: 'vac_date',
|
|
140
|
+
type: 'obs',
|
|
141
|
+
label: 'Vaccination date',
|
|
142
|
+
placeholder: '',
|
|
143
|
+
showHeading: false,
|
|
144
|
+
uuid: 'vaccination-date-uuid',
|
|
145
|
+
validation: {
|
|
146
|
+
required: false,
|
|
147
|
+
matches: null,
|
|
148
|
+
},
|
|
149
|
+
answerConceptSetUuid: null,
|
|
150
|
+
customConceptAnswers: [],
|
|
151
|
+
};
|
|
152
|
+
|
|
121
153
|
const codedFieldDef: FieldDefinition = {
|
|
122
154
|
id: 'nationality',
|
|
123
155
|
type: 'obs',
|
|
124
|
-
label: '',
|
|
156
|
+
label: 'Nationality',
|
|
125
157
|
placeholder: '',
|
|
126
158
|
showHeading: false,
|
|
127
159
|
uuid: 'nationality-uuid',
|
|
@@ -133,57 +165,119 @@ const codedFieldDef: FieldDefinition = {
|
|
|
133
165
|
customConceptAnswers: [],
|
|
134
166
|
};
|
|
135
167
|
|
|
168
|
+
const mockInitialFormValues = {
|
|
169
|
+
additionalFamilyName: '',
|
|
170
|
+
additionalGivenName: '',
|
|
171
|
+
additionalMiddleName: '',
|
|
172
|
+
addNameInLocalLanguage: false,
|
|
173
|
+
address: {},
|
|
174
|
+
birthdate: null,
|
|
175
|
+
birthdateEstimated: false,
|
|
176
|
+
deathCause: '',
|
|
177
|
+
deathDate: '',
|
|
178
|
+
familyName: 'Doe',
|
|
179
|
+
gender: 'male',
|
|
180
|
+
givenName: 'John',
|
|
181
|
+
identifiers: mockOpenmrsId,
|
|
182
|
+
isDead: false,
|
|
183
|
+
middleName: 'Test',
|
|
184
|
+
monthsEstimated: 0,
|
|
185
|
+
patientUuid: mockPatient.uuid,
|
|
186
|
+
relationships: [],
|
|
187
|
+
telephoneNumber: '',
|
|
188
|
+
yearsEstimated: 0,
|
|
189
|
+
deathTime: '',
|
|
190
|
+
deathTimeFormat: 'AM' as const,
|
|
191
|
+
nonCodedCauseOfDeath: '',
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const initialContextValues: PatientRegistrationContextProps = {
|
|
195
|
+
currentPhoto: null,
|
|
196
|
+
inEditMode: false,
|
|
197
|
+
identifierTypes: [],
|
|
198
|
+
initialFormValues: mockInitialFormValues,
|
|
199
|
+
isOffline: false,
|
|
200
|
+
setCapturePhotoProps: jest.fn(),
|
|
201
|
+
setFieldValue: jest.fn(),
|
|
202
|
+
setInitialFormValues: jest.fn(),
|
|
203
|
+
validationSchema: null,
|
|
204
|
+
values: mockInitialFormValues,
|
|
205
|
+
setFieldTouched: jest.fn(),
|
|
206
|
+
};
|
|
207
|
+
|
|
136
208
|
describe('ObsField', () => {
|
|
137
209
|
beforeEach(() => {
|
|
138
|
-
mockUseConfig.mockReturnValue({
|
|
139
|
-
|
|
140
|
-
|
|
210
|
+
mockUseConfig.mockReturnValue({
|
|
211
|
+
...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
|
|
212
|
+
registrationObs: { encounterTypeUuid: 'reg-enc-uuid' },
|
|
213
|
+
} as RegistrationConfig);
|
|
214
|
+
mockUseConcept.mockImplementation(useConceptMockImpl);
|
|
215
|
+
mockUseConceptAnswers.mockImplementation(useConceptAnswersMockImpl);
|
|
141
216
|
});
|
|
142
217
|
|
|
143
218
|
it("logs an error and doesn't render if no registration encounter type is provided", () => {
|
|
144
|
-
mockUseConfig.mockReturnValue({
|
|
219
|
+
mockUseConfig.mockReturnValue({
|
|
220
|
+
...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
|
|
221
|
+
registrationObs: { encounterTypeUuid: null },
|
|
222
|
+
} as RegistrationConfig);
|
|
223
|
+
|
|
145
224
|
console.error = jest.fn();
|
|
146
225
|
render(<ObsField fieldDefinition={textFieldDef} />);
|
|
147
226
|
expect(console.error).toHaveBeenCalledWith(
|
|
148
227
|
expect.stringMatching(/no registration encounter type has been configured/i),
|
|
149
228
|
);
|
|
150
|
-
expect(screen.queryByRole('textbox')).
|
|
229
|
+
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
|
|
151
230
|
});
|
|
152
231
|
|
|
153
232
|
it('renders a text box for text concept', () => {
|
|
154
233
|
render(<ObsField fieldDefinition={textFieldDef} />);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
234
|
+
|
|
235
|
+
expect(screen.getByRole('textbox', { name: 'Chief complaint (optional)' })).toBeInTheDocument();
|
|
158
236
|
});
|
|
159
237
|
|
|
160
238
|
it('renders a number box for number concept', () => {
|
|
161
239
|
render(<ObsField fieldDefinition={numberFieldDef} />);
|
|
162
|
-
|
|
163
|
-
expect(screen.getByRole('spinbutton')).toBeInTheDocument();
|
|
240
|
+
|
|
241
|
+
expect(screen.getByRole('spinbutton', { name: 'Weight (optional)' })).toBeInTheDocument();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('renders a datepicker for date concept', async () => {
|
|
245
|
+
const user = userEvent.setup();
|
|
246
|
+
render(
|
|
247
|
+
<PatientRegistrationContextProvider value={initialContextValues}>
|
|
248
|
+
<ObsField fieldDefinition={dateFieldDef} />
|
|
249
|
+
</PatientRegistrationContextProvider>,
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
expect(screen.getByText(/vaccination date/i)).toBeInTheDocument();
|
|
253
|
+
|
|
254
|
+
const dateInput = screen.getByLabelText(/vaccination date/i);
|
|
255
|
+
expect(dateInput).toBeInTheDocument();
|
|
256
|
+
await user.clear(dateInput);
|
|
257
|
+
await user.type(dateInput, '28/05/2024');
|
|
258
|
+
// FIXME: Make the date input work
|
|
259
|
+
// expect(dateInput).toHaveValue('28/05/2024');
|
|
164
260
|
});
|
|
165
261
|
|
|
166
262
|
it('renders a select for a coded concept', () => {
|
|
167
263
|
render(<ObsField fieldDefinition={codedFieldDef} />);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
expect(
|
|
171
|
-
expect(
|
|
264
|
+
|
|
265
|
+
expect(screen.getByRole('combobox', { name: 'Nationality' })).toBeInTheDocument();
|
|
266
|
+
expect(screen.getByRole('option', { name: 'USA' })).toBeInTheDocument();
|
|
267
|
+
expect(screen.getByRole('option', { name: 'Mexico' })).toBeInTheDocument();
|
|
172
268
|
});
|
|
173
269
|
|
|
174
270
|
it('select uses answerConcept for answers when it is provided', async () => {
|
|
175
|
-
const user = userEvent.setup();
|
|
176
|
-
|
|
177
271
|
render(<ObsField fieldDefinition={{ ...codedFieldDef, answerConceptSetUuid: 'other-countries-uuid' }} />);
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
expect(
|
|
181
|
-
|
|
272
|
+
|
|
273
|
+
expect(screen.getByRole('combobox', { name: 'Nationality' })).toBeInTheDocument();
|
|
274
|
+
expect(screen.getByRole('option', { name: 'Kenya' })).toBeInTheDocument();
|
|
275
|
+
expect(screen.getByRole('option', { name: 'Uganda' })).toBeInTheDocument();
|
|
276
|
+
expect(screen.queryByRole('option', { name: 'USA' })).not.toBeInTheDocument();
|
|
277
|
+
expect(screen.queryByRole('option', { name: 'Mexico' })).not.toBeInTheDocument();
|
|
182
278
|
});
|
|
183
279
|
|
|
184
280
|
it('select uses customConceptAnswers for answers when provided', async () => {
|
|
185
|
-
const user = userEvent.setup();
|
|
186
|
-
|
|
187
281
|
render(
|
|
188
282
|
<ObsField
|
|
189
283
|
fieldDefinition={{
|
|
@@ -197,9 +291,9 @@ describe('ObsField', () => {
|
|
|
197
291
|
}}
|
|
198
292
|
/>,
|
|
199
293
|
);
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
expect(
|
|
203
|
-
|
|
294
|
+
|
|
295
|
+
expect(screen.getByRole('combobox', { name: 'Nationality' })).toBeInTheDocument();
|
|
296
|
+
expect(screen.getByRole('option', { name: 'Mozambique' })).toBeInTheDocument();
|
|
297
|
+
expect(screen.queryByRole('option', { name: 'Uganda' })).not.toBeInTheDocument();
|
|
204
298
|
});
|
|
205
299
|
});
|
package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx
CHANGED
|
@@ -3,10 +3,10 @@ import classNames from 'classnames';
|
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { Field } from 'formik';
|
|
5
5
|
import { Layer, Select, SelectItem } from '@carbon/react';
|
|
6
|
+
import { reportError } from '@openmrs/esm-framework';
|
|
6
7
|
import { type PersonAttributeTypeResponse } from '../../patient-registration.types';
|
|
7
8
|
import { useConceptAnswers } from '../field.resource';
|
|
8
9
|
import styles from './../field.scss';
|
|
9
|
-
import { reportError } from '@openmrs/esm-framework';
|
|
10
10
|
|
|
11
11
|
export interface CodedPersonAttributeFieldProps {
|
|
12
12
|
id: string;
|
|
@@ -44,7 +44,7 @@ export function CodedPersonAttributeField({
|
|
|
44
44
|
);
|
|
45
45
|
setError(true);
|
|
46
46
|
}
|
|
47
|
-
}, [answerConceptSetUuid, customConceptAnswers]);
|
|
47
|
+
}, [answerConceptSetUuid, customConceptAnswers, id, t]);
|
|
48
48
|
|
|
49
49
|
useEffect(() => {
|
|
50
50
|
if (!isLoadingConceptAnswers && !customConceptAnswers.length) {
|
|
@@ -72,7 +72,7 @@ export function CodedPersonAttributeField({
|
|
|
72
72
|
setError(true);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
}, [isLoadingConceptAnswers, conceptAnswers, customConceptAnswers]);
|
|
75
|
+
}, [isLoadingConceptAnswers, conceptAnswers, customConceptAnswers, t, id, answerConceptSetUuid]);
|
|
76
76
|
|
|
77
77
|
const answers = useMemo(() => {
|
|
78
78
|
if (customConceptAnswers.length) {
|
package/src/patient-registration/field/person-attributes/coded-person-attribute-field.test.tsx
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Form, Formik } from 'formik';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { useConceptAnswers } from '../field.resource';
|
|
5
|
+
import { CodedPersonAttributeField } from './coded-person-attribute-field.component';
|
|
6
|
+
|
|
7
|
+
const mockUseConceptAnswers = jest.mocked(useConceptAnswers);
|
|
8
|
+
|
|
9
|
+
jest.mock('../field.resource', () => ({
|
|
10
|
+
...jest.requireActual('../field.resource'),
|
|
11
|
+
useConceptAnswers: jest.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
describe('CodedPersonAttributeField', () => {
|
|
15
|
+
const conceptAnswers = [
|
|
16
|
+
{ uuid: '1', display: 'Option 1' },
|
|
17
|
+
{ uuid: '2', display: 'Option 2' },
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
const personAttributeType = {
|
|
21
|
+
format: 'org.openmrs.Concept',
|
|
22
|
+
display: 'Referred by',
|
|
23
|
+
uuid: '4dd56a75-14ab-4148-8700-1f4f704dc5b0',
|
|
24
|
+
name: '',
|
|
25
|
+
description: '',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const answerConceptSetUuid = '6682d17f-0777-45e4-a39b-93f77eb3531c';
|
|
29
|
+
let consoleSpy: jest.SpyInstance;
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
mockUseConceptAnswers.mockReturnValue({
|
|
33
|
+
data: conceptAnswers,
|
|
34
|
+
isLoading: false,
|
|
35
|
+
error: null,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
consoleSpy.mockRestore();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('renders an error if there is no concept answer set provided', () => {
|
|
46
|
+
expect(() => {
|
|
47
|
+
render(
|
|
48
|
+
<Formik initialValues={{}} onSubmit={() => {}}>
|
|
49
|
+
<Form>
|
|
50
|
+
<CodedPersonAttributeField
|
|
51
|
+
answerConceptSetUuid={null}
|
|
52
|
+
customConceptAnswers={[]}
|
|
53
|
+
id="attributeId"
|
|
54
|
+
label={personAttributeType.display}
|
|
55
|
+
personAttributeType={personAttributeType}
|
|
56
|
+
required={false}
|
|
57
|
+
/>
|
|
58
|
+
</Form>
|
|
59
|
+
</Formik>,
|
|
60
|
+
);
|
|
61
|
+
}).toThrow(expect.stringMatching(/has been defined without an answer concept set UUID/i));
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('renders an error if the concept answer set does not have any concept answers', () => {
|
|
65
|
+
mockUseConceptAnswers.mockReturnValue({
|
|
66
|
+
data: [],
|
|
67
|
+
isLoading: false,
|
|
68
|
+
error: null,
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
expect(() => {
|
|
72
|
+
render(
|
|
73
|
+
<Formik initialValues={{}} onSubmit={() => {}}>
|
|
74
|
+
<Form>
|
|
75
|
+
<CodedPersonAttributeField
|
|
76
|
+
id="attributeId"
|
|
77
|
+
personAttributeType={personAttributeType}
|
|
78
|
+
answerConceptSetUuid={answerConceptSetUuid}
|
|
79
|
+
label={personAttributeType.display}
|
|
80
|
+
customConceptAnswers={[]}
|
|
81
|
+
required={false}
|
|
82
|
+
/>
|
|
83
|
+
</Form>
|
|
84
|
+
</Formik>,
|
|
85
|
+
);
|
|
86
|
+
}).toThrow(expect.stringMatching(/does not have any concept answers/i));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('renders the conceptAnswers as select options', () => {
|
|
90
|
+
render(
|
|
91
|
+
<Formik initialValues={{}} onSubmit={() => {}}>
|
|
92
|
+
<Form>
|
|
93
|
+
<CodedPersonAttributeField
|
|
94
|
+
id="attributeId"
|
|
95
|
+
personAttributeType={personAttributeType}
|
|
96
|
+
answerConceptSetUuid={answerConceptSetUuid}
|
|
97
|
+
label={personAttributeType.display}
|
|
98
|
+
customConceptAnswers={[]}
|
|
99
|
+
required={false}
|
|
100
|
+
/>
|
|
101
|
+
</Form>
|
|
102
|
+
</Formik>,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
expect(screen.getByLabelText(/Referred by/i)).toBeInTheDocument();
|
|
106
|
+
expect(screen.getByText(/Option 1/i)).toBeInTheDocument();
|
|
107
|
+
expect(screen.getByText(/Option 2/i)).toBeInTheDocument();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('renders customConceptAnswers as select options when they are provided', () => {
|
|
111
|
+
render(
|
|
112
|
+
<Formik initialValues={{}} onSubmit={() => {}}>
|
|
113
|
+
<Form>
|
|
114
|
+
<CodedPersonAttributeField
|
|
115
|
+
id="attributeId"
|
|
116
|
+
personAttributeType={personAttributeType}
|
|
117
|
+
answerConceptSetUuid={answerConceptSetUuid}
|
|
118
|
+
label={personAttributeType.display}
|
|
119
|
+
customConceptAnswers={[
|
|
120
|
+
{
|
|
121
|
+
uuid: 'A',
|
|
122
|
+
label: 'Special Option A',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
uuid: 'B',
|
|
126
|
+
label: 'Special Option B',
|
|
127
|
+
},
|
|
128
|
+
]}
|
|
129
|
+
required={false}
|
|
130
|
+
/>
|
|
131
|
+
</Form>
|
|
132
|
+
</Formik>,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
expect(screen.getByLabelText(/Referred by/i)).toBeInTheDocument();
|
|
136
|
+
expect(screen.getByText(/Special Option A/i)).toBeInTheDocument();
|
|
137
|
+
expect(screen.getByText(/Special Option B/i)).toBeInTheDocument();
|
|
138
|
+
expect(screen.queryByText(/Option 1/i)).not.toBeInTheDocument();
|
|
139
|
+
expect(screen.queryByText(/Option 2/i)).not.toBeInTheDocument();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { Field, useField } from 'formik';
|
|
4
|
+
import { type PersonAttributeTypeResponse } from '../../patient-registration.types';
|
|
5
|
+
import styles from './../field.scss';
|
|
6
|
+
import { useLocations } from './location-person-attribute-field.resource';
|
|
7
|
+
import { ComboBox, InlineLoading, Layer } from '@carbon/react';
|
|
8
|
+
import { useTranslation } from 'react-i18next';
|
|
9
|
+
|
|
10
|
+
export interface LocationPersonAttributeFieldProps {
|
|
11
|
+
id: string;
|
|
12
|
+
personAttributeType: PersonAttributeTypeResponse;
|
|
13
|
+
label?: string;
|
|
14
|
+
locationTag: string;
|
|
15
|
+
required?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function LocationPersonAttributeField({
|
|
19
|
+
personAttributeType,
|
|
20
|
+
id,
|
|
21
|
+
label,
|
|
22
|
+
locationTag,
|
|
23
|
+
required,
|
|
24
|
+
}: LocationPersonAttributeFieldProps) {
|
|
25
|
+
const { t } = useTranslation();
|
|
26
|
+
const fieldName = `attributes.${personAttributeType.uuid}`;
|
|
27
|
+
const [field, meta, { setValue }] = useField(`attributes.${personAttributeType.uuid}`);
|
|
28
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
29
|
+
const { locations, isLoading, loadingNewData } = useLocations(locationTag || null, searchQuery);
|
|
30
|
+
const prevLocationOptions = useRef([]);
|
|
31
|
+
|
|
32
|
+
const locationOptions = useMemo(() => {
|
|
33
|
+
if (!(isLoading && loadingNewData)) {
|
|
34
|
+
const newOptions = locations.map(({ resource: { id, name } }) => ({ value: id, label: name }));
|
|
35
|
+
prevLocationOptions.current = newOptions;
|
|
36
|
+
return newOptions;
|
|
37
|
+
}
|
|
38
|
+
return prevLocationOptions.current;
|
|
39
|
+
}, [locations, isLoading, loadingNewData]);
|
|
40
|
+
|
|
41
|
+
const selectedItem = useMemo(() => {
|
|
42
|
+
if (typeof meta.value === 'string') {
|
|
43
|
+
return locationOptions.find(({ value }) => value === meta.value) || null;
|
|
44
|
+
}
|
|
45
|
+
if (typeof meta.value === 'object' && meta.value) {
|
|
46
|
+
return locationOptions.find(({ value }) => value === meta.value.uuid) || null;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}, [locationOptions, meta.value]);
|
|
50
|
+
|
|
51
|
+
// Callback for when updating the combobox input
|
|
52
|
+
const handleInputChange = useCallback(
|
|
53
|
+
(value: string | null) => {
|
|
54
|
+
if (value) {
|
|
55
|
+
// If the value exists in the locationOptions (i.e. a label matches the input), exit the function
|
|
56
|
+
if (locationOptions.find(({ label }) => label === value)) return;
|
|
57
|
+
// If the input is a new value, set the search query
|
|
58
|
+
setSearchQuery(value);
|
|
59
|
+
// Clear the current selected value since the input doesn't match any existing options
|
|
60
|
+
setValue(null);
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
[locationOptions, setValue],
|
|
64
|
+
);
|
|
65
|
+
const handleSelect = useCallback(
|
|
66
|
+
({ selectedItem }) => {
|
|
67
|
+
if (selectedItem) {
|
|
68
|
+
setValue(selectedItem.value);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
[setValue],
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<div
|
|
76
|
+
className={classNames(styles.customField, styles.halfWidthInDesktopView, styles.locationAttributeFieldContainer)}>
|
|
77
|
+
<Layer>
|
|
78
|
+
<Field name={fieldName}>
|
|
79
|
+
{({ field, form: { touched, errors } }) => {
|
|
80
|
+
return (
|
|
81
|
+
<ComboBox
|
|
82
|
+
id={id}
|
|
83
|
+
name={`person-attribute-${personAttributeType.uuid}`}
|
|
84
|
+
titleText={label}
|
|
85
|
+
items={locationOptions}
|
|
86
|
+
placeholder={t('searchLocationPersonAttribute', 'Search location')}
|
|
87
|
+
onInputChange={handleInputChange}
|
|
88
|
+
required={required}
|
|
89
|
+
onChange={handleSelect}
|
|
90
|
+
selectedItem={selectedItem}
|
|
91
|
+
invalid={errors[fieldName] && touched[fieldName]}
|
|
92
|
+
typeahead
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}}
|
|
96
|
+
</Field>
|
|
97
|
+
</Layer>
|
|
98
|
+
{loadingNewData && (
|
|
99
|
+
<div className={styles.loadingContainer}>
|
|
100
|
+
<InlineLoading />
|
|
101
|
+
</div>
|
|
102
|
+
)}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { type FetchResponse, fhirBaseUrl, openmrsFetch, useDebounce } from '@openmrs/esm-framework';
|
|
3
|
+
import { type LocationEntry, type LocationResponse } from '@openmrs/esm-service-queues-app/src/types';
|
|
4
|
+
import useSWR from 'swr';
|
|
5
|
+
|
|
6
|
+
interface UseLocationsResult {
|
|
7
|
+
locations: Array<LocationEntry>;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
loadingNewData: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useLocations(locationTag: string | null, searchQuery: string = ''): UseLocationsResult {
|
|
13
|
+
const debouncedSearchQuery = useDebounce(searchQuery);
|
|
14
|
+
|
|
15
|
+
const constructUrl = useMemo(() => {
|
|
16
|
+
let url = `${fhirBaseUrl}/Location?`;
|
|
17
|
+
let urlSearchParameters = new URLSearchParams();
|
|
18
|
+
urlSearchParameters.append('_summary', 'data');
|
|
19
|
+
|
|
20
|
+
if (!debouncedSearchQuery) {
|
|
21
|
+
urlSearchParameters.append('_count', '10');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (locationTag) {
|
|
25
|
+
urlSearchParameters.append('_tag', locationTag);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof debouncedSearchQuery === 'string' && debouncedSearchQuery != '') {
|
|
29
|
+
urlSearchParameters.append('name:contains', debouncedSearchQuery);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return url + urlSearchParameters.toString();
|
|
33
|
+
}, [locationTag, debouncedSearchQuery]);
|
|
34
|
+
|
|
35
|
+
const { data, error, isLoading, isValidating } = useSWR<FetchResponse<LocationResponse>, Error>(
|
|
36
|
+
constructUrl,
|
|
37
|
+
openmrsFetch,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
return useMemo(
|
|
41
|
+
() => ({
|
|
42
|
+
locations: data?.data?.entry || [],
|
|
43
|
+
isLoading,
|
|
44
|
+
loadingNewData: isValidating,
|
|
45
|
+
}),
|
|
46
|
+
[data, isLoading, isValidating],
|
|
47
|
+
);
|
|
48
|
+
}
|
package/src/patient-registration/field/person-attributes/person-attribute-field.component.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { InlineNotification, TextInputSkeleton
|
|
2
|
+
import { InlineNotification, TextInputSkeleton } from '@carbon/react';
|
|
3
3
|
import { type FieldDefinition } from '../../../config-schema';
|
|
4
4
|
import { CodedPersonAttributeField } from './coded-person-attribute-field.component';
|
|
5
5
|
import { usePersonAttributeType } from './person-attributes.resource';
|
|
6
6
|
import { TextPersonAttributeField } from './text-person-attribute-field.component';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
import styles from '../field.scss';
|
|
9
|
-
import
|
|
9
|
+
import { LocationPersonAttributeField } from './location-person-attribute-field.component';
|
|
10
10
|
|
|
11
11
|
export interface PersonAttributeFieldProps {
|
|
12
12
|
fieldDefinition: FieldDefinition;
|
|
@@ -23,26 +23,13 @@ export function PersonAttributeField({ fieldDefinition }: PersonAttributeFieldPr
|
|
|
23
23
|
switch (personAttributeType.format) {
|
|
24
24
|
case 'java.lang.String':
|
|
25
25
|
return (
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
customConceptAnswers={fieldDefinition.customConceptAnswers ?? []}
|
|
34
|
-
required={fieldDefinition.validation?.required ?? false}
|
|
35
|
-
/>
|
|
36
|
-
) : (
|
|
37
|
-
<TextPersonAttributeField
|
|
38
|
-
personAttributeType={personAttributeType}
|
|
39
|
-
validationRegex={fieldDefinition.validation?.matches ?? ''}
|
|
40
|
-
label={fieldDefinition.label}
|
|
41
|
-
required={fieldDefinition.validation?.required ?? false}
|
|
42
|
-
id={fieldDefinition?.id}
|
|
43
|
-
/>
|
|
44
|
-
)}
|
|
45
|
-
</>
|
|
26
|
+
<TextPersonAttributeField
|
|
27
|
+
personAttributeType={personAttributeType}
|
|
28
|
+
validationRegex={fieldDefinition.validation?.matches ?? ''}
|
|
29
|
+
label={fieldDefinition.label}
|
|
30
|
+
required={fieldDefinition.validation?.required ?? false}
|
|
31
|
+
id={fieldDefinition?.id}
|
|
32
|
+
/>
|
|
46
33
|
);
|
|
47
34
|
case 'org.openmrs.Concept':
|
|
48
35
|
return (
|
|
@@ -55,6 +42,16 @@ export function PersonAttributeField({ fieldDefinition }: PersonAttributeFieldPr
|
|
|
55
42
|
required={fieldDefinition.validation?.required ?? false}
|
|
56
43
|
/>
|
|
57
44
|
);
|
|
45
|
+
case 'org.openmrs.Location':
|
|
46
|
+
return (
|
|
47
|
+
<LocationPersonAttributeField
|
|
48
|
+
personAttributeType={personAttributeType}
|
|
49
|
+
locationTag={fieldDefinition.locationTag}
|
|
50
|
+
label={fieldDefinition.label}
|
|
51
|
+
id={fieldDefinition?.id}
|
|
52
|
+
required={fieldDefinition.validation?.required ?? false}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
58
55
|
default:
|
|
59
56
|
return (
|
|
60
57
|
<InlineNotification kind="error" title="Error">
|