@ampath/esm-dha-workflow-app 4.0.0-next.13 → 4.0.0-next.15

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 (80) hide show
  1. package/dist/104.js +2 -0
  2. package/dist/104.js.LICENSE.txt +9 -0
  3. package/dist/104.js.map +1 -0
  4. package/dist/306.js +1 -0
  5. package/dist/306.js.map +1 -0
  6. package/dist/388.js +2 -0
  7. package/dist/388.js.map +1 -0
  8. package/dist/460.js +1 -0
  9. package/dist/460.js.map +1 -0
  10. package/dist/560.js +1 -0
  11. package/dist/560.js.map +1 -0
  12. package/dist/635.js +1 -0
  13. package/dist/635.js.map +1 -0
  14. package/dist/695.js +1 -0
  15. package/dist/695.js.map +1 -0
  16. package/dist/709.js +1 -0
  17. package/dist/709.js.map +1 -0
  18. package/dist/710.js +2 -0
  19. package/dist/{198.js.LICENSE.txt → 710.js.LICENSE.txt} +0 -10
  20. package/dist/710.js.map +1 -0
  21. package/dist/91.js +1 -1
  22. package/dist/91.js.map +1 -1
  23. package/dist/93.js +1 -1
  24. package/dist/978.js +1 -0
  25. package/dist/978.js.map +1 -0
  26. package/dist/esm-dha-workflow-app.js +1 -0
  27. package/dist/{openmrs-esm-home-app.js.buildmanifest.json → esm-dha-workflow-app.js.buildmanifest.json} +266 -97
  28. package/dist/esm-dha-workflow-app.js.map +1 -0
  29. package/dist/main.js +1 -1
  30. package/dist/main.js.map +1 -1
  31. package/dist/routes.json +1 -1
  32. package/package.json +2 -2
  33. package/src/config-schema.ts +115 -33
  34. package/src/consultation/action-button.component.tsx +34 -0
  35. package/src/consultation/action-overflow-menu-item.component.tsx +34 -0
  36. package/src/consultation/consultation-room.component.tsx +60 -0
  37. package/src/consultation/consultation.scss +5 -0
  38. package/src/consultation/consultation.tsx +9 -2
  39. package/src/hooks/useActions.ts +148 -0
  40. package/src/hooks/useQueueEntries.ts +35 -0
  41. package/src/index.ts +11 -1
  42. package/src/left-panel/left-panel.component.tsx +0 -2
  43. package/src/metrics/metrics-cards/attended-patients.extension.tsx +18 -0
  44. package/src/metrics/metrics-cards/metrics-card.component.tsx +86 -0
  45. package/src/metrics/metrics-cards/metrics-card.scss +106 -0
  46. package/src/metrics/metrics-cards/waiting-patients.extension.tsx +18 -0
  47. package/src/metrics/metrics-container.component.tsx +16 -0
  48. package/src/metrics/metrics-container.scss +36 -0
  49. package/src/metrics/metrics.resource.ts +101 -0
  50. package/src/modals/sign-off-modal.scss +7 -0
  51. package/src/modals/sign-off-modal.tsx +52 -0
  52. package/src/registry/mock-client.ts +627 -0
  53. package/src/registry/modal/otp-verification-modal/otp-verification-modal.tsx +13 -11
  54. package/src/registry/modal/send-to-triage/send-to-triage.modal.scss +7 -0
  55. package/src/registry/modal/send-to-triage/send-to-triage.modal.tsx +97 -72
  56. package/src/registry/registry.component.scss +12 -1
  57. package/src/registry/registry.component.tsx +168 -104
  58. package/src/registry/types/index.ts +59 -1
  59. package/src/registry/utils/error-handler.ts +33 -0
  60. package/src/registry/utils/format-dependant-display-data.ts +8 -0
  61. package/src/registry/utils/hie-client-adapter.ts +309 -0
  62. package/src/resources/hie-amrs-automatic-registration.service.ts +16 -0
  63. package/src/resources/identifier-types.ts +27 -0
  64. package/src/resources/patient-resource.ts +60 -0
  65. package/src/routes.json +18 -0
  66. package/src/service-queues/service-queues.resource.ts +62 -0
  67. package/src/shared/constants/civil-status.ts +29 -0
  68. package/src/shared/constants/person-attributes.ts +33 -0
  69. package/src/types/types.ts +100 -0
  70. package/dist/16.js +0 -1
  71. package/dist/16.js.map +0 -1
  72. package/dist/198.js +0 -2
  73. package/dist/198.js.map +0 -1
  74. package/dist/200.js +0 -2
  75. package/dist/200.js.map +0 -1
  76. package/dist/860.js +0 -1
  77. package/dist/860.js.map +0 -1
  78. package/dist/openmrs-esm-home-app.js +0 -1
  79. package/dist/openmrs-esm-home-app.js.map +0 -1
  80. /package/dist/{200.js.LICENSE.txt → 388.js.LICENSE.txt} +0 -0
@@ -0,0 +1,309 @@
1
+ import { IdentifierTypesUuids } from '../../resources/identifier-types';
2
+ import { CivilStatusUids } from '../../shared/constants/civil-status';
3
+ import { PersonAttributeTypeUuids } from '../../shared/constants/person-attributes';
4
+ import {
5
+ type AlternateContact,
6
+ type CreatePersonDto,
7
+ type HieClient,
8
+ type HieIdentifications,
9
+ HieIdentificationType,
10
+ } from '../types';
11
+
12
+ const clientDatailsFields = [
13
+ 'id',
14
+ 'other_identifications',
15
+ 'first_name',
16
+ 'middle_name',
17
+ 'last_name',
18
+ 'gender',
19
+ 'date_of_birth',
20
+ 'is_alive',
21
+ 'deceased_datetime',
22
+ 'phone',
23
+ 'email',
24
+ 'civil_status',
25
+ 'place_of_birth',
26
+ 'citizenship',
27
+ 'country',
28
+ 'county',
29
+ 'sub_county',
30
+ 'ward',
31
+ 'village_estate',
32
+ 'longitude',
33
+ 'latitude',
34
+ 'identification_type',
35
+ ];
36
+
37
+ const nameFields = ['first_name', 'middle_name', 'last_name'];
38
+ const otherPersonFields = ['gender', 'date_of_birth', 'is_alive', 'deceased_datetime'];
39
+ const attributeFields = ['phone', 'email', 'civil_status', 'place_of_birth', 'citizenship'];
40
+ const addressFields = ['country', 'county', 'sub_county', 'ward', 'village_estate', 'longitude', 'latitude'];
41
+ const otherFields = ['gender', 'date_of_birth'];
42
+ const identifierFields = [
43
+ HieIdentificationType.Cr,
44
+ HieIdentificationType.SHANumber,
45
+ HieIdentificationType.HouseholdNumber,
46
+ HieIdentificationType.RefugeeID,
47
+ HieIdentificationType.MandateNumber,
48
+ HieIdentificationType.AlienID,
49
+ HieIdentificationType.NationalID,
50
+ HieIdentificationType.TemporaryDependantID,
51
+ ];
52
+ const hieAmrsSyncFields = [
53
+ ...identifierFields,
54
+ ...nameFields,
55
+ ...otherPersonFields,
56
+ ...attributeFields,
57
+ ...addressFields,
58
+ ];
59
+
60
+ export function generateHieClientDetails(hieClient: HieClient) {
61
+ let data = {};
62
+ Object.keys(hieClient)
63
+ .filter((key) => {
64
+ return clientDatailsFields.includes(key);
65
+ })
66
+ .forEach((key) => {
67
+ if (key === 'other_identifications') {
68
+ const otherIds = generateOtherIdentifications(hieClient[key]);
69
+ data = {
70
+ ...data,
71
+ ...otherIds,
72
+ };
73
+ } else if (key === 'identification_type') {
74
+ data[hieClient['identification_type']] = hieClient.identification_number;
75
+ } else {
76
+ const value = hieClient[key];
77
+ data[key] = value;
78
+ }
79
+ });
80
+ return data;
81
+ }
82
+ function generateOtherIdentifications(hieIdentifications: HieIdentifications[]) {
83
+ const other = {};
84
+ hieIdentifications.forEach((id) => {
85
+ other[id.identification_type] = id.identification_number;
86
+ });
87
+ return other;
88
+ }
89
+
90
+ export function generateAmrsPersonPayload(hieClient: HieClient): CreatePersonDto {
91
+ const createPersonPayload: CreatePersonDto = {};
92
+ const namesAttribute = {};
93
+ const addresses = {};
94
+ let attributes = [];
95
+ hieAmrsSyncFields.forEach((d) => {
96
+ if (d === 'first_name') {
97
+ namesAttribute['givenName'] = hieClient.first_name;
98
+ }
99
+ if (d === 'middle_name') {
100
+ namesAttribute['middleName'] = hieClient.middle_name;
101
+ }
102
+ if (d === 'last_name') {
103
+ namesAttribute['familyName'] = hieClient.last_name;
104
+ }
105
+ if (d === 'gender') {
106
+ createPersonPayload['gender'] = hieClient.gender === 'Male' ? 'M' : 'F';
107
+ }
108
+ if (d === 'date_of_birth') {
109
+ createPersonPayload['birthdate'] = hieClient.date_of_birth;
110
+ createPersonPayload['birthdateEstimated'] = false;
111
+ }
112
+ if (d === 'is_alive') {
113
+ createPersonPayload['dead'] = hieClient.is_alive === 0 ? true : false;
114
+ }
115
+ if (d === 'deceased_datetime') {
116
+ if (hieClient.deceased_datetime.length > 0) {
117
+ createPersonPayload['deathDate'] = hieClient.deceased_datetime;
118
+ }
119
+ }
120
+ if (d === 'country' && hieClient.country.length > 0) {
121
+ addresses['country'] = hieClient.country;
122
+ addresses['address1'] = hieClient.country;
123
+ }
124
+ if (d === 'place_of_birth' && hieClient.place_of_birth.length > 0) {
125
+ addresses['address10'] = hieClient.place_of_birth;
126
+ }
127
+ if (d === 'county' && hieClient.county.length > 0) {
128
+ addresses['countyDistrict'] = hieClient.county;
129
+ }
130
+ if (d === 'sub_county' && hieClient.sub_county.length > 0) {
131
+ addresses['address2'] = hieClient.sub_county;
132
+ addresses['stateProvince'] = hieClient.sub_county;
133
+ }
134
+ if (d === 'ward' && hieClient.sub_county.length > 0) {
135
+ addresses['address7'] = hieClient.sub_county;
136
+ addresses['address4'] = hieClient.sub_county;
137
+ }
138
+ if (d === 'village_estate' && hieClient.village_estate.length > 0) {
139
+ addresses['cityVillage'] = hieClient.village_estate;
140
+ }
141
+ if (d === 'longitude' && hieClient.longitude.length > 0) {
142
+ addresses['longitude'] = hieClient.longitude;
143
+ }
144
+ if (d === 'latitude' && hieClient.latitude.length > 0) {
145
+ addresses['latitude'] = hieClient.latitude;
146
+ }
147
+ if (d === 'place_of_birth' && hieClient.place_of_birth.length > 0) {
148
+ attributes.push({
149
+ value: hieClient.place_of_birth,
150
+ attributeType: PersonAttributeTypeUuids.PLACE_OF_BIRTH_UUID,
151
+ });
152
+ }
153
+ if (d === 'phone' && hieClient.phone.length > 0) {
154
+ attributes.push({
155
+ value: hieClient.phone,
156
+ attributeType: PersonAttributeTypeUuids.CONTACT_PHONE_NUMBER_UUID,
157
+ });
158
+ }
159
+ if (d === 'email' && hieClient.email.length > 0) {
160
+ attributes.push({
161
+ value: hieClient.email,
162
+ attributeType: PersonAttributeTypeUuids.CONTACT_EMAIL_ADDRESS_UUID,
163
+ });
164
+ }
165
+ if (d === 'civil_status' && hieClient.civil_status.length > 0) {
166
+ attributes.push({
167
+ value: getAmrsConceptUuidFromField(hieClient.civil_status),
168
+ attributeType: PersonAttributeTypeUuids.CIVIL_STATUS_UUID,
169
+ });
170
+ }
171
+ if (d === 'id' && hieClient.id) {
172
+ attributes.push({
173
+ value: hieClient.id,
174
+ attributeType: PersonAttributeTypeUuids.CLIENT_REGISTRY_ID_UUID,
175
+ });
176
+ }
177
+ if (d === 'citizenship' && hieClient.citizenship) {
178
+ attributes.push({
179
+ value: hieClient.citizenship,
180
+ attributeType: PersonAttributeTypeUuids.CITIZENSHIP_UUID,
181
+ });
182
+ }
183
+ });
184
+ // Add next of kin details
185
+ const nextOfKinAndAlternativeAttributes = generateNextOfKinAndAlternateContactDetails(hieClient.alternative_contacts);
186
+ attributes = [...attributes, ...nextOfKinAndAlternativeAttributes];
187
+ if (Object.keys(namesAttribute).length > 0) {
188
+ createPersonPayload['names'] = [namesAttribute];
189
+ }
190
+ if (Object.keys(addresses).length > 0) {
191
+ createPersonPayload['addresses'] = [addresses];
192
+ }
193
+ if (attributes.length > 0) {
194
+ createPersonPayload['attributes'] = attributes;
195
+ }
196
+ return createPersonPayload;
197
+ }
198
+ function generateNextOfKinAndAlternateContactDetails(alternativeContacts: AlternateContact[]) {
199
+ const attributes = [];
200
+ const alterNativeClientContact = alternativeContacts.find((a) => {
201
+ return a.relationship === 'Alternative Phone Number';
202
+ });
203
+ const nextOfKinContact = alternativeContacts.find((a) => {
204
+ return a.remarks === 'Next Of Kin';
205
+ });
206
+ if (alterNativeClientContact) {
207
+ if (alterNativeClientContact.contact_type === 'Phone') {
208
+ attributes.push({
209
+ value: alterNativeClientContact.contact_id,
210
+ attributeType: PersonAttributeTypeUuids.ALTERNATIVE_CONTACT_PHONE_NUMBER_UUID,
211
+ });
212
+ }
213
+ }
214
+ if (nextOfKinContact) {
215
+ if (nextOfKinContact.contact_type === 'Phone') {
216
+ attributes.push({
217
+ value: nextOfKinContact.contact_id,
218
+ attributeType: PersonAttributeTypeUuids.NEXT_OF_KIN_CONTACT_PHONE_NUMBER_UUID,
219
+ });
220
+ }
221
+ attributes.push({
222
+ value: nextOfKinContact.relationship,
223
+ attributeType: PersonAttributeTypeUuids.NEXT_OF_KIN_RELATIONSHIP_UUID,
224
+ });
225
+ attributes.push({
226
+ value: nextOfKinContact.contact_name,
227
+ attributeType: PersonAttributeTypeUuids.NEXT_OF_KIN_NAME_UUID,
228
+ });
229
+ }
230
+ return attributes;
231
+ }
232
+ function getAmrsConceptUuidFromField(fieldName: string): string {
233
+ let conceptUuid = '';
234
+ switch (fieldName) {
235
+ case 'Divorced':
236
+ conceptUuid = CivilStatusUids.DIVORCED_UUID;
237
+ break;
238
+ case 'Married':
239
+ conceptUuid = CivilStatusUids.MARRIED_UUID;
240
+ break;
241
+ case 'Single':
242
+ conceptUuid = CivilStatusUids.SINGLE_UUID;
243
+ break;
244
+ default:
245
+ conceptUuid = CivilStatusUids.NOT_APPLICABLE_UUID;
246
+ }
247
+ return conceptUuid;
248
+ }
249
+ export function generateAmrsCreatePatientIdentifiersPayload(hieClient: HieClient, identifierLocation: string) {
250
+ const identifiers = [];
251
+ // add CR number
252
+ identifiers.push({
253
+ identifierType: getAmrsIdentifierTypeUuid(HieIdentificationType.Cr),
254
+ identifier: hieClient.id,
255
+ location: identifierLocation,
256
+ });
257
+
258
+ // add main identifier
259
+ identifiers.push({
260
+ identifierType: getAmrsIdentifierTypeUuid(hieClient.identification_type),
261
+ identifier: hieClient.identification_number,
262
+ location: identifierLocation,
263
+ });
264
+
265
+ // add other idenfications
266
+ hieClient.other_identifications.forEach((id) => {
267
+ identifiers.push({
268
+ identifierType: getAmrsIdentifierTypeUuid(id.identification_type),
269
+ identifier: id.identification_number,
270
+ location: identifierLocation,
271
+ });
272
+ });
273
+
274
+ return identifiers;
275
+ }
276
+
277
+ export function getAmrsIdentifierTypeUuid(hieIdentifierName: string) {
278
+ let idTypeUuid;
279
+ switch (hieIdentifierName) {
280
+ case HieIdentificationType.NationalID:
281
+ idTypeUuid = IdentifierTypesUuids.NATIONAL_ID_UUID;
282
+ break;
283
+ case HieIdentificationType.HouseholdNumber:
284
+ idTypeUuid = IdentifierTypesUuids.HOUSE_HOLD_NUMBER_UUID;
285
+ break;
286
+ case HieIdentificationType.AlienID:
287
+ idTypeUuid = IdentifierTypesUuids.ALIEN_ID_UUID;
288
+ break;
289
+ case HieIdentificationType.SHANumber:
290
+ idTypeUuid = IdentifierTypesUuids.SHA_UUID;
291
+ break;
292
+ case HieIdentificationType.MandateNumber:
293
+ idTypeUuid = IdentifierTypesUuids.MANDATE_NUMBER_UUID;
294
+ break;
295
+ case HieIdentificationType.RefugeeID:
296
+ idTypeUuid = IdentifierTypesUuids.REFUGEE_ID_UUID;
297
+ break;
298
+ case HieIdentificationType.Cr:
299
+ idTypeUuid = IdentifierTypesUuids.CLIENT_REGISTRY_NO_UUID;
300
+ break;
301
+ case HieIdentificationType.BirthCertificate:
302
+ idTypeUuid = IdentifierTypesUuids.BIRTH_CERTIFICATE_NUMBER_UUID;
303
+ break;
304
+ case HieIdentificationType.TemporaryDependantID:
305
+ idTypeUuid = IdentifierTypesUuids.TEMPORARY_DEPENDANT_ID_UUID;
306
+ break;
307
+ }
308
+ return idTypeUuid;
309
+ }
@@ -0,0 +1,16 @@
1
+ import { type Patient } from '@openmrs/esm-framework';
2
+ import { type HieClient } from '../registry/types';
3
+ import { generateAmrsPersonPayload } from '../registry/utils/hie-client-adapter';
4
+ import { createPatient, generatePatientIdentifiers } from './patient-resource';
5
+
6
+ export async function registerHieClientInAmrs(client: HieClient, identifierLocation: string): Promise<Patient> {
7
+ const createPersonPayload = generateAmrsPersonPayload(client);
8
+ const identifiers = await generatePatientIdentifiers(identifierLocation, client);
9
+ const resp = await createPatient({
10
+ person: createPersonPayload,
11
+ identifiers: identifiers,
12
+ });
13
+
14
+ const res = await resp.json();
15
+ return res;
16
+ }
@@ -0,0 +1,27 @@
1
+ const HOUSE_HOLD_NUMBER_UUID = 'bb74b20e-dcee-4f59-bdf1-2dffc3abf106';
2
+ const SHA_UUID = 'cf5362b2-8049-4442-b3c6-36f870e320cb';
3
+ const CLIENT_REGISTRY_NO_UUID = 'e88dc246-3614-4ee3-8141-1f2a83054e72';
4
+ const NATIONAL_ID_UUID = '58a47054-1359-11df-a1f1-0026b9348838';
5
+ const PROVIDER_NATIONAL_ID_UUID = '4550df92-c684-4597-8ab8-d6b10eabdcfb';
6
+ const REFUGEE_ID_UUID = '465e81af-8d69-47e9-9127-53a94adc75fb';
7
+ const MANDATE_NUMBER_UUID = 'aae2d097-20ba-43ca-9b71-fd8296068f39';
8
+ const ALIEN_ID_UUID = '12f5b147-3403-4a73-913d-7ded9ffec094';
9
+ const TEMPORARY_DEPENDANT_ID_UUID = 'a3d34214-93e8-4faf-bf4d-0272eee079eb';
10
+ const AMRS_UNIVERSAL_ID_UUID = '58a4732e-1359-11df-a1f1-0026b9348838';
11
+ const UPI_NUMBER_UUID = 'cba702b9-4664-4b43-83f1-9ab473cbd64d';
12
+ const BIRTH_CERTIFICATE_NUMBER_UUID = '7924e13b-131a-4da8-8efa-e294184a1b0d';
13
+
14
+ export const IdentifierTypesUuids = {
15
+ HOUSE_HOLD_NUMBER_UUID,
16
+ SHA_UUID,
17
+ CLIENT_REGISTRY_NO_UUID,
18
+ NATIONAL_ID_UUID,
19
+ PROVIDER_NATIONAL_ID_UUID,
20
+ REFUGEE_ID_UUID,
21
+ MANDATE_NUMBER_UUID,
22
+ ALIEN_ID_UUID,
23
+ TEMPORARY_DEPENDANT_ID_UUID,
24
+ AMRS_UNIVERSAL_ID_UUID,
25
+ UPI_NUMBER_UUID,
26
+ BIRTH_CERTIFICATE_NUMBER_UUID,
27
+ };
@@ -0,0 +1,60 @@
1
+ import { openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import { type HieClient, type CreatePatientDto, HieIdentificationType } from '../registry/types';
3
+ import { IdentifierTypesUuids } from './identifier-types';
4
+ import { getAmrsIdentifierTypeUuid } from '../registry/utils/hie-client-adapter';
5
+
6
+ export async function createPatient(payload: CreatePatientDto) {
7
+ return await openmrsFetch(`${restBaseUrl}/patient`, {
8
+ method: 'POST',
9
+ headers: {
10
+ 'Content-Type': 'application/json',
11
+ },
12
+ body: payload,
13
+ });
14
+ }
15
+
16
+ export const generatePatientIdentifiers = async (identifierLocation: string, client: HieClient) => {
17
+ const amrsUniverSalId = await generateAmrsUniversalIdentifier();
18
+ const identifiers = generateAmrsCreatePatientIdentifiersPayload(client, identifierLocation);
19
+ identifiers.push({
20
+ identifierType: IdentifierTypesUuids.AMRS_UNIVERSAL_ID_UUID,
21
+ identifier: amrsUniverSalId,
22
+ location: identifierLocation,
23
+ preferred: true,
24
+ });
25
+ return identifiers;
26
+ };
27
+
28
+ export function generateAmrsCreatePatientIdentifiersPayload(hieClient: HieClient, identifierLocation: string) {
29
+ const identifiers = [];
30
+ // add CR number
31
+ identifiers.push({
32
+ identifierType: getAmrsIdentifierTypeUuid(HieIdentificationType.Cr),
33
+ identifier: hieClient.id,
34
+ location: identifierLocation,
35
+ });
36
+
37
+ // add main identifier
38
+ identifiers.push({
39
+ identifierType: getAmrsIdentifierTypeUuid(hieClient.identification_type),
40
+ identifier: hieClient.identification_number,
41
+ location: identifierLocation,
42
+ });
43
+ return identifiers;
44
+ }
45
+
46
+ export async function generateAmrsUniversalIdentifier() {
47
+ const abortController = new AbortController();
48
+ const resp = await openmrsFetch(`https://staging.ampath.or.ke/amrs-id-generator/generateidentifier`, {
49
+ headers: {
50
+ 'Content-Type': 'application/json',
51
+ },
52
+ method: 'POST',
53
+ body: {
54
+ user: 1,
55
+ },
56
+ signal: abortController.signal,
57
+ });
58
+ const data = await resp.json();
59
+ return data['identifier'] ?? '';
60
+ }
package/src/routes.json CHANGED
@@ -23,6 +23,24 @@
23
23
  "slot": "dha-workflow-slot",
24
24
  "online": true,
25
25
  "offline": true
26
+ },
27
+ {
28
+ "name": "metrics-card-patients-in-waiting",
29
+ "component": "waitingPatientsExtension",
30
+ "slot": "clinic-metrics-slot",
31
+ "order": 1
32
+ },
33
+ {
34
+ "name": "metrics-card-patients-attended-to",
35
+ "component": "attendedToPatientsExtension",
36
+ "slot": "clinic-metrics-slot",
37
+ "order": 2
38
+ }
39
+ ],
40
+ "modals": [
41
+ {
42
+ "name": "sign-off-queue-entry-modal",
43
+ "component": "signOffModal"
26
44
  }
27
45
  ]
28
46
  }
@@ -0,0 +1,62 @@
1
+ import { type Encounter, formatDate, openmrsFetch, parseDate, restBaseUrl } from "@openmrs/esm-framework";
2
+ import { type Identifer, type MappedEncounter, type MappedVisitQueueEntry, type QueueEntry } from "../types/types";
3
+ import dayjs from "dayjs";
4
+
5
+ export function serveQueueEntry(servicePointName: string, ticketNumber: string, status: string) {
6
+ const abortController = new AbortController();
7
+
8
+ return openmrsFetch(`${restBaseUrl}/queueutil/assignticket`, {
9
+ method: 'POST',
10
+ headers: {
11
+ 'Content-Type': 'application/json',
12
+ },
13
+ signal: abortController.signal,
14
+ body: {
15
+ servicePointName,
16
+ ticketNumber,
17
+ status,
18
+ },
19
+ });
20
+ }
21
+
22
+ const mapEncounterProperties = (encounter: Encounter): MappedEncounter => ({
23
+ diagnoses: encounter.diagnoses,
24
+ encounterDatetime: encounter.encounterDatetime,
25
+ encounterType: encounter.encounterType.display,
26
+ obs: encounter.obs,
27
+ provider: encounter.encounterProviders[0]?.provider?.person?.display,
28
+ uuid: encounter.uuid,
29
+ voided: encounter.voided,
30
+ });
31
+
32
+ export const mapVisitQueueEntryProperties = (
33
+ queueEntry: QueueEntry,
34
+ visitQueueNumberAttributeUuid: string,
35
+ ): MappedVisitQueueEntry => ({
36
+ id: queueEntry.uuid,
37
+ encounters: queueEntry.visit?.encounters?.map(mapEncounterProperties),
38
+ name: queueEntry.display,
39
+ patientUuid: queueEntry.patient.uuid,
40
+ patientAge: queueEntry.patient.person?.age + '',
41
+ patientDob: queueEntry?.patient?.person?.birthdate
42
+ ? formatDate(parseDate(queueEntry.patient.person.birthdate), { time: false })
43
+ : '--',
44
+ patientGender: queueEntry.patient.person.gender,
45
+ queue: queueEntry.queue,
46
+ priority: queueEntry.priority,
47
+ priorityComment: queueEntry.priorityComment,
48
+ status: queueEntry.status,
49
+ startedAt: dayjs(queueEntry.startedAt).toDate(),
50
+ endedAt: queueEntry.endedAt ? dayjs(queueEntry.endedAt).toDate() : null,
51
+ visitType: queueEntry.visit?.visitType?.display,
52
+ queueLocation: (queueEntry?.queue as any)?.location?.uuid,
53
+ visitTypeUuid: queueEntry.visit?.visitType?.uuid,
54
+ visitUuid: queueEntry.visit?.uuid,
55
+ queueUuid: queueEntry.queue.uuid,
56
+ queueEntryUuid: queueEntry.uuid,
57
+ sortWeight: queueEntry.sortWeight,
58
+ visitQueueNumber: queueEntry.visit?.attributes?.find((e) => e?.attributeType?.uuid === visitQueueNumberAttributeUuid)
59
+ ?.value,
60
+ identifiers: queueEntry.patient?.identifiers as Identifer[],
61
+ queueComingFrom: queueEntry?.queueComingFrom?.name,
62
+ });
@@ -0,0 +1,29 @@
1
+ const SEPARATED_UUID = 'a899aba0-1350-11df-a1f1-0026b9348838';
2
+ const NEVER_MARRIED_UUID = 'a899ac7c-1350-11df-a1f1-0026b9348838';
3
+ const DIVORCED_UUID = 'a899ad58-1350-11df-a1f1-0026b9348838';
4
+ const WIDOWED_UUID = 'a899ae34-1350-11df-a1f1-0026b9348838';
5
+ const MARRIED_UUID = 'a8aa76b0-1350-11df-a1f1-0026b9348838';
6
+ const LIVING_WITH_PARTNER_UUID = 'a899af10-1350-11df-a1f1-0026b9348838';
7
+ const FRIEND_UUID = 'a8aaf07c-1350-11df-a1f1-0026b9348838';
8
+ const NOT_APPLICABLE_UUID = 'a89ad3a4-1350-11df-a1f1-0026b9348838';
9
+ const POLYGAMOUS_UUID = 'a8b03712-1350-11df-a1f1-0026b9348838';
10
+ const PARTNER_UUID = 'a89ebd3e-1350-11df-a1f1-0026b9348838';
11
+ const CASUAL_SEX_PARTNER_UUID = '7831f002-331d-4f07-bf91-6bb65cd31050';
12
+ const OTHER_UUID = 'a8aaf3e2-1350-11df-a1f1-0026b9348838';
13
+ const SINGLE_UUID = 'a899ac7c-1350-11df-a1f1-0026b9348838';
14
+
15
+ export const CivilStatusUids = {
16
+ SEPARATED_UUID,
17
+ NEVER_MARRIED_UUID,
18
+ DIVORCED_UUID,
19
+ WIDOWED_UUID,
20
+ MARRIED_UUID,
21
+ LIVING_WITH_PARTNER_UUID,
22
+ FRIEND_UUID,
23
+ NOT_APPLICABLE_UUID,
24
+ POLYGAMOUS_UUID,
25
+ PARTNER_UUID,
26
+ CASUAL_SEX_PARTNER_UUID,
27
+ SINGLE_UUID,
28
+ OTHER_UUID,
29
+ };
@@ -0,0 +1,33 @@
1
+ const CONTACT_PHONE_NUMBER_UUID = '72a759a8-1359-11df-a1f1-0026b9348838';
2
+ const CITIZENSHIP_UUID = '8d871afc-c2cc-11de-8d13-0010c6dffd0f';
3
+ const CONTACT_EMAIL_ADDRESS_UUID = '2f65dbcb-3e58-45a3-8be7-fd1dc9aa0faa';
4
+ const ALTERNATIVE_CONTACT_PHONE_NUMBER_UUID = 'c725f524-c14a-4468-ac19-4a0e6661c930';
5
+ const KRA_PIN_UUID = 'ae683747-b3fc-4e5c-bad3-c3be743b248f';
6
+ const CIVIL_STATUS_UUID = '8d871f2a-c2cc-11de-8d13-0010c6dffd0f';
7
+ const CLIENT_REGISTRY_ID_UUID = 'e068e02b-faac-4baf-bd58-fe6e0c29a81f';
8
+ const PLACE_OF_BIRTH_UUID = '8d8718c2-c2cc-11de-8d13-0010c6dffd0f';
9
+ const EMAIL_UUID = '2f65dbcb-3e58-45a3-8be7-fd1dc9aa0faa';
10
+ const HIGHEST_LEVEL_OF_EDUCATION_UUID = '352b0d51-63c6-47d0-a295-156bebee4fd5';
11
+ const RELIGION_UUID = '4ae16101-cfba-4c08-9c9c-d848e6f609aa';
12
+ const OCCUPATION_UUID = '9e86409f-9c20-42d0-aeb3-f29a4ca0a7a0';
13
+ const NEXT_OF_KIN_CONTACT_PHONE_NUMBER_UUID = 'a657a4f1-9c0f-444b-a1fd-445bb91dd12d';
14
+ const NEXT_OF_KIN_NAME_UUID = '72a75bec-1359-11df-a1f1-0026b9348838';
15
+ const NEXT_OF_KIN_RELATIONSHIP_UUID = '5730994e-c267-426b-87b6-c152b606973d';
16
+
17
+ export const PersonAttributeTypeUuids = {
18
+ CONTACT_PHONE_NUMBER_UUID,
19
+ CITIZENSHIP_UUID,
20
+ CONTACT_EMAIL_ADDRESS_UUID,
21
+ ALTERNATIVE_CONTACT_PHONE_NUMBER_UUID,
22
+ KRA_PIN_UUID,
23
+ CIVIL_STATUS_UUID,
24
+ CLIENT_REGISTRY_ID_UUID,
25
+ PLACE_OF_BIRTH_UUID,
26
+ EMAIL_UUID,
27
+ HIGHEST_LEVEL_OF_EDUCATION_UUID,
28
+ RELIGION_UUID,
29
+ OCCUPATION_UUID,
30
+ NEXT_OF_KIN_CONTACT_PHONE_NUMBER_UUID,
31
+ NEXT_OF_KIN_NAME_UUID,
32
+ NEXT_OF_KIN_RELATIONSHIP_UUID,
33
+ };
@@ -0,0 +1,100 @@
1
+ import { type Visit, type Concept, type Patient, type OpenmrsResource, type Obs, type FetchResponse } from "@openmrs/esm-framework";
2
+
3
+ export interface QueueEntry {
4
+ uuid: string;
5
+ display: string;
6
+ endedAt: string;
7
+ locationWaitingFor: Location;
8
+ patient: Patient;
9
+ priority: Concept;
10
+ priorityComment: string | null;
11
+ providerWaitingFor: Provider;
12
+ queue: Queue;
13
+ startedAt: string;
14
+ status: Concept;
15
+ visit: Visit;
16
+ sortWeight: number;
17
+ queueComingFrom: Queue;
18
+ previousQueueEntry: QueueEntry;
19
+ }
20
+
21
+ export interface Provider {
22
+ uuid: string;
23
+ display: string;
24
+ comments: string;
25
+ response?: string;
26
+ person: OpenmrsResource;
27
+ location: string;
28
+ serviceType: string;
29
+ }
30
+
31
+ export interface Queue {
32
+ uuid: string;
33
+ display: string;
34
+ name: string;
35
+ description: string;
36
+ location: Location;
37
+ service: Concept;
38
+ allowedPriorities: Array<Concept>;
39
+ allowedStatuses: Array<Concept>;
40
+ }
41
+
42
+ export interface Identifer {
43
+ identifier: string;
44
+ display: string;
45
+ uuid: string;
46
+ identifierType: {
47
+ uuid: string;
48
+ display: string;
49
+ };
50
+ }
51
+
52
+ interface Encounter {
53
+ diagnoses?: Array<any>;
54
+ encounterDatetime?: string;
55
+ encounterProviders?: Array<{ provider?: { person?: { display?: string } } }>;
56
+ encounterType?: { display: string; uuid: string };
57
+ obs?: Array<Obs>;
58
+ uuid: string;
59
+ voided?: boolean;
60
+ }
61
+
62
+ export interface MappedEncounter extends Omit<Encounter, 'encounterType' | 'provider'> {
63
+ encounterType: string;
64
+ provider: string;
65
+ }
66
+
67
+ export interface MappedVisitQueueEntry {
68
+ id: string;
69
+ encounters: Array<MappedEncounter>;
70
+ name: string;
71
+ patientAge: string;
72
+ patientDob: string;
73
+ patientGender: string;
74
+ patientUuid: string;
75
+ queue: Queue;
76
+ priority: Concept;
77
+ priorityComment: string;
78
+ status: Concept;
79
+ startedAt: Date;
80
+ endedAt: Date;
81
+ visitType: string;
82
+ visitUuid: string;
83
+ visitTypeUuid: string;
84
+ queueUuid: string;
85
+ queueEntryUuid: string;
86
+ queueLocation: string;
87
+ sortWeight: number;
88
+ visitQueueNumber: string;
89
+ identifiers: Array<Identifer>;
90
+ queueComingFrom: string;
91
+ }
92
+
93
+ export type QueueEntryResponse = FetchResponse<{
94
+ results: Array<QueueEntry>;
95
+ links: Array<{
96
+ rel: 'prev' | 'next';
97
+ uri: string;
98
+ }>;
99
+ totalCount: number;
100
+ }>;