@kenyaemr/esm-patient-registration-app 8.1.1-pre.111 → 8.1.1-pre.116

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 (101) hide show
  1. package/.turbo/turbo-build.log +22 -23
  2. package/dist/108.js +1 -1
  3. package/dist/130.js +1 -1
  4. package/dist/130.js.LICENSE.txt +2 -0
  5. package/dist/130.js.map +1 -1
  6. package/dist/2.js +1 -0
  7. package/dist/2.js.map +1 -0
  8. package/dist/250.js +1 -0
  9. package/dist/250.js.map +1 -0
  10. package/dist/271.js +1 -1
  11. package/dist/319.js +1 -1
  12. package/dist/325.js +1 -0
  13. package/dist/325.js.map +1 -0
  14. package/dist/372.js +2 -0
  15. package/dist/372.js.map +1 -0
  16. package/dist/460.js +1 -1
  17. package/dist/471.js +1 -0
  18. package/dist/471.js.map +1 -0
  19. package/dist/574.js +1 -1
  20. package/dist/644.js +1 -1
  21. package/dist/662.js +1 -0
  22. package/dist/662.js.map +1 -0
  23. package/dist/757.js +1 -1
  24. package/dist/76.js +1 -1
  25. package/dist/788.js +1 -1
  26. package/dist/807.js +1 -1
  27. package/dist/833.js +1 -1
  28. package/dist/895.js +2 -0
  29. package/dist/{745.js.LICENSE.txt → 895.js.LICENSE.txt} +10 -0
  30. package/dist/895.js.map +1 -0
  31. package/dist/kenyaemr-esm-patient-registration-app.js +1 -1
  32. package/dist/kenyaemr-esm-patient-registration-app.js.buildmanifest.json +150 -177
  33. package/dist/kenyaemr-esm-patient-registration-app.js.map +1 -1
  34. package/dist/main.js +1 -1
  35. package/dist/main.js.map +1 -1
  36. package/dist/routes.json +1 -1
  37. package/package.json +2 -2
  38. package/src/config-schema.ts +28 -2
  39. package/src/index.ts +1 -4
  40. package/src/patient-registration/field/cause-of-death/cause-of-death.component.tsx +98 -0
  41. package/src/patient-registration/field/date-and-time-of-death/date-and-time-of-death.component.tsx +84 -0
  42. package/src/patient-registration/field/dob/dob.component.tsx +21 -7
  43. package/src/patient-registration/field/field.component.tsx +11 -5
  44. package/src/patient-registration/field/field.resource.ts +11 -4
  45. package/src/patient-registration/field/field.scss +23 -1
  46. package/src/patient-registration/field/gender/gender-field.component.tsx +2 -1
  47. package/src/patient-registration/field/gender/gender-field.test.tsx +1 -0
  48. package/src/patient-registration/field/name/name-field.component.tsx +5 -1
  49. package/src/patient-registration/form-manager.test.ts +3 -0
  50. package/src/patient-registration/form-manager.ts +30 -15
  51. package/src/patient-registration/input/basic-input/input/input.component.tsx +5 -1
  52. package/src/patient-registration/input/custom-input/identifier/identifier-input.component.tsx +2 -2
  53. package/src/patient-registration/input/custom-input/identifier/identifier-input.test.tsx +122 -71
  54. package/src/patient-registration/input/dummy-data/dummy-data-input.component.tsx +3 -0
  55. package/src/patient-registration/patient-registration-context.ts +4 -3
  56. package/src/patient-registration/patient-registration-hooks.ts +63 -8
  57. package/src/patient-registration/patient-registration-utils.ts +3 -7
  58. package/src/patient-registration/patient-registration.component.tsx +20 -13
  59. package/src/patient-registration/patient-registration.resource.ts +8 -0
  60. package/src/patient-registration/patient-registration.test.tsx +9 -3
  61. package/src/patient-registration/patient-registration.types.ts +4 -1
  62. package/src/patient-registration/section/death-info/death-info-section.component.tsx +22 -17
  63. package/src/patient-registration/section/death-info/death-info-section.test.tsx +4 -14
  64. package/src/patient-registration/section/section.component.tsx +1 -1
  65. package/src/patient-registration/section/section.scss +5 -0
  66. package/src/patient-registration/validation/{patient-registration-validation.test.tsx → patient-registration-validation.test.ts} +26 -4
  67. package/src/patient-registration/validation/patient-registration-validation.ts +126 -0
  68. package/src/routes.json +10 -18
  69. package/src/widgets/cancel-patient-edit.modal.tsx +33 -0
  70. package/src/widgets/cancel-patient-edit.test.tsx +2 -3
  71. package/src/widgets/delete-identifier-confirmation.modal.tsx +22 -15
  72. package/src/widgets/delete-identifier-confirmation.test.tsx +2 -1
  73. package/translations/am.json +36 -25
  74. package/translations/ar.json +37 -26
  75. package/translations/en.json +37 -20
  76. package/translations/es.json +38 -26
  77. package/translations/fr.json +47 -35
  78. package/translations/he.json +37 -30
  79. package/translations/km.json +37 -30
  80. package/translations/zh.json +37 -20
  81. package/translations/zh_CN.json +37 -20
  82. package/dist/152.js +0 -1
  83. package/dist/152.js.map +0 -1
  84. package/dist/255.js +0 -2
  85. package/dist/255.js.map +0 -1
  86. package/dist/303.js +0 -1
  87. package/dist/303.js.map +0 -1
  88. package/dist/623.js +0 -1
  89. package/dist/623.js.map +0 -1
  90. package/dist/729.js +0 -1
  91. package/dist/729.js.map +0 -1
  92. package/dist/735.js +0 -1
  93. package/dist/735.js.map +0 -1
  94. package/dist/745.js +0 -2
  95. package/dist/745.js.map +0 -1
  96. package/dist/830.js +0 -1
  97. package/dist/830.js.map +0 -1
  98. package/src/patient-registration/validation/patient-registration-validation.tsx +0 -60
  99. package/src/widgets/cancel-patient-edit.component.tsx +0 -37
  100. package/src/widgets/delete-identifier-confirmation.scss +0 -34
  101. /package/dist/{255.js.LICENSE.txt → 372.js.LICENSE.txt} +0 -0
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
- import { Formik, Form } from 'formik';
3
+ import { Form, Formik } from 'formik';
4
4
  import { initialFormValues } from '../../patient-registration.component';
5
- import { DeathInfoSection } from './death-info-section.component';
6
5
  import { type FormValues } from '../../patient-registration.types';
7
6
  import { PatientRegistrationContext } from '../../patient-registration-context';
7
+ import { DeathInfoSection } from './death-info-section.component';
8
8
 
9
9
  const initialContextValues = {
10
10
  currentPhoto: 'data:image/png;base64,1234567890',
@@ -29,7 +29,7 @@ describe('Death info section', () => {
29
29
  <PatientRegistrationContext.Provider value={initialContextValues}>
30
30
  <Formik initialValues={initialFormValues} onSubmit={jest.fn()}>
31
31
  <Form>
32
- <DeathInfoSection />
32
+ <DeathInfoSection fields={[]} />
33
33
  </Form>
34
34
  </Formik>
35
35
  </PatientRegistrationContext.Provider>,
@@ -40,16 +40,6 @@ describe('Death info section', () => {
40
40
  renderDeathInfoSection(true);
41
41
 
42
42
  expect(screen.getByRole('region', { name: /death info section/i })).toBeInTheDocument();
43
- expect(screen.getByRole('heading', { name: /death info/i })).toBeInTheDocument();
44
- expect(screen.getByRole('textbox', { name: /is dead \(optional\)/i })).toBeInTheDocument();
45
- expect(screen.getByRole('textbox', { name: /date of death \(optional\)/i })).toBeInTheDocument();
46
- expect(screen.getByRole('combobox', { name: /cause of death \(optional\)/i })).toBeInTheDocument();
47
- });
48
-
49
- it('has the correct number of inputs if is dead is not checked', async () => {
50
- renderDeathInfoSection(false);
51
-
52
- expect(screen.queryByRole('textbox', { name: /date of death \(optional\)/i })).not.toBeInTheDocument();
53
- expect(screen.queryByRole('combobox', { name: /cause of death \(optional\)/i })).not.toBeInTheDocument();
43
+ expect(screen.getByRole('checkbox', { name: /is dead/i })).toBeInTheDocument();
54
44
  });
55
45
  });
@@ -14,7 +14,7 @@ export function Section({ sectionDefinition }: SectionProps) {
14
14
  case 'demographics':
15
15
  return <DemographicsSection fields={sectionDefinition.fields} />;
16
16
  case 'death':
17
- return <DeathInfoSection />;
17
+ return <DeathInfoSection fields={sectionDefinition.fields} />;
18
18
  case 'relationships':
19
19
  return <RelationshipsSection />;
20
20
  default: // includes 'contact'
@@ -1,3 +1,4 @@
1
+ @use '@carbon/colors';
1
2
  @use '@carbon/layout';
2
3
  @use '@carbon/type';
3
4
  @use '@openmrs/esm-styleguide/src/vars' as *;
@@ -14,3 +15,7 @@
14
15
  color: $ui-04;
15
16
  cursor: pointer;
16
17
  }
18
+
19
+ .isDeadFieldContainer {
20
+ margin-bottom: layout.$spacing-05;
21
+ }
@@ -1,6 +1,7 @@
1
1
  import { getConfig } from '@openmrs/esm-framework';
2
2
  import { type RegistrationConfig } from '../../config-schema';
3
3
  import { getValidationSchema } from './patient-registration-validation';
4
+ import dayjs from 'dayjs';
4
5
 
5
6
  const mockGetConfig = jest.mocked(getConfig);
6
7
 
@@ -35,6 +36,8 @@ describe('Patient registration validation', () => {
35
36
  additionalGivenName: '',
36
37
  birthdate: new Date('1990-01-01'),
37
38
  birthdateEstimated: false,
39
+ isDead: false,
40
+ causeOfDeath: null,
38
41
  deathDate: null,
39
42
  email: 'john.doe@example.com',
40
43
  familyName: 'Doe',
@@ -142,7 +145,7 @@ describe('Patient registration validation', () => {
142
145
  expect(validationError).toBeFalsy();
143
146
  });
144
147
 
145
- it('should throw error when date of birth is a future date', async () => {
148
+ it('should throw an error when date of birth is a future date', async () => {
146
149
  const invalidFormValues = {
147
150
  ...validFormValues,
148
151
  birthdate: new Date('2100-01-01'),
@@ -151,6 +154,15 @@ describe('Patient registration validation', () => {
151
154
  expect(validationError.errors).toContain('birthdayNotInTheFuture');
152
155
  });
153
156
 
157
+ it('should throw an error when date of birth is more than 140 years ago', async () => {
158
+ const invalidFormValues = {
159
+ ...validFormValues,
160
+ birthdate: dayjs().subtract(141, 'years').toDate(),
161
+ };
162
+ const validationError = await validateFormValues(invalidFormValues);
163
+ expect(validationError.errors).toContain('birthdayNotOver140YearsAgo');
164
+ });
165
+
154
166
  it('should require yearsEstimated when birthdateEstimated is true', async () => {
155
167
  const invalidFormValues = {
156
168
  ...validFormValues,
@@ -160,7 +172,7 @@ describe('Patient registration validation', () => {
160
172
  expect(validationError.errors).toContain('yearsEstimateRequired');
161
173
  });
162
174
 
163
- it('should throw error when monthEstimated is negative', async () => {
175
+ it('should throw an error when monthEstimated is negative', async () => {
164
176
  const invalidFormValues = {
165
177
  ...validFormValues,
166
178
  birthdateEstimated: true,
@@ -171,12 +183,22 @@ describe('Patient registration validation', () => {
171
183
  expect(validationError.errors).toContain('negativeMonths');
172
184
  });
173
185
 
174
- it('should throw error when deathDate is in future', async () => {
186
+ it('should throw an error when yearsEstimated is more than 140', async () => {
187
+ const invalidFormValues = {
188
+ ...validFormValues,
189
+ birthdateEstimated: true,
190
+ yearsEstimated: 141,
191
+ };
192
+ const validationError = await validateFormValues(invalidFormValues);
193
+ expect(validationError.errors).toContain('nonsensicalYears');
194
+ });
195
+
196
+ it('should throw an error when deathDate is in future', async () => {
175
197
  const invalidFormValues = {
176
198
  ...validFormValues,
177
199
  deathDate: new Date('2100-01-01'),
178
200
  };
179
201
  const validationError = await validateFormValues(invalidFormValues);
180
- expect(validationError.errors).toContain('deathdayNotInTheFuture');
202
+ expect(validationError.errors).toContain('deathDateInFuture');
181
203
  });
182
204
  });
@@ -0,0 +1,126 @@
1
+ import dayjs from 'dayjs';
2
+ import * as Yup from 'yup';
3
+ import mapValues from 'lodash/mapValues';
4
+ import { translateFrom } from '@openmrs/esm-framework';
5
+ import { type RegistrationConfig } from '../../config-schema';
6
+ import { type FormValues } from '../patient-registration.types';
7
+ import { getDatetime } from '../patient-registration.resource';
8
+
9
+ const t = (key: string, value: string) => translateFrom('@openmrs/esm-framework', key, value);
10
+
11
+ export function getValidationSchema(config: RegistrationConfig) {
12
+ return Yup.object({
13
+ givenName: Yup.string().required(t('givenNameRequired', 'Given name is required')),
14
+ familyName: Yup.string().required(t('familyNameRequired', 'Family name is required')),
15
+ additionalGivenName: Yup.string().when('addNameInLocalLanguage', {
16
+ is: true,
17
+ then: Yup.string().required(t('givenNameRequired', 'Given name is required')),
18
+ otherwise: Yup.string().notRequired(),
19
+ }),
20
+ additionalFamilyName: Yup.string().when('addNameInLocalLanguage', {
21
+ is: true,
22
+ then: Yup.string().required(t('familyNameRequired', 'Family name is required')),
23
+ otherwise: Yup.string().notRequired(),
24
+ }),
25
+ gender: Yup.string()
26
+ .oneOf(
27
+ config.fieldConfigurations.gender.map((g) => g.value),
28
+ t('genderUnspecified', 'Gender unspecified'),
29
+ )
30
+ .required(t('genderRequired', 'Gender is required')),
31
+ birthdate: Yup.date().when('birthdateEstimated', {
32
+ is: false,
33
+ then: Yup.date()
34
+ .required(t('birthdayRequired', 'Birthday is required'))
35
+ .max(Date(), t('birthdayNotInTheFuture', 'Birthday cannot be in future'))
36
+ .min(
37
+ dayjs().subtract(140, 'years').toDate(),
38
+ t('birthdayNotOver140YearsAgo', 'Birthday cannot be more than 140 years ago'),
39
+ )
40
+ .nullable(),
41
+ otherwise: Yup.date().nullable(),
42
+ }),
43
+ yearsEstimated: Yup.number().when('birthdateEstimated', {
44
+ is: true,
45
+ then: Yup.number()
46
+ .required(t('yearsEstimateRequired', 'Estimated years required'))
47
+ .min(0, t('negativeYears', 'Estimated years cannot be negative'))
48
+ .max(140, t('nonsensicalYears', 'Estimated years cannot be more than 140')),
49
+ otherwise: Yup.number().nullable(),
50
+ }),
51
+ monthsEstimated: Yup.number().min(0, t('negativeMonths', 'Estimated months cannot be negative')),
52
+ isDead: Yup.boolean(),
53
+ deathDate: Yup.date()
54
+ .when('isDead', {
55
+ is: true,
56
+ then: Yup.date().required(t('deathDateRequired', 'Death date is required')),
57
+ otherwise: Yup.date().nullable(),
58
+ })
59
+ .max(new Date(), 'deathDateInFuture')
60
+ .test(
61
+ 'deathDate-after-birthdate',
62
+ t('deathdayInvalidDate', 'Death date and time cannot be before the birthday'),
63
+ function (value) {
64
+ const { birthdate } = this.parent;
65
+ if (birthdate && value) {
66
+ return dayjs(value).isAfter(birthdate);
67
+ }
68
+ return true;
69
+ },
70
+ )
71
+ .test('deathDate-before-today', t('deathDateInFuture', 'Death date cannot be in future'), function (value) {
72
+ const { deathTime, deathTimeFormat } = this.parent;
73
+ if (value && deathTime && deathTimeFormat && /^(1[0-2]|0?[1-9]):([0-5]?[0-9])$/.test(deathTime)) {
74
+ return dayjs(getDatetime(value, deathTime, deathTimeFormat)).isBefore(dayjs());
75
+ }
76
+ return true;
77
+ }),
78
+ deathTime: Yup.string()
79
+ .when('isDead', {
80
+ is: true,
81
+ then: Yup.string().required(t('deathTimeRequired', 'Death time is required')),
82
+ otherwise: Yup.string().nullable(),
83
+ })
84
+ .matches(/^(1[0-2]|0?[1-9]):([0-5]?[0-9])$/, t('deathTimeInvalid', "Time doesn't match the format 'hh:mm'")),
85
+
86
+ deathTimeFormat: Yup.string()
87
+ .when('isDead', {
88
+ is: true,
89
+ then: Yup.string().required(t('deathTimeFormatRequired', 'Time format is required')),
90
+ otherwise: Yup.string().nullable(),
91
+ })
92
+ .oneOf(['AM', 'PM'], t('deathTimeFormatInvalid', 'Time format is invalid')),
93
+
94
+ deathCause: Yup.string().when('isDead', {
95
+ is: true,
96
+ then: Yup.string().required(t('deathCauseRequired', 'Cause of death is required')),
97
+ otherwise: Yup.string().nullable(),
98
+ }),
99
+ nonCodedCauseOfDeath: Yup.string().when(['isDead', 'deathCause'], {
100
+ is: (isDead, deathCause) => isDead && deathCause === config.freeTextFieldConceptUuid,
101
+ then: Yup.string().required(t('nonCodedCauseOfDeathRequired', 'Cause of death is required')),
102
+ otherwise: Yup.string().nullable(),
103
+ }),
104
+ email: Yup.string().optional().email(t('invalidEmail', 'Invalid email')),
105
+ identifiers: Yup.lazy((obj: FormValues['identifiers']) =>
106
+ Yup.object(
107
+ mapValues(obj, () =>
108
+ Yup.object({
109
+ required: Yup.bool(),
110
+ identifierValue: Yup.string().when('required', {
111
+ is: true,
112
+ then: Yup.string().required(t('identifierValueRequired', 'Identifier value is required')),
113
+ otherwise: Yup.string().notRequired(),
114
+ }),
115
+ }),
116
+ ),
117
+ ),
118
+ ),
119
+ relationships: Yup.array().of(
120
+ Yup.object().shape({
121
+ relatedPersonUuid: Yup.string().required(),
122
+ relationshipType: Yup.string().required(),
123
+ }),
124
+ ),
125
+ });
126
+ }
package/src/routes.json CHANGED
@@ -25,12 +25,6 @@
25
25
  "online": true,
26
26
  "offline": true
27
27
  },
28
- {
29
- "component": "cancelPatientEditModal",
30
- "name": "cancel-patient-edit-modal",
31
- "online": true,
32
- "offline": true
33
- },
34
28
  {
35
29
  "component": "patientPhotoExtension",
36
30
  "name": "patient-photo-widget",
@@ -51,27 +45,25 @@
51
45
  "slot": "patient-search-actions-slot",
52
46
  "online": true,
53
47
  "offline": true
48
+ }
49
+ ],
50
+ "modals": [
51
+ {
52
+ "name": "cancel-patient-edit-modal",
53
+ "component": "cancelPatientEditModal"
54
54
  },
55
55
  {
56
- "component": "deleteIdentifierConfirmationModal",
57
56
  "name": "delete-identifier-confirmation-modal",
58
- "online": true,
59
- "offline": true
57
+ "component": "deleteIdentifierConfirmationModal"
60
58
  },
61
59
  {
62
60
  "component": "emptyClientRegistryModal",
63
- "name": "empty-client-registry-modal",
64
- "online": true,
65
- "offline": true
61
+ "name": "empty-client-registry-modal"
66
62
  },
67
63
  {
68
64
  "component": "confirmClientRegistryModal",
69
- "name": "confirm-client-registry-modal",
70
- "online": true,
71
- "offline": true
72
- }
73
- ],
74
- "modals": [
65
+ "name": "confirm-client-registry-modal"
66
+ },
75
67
  {
76
68
  "component": "hieConfirmationModal",
77
69
  "name": "hie-confirmation-modal"
@@ -0,0 +1,33 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, ModalBody, ModalFooter, ModalHeader } from '@carbon/react';
4
+
5
+ interface CancelPatientEditPropsModal {
6
+ close(): void;
7
+ onConfirm(): void;
8
+ }
9
+
10
+ const CancelPatientEditModal: React.FC<CancelPatientEditPropsModal> = ({ close, onConfirm }) => {
11
+ const { t } = useTranslation();
12
+ return (
13
+ <>
14
+ <ModalHeader
15
+ closeModal={close}
16
+ title={t('confirmDiscardChangesTitle', 'Are you sure you want to discard these changes?')}
17
+ />
18
+ <ModalBody>
19
+ <p>{t('confirmDiscardChangesBody', 'Your unsaved changes will be lost if you proceed to discard the form')}.</p>
20
+ </ModalBody>
21
+ <ModalFooter>
22
+ <Button kind="secondary" onClick={close}>
23
+ {t('cancel', 'Cancel')}
24
+ </Button>
25
+ <Button kind="danger" onClick={onConfirm}>
26
+ {t('discard', 'Discard')}
27
+ </Button>
28
+ </ModalFooter>
29
+ </>
30
+ );
31
+ };
32
+
33
+ export default CancelPatientEditModal;
@@ -1,15 +1,14 @@
1
1
  import React from 'react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { screen, render } from '@testing-library/react';
4
- import CancelPatientEdit from './cancel-patient-edit.component';
4
+ import CancelPatientEdit from './cancel-patient-edit.modal';
5
5
 
6
- describe('CancelPatientEdit component', () => {
6
+ describe('CancelPatientEdit modal', () => {
7
7
  const mockClose = jest.fn();
8
8
  const mockOnConfirm = jest.fn();
9
9
 
10
10
  it('renders the modal and triggers close and onConfirm functions', async () => {
11
11
  const user = userEvent.setup();
12
-
13
12
  render(<CancelPatientEdit close={mockClose} onConfirm={mockOnConfirm} />);
14
13
 
15
14
  const cancelButton = screen.getByRole('button', { name: /Cancel/i });
@@ -1,15 +1,16 @@
1
1
  import React from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
- import { Button } from '@carbon/react';
4
- import styles from './delete-identifier-confirmation.scss';
3
+ import { Button, ModalBody, ModalHeader, ModalFooter } from '@carbon/react';
5
4
 
6
5
  interface DeleteIdentifierConfirmationModalProps {
6
+ closeModal: () => void;
7
7
  deleteIdentifier: (x: boolean) => void;
8
8
  identifierName: string;
9
9
  identifierValue: string;
10
10
  }
11
11
 
12
12
  const DeleteIdentifierConfirmationModal: React.FC<DeleteIdentifierConfirmationModalProps> = ({
13
+ closeModal,
13
14
  deleteIdentifier,
14
15
  identifierName,
15
16
  identifierValue,
@@ -17,24 +18,30 @@ const DeleteIdentifierConfirmationModal: React.FC<DeleteIdentifierConfirmationMo
17
18
  const { t } = useTranslation();
18
19
 
19
20
  return (
20
- <div className={styles.modalContent}>
21
- <h1 className={styles.productiveHeading}>{t('deleteIdentifierModalHeading', 'Remove identifier?')}</h1>
22
- <h3 className={styles.modalSubtitle}>
23
- {identifierName}
24
- {t('deleteIdentifierModalText', ' has a value of ')} {identifierValue}
25
- </h3>
26
- <p className={styles.modalBody}>
27
- {t('confirmIdentifierDeletionText', 'Are you sure you want to remove this identifier?')}
28
- </p>
29
- <div className={styles.buttonSet}>
21
+ <>
22
+ <ModalHeader
23
+ closeModal={closeModal}
24
+ title={t('deleteIdentifierModalHeading', 'Delete identifier?')}></ModalHeader>
25
+ <ModalBody>
26
+ <p>
27
+ {identifierName && identifierValue && (
28
+ <span>
29
+ <strong>{identifierName}</strong>
30
+ {t('deleteIdentifierModalText', ' has a value of ')} <strong>{identifierValue}</strong>.{' '}
31
+ </span>
32
+ )}
33
+ {t('confirmIdentifierDeletionText', 'Are you sure you want to delete this identifier?')}
34
+ </p>
35
+ </ModalBody>
36
+ <ModalFooter>
30
37
  <Button kind="secondary" size="lg" onClick={() => deleteIdentifier(false)}>
31
38
  {t('cancel', 'Cancel')}
32
39
  </Button>
33
40
  <Button kind="danger" size="lg" onClick={() => deleteIdentifier(true)}>
34
- {t('removeIdentifierButton', 'Remove Identifier')}
41
+ {t('removeIdentifierButton', 'Remove identifier')}
35
42
  </Button>
36
- </div>
37
- </div>
43
+ </ModalFooter>
44
+ </>
38
45
  );
39
46
  };
40
47
 
@@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event';
3
3
  import { render, screen } from '@testing-library/react';
4
4
  import DeleteIdentifierConfirmationModal from './delete-identifier-confirmation.modal';
5
5
 
6
- describe('DeleteIdentifierConfirmationModal component', () => {
6
+ describe('DeleteIdentifierConfirmationModal', () => {
7
7
  const mockDeleteIdentifier = jest.fn();
8
8
  const mockIdentifierName = 'Identifier Name';
9
9
  const mockIdentifierValue = 'Identifier Value';
@@ -13,6 +13,7 @@ describe('DeleteIdentifierConfirmationModal component', () => {
13
13
 
14
14
  render(
15
15
  <DeleteIdentifierConfirmationModal
16
+ closeModal={jest.fn()}
16
17
  deleteIdentifier={mockDeleteIdentifier}
17
18
  identifierName={mockIdentifierName}
18
19
  identifierValue={mockIdentifierValue}
@@ -4,68 +4,78 @@
4
4
  "age": "Age",
5
5
  "allFieldsRequiredText": "All fields are required unless marked optional",
6
6
  "autoGeneratedPlaceholderText": "Auto-generated",
7
- "birthdayNotInTheFuture": "Birthday cannot be in the future",
7
+ "birthdayNotInTheFuture": "Birthday cannot be in future",
8
+ "birthdayNotOver140YearsAgo": "Birthday cannot be more than 140 years ago",
8
9
  "birthdayRequired": "Birthday is required",
9
10
  "birthFieldLabelText": "Birth",
10
11
  "cancel": "Cancel",
11
- "causeOfDeathInputLabel": "Cause of Death",
12
- "clientRegistryEmpty": "Create & Post Patient",
13
- "clientVerificationWithClientRegistry": "Client verification with client registry",
12
+ "causeOfDeathInputLabel": "Cause of death",
14
13
  "closeOverlay": "Close overlay",
15
14
  "codedPersonAttributeAnswerSetEmpty": "The coded person attribute field '{{codedPersonAttributeFieldId}}' has been defined with an answer concept set UUID '{{answerConceptSetUuid}}' that does not have any concept answers.",
16
15
  "codedPersonAttributeAnswerSetInvalid": "The coded person attribute field '{{codedPersonAttributeFieldId}}' has been defined with an invalid answer concept set UUID '{{answerConceptSetUuid}}'.",
17
16
  "codedPersonAttributeNoAnswerSet": "The person attribute field '{{codedPersonAttributeFieldId}}' is of type 'coded' but has been defined without an answer concept set UUID. The 'answerConceptSetUuid' key is required.",
18
17
  "configure": "Configure",
19
18
  "configureIdentifiers": "Configure identifiers",
19
+ "confirmDiscardChangesBody": "Your unsaved changes will be lost if you proceed to discard the form",
20
+ "confirmDiscardChangesTitle": "Are you sure you want to discard these changes?",
20
21
  "confirmIdentifierDeletionText": "Are you sure you want to remove this identifier?",
21
22
  "contactSection": "Contact Details",
22
23
  "createNewPatient": "Create new patient",
23
- "continue": "Continue to registration",
24
- "createNew": "Create New",
25
- "dateOfBirth": "Date of birth",
26
- "dateOfBirthLabelText": "Date of Birth",
27
- "deathDateInputLabel": "Date of Death",
28
- "deathdayNotInTheFuture": "Death day cannot be in the future",
24
+ "dateOfBirthLabelText": "Date of birth",
25
+ "deathCauseRequired": "Cause of death is required",
26
+ "deathDateInFuture": "Death date cannot be in future",
27
+ "deathDateInputLabel": "Date of death",
28
+ "deathDateRequired": "Death date is required",
29
+ "deathdayInvalidDate": "Death date and time cannot be before the birthday",
30
+ "deathdayIsRequired": "Death date is required when the patient is marked as deceased.",
31
+ "deathdayNotInTheFuture": "",
29
32
  "deathSection": "Death Info",
33
+ "deathTimeFormatInvalid": "Time format is invalid",
34
+ "deathTimeFormatRequired": "Time format is required",
35
+ "deathTimeInvalid": "Time doesn't match the format 'hh:mm'",
36
+ "deathTimeRequired": "Death time is required",
30
37
  "deleteIdentifierModalHeading": "Remove identifier?",
31
38
  "deleteIdentifierModalText": " has a value of ",
32
39
  "deleteIdentifierTooltip": "Delete",
33
40
  "deleteRelationshipTooltipText": "Delete",
34
41
  "demographicsSection": "Basic Info",
35
42
  "discard": "Discard",
36
- "discardModalBody": "The changes you made to this patient's details have not been saved. Discard changes?",
37
- "discardModalHeader": "Confirm Discard Changes",
38
43
  "dobToggleLabelText": "Date of Birth Known?",
39
44
  "editIdentifierTooltip": "Edit",
40
45
  "editPatientDetails": "Edit patient details",
41
46
  "editPatientDetailsBreadcrumb": "Edit patient details",
47
+ "enterNonCodedCauseOfDeath": "Enter non-coded cause of death",
42
48
  "error": "Error",
49
+ "errorFetchingCodedCausesOfDeath": "Error fetching coded causes of death",
43
50
  "errorFetchingOrderedFields": "Error occured fetching ordered fields for address hierarchy",
44
51
  "estimatedAgeInMonthsLabelText": "Estimated age in months",
45
52
  "estimatedAgeInYearsLabelText": "Estimated age in years",
46
53
  "familyNameLabelText": "Family Name",
47
54
  "familyNameRequired": "Family name is required",
48
55
  "female": "Female",
56
+ "fieldsWithErrors": "The following fields have errors: ",
49
57
  "fullNameLabelText": "Full Name",
50
58
  "gender": "Gender",
51
59
  "genderLabelText": "Sex",
52
60
  "genderRequired": "Gender is required",
53
- "genderUnspecified": "Gender is not specified",
61
+ "genderUnspecified": "Gender unspecified",
54
62
  "givenNameLabelText": "First Name",
55
63
  "givenNameRequired": "Given name is required",
56
64
  "identifierValueRequired": "Identifier value is required",
57
65
  "idFieldLabelText": "Identifiers",
58
66
  "IDInstructions": "Select the identifiers you'd like to add for this patient:",
59
- "incompleteForm": "Incomplete form",
60
- "invalidEmail": "A valid email has to be given",
67
+ "invalidEmail": "Invalid email",
61
68
  "invalidInput": "Invalid Input",
62
- "isDeadInputLabel": "Is Dead",
69
+ "isDeadInputLabel": "Is dead",
63
70
  "jumpTo": "Jump to",
64
71
  "male": "Male",
65
72
  "middleNameLabelText": "Middle Name",
66
- "negativeMonths": "Negative months",
67
- "negativeYears": "Negative years",
73
+ "negativeMonths": "Estimated months cannot be negative",
74
+ "negativeYears": "Estimated years cannot be negative",
68
75
  "no": "No",
76
+ "nonCodedCauseOfDeath": "Non-coded cause of death",
77
+ "nonCodedCauseOfDeathRequired": "Cause of death is required",
78
+ "nonsensicalYears": "Estimated years cannot be more than 140",
69
79
  "numberInNameDubious": "Number in name is dubious",
70
80
  "obsFieldUnknownDatatype": "Concept for obs field '{{fieldDefinitionId}}' has unknown datatype '{{datatypeName}}'",
71
81
  "optional": "optional",
@@ -78,8 +88,8 @@
78
88
  "patientNameKnown": "Patient's Name is Known?",
79
89
  "patientNotFound": "The patient records could not be found in Client registry, do you want to continue to create and post patient to registry",
80
90
  "patientRegistrationBreadcrumb": "Patient Registration",
81
- "postToRegistry": "Post to registry",
82
- "registerPatient": "Register Patient",
91
+ "refreshOrContactAdmin": "Try refreshing the page or contact your system administrator",
92
+ "registerPatient": "Register patient",
83
93
  "registerPatientSuccessSnackbarSubtitle": "The patient can now be found by searching for them using their name or ID number",
84
94
  "registerPatientSuccessSnackbarTitle": "New Patient Created",
85
95
  "registrationErrorSnackbarTitle": "Patient Registration Failed",
@@ -89,9 +99,9 @@
89
99
  "relationshipRemovedText": "Relationship removed",
90
100
  "relationshipsSection": "Relationships",
91
101
  "relationshipToPatient": "Relationship to patient",
92
- "relativeFullNameLabelText": "Related person",
102
+ "relativeFullNameLabelText": "Full name",
93
103
  "relativeNamePlaceholder": "Firstname Familyname",
94
- "removeIdentifierButton": "Remove Identifier",
104
+ "removeIdentifierButton": "Remove identifier",
95
105
  "resetIdentifierTooltip": "Reset",
96
106
  "restoreRelationshipActionButton": "Undo",
97
107
  "searchAddress": "Search address",
@@ -101,15 +111,16 @@
101
111
  "selectIdentifierType": "Select identifier type",
102
112
  "sexFieldLabelText": "Sex",
103
113
  "source": "Source",
104
- "stroke": "Stroke",
105
114
  "submitting": "Submitting",
115
+ "timeFormat": "Time Format",
116
+ "timeOfDeathInputLabel": "Time of death (hh:mm)",
106
117
  "unableToFetch": "Unable to fetch person attribute type - {{personattributetype}}",
107
118
  "unknown": "Unknown",
108
119
  "unknownPatientAttributeType": "Patient attribute type has unknown format {{personAttributeTypeFormat}}",
109
- "updatePatient": "Update Patient",
120
+ "updatePatient": "Update patient",
110
121
  "updatePatientErrorSnackbarTitle": "Patient Details Update Failed",
111
122
  "updatePatientSuccessSnackbarSubtitle": "The patient's information has been successfully updated",
112
123
  "updatePatientSuccessSnackbarTitle": "Patient Details Updated",
113
- "yearsEstimateRequired": "Years estimate required",
124
+ "yearsEstimateRequired": "Estimated years required",
114
125
  "yes": "Yes"
115
126
  }