@kenyaemr/esm-patient-registration-app 8.0.1-pre.101 → 8.0.1-pre.103

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 (34) hide show
  1. package/.turbo/turbo-build.log +18 -16
  2. package/dist/108.js +1 -1
  3. package/dist/108.js.map +1 -1
  4. package/dist/574.js +1 -1
  5. package/dist/623.js +1 -1
  6. package/dist/735.js +1 -1
  7. package/dist/745.js +2 -0
  8. package/dist/{831.js.LICENSE.txt → 745.js.LICENSE.txt} +10 -0
  9. package/dist/745.js.map +1 -0
  10. package/dist/76.js +1 -1
  11. package/dist/830.js +1 -0
  12. package/dist/830.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 +46 -46
  15. package/dist/main.js +1 -1
  16. package/dist/main.js.LICENSE.txt +10 -0
  17. package/dist/main.js.map +1 -1
  18. package/dist/routes.json +1 -1
  19. package/package.json +1 -1
  20. package/src/client-registry/hie-client-registry/hie-client-registry.component.tsx +97 -21
  21. package/src/client-registry/hie-client-registry/hie-client-registry.scss +8 -1
  22. package/src/client-registry/hie-client-registry/hie-resource.ts +143 -0
  23. package/src/client-registry/hie-client-registry/hie-types.ts +29 -0
  24. package/src/client-registry/hie-client-registry/modal/confirm-hie.modal.tsx +82 -0
  25. package/src/client-registry/hie-client-registry/modal/confirm-hie.scss +10 -0
  26. package/src/client-registry/patient-verification/verification-modal/empty-prompt.component.tsx +9 -6
  27. package/src/config-schema.ts +13 -1
  28. package/src/index.ts +3 -0
  29. package/src/routes.json +7 -2
  30. package/translations/en.json +7 -1
  31. package/dist/790.js +0 -1
  32. package/dist/790.js.map +0 -1
  33. package/dist/831.js +0 -2
  34. package/dist/831.js.map +0 -1
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.24.0"},"pages":[{"component":"root","route":"patient-registration","online":true,"offline":true},{"component":"editPatient","routeRegex":"patient\\/([a-zA-Z0-9\\-]+)\\/edit","online":true,"offline":true}],"extensions":[{"component":"addPatientLink","name":"add-patient-action","slot":"top-nav-actions-slot","online":true,"offline":true},{"component":"cancelPatientEditModal","name":"cancel-patient-edit-modal","online":true,"offline":true},{"component":"patientPhotoExtension","name":"patient-photo-widget","slot":"patient-photo-slot","online":true,"offline":true},{"component":"editPatientDetailsButton","name":"edit-patient-details-button","slot":"patient-actions-slot","online":true,"offline":true},{"component":"editPatientDetailsButton","name":"edit-patient-details-button","slot":"patient-search-actions-slot","online":true,"offline":true},{"component":"deleteIdentifierConfirmationModal","name":"delete-identifier-confirmation-modal","online":true,"offline":true},{"component":"emptyClientRegistryModal","name":"empty-client-registry-modal","online":true,"offline":true},{"component":"confirmClientRegistryModal","name":"confirm-client-registry-modal","online":true,"offline":true}],"version":"8.0.1-pre.101"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"webservices.rest":"^2.24.0"},"pages":[{"component":"root","route":"patient-registration","online":true,"offline":true},{"component":"editPatient","routeRegex":"patient\\/([a-zA-Z0-9\\-]+)\\/edit","online":true,"offline":true}],"extensions":[{"component":"addPatientLink","name":"add-patient-action","slot":"top-nav-actions-slot","online":true,"offline":true},{"component":"cancelPatientEditModal","name":"cancel-patient-edit-modal","online":true,"offline":true},{"component":"patientPhotoExtension","name":"patient-photo-widget","slot":"patient-photo-slot","online":true,"offline":true},{"component":"editPatientDetailsButton","name":"edit-patient-details-button","slot":"patient-actions-slot","online":true,"offline":true},{"component":"editPatientDetailsButton","name":"edit-patient-details-button","slot":"patient-search-actions-slot","online":true,"offline":true},{"component":"deleteIdentifierConfirmationModal","name":"delete-identifier-confirmation-modal","online":true,"offline":true},{"component":"emptyClientRegistryModal","name":"empty-client-registry-modal","online":true,"offline":true},{"component":"confirmClientRegistryModal","name":"confirm-client-registry-modal","online":true,"offline":true}],"modals":[{"component":"hieConfirmationModal","name":"hie-confirmation-modal"}],"version":"8.0.1-pre.103"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-patient-registration-app",
3
- "version": "8.0.1-pre.101",
3
+ "version": "8.0.1-pre.103",
4
4
  "description": "Patient registration microfrontend for the OpenMRS SPA",
5
5
  "browser": "dist/kenyaemr-esm-patient-registration-app.js",
6
6
  "main": "src/index.ts",
@@ -3,23 +3,76 @@ import styles from './hie-client-registry.scss';
3
3
  import { type FormikProps } from 'formik';
4
4
  import { type FormValues } from '../../patient-registration/patient-registration.types';
5
5
  import { useTranslation } from 'react-i18next';
6
- import { Tile, ComboBox, Button, TextInput } from '@carbon/react';
6
+ import { Tile, ComboBox, Button, TextInput, InlineLoading } from '@carbon/react';
7
7
  import { Search } from '@carbon/react/icons';
8
- import { useConfig } from '@openmrs/esm-framework';
8
+ import { showModal, showSnackbar, useConfig } from '@openmrs/esm-framework';
9
+ import { z } from 'zod';
9
10
  import { type RegistrationConfig } from '../../config-schema';
11
+ import { useForm, Controller, type SubmitHandler } from 'react-hook-form';
12
+ import { zodResolver } from '@hookform/resolvers/zod';
13
+ import { fetchPatientFromHIE, mapHIEPatientToFormValues } from './hie-resource';
14
+ import { type HIEPatient } from './hie-types';
10
15
 
11
16
  type HIEClientRegistryProps = {
12
17
  props: FormikProps<FormValues>;
13
18
  setInitialFormValues: Dispatch<FormValues>;
14
19
  };
15
20
 
16
- const HIEClientRegistry: React.FC<HIEClientRegistryProps> = () => {
21
+ type HIEFormValues = {
22
+ identifierType: string;
23
+ identifierValue: string;
24
+ };
25
+
26
+ const HIEFormSchema = z.object({
27
+ identifierType: z.string().min(1, { message: 'Identifier type is required' }),
28
+ identifierValue: z.string().min(1, { message: 'Identifier value is required' }),
29
+ });
30
+
31
+ const HIEClientRegistry: React.FC<HIEClientRegistryProps> = ({ setInitialFormValues, props }) => {
17
32
  const { t } = useTranslation();
33
+ const { control, handleSubmit, watch, formState } = useForm<HIEFormValues>({
34
+ mode: 'all',
35
+ defaultValues: { identifierType: '', identifierValue: '' },
36
+ resolver: zodResolver(HIEFormSchema),
37
+ });
18
38
  const {
19
39
  hieClientRegistry: { identifierTypes },
20
40
  } = useConfig<RegistrationConfig>();
41
+
42
+ const onSubmit: SubmitHandler<HIEFormValues> = async (data: HIEFormValues, event: React.BaseSyntheticEvent) => {
43
+ try {
44
+ const hieClientRegistry = await fetchPatientFromHIE(data.identifierType, data.identifierValue);
45
+
46
+ if (hieClientRegistry && hieClientRegistry.resourceType === 'Patient') {
47
+ const dispose = showModal('hie-confirmation-modal', {
48
+ patient: hieClientRegistry,
49
+ closeModal: () => dispose(),
50
+ onUseValues: () =>
51
+ setInitialFormValues(mapHIEPatientToFormValues(hieClientRegistry as HIEPatient, props.values)),
52
+ });
53
+ }
54
+
55
+ if (hieClientRegistry && hieClientRegistry.resourceType === 'OperationOutcome') {
56
+ const issueMessage = hieClientRegistry?.['issue']?.map((issue) => issue.diagnostics).join(', ');
57
+ const dispose = showModal('empty-client-registry-modal', {
58
+ onConfirm: () => dispose(),
59
+ close: () => dispose(),
60
+ title: t('clientRegistryEmpty', 'Create & Post Patient'),
61
+ message: issueMessage,
62
+ });
63
+ }
64
+ } catch (error) {
65
+ showSnackbar({
66
+ title: t('errorFetchingPatient', 'Error fetching patient'),
67
+ subtitle: error.message,
68
+ kind: 'error',
69
+ isLowContrast: true,
70
+ });
71
+ }
72
+ };
73
+
21
74
  return (
22
- <div className={styles.hieContainer}>
75
+ <form onSubmit={handleSubmit(onSubmit)} className={styles.hieContainer}>
23
76
  <h3 className={styles.productiveHeading02} style={{ color: '#161616' }}>
24
77
  {t('patientVerificationFromHIE', 'Patient verification from HIE')}
25
78
  </h3>
@@ -27,31 +80,54 @@ const HIEClientRegistry: React.FC<HIEClientRegistryProps> = () => {
27
80
  {t('allFieldsRequiredText', 'All fields are required unless marked optional')}
28
81
  </span>
29
82
  <Tile className={styles.grid}>
30
- <ComboBox
31
- light
32
- onChange={() => {}}
33
- id="identifier-combobox"
34
- items={identifierTypes}
35
- placeholder={t('selectIdentifierType', 'Select identifier type')}
36
- itemToString={(item) => (item ? item.identifierType : '')}
37
- titleText={t('identifierType', 'Identifier type')}
83
+ <Controller
84
+ control={control}
85
+ name="identifierType"
86
+ render={({ field: { onChange, value, onBlur, ref }, fieldState }) => (
87
+ <ComboBox
88
+ light
89
+ style={{ borderBottom: 'none' }}
90
+ onChange={({ selectedItem }) => onChange(selectedItem?.identifierValue)}
91
+ id="identifier-combobox"
92
+ items={identifierTypes}
93
+ placeholder={t('selectIdentifierType', 'Select identifier type')}
94
+ itemToString={(item) => (item ? item.identifierType : '')}
95
+ titleText={t('identifierType', 'Identifier type')}
96
+ invalid={!!fieldState?.error?.message}
97
+ invalidText={fieldState?.error?.message}
98
+ />
99
+ )}
38
100
  />
39
- <TextInput
40
- light
41
- id="identifier-search"
42
- placeholder={t('enterIdentifierSearchValue', 'Enter identifier search value')}
43
- type="text"
44
- labelText={t('identifierSearch', 'Identifier search')}
101
+ <Controller
102
+ control={control}
103
+ name="identifierValue"
104
+ render={({ field, fieldState }) => (
105
+ <TextInput
106
+ disabled={watch('identifierType') === ''}
107
+ light
108
+ id="identifier-search"
109
+ placeholder={t('enterIdentifierSearchValue', 'Enter identifier search value')}
110
+ type="text"
111
+ labelText={t('identifierSearch', 'Identifier search')}
112
+ invalid={!!fieldState?.error?.message}
113
+ invalidText={fieldState?.error?.message}
114
+ {...field}
115
+ />
116
+ )}
45
117
  />
46
118
  <Button
119
+ onClick={handleSubmit(onSubmit)}
47
120
  renderIcon={(props) => <Search size={24} {...props} />}
48
121
  iconDescription={t('searchRegistry', 'Search registry')}
49
122
  size="md"
50
- kind="secondary">
51
- {t('search', 'Search')}
123
+ disabled={!watch('identifierType') || !watch('identifierValue') || formState.isSubmitting}
124
+ kind="tertiary">
125
+ {formState.isSubmitting
126
+ ? t('searchingRegistry', 'Searching registry...')
127
+ : t('searchRegistry', 'Search registry')}
52
128
  </Button>
53
129
  </Tile>
54
- </div>
130
+ </form>
55
131
  );
56
132
  };
57
133
 
@@ -41,6 +41,13 @@
41
41
  display: grid;
42
42
  grid-template-columns: 1fr 1fr 0.5fr;
43
43
  column-gap: layout.$spacing-05;
44
- align-items: flex-end;
44
+ align-items: flex-start;
45
+
46
+ & > button {
47
+ align-self: flex-start;
48
+ margin-top: 1.4rem;
49
+ max-width: 14rem;
50
+ min-width: 14rem;
51
+ }
45
52
  }
46
53
  }
@@ -0,0 +1,143 @@
1
+ import { add, capitalize } from 'lodash-es';
2
+ import { type PatientIdentifierValue, type FormValues } from '../../patient-registration/patient-registration.types';
3
+ import { APIClientConfig, type MapperConfig, type HIEPatient, type ErrorResponse } from './hie-types';
4
+ import { getConfig } from '@openmrs/esm-framework';
5
+ import { type RegistrationConfig } from '../../config-schema';
6
+ /**
7
+ * Represents a client for interacting with a Health Information Exchange (HIE) resource.
8
+ * @template T - The type of the resource being fetched.
9
+ */
10
+ class HealthInformationExchangeClient<T> {
11
+ async fetchResource(resourceType: string, params: Record<string, string>): Promise<T> {
12
+ const {
13
+ hieClientRegistry: { baseUrl, encodedCredentials },
14
+ } = await getConfig<RegistrationConfig>('@kenyaemr/esm-patient-registration-app');
15
+ const urlParams = new URLSearchParams(params);
16
+ const response = await fetch(`${baseUrl}${resourceType}?${urlParams}`, {
17
+ headers: new Headers({
18
+ Authorization: `Basic ${encodedCredentials}`,
19
+ }),
20
+ });
21
+
22
+ return response.json();
23
+ }
24
+ }
25
+
26
+ /**
27
+ * Represents a generic Mapper class.
28
+ * @template T - The source type.
29
+ * @template U - The target type.
30
+ */
31
+ class Mapper<T, U> {
32
+ protected config: MapperConfig;
33
+
34
+ constructor(config: MapperConfig) {
35
+ this.config = config;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Maps HIEPatient objects to FormValues objects.
41
+ */
42
+ class PatientMapper extends Mapper<HIEPatient, FormValues> {
43
+ mapHIEPatientToFormValues(hiePatient: HIEPatient, currentFormValues: FormValues): FormValues {
44
+ const name = hiePatient.name?.[0] || {};
45
+ const telecom = hiePatient.telecom || [];
46
+
47
+ const telecomAttributes = this.mapTelecomToAttributes(telecom);
48
+ const updatedIdentifiers = this.mapIdentifiers(hiePatient, currentFormValues);
49
+ const extensionAddressEntries = this.mapExtensionsToAddress(hiePatient.extension);
50
+
51
+ return {
52
+ isDead: hiePatient.deceasedBoolean || false,
53
+ gender: hiePatient.gender || '',
54
+ birthdate: hiePatient.birthDate || '',
55
+ givenName: name.given?.[0] || '',
56
+ familyName: name.family || '',
57
+ telephoneNumber: telecom.find((t) => t.system === 'phone')?.value || '',
58
+ middleName: name.given?.[1],
59
+ address: extensionAddressEntries,
60
+ identifiers: updatedIdentifiers,
61
+ attributes: telecomAttributes,
62
+ } as FormValues;
63
+ }
64
+
65
+ private mapTelecomToAttributes(telecom: Array<fhir.ContactPoint>): Record<string, string> {
66
+ return telecom.reduce<Record<string, string>>((acc, { system, value }) => {
67
+ if (system && value && this.config.teleComMap[system]) {
68
+ acc[this.config.teleComMap[system]] = value.replace(/^254/, '0');
69
+ }
70
+ return acc;
71
+ }, {});
72
+ }
73
+
74
+ private mapIdentifiers(
75
+ hiePatient: HIEPatient,
76
+ currentFormValues: FormValues,
77
+ ): Record<string, PatientIdentifierValue> {
78
+ const updatedIdentifiers: Record<string, PatientIdentifierValue> = { ...currentFormValues.identifiers };
79
+
80
+ // Map healthId to hiePatient.id
81
+ updatedIdentifiers.healthId = {
82
+ ...currentFormValues.identifiers['healthId'],
83
+ identifierValue: hiePatient.id,
84
+ };
85
+
86
+ // Map fhir.Patient.Identifier to identifiers
87
+ hiePatient.identifier?.forEach((identifier) => {
88
+ const system = identifier.system?.split('/').pop();
89
+ if (system && this.config.identifierMap[system]) {
90
+ const key = this.config.identifierMap[system];
91
+ updatedIdentifiers[key] = {
92
+ ...currentFormValues.identifiers[key],
93
+ identifierValue: identifier.value || '',
94
+ };
95
+ }
96
+ });
97
+
98
+ return updatedIdentifiers;
99
+ }
100
+
101
+ private mapExtensionsToAddress(extensions: HIEPatient['extension']): Record<string, string> {
102
+ return extensions
103
+ .map((ext) => {
104
+ const identifierType = ext.url.split('/').pop();
105
+ const identifierValue = ext.valueString;
106
+ return { [this.config.addressHierarchyMap[identifierType]]: capitalize(identifierValue) };
107
+ })
108
+ .reduce<Record<string, string>>((acc, curr) => ({ ...acc, ...curr }), {});
109
+ }
110
+ }
111
+
112
+ // Update MapperConfig interface in hie-types.ts
113
+
114
+ const mapperConfig: MapperConfig = {
115
+ teleComMap: {
116
+ email: 'b8d0b331-1d2d-4a9a-b741-1816f498bdb6',
117
+ phone: 'b2c38640-2603-4629-aebd-3b54f33f1e3a',
118
+ },
119
+ addressHierarchyMap: {
120
+ county: 'countyDistrict',
121
+ 'sub-county': 'stateProvince',
122
+ ward: 'address4',
123
+ },
124
+ addressMap: {},
125
+ // Map FHIR Patient identifiers to identifiers, at the moment HIE teams returns null for all identifiers type codings
126
+ identifierMap: {},
127
+ };
128
+
129
+ // Create instances
130
+ const hieApiClient = new HealthInformationExchangeClient<HIEPatient | ErrorResponse>();
131
+ const patientMapper = new PatientMapper(mapperConfig);
132
+
133
+ // Exported functions
134
+ export const fetchPatientFromHIE = async (
135
+ identifierType: string,
136
+ identifierValue: string,
137
+ ): Promise<HIEPatient | ErrorResponse> => {
138
+ return hieApiClient.fetchResource('Patient', { [identifierType]: identifierValue });
139
+ };
140
+
141
+ export const mapHIEPatientToFormValues = (hiePatient: HIEPatient, currentFormValues: FormValues): FormValues => {
142
+ return patientMapper.mapHIEPatientToFormValues(hiePatient, currentFormValues);
143
+ };
@@ -0,0 +1,29 @@
1
+ export type HIEPatient = fhir.Patient & {
2
+ extension: Array<{
3
+ url: string;
4
+ valueString: string;
5
+ }>;
6
+ };
7
+
8
+ export type APIClientConfig = {
9
+ baseUrl: string;
10
+ credentials: string;
11
+ };
12
+
13
+ export interface MapperConfig {
14
+ teleComMap: Record<string, string>;
15
+ addressHierarchyMap: Record<string, string>;
16
+ identifierMap: Record<string, string>;
17
+ addressMap: Record<string, string>;
18
+ }
19
+
20
+ export type ErrorResponse = {
21
+ resourceType: string;
22
+ issue: Array<Issue>;
23
+ };
24
+
25
+ export type Issue = {
26
+ severity: string;
27
+ code: string;
28
+ diagnostics: string;
29
+ };
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Button, ModalBody, ModalHeader, ModalFooter, Accordion, AccordionItem, CodeSnippet } from '@carbon/react';
4
+ import styles from './confirm-hie.scss';
5
+ import { age, ExtensionSlot, formatDate } from '@openmrs/esm-framework';
6
+ import { type HIEPatient } from '../hie-types';
7
+ import capitalize from 'lodash-es/capitalize';
8
+
9
+ const PatientInfo: React.FC<{ label: string; value: string }> = ({ label, value }) => {
10
+ return (
11
+ <div style={{ display: 'grid', gridTemplateColumns: '0.25fr 0.75fr', margin: '0.25rem' }}>
12
+ <span style={{ minWidth: '5rem', fontWeight: 'bold' }}>{label}</span>
13
+ <span>{value}</span>
14
+ </div>
15
+ );
16
+ };
17
+
18
+ interface HIEConfirmationModalProps {
19
+ closeModal: () => void;
20
+ patient: HIEPatient;
21
+ onUseValues: () => void;
22
+ }
23
+
24
+ const HIEConfirmationModal: React.FC<HIEConfirmationModalProps> = ({ closeModal, patient, onUseValues }) => {
25
+ const { t } = useTranslation();
26
+ const firstName = patient?.name[0]['given']?.[0];
27
+ const lastName = patient?.name[0]['family'];
28
+
29
+ const handleUseValues = () => {
30
+ onUseValues();
31
+ closeModal();
32
+ };
33
+
34
+ return (
35
+ <div>
36
+ <ModalHeader closeModal={closeModal}>
37
+ <span className={styles.header}>{t('hieModal', 'HIE Patient Record Found')}</span>
38
+ </ModalHeader>
39
+ <ModalBody>
40
+ <div style={{ display: 'flex', margin: '1rem' }}>
41
+ <ExtensionSlot
42
+ style={{ display: 'flex', alignItems: 'center' }}
43
+ name="patient-photo-slot"
44
+ state={{ patientName: `${firstName} ${lastName}` }}
45
+ />
46
+ <div style={{ width: '100%', marginLeft: '0.625rem' }}>
47
+ <PatientInfo label={t('healthID', 'HealthID')} value={patient.id} />
48
+ <PatientInfo label={t('patientName', 'Patient name')} value={`${firstName} ${lastName}`} />
49
+ <PatientInfo label={t('age', 'Age')} value={age(patient?.birthDate)} />
50
+ <PatientInfo label={t('dateOfBirth', 'Date of birth')} value={formatDate(new Date(patient?.birthDate))} />
51
+ <PatientInfo label={t('gender', 'Gender')} value={capitalize(patient?.gender)} />
52
+ <PatientInfo
53
+ label={t('maritalStatus', 'Marital status')}
54
+ value={patient.maritalStatus.coding.map((m) => m.code).join('')}
55
+ />
56
+ <PatientInfo label={t('relationships', 'Relationships')} value="--" />
57
+ </div>
58
+ </div>
59
+ <div>
60
+ <Accordion>
61
+ <AccordionItem title={t('viewFullResponse', 'View full response')}>
62
+ <CodeSnippet type="multi" feedback="Copied to clipboard">
63
+ {JSON.stringify(patient, null, 2)}
64
+ </CodeSnippet>
65
+ </AccordionItem>
66
+ </Accordion>
67
+ </div>
68
+ </ModalBody>
69
+ <ModalFooter>
70
+ <Button kind="secondary" onClick={closeModal}>
71
+ {t('cancel', 'Cancel')}
72
+ </Button>
73
+
74
+ <Button onClick={handleUseValues} kind="primary">
75
+ {t('useValues', 'Use values')}
76
+ </Button>
77
+ </ModalFooter>
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export default HIEConfirmationModal;
@@ -0,0 +1,10 @@
1
+ @use '@carbon/type';
2
+ @use '@openmrs/esm-styleguide/src/vars' as *;
3
+
4
+ .header {
5
+ @include type.type-style('heading-03');
6
+ }
7
+
8
+ .body {
9
+ @include type.type-style('body-01');
10
+ }
@@ -5,21 +5,24 @@ import { Button } from '@carbon/react';
5
5
  interface EmptyPromptProps {
6
6
  onConfirm: void;
7
7
  close: void;
8
+ title?: string;
9
+ message?: string;
8
10
  }
9
11
 
10
- const EmptyPrompt: React.FC<EmptyPromptProps> = ({ close, onConfirm }) => {
12
+ const EmptyPrompt: React.FC<EmptyPromptProps> = ({ close, onConfirm, title, message }) => {
11
13
  const { t } = useTranslation();
12
14
  return (
13
15
  <>
14
16
  <div className="cds--modal-header">
15
- <h3 className="cds--modal-header__heading">{t('clientRegistryEmpty', 'Create & Post Patient')}</h3>
17
+ <h3 className="cds--modal-header__heading">{title ?? t('clientRegistryEmpty', 'Create & Post Patient')}</h3>
16
18
  </div>
17
19
  <div className="cds--modal-content">
18
20
  <p>
19
- {t(
20
- 'patientNotFound',
21
- 'The patient records could not be found in Client registry, do you want to continue to create and post patient to registry',
22
- )}
21
+ {message ??
22
+ t(
23
+ 'patientNotFound',
24
+ 'The patient records could not be found in Client registry, do you want to continue to create and post patient to registry',
25
+ )}
23
26
  </p>
24
27
  </div>
25
28
  <div className="cds--modal-footer">
@@ -85,6 +85,8 @@ export interface RegistrationConfig {
85
85
  };
86
86
  hieClientRegistry: {
87
87
  identifierTypes: Array<{ identifierType: string; identifierValue: string }>;
88
+ baseUrl: string;
89
+ encodedCredentials: string;
88
90
  };
89
91
  }
90
92
 
@@ -382,12 +384,22 @@ export const esmPatientRegistrationSchema = {
382
384
  },
383
385
  _default: [
384
386
  { identifierType: 'National ID', identifierValue: 'national-id' },
385
- { identifierType: 'Passport Number', identifierValue: 'passport number' },
387
+ { identifierType: 'Passport Number', identifierValue: 'passport-number' },
386
388
  { identifierType: 'Birth Certificate Number', identifierValue: 'birth-certificate-number' },
387
389
  { identifierType: 'Alien ID Number', identifierValue: 'alien-id-number' },
388
390
  { identifierType: 'Refugee ID Number', identifierValue: 'refugee-number' },
389
391
  ],
390
392
  },
393
+ baseUrl: {
394
+ _type: Type.String,
395
+ _default: 'https://hie.paperless.co.ke/v4/custom/',
396
+ _description: 'The base URL for the HIE API',
397
+ },
398
+ encodedCredentials: {
399
+ _type: Type.String,
400
+ _default: 'a2VueWFfZW1yOkFsZG5iJmtmayZKc2whMjM0',
401
+ _description: 'The base64 encoded credentials for the HIE API',
402
+ },
391
403
  },
392
404
  _validators: [
393
405
  validator(
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import rootComponent from './root.component';
6
6
  import addPatientLinkComponent from './add-patient-link';
7
7
  import editPatientDetailsButtonComponent from './widgets/edit-patient-details-button.component';
8
8
  import { PatientPhotoExtension } from './patient-photo.extension';
9
+ import HIEConfirmationModal from './client-registry/hie-client-registry/modal/confirm-hie.modal';
9
10
 
10
11
  export const importTranslation = require.context('../translations', false, /.json$/, 'lazy');
11
12
 
@@ -76,3 +77,5 @@ export const emptyClientRegistryModal = getAsyncLifecycle(
76
77
  () => import('./client-registry/patient-verification/verification-modal/empty-prompt.component'),
77
78
  options,
78
79
  );
80
+
81
+ export const hieConfirmationModal = getSyncLifecycle(HIEConfirmationModal, options);
package/src/routes.json CHANGED
@@ -70,6 +70,11 @@
70
70
  "online": true,
71
71
  "offline": true
72
72
  }
73
+ ],
74
+ "modals": [
75
+ {
76
+ "component": "hieConfirmationModal",
77
+ "name": "hie-confirmation-modal"
78
+ }
73
79
  ]
74
- }
75
-
80
+ }
@@ -43,6 +43,7 @@
43
43
  "enterIdentifierSearchValue": "Enter identifier search value",
44
44
  "error": "Error",
45
45
  "errorFetchingOrderedFields": "Error occured fetching ordered fields for address hierarchy",
46
+ "errorFetchingPatient": "Error fetching patient",
46
47
  "estimatedAgeInMonthsLabelText": "Estimated age in months",
47
48
  "estimatedAgeInYearsLabelText": "Estimated age in years",
48
49
  "familyNameLabelText": "Family Name",
@@ -55,6 +56,8 @@
55
56
  "genderUnspecified": "Gender is not specified",
56
57
  "givenNameLabelText": "First Name",
57
58
  "givenNameRequired": "Given name is required",
59
+ "healthID": "HealthID",
60
+ "hieModal": "HIE Patient Record Found",
58
61
  "identifierSearch": "Identifier search",
59
62
  "identifierType": "Identifier type",
60
63
  "identifierValueRequired": "Identifier value is required",
@@ -66,6 +69,7 @@
66
69
  "isDeadInputLabel": "Is Dead",
67
70
  "jumpTo": "Jump to",
68
71
  "male": "Male",
72
+ "maritalStatus": "Marital status",
69
73
  "middleNameLabelText": "Middle Name",
70
74
  "nationalId": "National ID",
71
75
  "negativeMonths": "Negative months",
@@ -91,6 +95,7 @@
91
95
  "relationshipPersonMustExist": "Related person must be an existing person",
92
96
  "relationshipPlaceholder": "Relationship",
93
97
  "relationshipRemovedText": "Relationship removed",
98
+ "relationships": "Relationships",
94
99
  "relationshipsSection": "Relationships",
95
100
  "relationshipToPatient": "Relationship to patient",
96
101
  "relativeFullNameLabelText": "Related person",
@@ -98,10 +103,10 @@
98
103
  "removeIdentifierButton": "Remove Identifier",
99
104
  "resetIdentifierTooltip": "Reset",
100
105
  "restoreRelationshipActionButton": "Undo",
101
- "search": "Search",
102
106
  "searchAddress": "Search address",
103
107
  "searchClientRegistry": "Search client registry",
104
108
  "searchIdentifierPlaceholder": "Search identifier",
109
+ "searchingRegistry": "Searching registry...",
105
110
  "searchRegistry": "Search registry",
106
111
  "selectAnOption": "Select an option",
107
112
  "selectCountry": "Select country",
@@ -120,6 +125,7 @@
120
125
  "updatePatientSuccessSnackbarTitle": "Patient Details Updated",
121
126
  "useValues": "Use values",
122
127
  "validate": "Validate",
128
+ "viewFullResponse": "View full response",
123
129
  "yearsEstimateRequired": "Years estimate required",
124
130
  "yes": "Yes"
125
131
  }