@olaboot/esm-patient-registration-app 9.2.0
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/ADDRESS_CONFIGURATION.md +152 -0
- package/IDENTIFIER_CONFIGURATION.md +142 -0
- package/IMPLEMENTATION_SUMMARY.md +111 -0
- package/QUICK_START.md +95 -0
- package/README.md +7 -0
- package/address-required-fields-config.json +26 -0
- package/dist/126.js +1 -0
- package/dist/15.js +1 -0
- package/dist/1564.js +1 -0
- package/dist/1567.js +1 -0
- package/dist/1845.js +1 -0
- package/dist/1953.js +1 -0
- package/dist/200.js +1 -0
- package/dist/200.js.map +1 -0
- package/dist/215.js +1 -0
- package/dist/2178.js +1 -0
- package/dist/250.js +1 -0
- package/dist/250.js.map +1 -0
- package/dist/2523.js +1 -0
- package/dist/2523.js.map +1 -0
- package/dist/2566.js +1 -0
- package/dist/2586.js +1 -0
- package/dist/2586.js.map +1 -0
- package/dist/2716.js +1 -0
- package/dist/2716.js.map +1 -0
- package/dist/2759.js +1 -0
- package/dist/2821.js +6 -0
- package/dist/2821.js.map +1 -0
- package/dist/3089.js +1 -0
- package/dist/3089.js.map +1 -0
- package/dist/3230.js +1 -0
- package/dist/3441.js +1 -0
- package/dist/3565.js +1 -0
- package/dist/3571.js +1 -0
- package/dist/3571.js.map +1 -0
- package/dist/3746.js +1 -0
- package/dist/3925.js +1 -0
- package/dist/3946.js +1 -0
- package/dist/4024.js +1 -0
- package/dist/4024.js.map +1 -0
- package/dist/4744.js +1 -0
- package/dist/4744.js.map +1 -0
- package/dist/4809.js +1 -0
- package/dist/4894.js +1 -0
- package/dist/4970.js +1 -0
- package/dist/4970.js.map +1 -0
- package/dist/5130.js +1 -0
- package/dist/5187.js +1 -0
- package/dist/5491.js +1 -0
- package/dist/5491.js.map +1 -0
- package/dist/5595.js +1 -0
- package/dist/5961.js +1 -0
- package/dist/6133.js +1 -0
- package/dist/634.js +1 -0
- package/dist/634.js.map +1 -0
- package/dist/6456.js +1 -0
- package/dist/6466.js +1 -0
- package/dist/6613.js +1 -0
- package/dist/6783.js +1 -0
- package/dist/7073.js +38 -0
- package/dist/7073.js.map +1 -0
- package/dist/7154.js +1 -0
- package/dist/7154.js.map +1 -0
- package/dist/7348.js +1 -0
- package/dist/7439.js +1 -0
- package/dist/7439.js.map +1 -0
- package/dist/7543.js +1 -0
- package/dist/7607.js +1 -0
- package/dist/772.js +1 -0
- package/dist/7984.js +1 -0
- package/dist/7984.js.map +1 -0
- package/dist/8538.js +1 -0
- package/dist/8538.js.map +1 -0
- package/dist/8599.js +1 -0
- package/dist/8727.js +1 -0
- package/dist/8847.js +1 -0
- package/dist/9015.js +1 -0
- package/dist/906.js +1 -0
- package/dist/9065.js +1 -0
- package/dist/9182.js +1 -0
- package/dist/9339.js +1 -0
- package/dist/9453.js +1 -0
- package/dist/9833.js +1 -0
- package/dist/9833.js.map +1 -0
- package/dist/9856.js +1 -0
- package/dist/9856.js.map +1 -0
- package/dist/9920.js +1 -0
- package/dist/9938.js +1 -0
- package/dist/9943.js +1 -0
- package/dist/9943.js.map +1 -0
- package/dist/main.js +10 -0
- package/dist/main.js.map +1 -0
- package/dist/olaboot-esm-patient-registration-app.js +5 -0
- package/dist/olaboot-esm-patient-registration-app.js.buildmanifest.json +1627 -0
- package/dist/olaboot-esm-patient-registration-app.js.map +1 -0
- package/dist/routes.json +1 -0
- package/docs/images/patient-registration-hierarchy.png +0 -0
- package/example-config.json +14 -0
- package/jest.config.js +3 -0
- package/package.json +60 -0
- package/rspack.config.js +1 -0
- package/src/add-patient-link.extension.tsx +21 -0
- package/src/add-patient-link.scss +3 -0
- package/src/add-patient-link.test.tsx +16 -0
- package/src/config-schema.ts +507 -0
- package/src/constants.ts +14 -0
- package/src/declarations.d.ts +4 -0
- package/src/index.ts +59 -0
- package/src/nav-link.test.tsx +13 -0
- package/src/nav-link.tsx +10 -0
- package/src/offline.resources.ts +157 -0
- package/src/offline.ts +93 -0
- package/src/patient-photo.extension.tsx +11 -0
- package/src/patient-registration/before-save-prompt.component.tsx +72 -0
- package/src/patient-registration/field/__mocks__/field.resource.ts +60 -0
- package/src/patient-registration/field/address/address-field.component.tsx +186 -0
- package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +71 -0
- package/src/patient-registration/field/address/address-hierarchy.resource.tsx +157 -0
- package/src/patient-registration/field/address/address-hierarchy.test.tsx +296 -0
- package/src/patient-registration/field/address/address-search.component.tsx +87 -0
- package/src/patient-registration/field/address/address-search.scss +53 -0
- package/src/patient-registration/field/address/address-search.test.tsx +141 -0
- package/src/patient-registration/field/address/custom-address-field.component.tsx +32 -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 +25 -0
- package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +79 -0
- package/src/patient-registration/field/dob/dob.component.tsx +167 -0
- package/src/patient-registration/field/dob/dob.test.tsx +90 -0
- package/src/patient-registration/field/field.component.tsx +53 -0
- package/src/patient-registration/field/field.resource.ts +42 -0
- package/src/patient-registration/field/field.scss +171 -0
- package/src/patient-registration/field/field.test.tsx +330 -0
- package/src/patient-registration/field/gender/gender-field.component.tsx +54 -0
- package/src/patient-registration/field/gender/gender-field.test.tsx +99 -0
- package/src/patient-registration/field/id/id-field.component.tsx +136 -0
- package/src/patient-registration/field/id/id-field.test.tsx +121 -0
- package/src/patient-registration/field/id/identifier-selection-overlay.component.tsx +200 -0
- package/src/patient-registration/field/id/identifier-selection.scss +41 -0
- package/src/patient-registration/field/name/name-field.component.tsx +148 -0
- package/src/patient-registration/field/obs/obs-field.component.tsx +261 -0
- package/src/patient-registration/field/obs/obs-field.test.tsx +299 -0
- package/src/patient-registration/field/person-attributes/coded-person-attribute-field.component.tsx +120 -0
- 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 +100 -0
- package/src/patient-registration/field/person-attributes/person-attribute-field.test.tsx +193 -0
- package/src/patient-registration/field/person-attributes/person-attributes.resource.ts +20 -0
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.component.tsx +58 -0
- package/src/patient-registration/field/person-attributes/text-person-attribute-field.test.tsx +90 -0
- package/src/patient-registration/field/phone/phone-field.component.tsx +17 -0
- package/src/patient-registration/form-manager.test.ts +91 -0
- package/src/patient-registration/form-manager.ts +443 -0
- package/src/patient-registration/input/basic-input/input/input.component.tsx +183 -0
- package/src/patient-registration/input/basic-input/input/input.test.tsx +72 -0
- package/src/patient-registration/input/basic-input/select/select-input.component.tsx +32 -0
- package/src/patient-registration/input/basic-input/select/select-input.test.tsx +49 -0
- package/src/patient-registration/input/combo-input/combo-input.component.tsx +130 -0
- package/src/patient-registration/input/combo-input/selection-tick.component.tsx +20 -0
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.component.tsx +187 -0
- package/src/patient-registration/input/custom-input/autosuggest/autosuggest.scss +62 -0
- 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 +193 -0
- package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +335 -0
- package/src/patient-registration/input/custom-input/identifier/utils.test.ts +81 -0
- package/src/patient-registration/input/custom-input/identifier/utils.ts +19 -0
- package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +56 -0
- package/src/patient-registration/input/dummy-data/dummy-data-input.test.tsx +34 -0
- package/src/patient-registration/input/input.scss +122 -0
- package/src/patient-registration/patient-registration-context.ts +35 -0
- package/src/patient-registration/patient-registration-hooks.ts +376 -0
- package/src/patient-registration/patient-registration-utils.test.ts +33 -0
- package/src/patient-registration/patient-registration-utils.ts +214 -0
- package/src/patient-registration/patient-registration.component.tsx +266 -0
- package/src/patient-registration/patient-registration.resource.test.tsx +22 -0
- package/src/patient-registration/patient-registration.resource.ts +198 -0
- package/src/patient-registration/patient-registration.scss +103 -0
- package/src/patient-registration/patient-registration.test.tsx +580 -0
- package/src/patient-registration/patient-registration.types.ts +322 -0
- package/src/patient-registration/section/death-info/death-info-section.component.tsx +36 -0
- package/src/patient-registration/section/death-info/death-info-section.test.tsx +47 -0
- package/src/patient-registration/section/demographics/demographics-section.component.tsx +30 -0
- package/src/patient-registration/section/demographics/demographics-section.test.tsx +98 -0
- package/src/patient-registration/section/generic-section.component.tsx +17 -0
- package/src/patient-registration/section/patient-relationships/relationships-section.component.tsx +234 -0
- package/src/patient-registration/section/patient-relationships/relationships-section.test.tsx +113 -0
- package/src/patient-registration/section/patient-relationships/relationships.resource.tsx +78 -0
- package/src/patient-registration/section/patient-relationships/relationships.scss +35 -0
- package/src/patient-registration/section/section-wrapper.component.tsx +40 -0
- package/src/patient-registration/section/section.component.tsx +23 -0
- package/src/patient-registration/section/section.scss +21 -0
- package/src/patient-registration/ui-components/overlay/overlay.component.tsx +51 -0
- package/src/patient-registration/ui-components/overlay/overlay.scss +63 -0
- package/src/patient-registration/validation/patient-registration-validation.test.ts +205 -0
- package/src/patient-registration/validation/patient-registration-validation.ts +123 -0
- package/src/resource.ts +12 -0
- package/src/resources-context.ts +14 -0
- package/src/root.component.tsx +63 -0
- package/src/root.scss +7 -0
- package/src/routes.json +61 -0
- 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.test.tsx +32 -0
- package/src/widgets/edit-patient-details-button.component.tsx +33 -0
- package/src/widgets/edit-patient-details-button.scss +3 -0
- package/src/widgets/edit-patient-details-button.test.tsx +35 -0
- package/translations/am.json +120 -0
- package/translations/ar.json +120 -0
- package/translations/ar_SY.json +120 -0
- package/translations/bn.json +120 -0
- package/translations/cs.json +120 -0
- package/translations/de.json +120 -0
- package/translations/en.json +120 -0
- package/translations/en_US.json +120 -0
- package/translations/es.json +120 -0
- package/translations/es_MX.json +120 -0
- package/translations/fr.json +120 -0
- package/translations/he.json +120 -0
- package/translations/hi.json +120 -0
- package/translations/hi_IN.json +120 -0
- package/translations/id.json +120 -0
- package/translations/it.json +120 -0
- package/translations/ka.json +120 -0
- package/translations/km.json +120 -0
- package/translations/ku.json +120 -0
- package/translations/ky.json +120 -0
- package/translations/lg.json +120 -0
- package/translations/ne.json +120 -0
- package/translations/pl.json +120 -0
- package/translations/pt.json +120 -0
- package/translations/pt_BR.json +120 -0
- package/translations/qu.json +120 -0
- package/translations/ro_RO.json +120 -0
- package/translations/ru_RU.json +120 -0
- package/translations/si.json +120 -0
- package/translations/sq.json +120 -0
- package/translations/sw.json +120 -0
- package/translations/sw_KE.json +120 -0
- package/translations/tr.json +120 -0
- package/translations/tr_TR.json +120 -0
- package/translations/uk.json +120 -0
- package/translations/uz.json +120 -0
- package/translations/uz@Latn.json +120 -0
- package/translations/uz_UZ.json +120 -0
- package/translations/vi.json +120 -0
- package/translations/zh.json +120 -0
- package/translations/zh_CN.json +120 -0
- package/translations/zh_TW.json +120 -0
- package/tsconfig.json +5 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { useField, Field } from 'formik';
|
|
4
|
+
import { Button } from '@carbon/react';
|
|
5
|
+
import { TrashCan, Edit, Reset } from '@carbon/react/icons';
|
|
6
|
+
import { type RegistrationConfig } from '../../../../config-schema';
|
|
7
|
+
import { showModal, useConfig, UserHasAccess } from '@openmrs/esm-framework';
|
|
8
|
+
import { deleteIdentifierType, setIdentifierSource } from '../../../field/id/id-field.component';
|
|
9
|
+
import { Input } from '../../basic-input/input/input.component';
|
|
10
|
+
import { usePatientRegistrationContext } from '../../../patient-registration-context';
|
|
11
|
+
import { useResourcesContext } from '../../../../resources-context';
|
|
12
|
+
import { shouldBlockPatientIdentifierInOfflineMode } from './utils';
|
|
13
|
+
import { type PatientIdentifierValue } from '../../../patient-registration.types';
|
|
14
|
+
import styles from '../../input.scss';
|
|
15
|
+
|
|
16
|
+
interface IdentifierInputProps {
|
|
17
|
+
patientIdentifier: PatientIdentifierValue;
|
|
18
|
+
fieldName: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const IdentifierInput: React.FC<IdentifierInputProps> = ({ patientIdentifier, fieldName }) => {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const { defaultPatientIdentifierTypes } = useConfig<RegistrationConfig>();
|
|
24
|
+
const { identifierTypes } = useResourcesContext();
|
|
25
|
+
const { isOffline, values, setFieldValue } = usePatientRegistrationContext();
|
|
26
|
+
const identifierType = useMemo(
|
|
27
|
+
() => identifierTypes.find((identifierType) => identifierType.uuid === patientIdentifier.identifierTypeUuid),
|
|
28
|
+
[patientIdentifier, identifierTypes],
|
|
29
|
+
);
|
|
30
|
+
const { autoGeneration, initialValue, identifierValue, identifierName, required, selectedSource } = patientIdentifier;
|
|
31
|
+
const manualEntryEnabled = selectedSource?.autoGenerationOption?.manualEntryEnabled;
|
|
32
|
+
const [hideInputField, setHideInputField] = useState(autoGeneration || initialValue === identifierValue);
|
|
33
|
+
const name = `identifiers.${fieldName}.identifierValue`;
|
|
34
|
+
const [identifierField, identifierFieldMeta] = useField(name);
|
|
35
|
+
|
|
36
|
+
const disabled = isOffline && shouldBlockPatientIdentifierInOfflineMode(identifierType);
|
|
37
|
+
|
|
38
|
+
const defaultPatientIdentifierTypesMap = useMemo(() => {
|
|
39
|
+
const map = {};
|
|
40
|
+
defaultPatientIdentifierTypes?.forEach((typeUuid) => {
|
|
41
|
+
map[typeUuid] = true;
|
|
42
|
+
});
|
|
43
|
+
return map;
|
|
44
|
+
}, [defaultPatientIdentifierTypes]);
|
|
45
|
+
|
|
46
|
+
const validateInput = (value: string) => {
|
|
47
|
+
if (!value || value === '') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!identifierType?.format) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const regex = new RegExp(identifierType.format);
|
|
57
|
+
if (regex.test(value)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return identifierType.formatDescription ?? `Expected format: ${identifierType.format}`;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error('Invalid regex pattern:', identifierType.format);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const handleReset = useCallback(() => {
|
|
69
|
+
setHideInputField(true);
|
|
70
|
+
setFieldValue(`identifiers.${fieldName}`, {
|
|
71
|
+
...patientIdentifier,
|
|
72
|
+
identifierValue: initialValue,
|
|
73
|
+
selectedSource,
|
|
74
|
+
autoGeneration,
|
|
75
|
+
} as PatientIdentifierValue);
|
|
76
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
77
|
+
}, [initialValue, setHideInputField]);
|
|
78
|
+
|
|
79
|
+
const handleEdit = () => {
|
|
80
|
+
setHideInputField(false);
|
|
81
|
+
setFieldValue(`identifiers.${fieldName}`, {
|
|
82
|
+
...patientIdentifier,
|
|
83
|
+
...setIdentifierSource(identifierType?.identifierSources?.[0], initialValue, initialValue),
|
|
84
|
+
...(autoGeneration && manualEntryEnabled && { identifierValue: initialValue ?? '' }),
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const handleDelete = () => {
|
|
89
|
+
/*
|
|
90
|
+
If there is an initialValue to the identifier, a confirmation modal seeking
|
|
91
|
+
confirmation to delete the identifier should be shown, else in the other case,
|
|
92
|
+
we can directly delete the identifier.
|
|
93
|
+
*/
|
|
94
|
+
|
|
95
|
+
if (initialValue) {
|
|
96
|
+
const dispose = showModal('delete-identifier-confirmation-modal', {
|
|
97
|
+
closeModal: () => dispose(),
|
|
98
|
+
deleteIdentifier: (isConfirmed) => {
|
|
99
|
+
if (isConfirmed) {
|
|
100
|
+
setFieldValue('identifiers', deleteIdentifierType(values.identifiers, fieldName));
|
|
101
|
+
}
|
|
102
|
+
dispose();
|
|
103
|
+
},
|
|
104
|
+
identifierName,
|
|
105
|
+
identifierValue: initialValue,
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
setFieldValue('identifiers', deleteIdentifierType(values.identifiers, fieldName));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const showEditButton = !required && hideInputField && (!!initialValue || manualEntryEnabled);
|
|
113
|
+
const showResetButton =
|
|
114
|
+
(!!initialValue && initialValue !== identifierValue) || (!hideInputField && manualEntryEnabled);
|
|
115
|
+
return (
|
|
116
|
+
<div className={styles.IDInput}>
|
|
117
|
+
{!hideInputField ? (
|
|
118
|
+
<Field name={name} validate={validateInput}>
|
|
119
|
+
{({ field, form: { touched, errors } }) => (
|
|
120
|
+
<Input
|
|
121
|
+
id={name}
|
|
122
|
+
labelText={identifierName}
|
|
123
|
+
name={name}
|
|
124
|
+
disabled={disabled}
|
|
125
|
+
required={required}
|
|
126
|
+
invalid={errors[name] && touched[name]}
|
|
127
|
+
invalidText={errors[name] && t(errors[name])}
|
|
128
|
+
{...field}
|
|
129
|
+
/>
|
|
130
|
+
)}
|
|
131
|
+
</Field>
|
|
132
|
+
) : (
|
|
133
|
+
<div className={styles.textID}>
|
|
134
|
+
<p data-testid="identifier-label" className={styles.label}>
|
|
135
|
+
{required ? identifierName : `${t('optionalIdentifierLabel', { identifierName })}`}
|
|
136
|
+
</p>
|
|
137
|
+
<p data-testid="identifier-placeholder" className={styles.bodyShort02}>
|
|
138
|
+
{autoGeneration ? t('autoGeneratedPlaceholderText', 'Auto-generated') : identifierValue}
|
|
139
|
+
</p>
|
|
140
|
+
<input data-testid="identifier-input" type="hidden" {...identifierField} disabled />
|
|
141
|
+
{/* This is added for any error descriptions */}
|
|
142
|
+
{!!(identifierFieldMeta.touched && identifierFieldMeta.error) && (
|
|
143
|
+
<span className={styles.dangerLabel01}>{identifierFieldMeta.error && t(identifierFieldMeta.error)}</span>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
)}
|
|
147
|
+
<div className={styles.actionButtonContainer}>
|
|
148
|
+
{showEditButton && (
|
|
149
|
+
<UserHasAccess privilege="Edit Patient Identifiers">
|
|
150
|
+
<Button
|
|
151
|
+
data-testid="edit-button"
|
|
152
|
+
size="md"
|
|
153
|
+
kind="ghost"
|
|
154
|
+
onClick={handleEdit}
|
|
155
|
+
iconDescription={t('editIdentifierTooltip', 'Edit')}
|
|
156
|
+
disabled={disabled}
|
|
157
|
+
hasIconOnly>
|
|
158
|
+
<Edit size={16} />
|
|
159
|
+
</Button>
|
|
160
|
+
</UserHasAccess>
|
|
161
|
+
)}
|
|
162
|
+
{showResetButton && (
|
|
163
|
+
<UserHasAccess privilege="Edit Patient Identifiers">
|
|
164
|
+
<Button
|
|
165
|
+
size="md"
|
|
166
|
+
kind="ghost"
|
|
167
|
+
onClick={handleReset}
|
|
168
|
+
iconDescription={t('resetIdentifierTooltip', 'Reset')}
|
|
169
|
+
disabled={disabled}
|
|
170
|
+
hasIconOnly>
|
|
171
|
+
<Reset size={16} />
|
|
172
|
+
</Button>
|
|
173
|
+
</UserHasAccess>
|
|
174
|
+
)}
|
|
175
|
+
{!patientIdentifier.required && !defaultPatientIdentifierTypesMap[patientIdentifier.identifierTypeUuid] && (
|
|
176
|
+
<UserHasAccess privilege="Delete Patient Identifiers">
|
|
177
|
+
<Button
|
|
178
|
+
size="md"
|
|
179
|
+
kind="ghost"
|
|
180
|
+
onClick={handleDelete}
|
|
181
|
+
iconDescription={t('deleteIdentifierTooltip', 'Delete')}
|
|
182
|
+
disabled={disabled}
|
|
183
|
+
hasIconOnly>
|
|
184
|
+
<TrashCan size={16} />
|
|
185
|
+
</Button>
|
|
186
|
+
</UserHasAccess>
|
|
187
|
+
)}
|
|
188
|
+
</div>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export default IdentifierInput;
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
/* eslint-disable testing-library/no-node-access */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import userEvent from '@testing-library/user-event';
|
|
4
|
+
import { screen } from '@testing-library/react';
|
|
5
|
+
import { Form, Formik } from 'formik';
|
|
6
|
+
import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
|
|
7
|
+
import { esmPatientRegistrationSchema, type RegistrationConfig } from '../../../../config-schema';
|
|
8
|
+
import { renderWithContext } from 'tools';
|
|
9
|
+
import { ResourcesContextProvider } from '../../../../resources-context';
|
|
10
|
+
import { type Resources } from '../../../../offline.resources';
|
|
11
|
+
import {
|
|
12
|
+
PatientRegistrationContextProvider,
|
|
13
|
+
type PatientRegistrationContextProps,
|
|
14
|
+
} from '../../../patient-registration-context';
|
|
15
|
+
import type {
|
|
16
|
+
AddressTemplate,
|
|
17
|
+
FormValues,
|
|
18
|
+
IdentifierSource,
|
|
19
|
+
PatientIdentifierValue,
|
|
20
|
+
} from '../../../patient-registration.types';
|
|
21
|
+
import IdentifierInput from './identifier-input.component';
|
|
22
|
+
|
|
23
|
+
const mockIdentifierTypes = [
|
|
24
|
+
{
|
|
25
|
+
fieldName: 'openMrsId',
|
|
26
|
+
format: '',
|
|
27
|
+
identifierSources: [
|
|
28
|
+
{
|
|
29
|
+
uuid: '01af8526-cea4-4175-aa90-340acb411771',
|
|
30
|
+
name: 'Generator 2 for OpenMRS ID',
|
|
31
|
+
autoGenerationOption: {
|
|
32
|
+
manualEntryEnabled: true,
|
|
33
|
+
automaticGenerationEnabled: true,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
isPrimary: true,
|
|
38
|
+
name: 'OpenMRS ID',
|
|
39
|
+
required: true,
|
|
40
|
+
uniquenessBehavior: 'UNIQUE' as const,
|
|
41
|
+
uuid: '05a29f94-c0ed-11e2-94be-8c13b969e334',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
fieldName: 'ssn',
|
|
45
|
+
format: '^[A-Z]{1}-[0-9]{7}$',
|
|
46
|
+
formatDescription: 'Identifier should be one letter, followed by a dash, and then 7 digits e.g. A-1234567',
|
|
47
|
+
identifierSources: [
|
|
48
|
+
{
|
|
49
|
+
uuid: '01af8526-cea4-4175-aa90-340acb411771',
|
|
50
|
+
name: 'Generator 2 for SSN',
|
|
51
|
+
autoGenerationOption: {
|
|
52
|
+
manualEntryEnabled: true,
|
|
53
|
+
automaticGenerationEnabled: false,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
isPrimary: false,
|
|
58
|
+
name: 'SSN',
|
|
59
|
+
required: true,
|
|
60
|
+
uniquenessBehavior: 'UNIQUE' as const,
|
|
61
|
+
uuid: 'a71403f3-8584-4289-ab41-2b4e5570bd45',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
const mockResourcesContextValue: Resources = {
|
|
66
|
+
addressTemplate: {} as AddressTemplate,
|
|
67
|
+
currentSession: {
|
|
68
|
+
authenticated: true,
|
|
69
|
+
sessionId: 'JSESSION',
|
|
70
|
+
currentProvider: { uuid: 'provider-uuid', identifier: 'PRO-123' },
|
|
71
|
+
},
|
|
72
|
+
relationshipTypes: [],
|
|
73
|
+
identifierTypes: [...mockIdentifierTypes],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const mockInitialFormValues = {
|
|
77
|
+
additionalFamilyName: '',
|
|
78
|
+
additionalGivenName: '',
|
|
79
|
+
additionalMiddleName: '',
|
|
80
|
+
addNameInLocalLanguage: false,
|
|
81
|
+
address: {},
|
|
82
|
+
attributes: {},
|
|
83
|
+
birthdate: null,
|
|
84
|
+
deathDate: null,
|
|
85
|
+
familyName: '',
|
|
86
|
+
gender: '',
|
|
87
|
+
givenName: '',
|
|
88
|
+
identifiers: {},
|
|
89
|
+
middleName: '',
|
|
90
|
+
relationships: [],
|
|
91
|
+
} as FormValues;
|
|
92
|
+
|
|
93
|
+
const mockContextValues: PatientRegistrationContextProps = {
|
|
94
|
+
currentPhoto: '',
|
|
95
|
+
inEditMode: false,
|
|
96
|
+
identifierTypes: [],
|
|
97
|
+
initialFormValues: mockInitialFormValues,
|
|
98
|
+
isOffline: false,
|
|
99
|
+
setCapturePhotoProps: jest.fn(),
|
|
100
|
+
setFieldValue: jest.fn(),
|
|
101
|
+
setInitialFormValues: jest.fn(),
|
|
102
|
+
setFieldTouched: jest.fn(),
|
|
103
|
+
validationSchema: null,
|
|
104
|
+
values: mockInitialFormValues,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const mockUseConfig = jest.mocked(useConfig<RegistrationConfig>);
|
|
108
|
+
|
|
109
|
+
describe('identifier input', () => {
|
|
110
|
+
mockUseConfig.mockReturnValue({
|
|
111
|
+
...getDefaultsFromConfigSchema(esmPatientRegistrationSchema),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const fieldName = 'openMrsId';
|
|
115
|
+
const openmrsID = {
|
|
116
|
+
identifierTypeUuid: '05a29f94-c0ed-11e2-94be-8c13b969e334',
|
|
117
|
+
initialValue: '',
|
|
118
|
+
identifierName: 'OpenMRS ID',
|
|
119
|
+
selectedSource: {
|
|
120
|
+
uuid: '01af8526-cea4-4175-aa90-340acb411771',
|
|
121
|
+
name: 'Generator 2 for OpenMRS ID',
|
|
122
|
+
autoGenerationOption: {
|
|
123
|
+
manualEntryEnabled: false,
|
|
124
|
+
automaticGenerationEnabled: true,
|
|
125
|
+
},
|
|
126
|
+
} as IdentifierSource,
|
|
127
|
+
autoGeneration: false,
|
|
128
|
+
preferred: true,
|
|
129
|
+
required: true,
|
|
130
|
+
} as PatientIdentifierValue;
|
|
131
|
+
|
|
132
|
+
const setupIdentifierInput = (patientIdentifier: PatientIdentifierValue, initialValues = {}) => {
|
|
133
|
+
renderWithContext(
|
|
134
|
+
<Formik initialValues={initialValues} onSubmit={jest.fn()}>
|
|
135
|
+
<Form>
|
|
136
|
+
<PatientRegistrationContextProvider value={mockContextValues}>
|
|
137
|
+
<IdentifierInput patientIdentifier={patientIdentifier} fieldName={fieldName} />
|
|
138
|
+
</PatientRegistrationContextProvider>
|
|
139
|
+
</Form>
|
|
140
|
+
</Formik>,
|
|
141
|
+
ResourcesContextProvider,
|
|
142
|
+
mockResourcesContextValue,
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
it('shows the identifier input', () => {
|
|
147
|
+
openmrsID.autoGeneration = false;
|
|
148
|
+
setupIdentifierInput(openmrsID as PatientIdentifierValue);
|
|
149
|
+
expect(screen.getByLabelText(openmrsID.identifierName)).toBeInTheDocument();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('displays an edit button when there is an initial value', async () => {
|
|
153
|
+
// setup
|
|
154
|
+
openmrsID.autoGeneration = false;
|
|
155
|
+
openmrsID.required = false;
|
|
156
|
+
openmrsID.initialValue = '1002UU9';
|
|
157
|
+
openmrsID.identifierValue = '1002UU9';
|
|
158
|
+
// replay
|
|
159
|
+
setupIdentifierInput(openmrsID as PatientIdentifierValue);
|
|
160
|
+
expect(screen.getByText('Edit')).toBeInTheDocument();
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('hides the edit button when the identifier is required', async () => {
|
|
164
|
+
// setup
|
|
165
|
+
openmrsID.autoGeneration = false;
|
|
166
|
+
openmrsID.required = true;
|
|
167
|
+
openmrsID.initialValue = '1002UU9';
|
|
168
|
+
openmrsID.identifierValue = '1002UU9';
|
|
169
|
+
// replay
|
|
170
|
+
setupIdentifierInput(openmrsID);
|
|
171
|
+
expect(screen.queryByText('Edit')).not.toBeInTheDocument();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('displays a delete button when the identifier is not a default type', () => {
|
|
175
|
+
// setup
|
|
176
|
+
openmrsID.required = false;
|
|
177
|
+
// replay
|
|
178
|
+
setupIdentifierInput(openmrsID);
|
|
179
|
+
expect(screen.getByText('Delete')).toBeInTheDocument();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('auto-generated identifier', () => {
|
|
183
|
+
it('hides the input when the identifier is auto-generated', () => {
|
|
184
|
+
openmrsID.autoGeneration = true;
|
|
185
|
+
setupIdentifierInput(openmrsID);
|
|
186
|
+
expect(screen.getByTestId('identifier-input')).toHaveAttribute('type', 'hidden');
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("displays 'Auto-Generated' when the indentifier has auto generation", () => {
|
|
190
|
+
openmrsID.autoGeneration = true;
|
|
191
|
+
setupIdentifierInput(openmrsID);
|
|
192
|
+
expect(screen.getByTestId('identifier-placeholder').innerHTML).toBe('Auto-generated');
|
|
193
|
+
expect(screen.getByTestId('identifier-input')).toBeDisabled();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe('manual entry allowed', () => {
|
|
197
|
+
openmrsID.selectedSource = {
|
|
198
|
+
autoGenerationOption: {
|
|
199
|
+
manualEntryEnabled: true,
|
|
200
|
+
},
|
|
201
|
+
} as IdentifierSource;
|
|
202
|
+
|
|
203
|
+
it('shows the edit button', () => {
|
|
204
|
+
openmrsID.autoGeneration = true;
|
|
205
|
+
setupIdentifierInput(openmrsID);
|
|
206
|
+
expect(screen.getByText('Edit')).toBeInTheDocument();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe('edit button clicked', () => {
|
|
210
|
+
it('displays an empty input field', async () => {
|
|
211
|
+
const user = userEvent.setup();
|
|
212
|
+
openmrsID.autoGeneration = true;
|
|
213
|
+
openmrsID.required = false;
|
|
214
|
+
openmrsID.selectedSource = {
|
|
215
|
+
autoGenerationOption: {
|
|
216
|
+
manualEntryEnabled: true,
|
|
217
|
+
},
|
|
218
|
+
} as IdentifierSource;
|
|
219
|
+
setupIdentifierInput(openmrsID);
|
|
220
|
+
const editButton = screen.getByTestId('edit-button');
|
|
221
|
+
await user.click(editButton);
|
|
222
|
+
expect(screen.getByLabelText(new RegExp(`${openmrsID.identifierName}`))).toHaveValue('');
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('displays an input field with the identifier value if it exists', async () => {
|
|
226
|
+
const user = userEvent.setup();
|
|
227
|
+
openmrsID.autoGeneration = true;
|
|
228
|
+
openmrsID.required = false;
|
|
229
|
+
openmrsID.selectedSource = {
|
|
230
|
+
autoGenerationOption: {
|
|
231
|
+
manualEntryEnabled: true,
|
|
232
|
+
},
|
|
233
|
+
} as IdentifierSource;
|
|
234
|
+
setupIdentifierInput(openmrsID, { identifiers: { [fieldName]: { identifierValue: '10001V' } } });
|
|
235
|
+
const editButton = screen.getByTestId('edit-button');
|
|
236
|
+
await user.click(editButton);
|
|
237
|
+
expect(screen.getByLabelText(new RegExp(`${openmrsID.identifierName}`))).toHaveValue('10001V');
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it('validates identifier format correctly for identifier types with regex formats', async () => {
|
|
244
|
+
const user = userEvent.setup();
|
|
245
|
+
|
|
246
|
+
const ssnIdentifier = {
|
|
247
|
+
...openmrsID,
|
|
248
|
+
autoGeneration: false,
|
|
249
|
+
format: '^[A-Z]{1}-[0-9]{7}$',
|
|
250
|
+
identifierName: 'SSN',
|
|
251
|
+
identifierTypeUuid: 'a71403f3-8584-4289-ab41-2b4e5570bd45',
|
|
252
|
+
identifierValue: undefined,
|
|
253
|
+
initialValue: '',
|
|
254
|
+
required: true,
|
|
255
|
+
selectedSource: {
|
|
256
|
+
uuid: '01af8526-cea4-4175-aa90-340acb411771',
|
|
257
|
+
name: 'Generator 2 for SSN',
|
|
258
|
+
autoGenerationOption: {
|
|
259
|
+
manualEntryEnabled: true,
|
|
260
|
+
automaticGenerationEnabled: false,
|
|
261
|
+
},
|
|
262
|
+
} as IdentifierSource,
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const mockSetFieldTouched = jest.fn();
|
|
266
|
+
const mockSetFieldValue = jest.fn();
|
|
267
|
+
const testContextValues = {
|
|
268
|
+
...mockContextValues,
|
|
269
|
+
setFieldTouched: mockSetFieldTouched,
|
|
270
|
+
setFieldValue: mockSetFieldValue,
|
|
271
|
+
values: {
|
|
272
|
+
...mockInitialFormValues,
|
|
273
|
+
identifiers: {
|
|
274
|
+
[fieldName]: ssnIdentifier,
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const initialValues = {
|
|
280
|
+
identifiers: {
|
|
281
|
+
[fieldName]: {
|
|
282
|
+
identifierValue: '',
|
|
283
|
+
},
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
renderWithContext(
|
|
288
|
+
<Formik initialValues={initialValues} onSubmit={jest.fn()}>
|
|
289
|
+
<Form>
|
|
290
|
+
<PatientRegistrationContextProvider value={testContextValues}>
|
|
291
|
+
<IdentifierInput patientIdentifier={ssnIdentifier} fieldName={fieldName} />
|
|
292
|
+
</PatientRegistrationContextProvider>
|
|
293
|
+
</Form>
|
|
294
|
+
</Formik>,
|
|
295
|
+
ResourcesContextProvider,
|
|
296
|
+
mockResourcesContextValue,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const input = screen.getByRole('textbox', {
|
|
300
|
+
name: /ssn/i,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Valid cases
|
|
304
|
+
await user.type(input, 'A-1234567');
|
|
305
|
+
await user.tab();
|
|
306
|
+
expect(input).toHaveValue('A-1234567');
|
|
307
|
+
expect(input).not.toHaveClass('cds--text-input--invalid');
|
|
308
|
+
expect(screen.queryByText(/identifier should be/i)).not.toBeInTheDocument();
|
|
309
|
+
|
|
310
|
+
// Invalid cases
|
|
311
|
+
await user.clear(input);
|
|
312
|
+
await user.type(input, 'A-0010902aaa'); // Extra characters
|
|
313
|
+
await user.tab();
|
|
314
|
+
expect(input).toHaveClass('cds--text-input--invalid');
|
|
315
|
+
expect(screen.getByText(/identifier should be/i)).toBeInTheDocument();
|
|
316
|
+
|
|
317
|
+
await user.clear(input);
|
|
318
|
+
await user.type(input, 'a-1234567'); // Lowercase letter
|
|
319
|
+
await user.tab();
|
|
320
|
+
expect(input).toHaveClass('cds--text-input--invalid');
|
|
321
|
+
expect(screen.getByText(/identifier should be/i)).toBeInTheDocument();
|
|
322
|
+
|
|
323
|
+
await user.clear(input);
|
|
324
|
+
await user.type(input, 'AB-1234567'); // Two letters
|
|
325
|
+
await user.tab();
|
|
326
|
+
expect(input).toHaveClass('cds--text-input--invalid');
|
|
327
|
+
expect(screen.getByText(/identifier should be/i)).toBeInTheDocument();
|
|
328
|
+
|
|
329
|
+
await user.clear(input);
|
|
330
|
+
await user.type(input, 'A-123456'); // Only 6 digits
|
|
331
|
+
await user.tab();
|
|
332
|
+
expect(input).toHaveClass('cds--text-input--invalid');
|
|
333
|
+
expect(screen.getByText(/identifier should be/i)).toBeInTheDocument();
|
|
334
|
+
});
|
|
335
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { isUniqueIdentifierTypeForOffline, shouldBlockPatientIdentifierInOfflineMode } from './utils';
|
|
2
|
+
|
|
3
|
+
interface IdentifierTypeOptions {
|
|
4
|
+
uniquenessBehavior?: 'UNIQUE' | 'LOCATION' | 'NON_UNIQUE';
|
|
5
|
+
manualEntryEnabled?: boolean;
|
|
6
|
+
automaticGenerationEnabled?: boolean;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function createIdentifierType(options: IdentifierTypeOptions) {
|
|
10
|
+
return {
|
|
11
|
+
uniquenessBehavior: options.uniquenessBehavior,
|
|
12
|
+
identifierSources: [
|
|
13
|
+
{
|
|
14
|
+
uuid: 'identifier-source-uuid',
|
|
15
|
+
name: 'Identifier Source Name',
|
|
16
|
+
autoGenerationOption: {
|
|
17
|
+
manualEntryEnabled: options.manualEntryEnabled,
|
|
18
|
+
automaticGenerationEnabled: options.automaticGenerationEnabled,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
name: 'Identifier Type Name',
|
|
23
|
+
required: true,
|
|
24
|
+
uuid: 'identifier-type-uuid',
|
|
25
|
+
fieldName: 'identifierFieldName',
|
|
26
|
+
format: 'identifierFormat',
|
|
27
|
+
isPrimary: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe('shouldBlockPatientIdentifierInOfflineMode function', () => {
|
|
32
|
+
it('should return false if identifierType is not unique', () => {
|
|
33
|
+
const identifierType = createIdentifierType({ uniquenessBehavior: null });
|
|
34
|
+
|
|
35
|
+
const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
|
|
36
|
+
|
|
37
|
+
expect(result).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should return false if identifierType is unique and no manual entry is enabled', () => {
|
|
41
|
+
const identifierType = createIdentifierType({ uniquenessBehavior: null });
|
|
42
|
+
|
|
43
|
+
const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
|
|
44
|
+
|
|
45
|
+
expect(result).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should return true if identifierType is unique and manual entry is enabled', () => {
|
|
49
|
+
const identifierType = createIdentifierType({ manualEntryEnabled: true, uniquenessBehavior: 'UNIQUE' });
|
|
50
|
+
|
|
51
|
+
const result = shouldBlockPatientIdentifierInOfflineMode(identifierType);
|
|
52
|
+
|
|
53
|
+
expect(result).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('isUniqueIdentifierTypeForOffline function', () => {
|
|
58
|
+
it('should return true if uniquenessBehavior is UNIQUE', () => {
|
|
59
|
+
const identifierType = createIdentifierType({ uniquenessBehavior: 'UNIQUE' });
|
|
60
|
+
|
|
61
|
+
const result = isUniqueIdentifierTypeForOffline(identifierType);
|
|
62
|
+
|
|
63
|
+
expect(result).toBe(true);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should return true if uniquenessBehavior is LOCATION', () => {
|
|
67
|
+
const identifierType = createIdentifierType({ uniquenessBehavior: 'LOCATION' });
|
|
68
|
+
|
|
69
|
+
const result = isUniqueIdentifierTypeForOffline(identifierType);
|
|
70
|
+
|
|
71
|
+
expect(result).toBe(true);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should return false for other uniqueness behaviors', () => {
|
|
75
|
+
const identifierType = createIdentifierType({ uniquenessBehavior: null });
|
|
76
|
+
|
|
77
|
+
const result = isUniqueIdentifierTypeForOffline(identifierType);
|
|
78
|
+
|
|
79
|
+
expect(result).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type FetchedPatientIdentifierType, type PatientIdentifierType } from '../../../patient-registration.types';
|
|
2
|
+
|
|
3
|
+
export function shouldBlockPatientIdentifierInOfflineMode(identifierType: PatientIdentifierType) {
|
|
4
|
+
// Patient Identifiers which are unique and can be manually entered are prohibited while offline because
|
|
5
|
+
// of the chance of generating conflicts when syncing later.
|
|
6
|
+
return (
|
|
7
|
+
isUniqueIdentifierTypeForOffline(identifierType) &&
|
|
8
|
+
!identifierType.identifierSources.some(
|
|
9
|
+
(source) =>
|
|
10
|
+
!source.autoGenerationOption?.manualEntryEnabled && source.autoGenerationOption?.automaticGenerationEnabled,
|
|
11
|
+
)
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function isUniqueIdentifierTypeForOffline(identifierType: FetchedPatientIdentifierType) {
|
|
16
|
+
// In offline mode we consider each uniqueness behavior which could cause conflicts during syncing as 'unique'.
|
|
17
|
+
// Syncing conflicts can appear for the following behaviors:
|
|
18
|
+
return identifierType.uniquenessBehavior === 'UNIQUE' || identifierType.uniquenessBehavior === 'LOCATION';
|
|
19
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { v4 } from 'uuid';
|
|
4
|
+
import { type FormValues } from '../../patient-registration.types';
|
|
5
|
+
import styles from './../input.scss';
|
|
6
|
+
|
|
7
|
+
interface DummyDataInputProps {
|
|
8
|
+
setValues(values: FormValues, shouldValidate?: boolean): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const dummyFormValues: FormValues = {
|
|
12
|
+
patientUuid: v4(),
|
|
13
|
+
givenName: 'John',
|
|
14
|
+
middleName: '',
|
|
15
|
+
familyName: 'Smith',
|
|
16
|
+
additionalGivenName: 'Joey',
|
|
17
|
+
additionalMiddleName: '',
|
|
18
|
+
additionalFamilyName: 'Smitty',
|
|
19
|
+
addNameInLocalLanguage: true,
|
|
20
|
+
gender: 'Male',
|
|
21
|
+
birthdate: new Date(2020, 1, 1) as any,
|
|
22
|
+
yearsEstimated: 1,
|
|
23
|
+
monthsEstimated: 2,
|
|
24
|
+
birthdateEstimated: true,
|
|
25
|
+
telephoneNumber: '0800001066',
|
|
26
|
+
isDead: false,
|
|
27
|
+
deathDate: '',
|
|
28
|
+
deathTime: '',
|
|
29
|
+
deathTimeFormat: 'AM',
|
|
30
|
+
deathCause: '',
|
|
31
|
+
nonCodedCauseOfDeath: '',
|
|
32
|
+
relationships: [],
|
|
33
|
+
address: {
|
|
34
|
+
address1: 'Bom Jesus Street',
|
|
35
|
+
address2: '',
|
|
36
|
+
cityVillage: 'Recife',
|
|
37
|
+
stateProvince: 'Pernambuco',
|
|
38
|
+
country: 'Brazil',
|
|
39
|
+
postalCode: '50030-310',
|
|
40
|
+
},
|
|
41
|
+
identifiers: {},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const DummyDataInput: React.FC<DummyDataInputProps> = ({ setValues }) => {
|
|
45
|
+
return (
|
|
46
|
+
<main>
|
|
47
|
+
<button
|
|
48
|
+
className={classNames('omrs-btn omrs-filled-neutral', styles.dummyData)}
|
|
49
|
+
onClick={() => setValues(dummyFormValues)}
|
|
50
|
+
type="button"
|
|
51
|
+
aria-label="Dummy Data Input">
|
|
52
|
+
Input Dummy Data
|
|
53
|
+
</button>
|
|
54
|
+
</main>
|
|
55
|
+
);
|
|
56
|
+
};
|