@kenyaemr/esm-patient-registration-app 4.4.2 → 4.5.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.
Files changed (47) hide show
  1. package/dist/144.js +1 -1
  2. package/dist/207.js +1 -1
  3. package/dist/207.js.map +1 -1
  4. package/dist/574.js +1 -1
  5. package/dist/59.js +1 -1
  6. package/dist/59.js.map +1 -1
  7. package/dist/68.js +1 -1
  8. package/dist/68.js.map +1 -1
  9. package/dist/821.js +1 -1
  10. package/dist/833.js +1 -0
  11. package/dist/876.js +1 -0
  12. package/dist/876.js.map +1 -0
  13. package/dist/kenyaemr-esm-patient-registration-app.js +1 -1
  14. package/dist/kenyaemr-esm-patient-registration-app.js.buildmanifest.json +55 -33
  15. package/dist/kenyaemr-esm-patient-registration-app.old +1 -1
  16. package/dist/main.js +1 -1
  17. package/dist/main.js.map +1 -1
  18. package/package.json +1 -1
  19. package/src/config-schema.ts +5 -13
  20. package/src/constants.ts +1 -1
  21. package/src/patient-registration/field/address/address-field.component.tsx +180 -20
  22. package/src/patient-registration/field/address/address-hierarchy-levels.component.tsx +68 -0
  23. package/src/patient-registration/field/address/address-hierarchy.resource.tsx +102 -0
  24. package/src/patient-registration/field/address/custom-address-field.component.tsx +30 -0
  25. package/src/patient-registration/field/address/tests/address-hierarchy.test.tsx +140 -0
  26. package/src/patient-registration/field/address/{address-hierarchy.test.tsx → tests/mocks.ts} +3 -80
  27. package/src/patient-registration/field/custom-field.component.tsx +1 -1
  28. package/src/patient-registration/field/field.component.tsx +2 -2
  29. package/src/patient-registration/field/name/name-field.component.tsx +1 -1
  30. package/src/patient-registration/input/combo-input/combo-input.component.tsx +100 -62
  31. package/src/patient-registration/input/combo-input/selection-tick.component.tsx +20 -0
  32. package/src/patient-registration/input/input.scss +6 -1
  33. package/src/patient-registration/patient-registration-context.ts +1 -0
  34. package/src/patient-registration/patient-registration-hooks.ts +1 -0
  35. package/src/patient-registration/patient-registration-utils.ts +3 -3
  36. package/src/patient-registration/patient-registration.component.tsx +1 -0
  37. package/src/patient-registration/patient-registration.scss +14 -0
  38. package/src/patient-registration/validation/patient-registration-validation.test.tsx +128 -114
  39. package/src/patient-verification/verification-modal/confirm-prompt.component.tsx +1 -0
  40. package/src/root.component.tsx +1 -1
  41. package/translations/en.json +3 -5
  42. package/translations/he.json +89 -0
  43. package/dist/822.js +0 -1
  44. package/dist/822.js.map +0 -1
  45. package/src/patient-registration/field/address/address-hierarchy.component.tsx +0 -143
  46. package/src/patient-registration/input/combo-input/combo-input.test.tsx +0 -43
  47. /package/src/{declarations.d.tsx → declarations.d.ts} +0 -0
@@ -1,76 +1,114 @@
1
- import React, { useState } from 'react';
2
- import { ComboBox, ComboBoxProps, Layer } from '@carbon/react';
3
- import { useField } from 'formik';
4
- import { useTranslation } from 'react-i18next';
5
- import { performAdressHierarchyWithParentSearch } from '../../../resource';
1
+ import React, { useCallback, useMemo, useRef, useState } from 'react';
2
+ import { TextInput, Layer } from '@carbon/react';
3
+ import SelectionTick from './selection-tick.component';
4
+ import styles from '../input.scss';
6
5
 
7
- interface ComboInputProps extends Omit<ComboBoxProps, 'items'> {
6
+ interface ComboInputProps {
7
+ entries: Array<string>;
8
8
  name: string;
9
- labelText: string;
10
- placeholder?: string;
11
- setSelectedValue: any;
12
- selected: string;
13
- textFieldName: string;
14
- required?: boolean;
9
+ fieldProps: {
10
+ value: string;
11
+ labelText: string;
12
+ [x: string]: any;
13
+ };
14
+ handleInputChange: (newValue: string) => void;
15
+ handleSelection: (newSelection) => void;
15
16
  }
16
17
 
17
- export const ComboInput: React.FC<ComboInputProps> = ({
18
- name,
19
- labelText,
20
- placeholder,
21
- setSelectedValue,
22
- selected,
23
- textFieldName,
24
- required,
25
- }) => {
26
- const { t } = useTranslation();
27
- const [field, _, helpers] = useField(name);
28
- const [listItems, setListItems] = useState([]);
29
- const [error, setError] = useState<Error>();
30
- const { setValue } = helpers;
31
- const comboLabelText = !required ? `${labelText} (${t('optional', 'optional')})` : labelText;
32
- const comboBoxEvent = (text, id) => {
33
- if (text == '') {
34
- } else {
35
- performAdressHierarchyWithParentSearch(textFieldName.replace(' ', ''), selected, text)
36
- .then((value) => {
37
- setListItems(value.data.map((parent1) => ({ id: parent1['uuid'], text: parent1['name'] })));
38
- })
39
- .catch((err) => {
40
- setError(err);
41
- });
18
+ const ComboInput: React.FC<ComboInputProps> = ({ entries, fieldProps, handleInputChange, handleSelection }) => {
19
+ const [highlightedEntry, setHighlightedEntry] = useState(-1);
20
+ const { value = '' } = fieldProps;
21
+ const [showEntries, setShowEntries] = useState(false);
22
+ const comboInputRef = useRef(null);
23
+
24
+ const handleFocus = useCallback(() => {
25
+ setShowEntries(true);
26
+ setHighlightedEntry(-1);
27
+ }, [setShowEntries, setHighlightedEntry]);
28
+
29
+ const handleBlur = useCallback(
30
+ (e) => {
31
+ // This check is in place to not hide the entries when an entry is clicked
32
+ // Else the onClick of the entry will not be counted.
33
+ if (!comboInputRef?.current?.contains(e.target)) {
34
+ setShowEntries(false);
35
+ }
36
+ setHighlightedEntry(-1);
37
+ },
38
+ [setShowEntries, setHighlightedEntry],
39
+ );
40
+
41
+ const filteredEntries = useMemo(() => {
42
+ if (!entries) {
43
+ return [];
42
44
  }
43
- };
45
+ if (!value) {
46
+ return entries;
47
+ }
48
+ return entries.filter((entry) => entry.toLowerCase().includes(value.toLowerCase()));
49
+ }, [entries, value]);
44
50
 
45
- if (error) {
46
- return <span>{t(`${error.message}`)}</span>;
47
- }
51
+ const handleOptionClick = useCallback(
52
+ (newSelection: string, e: KeyboardEvent = null) => {
53
+ e?.preventDefault();
54
+ handleSelection(newSelection);
55
+ setShowEntries(false);
56
+ },
57
+ [handleSelection, setShowEntries],
58
+ );
59
+
60
+ const handleKeyPress = useCallback(
61
+ (e: KeyboardEvent) => {
62
+ const totalResults = filteredEntries.length ?? 0;
63
+ if (e.key === 'ArrowUp') {
64
+ setHighlightedEntry((prev) => Math.max(-1, prev - 1));
65
+ } else if (e.key === 'ArrowDown') {
66
+ setHighlightedEntry((prev) => Math.min(totalResults - 1, prev + 1));
67
+ } else if (e.key === 'Enter' && highlightedEntry > -1) {
68
+ handleOptionClick(filteredEntries[highlightedEntry], e);
69
+ }
70
+ },
71
+ [highlightedEntry, handleOptionClick, filteredEntries, setHighlightedEntry],
72
+ );
48
73
 
49
74
  return (
50
- <div style={{ marginBottom: '1rem' }}>
75
+ <div className={styles.comboInput} ref={comboInputRef}>
51
76
  <Layer>
52
- <ComboBox
53
- id={name}
54
- onInputChange={(event) => {
55
- comboBoxEvent(event, name);
56
- setValue(event);
57
- }}
58
- items={listItems}
59
- itemToString={(item) => item?.text ?? ''}
60
- {...field}
61
- onChange={(e) => {
62
- if (Boolean(e.selectedItem)) {
63
- setSelectedValue(e.selectedItem.id);
64
- setValue(e.selectedItem.text);
65
- } else {
66
- setSelectedValue(undefined);
67
- setValue(undefined);
68
- }
69
- }}
70
- placeholder={placeholder}
71
- titleText={comboLabelText}
77
+ <TextInput
78
+ {...fieldProps}
79
+ onChange={(e) => handleInputChange(e.target.value)}
80
+ onFocus={handleFocus}
81
+ onBlur={handleBlur}
82
+ autoComplete={'off'}
83
+ onKeyDown={handleKeyPress}
72
84
  />
73
85
  </Layer>
86
+ <div className={styles.comboInputEntries}>
87
+ {showEntries && (
88
+ <div id="downshift-1-menu" style={{ height: filteredEntries.length > 5 && "15rem" }} className="cds--list-box__menu" role="listbox">
89
+ {filteredEntries.map((entry, indx) => (
90
+ <div
91
+ key={indx}
92
+ id="downshift-1-item-0"
93
+ role="option"
94
+ className={`cds--list-box__menu-item ${indx === highlightedEntry && 'cds--list-box__menu-item--highlighted'
95
+ }`}
96
+ tabIndex={-1}
97
+ aria-selected="true"
98
+ onClick={() => handleOptionClick(entry)}>
99
+ <div
100
+ className={`cds--list-box__menu-item__option ${entry === value && 'cds--list-box__menu-item--active'
101
+ }`}>
102
+ {entry}
103
+ {entry === value && <SelectionTick />}
104
+ </div>
105
+ </div>
106
+ ))}
107
+ </div>
108
+ )}
109
+ </div>
74
110
  </div>
75
111
  );
76
112
  };
113
+
114
+ export default ComboInput;
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+
3
+ function SelectionTick() {
4
+ return (
5
+ <svg
6
+ focusable="false"
7
+ preserveAspectRatio="xMidYMid meet"
8
+ xmlns="http://www.w3.org/2000/svg"
9
+ fill="currentColor"
10
+ width="16"
11
+ height="16"
12
+ viewBox="0 0 32 32"
13
+ aria-hidden="true"
14
+ className="cds--list-box__menu-item__selected-icon">
15
+ <path d="M13 24L4 15 5.414 13.586 13 21.171 26.586 7.586 28 9 13 24z"></path>
16
+ </svg>
17
+ );
18
+ }
19
+
20
+ export default SelectionTick;
@@ -18,7 +18,8 @@
18
18
  color: $text-02;
19
19
  }
20
20
 
21
- .textID {
21
+ .textID,
22
+ .comboInput {
22
23
  margin-bottom: spacing.$spacing-05;
23
24
  }
24
25
 
@@ -106,3 +107,7 @@
106
107
  @include type.type-style('label-01');
107
108
  color: $danger;
108
109
  }
110
+
111
+ .comboInputEntries {
112
+ position: relative;
113
+ }
@@ -14,6 +14,7 @@ export interface PatientRegistrationContextProps {
14
14
  currentPhoto: string;
15
15
  isOffline: boolean;
16
16
  initialFormValues: FormValues;
17
+ setInitialFormValues?: React.Dispatch<SetStateAction<FormValues>>;
17
18
  }
18
19
 
19
20
  export const PatientRegistrationContext = createContext<PatientRegistrationContextProps | undefined>(undefined);
@@ -286,6 +286,7 @@ function getPatientAttributeUuidMapForPatient(attributes: Array<PersonAttributeR
286
286
  });
287
287
  return attributeUuidMap;
288
288
  }
289
+
289
290
  export function usePatientObs(patientUuid: string) {
290
291
  const {
291
292
  registrationObs: { encounterTypeUuid },
@@ -1,4 +1,3 @@
1
- import { navigate } from '@openmrs/esm-framework';
2
1
  import * as Yup from 'yup';
3
2
  import {
4
3
  AddressValidationSchemaType,
@@ -8,6 +7,7 @@ import {
8
7
  PatientIdentifierValue,
9
8
  Encounter,
10
9
  } from './patient-registration-types';
10
+ import { parseDate } from '@openmrs/esm-framework';
11
11
  import camelCase from 'lodash-es/camelCase';
12
12
  import capitalize from 'lodash-es/capitalize';
13
13
 
@@ -103,7 +103,7 @@ export function scrollIntoView(viewId: string) {
103
103
  }
104
104
 
105
105
  export function cancelRegistration() {
106
- navigate({ to: `${window.spaBase}/home` });
106
+ window.history.back();
107
107
  }
108
108
 
109
109
  export function getFormValuesFromFhirPatient(patient: fhir.Patient) {
@@ -124,7 +124,7 @@ export function getFormValuesFromFhirPatient(patient: fhir.Patient) {
124
124
  result.additionalFamilyName = additionalPatientName?.family;
125
125
 
126
126
  result.gender = capitalize(patient.gender);
127
- result.birthdate = patient.birthDate ? (new Date(patient.birthDate) as any) : undefined;
127
+ result.birthdate = patient.birthDate ? parseDate(patient.birthDate) : undefined;
128
128
  result.telephoneNumber = patient.telecom ? patient.telecom[0].value : '';
129
129
 
130
130
  if (patient.deceasedBoolean || patient.deceasedDateTime) {
@@ -225,6 +225,7 @@ export const PatientRegistration: React.FC<PatientRegistrationProps> = ({ savePa
225
225
  currentPhoto: photo?.imageSrc,
226
226
  isOffline,
227
227
  initialFormValues: props.initialValues,
228
+ setInitialFormValues,
228
229
  }}>
229
230
  <PatientVerification props={props} />
230
231
  {sections.map((section, index) => (
@@ -92,3 +92,17 @@
92
92
  max-width: unset;
93
93
  }
94
94
  }
95
+
96
+ // Overriding styles for RTL support
97
+ html[dir='rtl'] {
98
+ .linkName {
99
+ & > svg {
100
+ transform: scale(-1, 1);
101
+ }
102
+ }
103
+
104
+ .infoGrid {
105
+ padding-left: unset;
106
+ padding-right: spacing.$spacing-07;
107
+ }
108
+ }
@@ -1,129 +1,143 @@
1
- import React from 'react';
2
- import { render, fireEvent, screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import { Formik, Form } from 'formik';
5
- import { useConfig } from '@openmrs/esm-framework';
6
1
  import { validationSchema } from './patient-registration-validation';
7
- import { NameField } from '../field/name/name-field.component';
8
- import { PatientRegistrationContext } from '../patient-registration-context';
9
- import { initialFormValues } from '../patient-registration.component';
10
- import { FormValues } from '../patient-registration-types';
11
2
 
12
- const mockUseConfig = useConfig as jest.Mock;
13
- const mockFieldConfigs = {
14
- fieldConfigurations: {
15
- name: {
16
- displayMiddleName: true,
17
- },
18
- },
19
- };
3
+ describe('Patient Registration Validation', () => {
4
+ describe('validationSchema', () => {
5
+ const validFormValues = {
6
+ givenName: 'John',
7
+ familyName: 'Doe',
8
+ additionalGivenName: '',
9
+ additionalFamilyName: '',
10
+ gender: 'Male',
11
+ birthdate: new Date('1990-01-01'),
12
+ birthdateEstimated: false,
13
+ deathDate: null,
14
+ email: 'john.doe@example.com',
15
+ identifiers: {
16
+ nationalId: {
17
+ required: true,
18
+ identifierValue: '123456789',
19
+ },
20
+ passportId: {
21
+ required: false,
22
+ identifierValue: '',
23
+ },
24
+ },
25
+ };
20
26
 
21
- jest.mock('@openmrs/esm-framework', () => {
22
- const originalModule = jest.requireActual('@openmrs/esm-framework');
27
+ const validateFormValues = async (formValues) => {
28
+ try {
29
+ await validationSchema.validate(formValues, { abortEarly: false });
30
+ } catch (err) {
31
+ return err;
32
+ }
33
+ };
23
34
 
24
- return {
25
- ...originalModule,
26
- useConfig: jest.fn(),
27
- validator: jest.fn(),
28
- };
29
- });
35
+ it('should allow valid form values', async () => {
36
+ const validationError = await validateFormValues(validFormValues);
37
+ expect(validationError).toBeFalsy();
38
+ });
30
39
 
31
- describe('Name input', () => {
32
- const formValues: FormValues = initialFormValues;
40
+ it('should require givenName', async () => {
41
+ const invalidFormValues = {
42
+ ...validFormValues,
43
+ givenName: '',
44
+ };
45
+ const validationError = await validateFormValues(invalidFormValues);
46
+ expect(validationError.errors).toContain('givenNameRequired');
47
+ });
33
48
 
34
- const testValidName = (givenNameValue: string, middleNameValue: string, familyNameValue: string) => {
35
- it(
36
- 'does not display error message when givenNameValue: ' +
37
- givenNameValue +
38
- ', middleNameValue: ' +
39
- middleNameValue +
40
- ', familyNameValue: ' +
41
- familyNameValue,
42
- async () => {
43
- const error = await updateNameAndReturnError(givenNameValue, middleNameValue, familyNameValue);
44
- Object.values(error).map((currentError) => expect(currentError).toBeNull());
45
- },
46
- );
47
- };
49
+ it('should require familyName', async () => {
50
+ const invalidFormValues = {
51
+ ...validFormValues,
52
+ familyName: '',
53
+ };
54
+ const validationError = await validateFormValues(invalidFormValues);
55
+ expect(validationError.errors).toContain('familyNameRequired');
56
+ });
48
57
 
49
- const testInvalidName = (
50
- givenNameValue: string,
51
- middleNameValue: string,
52
- familyNameValue: string,
53
- expectedError: string,
54
- errorType: string,
55
- ) => {
56
- it.skip(
57
- 'displays error message when givenNameValue: ' +
58
- givenNameValue +
59
- ', middleNameValue: ' +
60
- middleNameValue +
61
- ', familyNameValue: ' +
62
- familyNameValue,
63
- async () => {
64
- const error = (await updateNameAndReturnError(givenNameValue, middleNameValue, familyNameValue))[errorType];
65
- expect(error.textContent).toEqual(expectedError);
66
- },
67
- );
68
- };
58
+ it('should require additionalGivenName when addNameInLocalLanguage is true', async () => {
59
+ const invalidFormValues = {
60
+ ...validFormValues,
61
+ addNameInLocalLanguage: true,
62
+ additionalGivenName: '',
63
+ };
64
+ const validationError = await validateFormValues(invalidFormValues);
65
+ expect(validationError.errors).toContain('givenNameRequired');
66
+ });
69
67
 
70
- const updateNameAndReturnError = async (givenNameValue: string, middleNameValue: string, familyNameValue: string) => {
71
- const user = userEvent.setup();
68
+ it('should require additionalFamilyName when addNameInLocalLanguage is true', async () => {
69
+ const invalidFormValues = {
70
+ ...validFormValues,
71
+ addNameInLocalLanguage: true,
72
+ additionalFamilyName: '',
73
+ };
74
+ const validationError = await validateFormValues(invalidFormValues);
75
+ expect(validationError.errors).toContain('familyNameRequired');
76
+ });
72
77
 
73
- mockUseConfig.mockReturnValue(mockFieldConfigs);
78
+ it('should require gender', async () => {
79
+ const invalidFormValues = {
80
+ ...validFormValues,
81
+ gender: '',
82
+ };
83
+ const validationError = await validateFormValues(invalidFormValues);
84
+ expect(validationError.errors).toContain('genderUnspecified');
85
+ });
74
86
 
75
- render(
76
- <Formik
77
- initialValues={{
78
- givenName: '',
79
- middleName: '',
80
- familyName: '',
81
- }}
82
- onSubmit={null}
83
- validationSchema={validationSchema}>
84
- <Form>
85
- <PatientRegistrationContext.Provider
86
- value={{
87
- initialFormValues: null,
88
- identifierTypes: [],
89
- validationSchema,
90
- setValidationSchema: () => {},
91
- values: formValues,
92
- inEditMode: false,
93
- setFieldValue: () => null,
94
- currentPhoto: 'TEST',
95
- isOffline: true,
96
- setCapturePhotoProps: (value) => {},
97
- }}>
98
- <NameField />
99
- </PatientRegistrationContext.Provider>
100
- </Form>
101
- </Formik>,
102
- );
103
- const givenNameInput = screen.getByLabelText('First Name') as HTMLInputElement;
104
- const middleNameInput = screen.getByLabelText(/Middle Name/i) as HTMLInputElement;
105
- const familyNameInput = screen.getByLabelText('Family Name') as HTMLInputElement;
87
+ it('should allow Male as a valid gender', async () => {
88
+ const validFormValuesWithOtherGender = {
89
+ ...validFormValues,
90
+ gender: 'Male',
91
+ };
92
+ const validationError = await validateFormValues(validFormValuesWithOtherGender);
93
+ expect(validationError).toBeFalsy();
94
+ });
106
95
 
107
- await user.click(givenNameInput);
96
+ it('should allow Female as a valid gender', async () => {
97
+ const validFormValuesWithOtherGender = {
98
+ ...validFormValues,
99
+ gender: 'Female',
100
+ };
101
+ const validationError = await validateFormValues(validFormValuesWithOtherGender);
102
+ expect(validationError).toBeFalsy();
103
+ });
108
104
 
109
- fireEvent.change(givenNameInput, { target: { value: givenNameValue } });
110
- fireEvent.blur(givenNameInput);
111
- fireEvent.change(middleNameInput, { target: { value: middleNameValue } });
112
- fireEvent.blur(middleNameInput);
113
- fireEvent.change(familyNameInput, { target: { value: familyNameValue } });
114
- fireEvent.blur(familyNameInput);
105
+ it('should throw error when date of birth is a future date', async () => {
106
+ const invalidFormValues = {
107
+ ...validFormValues,
108
+ birthdate: new Date('2100-01-01'),
109
+ };
110
+ const validationError = await validateFormValues(invalidFormValues);
111
+ expect(validationError.errors).toContain('birthdayNotInTheFuture');
112
+ });
115
113
 
116
- return {
117
- givenNameError: screen.queryByText('Given name is required'),
118
- middleNameError: screen.queryByText('Middle name is required'),
119
- familyNameError: screen.queryByText('Family name is required'),
120
- };
121
- };
114
+ it('should require yearsEstimated when birthdateEstimated is true', async () => {
115
+ const invalidFormValues = {
116
+ ...validFormValues,
117
+ birthdateEstimated: true,
118
+ };
119
+ const validationError = await validateFormValues(invalidFormValues);
120
+ expect(validationError.errors).toContain('yearsEstimateRequired');
121
+ });
122
+
123
+ it('should throw error when monthEstimated is negative', async () => {
124
+ const invalidFormValues = {
125
+ ...validFormValues,
126
+ birthdateEstimated: true,
127
+ yearsEstimated: 0,
128
+ monthsEstimated: -1,
129
+ };
130
+ const validationError = await validateFormValues(invalidFormValues);
131
+ expect(validationError.errors).toContain('negativeMonths');
132
+ });
122
133
 
123
- testValidName('Aaron', 'A', 'Aaronson');
124
- testValidName('No', '', 'Middle Name');
125
- testInvalidName('', '', '', 'Given name is required', 'givenNameError');
126
- testInvalidName('', '', '', 'Family name is required', 'familyNameError');
127
- testInvalidName('', 'No', 'Given Name', 'Given name is required', 'givenNameError');
128
- testInvalidName('No', 'Family Name', '', 'Family name is required', 'familyNameError');
134
+ it('should throw error when deathDate is in future', async () => {
135
+ const invalidFormValues = {
136
+ ...validFormValues,
137
+ deathDate: new Date('2100-01-01'),
138
+ };
139
+ const validationError = await validateFormValues(invalidFormValues);
140
+ expect(validationError.errors).toContain('deathdayNotInTheFuture');
141
+ });
142
+ });
129
143
  });
@@ -53,6 +53,7 @@ const ConfirmPrompt: React.FC<ConfirmPromptProps> = ({ close, onConfirm, patient
53
53
  <PatientInfo label={t('age', 'Age')} value={age(patient?.dateOfBirth)} />
54
54
  <PatientInfo label={t('dateOfBirth', 'Date of birth')} value={formatDate(new Date(patient?.dateOfBirth))} />
55
55
  <PatientInfo label={t('gender', 'Gender')} value={capitalize(patient?.gender)} />
56
+ <PatientInfo label={t('nascopNumber', 'Nascop facility no')} value={capitalize(patient?.nascopCCCNumber)} />
56
57
  </div>
57
58
  </div>
58
59
  </div>
@@ -34,7 +34,7 @@ export default function Root({ savePatientForm, isOffline }: RootProps) {
34
34
  <main className={`omrs-main-content ${styles.root}`}>
35
35
  <Grid className={styles.grid}>
36
36
  <Row>
37
- <ExtensionSlot extensionSlotName="breadcrumbs-slot" />
37
+ <ExtensionSlot name="breadcrumbs-slot" />
38
38
  </Row>
39
39
  <ResourcesContext.Provider
40
40
  value={{
@@ -36,6 +36,7 @@
36
36
  "editIdentifierTooltip": "Edit",
37
37
  "editPatientDetails": "Edit patient details",
38
38
  "error": "Error",
39
+ "errorFetchingOrderedFields": "Error occured fetching ordered fields for address hierarchy",
39
40
  "estimatedAgeInMonthsLabelText": "Estimated age in months",
40
41
  "estimatedAgeInYearsLabelText": "Estimated age in years",
41
42
  "familyNameLabelText": "Family Name",
@@ -59,7 +60,7 @@
59
60
  "loadingResults": "Loading results",
60
61
  "male": "Male",
61
62
  "middleNameLabelText": "Middle Name",
62
- "months": "Months",
63
+ "nascopNumber": "Nascop facility no",
63
64
  "nationalId": "National ID",
64
65
  "negativeMonths": "Negative months",
65
66
  "negativeYears": "Negative years",
@@ -73,8 +74,6 @@
73
74
  "patientName": "Patient name",
74
75
  "patientNameKnown": "Patient's Name is Known?",
75
76
  "patientNotFound": "The patient records could not be found in Client registry, do you want to continue to create and post patient to registry",
76
- "phoneEmailLabelText": "Phone, Email, etc.",
77
- "phoneNumberInputLabelText": "Phone number",
78
77
  "postalCode": "Postcode",
79
78
  "postToRegistry": "Post to registry",
80
79
  "registerPatient": "Register Patient",
@@ -90,20 +89,19 @@
90
89
  "resetIdentifierTooltip": "Reset",
91
90
  "restoreRelationshipActionButton": "Undo",
92
91
  "searchAddress": "Search address",
92
+ "selectAnOption": "Select an option",
93
93
  "selectCountry": "Select country",
94
94
  "selectIdentifierType": "Select identifier type",
95
95
  "sexFieldLabelText": "Sex",
96
96
  "stateProvince": "State",
97
97
  "stroke": "Stroke",
98
98
  "unableToFetch": "Unable to fetch person attribute type {personattributetype}",
99
- "unidentifiedPatient": "Unidentified Patient",
100
99
  "unknown": "Unknown",
101
100
  "updatePatient": "Update Patient",
102
101
  "updationSuccessToastDescription": "The patient's information has been successfully updated",
103
102
  "updationSuccessToastTitle": "Patient Details Updated",
104
103
  "useValues": "Use values",
105
104
  "validate": "Validate",
106
- "years": "Years",
107
105
  "yearsEstimateRequired": "Years estimate required",
108
106
  "yes": "Yes"
109
107
  }