@kenyaemr/esm-patient-clinical-view-app 5.4.1-pre.2075 → 5.4.1-pre.2083

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"clinical-view-section","component":"clinicalViewPatientDashboard","slot":"patient-chart-dashboard-slot"},{"name":"family-history","slot":"patient-chart-family-history-slot","component":"familyHistory","order":0,"online":true,"offline":false},{"name":"other-relationships","slot":"patient-chart-family-history-slot","component":"otherRelationships","order":0,"online":true,"offline":false},{"name":"relationships-link","component":"relationshipsLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationships-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationships","slot":"patient-chart-relationships-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"contact-list-form","component":"contactListForm"},{"name":"maternal-and-child-health-dashboard-group-link","slot":"clinical-view-section","component":"maternalAndChildHealthSideNavGroup"},{"name":"antenatal-care-dashboard-link","component":"antenatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-antenatal-care-dashboard-slot","path":"antenatal-care-dashboard","layoutMode":"anchored"}},{"name":"antenatal-care-dashboard","slot":"patient-chart-antenatal-care-dashboard-slot","component":"antenatalCare"},{"name":"postnatal-care-dashboard-link","component":"postnatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-postnatal-care-dashboard-slot","path":"postnatal-care-dashboard","layoutMode":"anchored"}},{"name":"postnatal-care-dashboard","slot":"patient-chart-postnatal-care-dashboard-slot","component":"postnatalCare"},{"name":"labour-and-delivery-dashboard-link","component":"labourAndDeliveryLink","slot":"maternal-and-child-health-slot","meta":{"fullWidth":true,"slot":"patient-chart-labour-and-delivery-dashboard-slot","path":"labour-and-delivery-dashboard","layoutMode":"anchored"}},{"name":"labour-and-delivery-dashboard","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"labourAndDelivery","meta":{"fullWidth":true}},{"name":"hiv-care-and-treatment-dashboard-group-link","slot":"special-clinics-slot","component":"hivCareAndTreatMentSideNavGroup"},{"name":"genericNavLinks","slot":"special-clinics-slot","component":"genericNavLinks","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinic-dashboard-slot","path":"special-clinics-dashboard","layoutMode":"anchored"}},{"name":"patient-chart-special-clinic-dashboard-slot","slot":"patient-chart-special-clinic-dashboard-slot","component":"genericDashboard"},{"name":"hts-dashboard-link","component":"htsDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hts-dashboard-slot","path":"hts-dashboard","layoutMode":"anchored"}},{"name":"hts-clinical-view","slot":"patient-chart-hts-dashboard-slot","component":"htsClinicalView","order":2,"online":true,"offline":false},{"name":"defaulter-tracing-dashboard-link","component":"defaulterTracingLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-defaulter-tracing-dashboard-slot","path":"defaulter-tracing-dashboard","layoutMode":"anchored"}},{"name":"defaulter-tracing-dashboard","slot":"patient-chart-defaulter-tracing-dashboard-slot","component":"defaulterTracing","order":3,"online":true,"offline":false},{"name":"special-clinics-dashboard-group-link","slot":"clinical-view-section","component":"specialClinicsSideNavGroup"},{"name":"clinical-encounter-link","component":"inPatientClinicalEncounterLink","slot":"clinical-view-section","order":40,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter","slot":"patient-chart-clinical-encounter-slot","component":"inPatientClinicalEncounter","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"in-patient-dashboard-link","component":"inPatientChartLink","slot":"patient-chart-dashboard-slot","order":7,"meta":{"slot":"patient-chart-in-patient-dashboard-slot","path":"in-patient","layoutMode":"anchored","columns":1,"columnSpan":1}},{"name":"in-patient-dashboard","slot":"patient-chart-in-patient-dashboard-slot","component":"inPatientChartDashboard","meta":{"fullWidth":false}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"deceased-panel-dashboard-link","component":"deceasedPanelDashboardLink","slot":"patient-chart-dashboard-slot","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-deceased-panel-slot","path":"deceased-panel","layoutMode":"anchored"}},{"name":"deceased-details-tabs","slot":"patient-chart-deceased-panel-slot","component":"deceasedDetailsTabs","order":0,"online":true,"offline":false},{"name":"parto-graph-chart","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"partograph","meta":{"fullWidth":true}}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"peer-calendar-form","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"relationship-update-form","component":"relationshipUpdateForm","title":"Relationship Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.1-pre.2075"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"kenyaemr":"^19.0.0"},"pages":[],"extensions":[{"name":"clinical-view-section","component":"clinicalViewPatientDashboard","slot":"patient-chart-dashboard-slot"},{"name":"family-history","slot":"patient-chart-family-history-slot","component":"familyHistory","order":0,"online":true,"offline":false},{"name":"other-relationships","slot":"patient-chart-family-history-slot","component":"otherRelationships","order":0,"online":true,"offline":false},{"name":"relationships-link","component":"relationshipsLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-relationships-slot","path":"relationships","layoutMode":"anchored"}},{"name":"relationships","slot":"patient-chart-relationships-slot","component":"relationships","order":0,"online":true,"offline":false},{"name":"contact-list-form","component":"contactListForm"},{"name":"maternal-and-child-health-dashboard-group-link","slot":"clinical-view-section","component":"maternalAndChildHealthSideNavGroup"},{"name":"antenatal-care-dashboard-link","component":"antenatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-antenatal-care-dashboard-slot","path":"antenatal-care-dashboard","layoutMode":"anchored"}},{"name":"antenatal-care-dashboard","slot":"patient-chart-antenatal-care-dashboard-slot","component":"antenatalCare"},{"name":"postnatal-care-dashboard-link","component":"postnatalCareLink","slot":"maternal-and-child-health-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-postnatal-care-dashboard-slot","path":"postnatal-care-dashboard","layoutMode":"anchored"}},{"name":"postnatal-care-dashboard","slot":"patient-chart-postnatal-care-dashboard-slot","component":"postnatalCare"},{"name":"labour-and-delivery-dashboard-link","component":"labourAndDeliveryLink","slot":"maternal-and-child-health-slot","meta":{"fullWidth":true,"slot":"patient-chart-labour-and-delivery-dashboard-slot","path":"labour-and-delivery-dashboard","layoutMode":"anchored"}},{"name":"labour-and-delivery-dashboard","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"labourAndDelivery","meta":{"fullWidth":true}},{"name":"hiv-care-and-treatment-dashboard-group-link","slot":"special-clinics-slot","component":"hivCareAndTreatMentSideNavGroup"},{"name":"genericNavLinks","slot":"special-clinics-slot","component":"genericNavLinks","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-special-clinic-dashboard-slot","path":"special-clinics-dashboard","layoutMode":"anchored"}},{"name":"patient-chart-special-clinic-dashboard-slot","slot":"patient-chart-special-clinic-dashboard-slot","component":"genericDashboard"},{"name":"hts-dashboard-link","component":"htsDashboardLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-hts-dashboard-slot","path":"hts-dashboard","layoutMode":"anchored"}},{"name":"hts-clinical-view","slot":"patient-chart-hts-dashboard-slot","component":"htsClinicalView","order":2,"online":true,"offline":false},{"name":"defaulter-tracing-dashboard-link","component":"defaulterTracingLink","slot":"hiv-care-and-treatment-slot","meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-defaulter-tracing-dashboard-slot","path":"defaulter-tracing-dashboard","layoutMode":"anchored"}},{"name":"defaulter-tracing-dashboard","slot":"patient-chart-defaulter-tracing-dashboard-slot","component":"defaulterTracing","order":3,"online":true,"offline":false},{"name":"special-clinics-dashboard-group-link","slot":"clinical-view-section","component":"specialClinicsSideNavGroup"},{"name":"clinical-encounter-link","component":"inPatientClinicalEncounterLink","slot":"clinical-view-section","order":40,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-clinical-encounter-slot","path":"clinical-encounter","layoutMode":"anchored"}},{"name":"clinical-encounter","slot":"patient-chart-clinical-encounter-slot","component":"inPatientClinicalEncounter","order":0,"online":true,"offline":false},{"component":"caseManagementDashboardLink","name":"case-management-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"case-management","title":"Case Management","slot":"case-management-dashboard-slot","path":"/case-management"}},{"name":"in-patient-dashboard-link","component":"inPatientChartLink","slot":"patient-chart-dashboard-slot","order":7,"meta":{"slot":"patient-chart-in-patient-dashboard-slot","path":"in-patient","layoutMode":"anchored","columns":1,"columnSpan":1}},{"name":"in-patient-dashboard","slot":"patient-chart-in-patient-dashboard-slot","component":"inPatientChartDashboard","meta":{"fullWidth":false}},{"name":"wrap-component-view","slot":"case-management-dashboard-slot","component":"wrapComponent","order":2,"online":true,"offline":false},{"name":"case-encounter-link","component":"caseEncounterDashboardLink","slot":"patient-chart-dashboard-slot","order":14,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-case-encounter-slot","path":"case-management-encounters","layoutMode":"anchored"}},{"name":"case-encounter-table","slot":"patient-chart-case-encounter-slot","component":"caseEncounterTable","order":0,"online":true,"offline":false},{"component":"peerCalendarDashboardLink","name":"peer-calendar-dashboard-link","slot":"homepage-dashboard-slot","meta":{"name":"peer-calendar","title":"Peer Calendar","slot":"peer-calendar-dashboard-slot","path":"peer-management"}},{"name":"peer-calendar","slot":"peer-calendar-dashboard-slot","component":"peerCalendar","order":0,"online":true,"offline":false},{"name":"deceased-panel-dashboard-link","component":"deceasedPanelDashboardLink","slot":"patient-chart-dashboard-slot","order":15,"meta":{"columns":1,"columnSpan":1,"slot":"patient-chart-deceased-panel-slot","path":"deceased-panel","layoutMode":"anchored"}},{"name":"deceased-details-tabs","slot":"patient-chart-deceased-panel-slot","component":"deceasedDetailsTabs","order":0,"online":true,"offline":false},{"name":"parto-graph-chart","slot":"patient-chart-labour-and-delivery-dashboard-slot","component":"partograph","meta":{"fullWidth":true}}],"modals":[{"name":"birth-date-calculator","component":"birthDateCalculator"},{"name":"relationship-delete-confirm-dialog","component":"relationshipDeleteConfirmialog"},{"name":"end-relationship-dialog","component":"endRelationshipModal"}],"workspaces":[{"name":"case-management-form","component":"caseManagementForm","title":"Case Management Form","type":"form"},{"name":"family-relationship-form","component":"familyRelationshipForm","title":"Family Relationship Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"peers-form","component":"peersForm","title":"Add New Peer","type":"form"},{"name":"kenyaemr-cusom-form-entry-workspace","component":"peerCalendarFormEntry","title":"KVP Peer Educator Outreach Calendar","type":"form","width":"extra-wide","canMaximize":true,"canHide":true},{"name":"relationship-update-form","component":"relationshipUpdateForm","title":"Relationship Update Form","type":"form"},{"name":"other-relationship-form","component":"otherRelationshipsForm","title":"Other Relationships Form","type":"form"},{"name":"end-relationship-form","component":"endRelationshipWorkspace","title":"Discontinue relationship form","type":"form"}],"version":"5.4.1-pre.2083"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kenyaemr/esm-patient-clinical-view-app",
3
- "version": "5.4.1-pre.2075",
3
+ "version": "5.4.1-pre.2083",
4
4
  "description": "Patient clinical view microfrontend for the OpenMRS SPA",
5
5
  "browser": "dist/kenyaemr-esm-patient-clinical-view-app.js",
6
6
  "main": "src/index.ts",
@@ -9,6 +9,7 @@ export const configSchema = {
9
9
  mchMotherConsultation: 'c6d09e05-1f25-4164-8860-9f32c5a02df0',
10
10
  hivTestingServices: '9c0a7a57-62ff-4f75-babe-5835b0e921b7',
11
11
  kpPeerCalender: 'c4f9db39-2c18-49a6-bf9b-b243d673c64d',
12
+ htsEcounterUuid: '9c0a7a57-62ff-4f75-babe-5835b0e921b7', // Used with Contact tracing
12
13
  },
13
14
  },
14
15
  caseManagementForms: {
@@ -45,6 +46,17 @@ export const configSchema = {
45
46
  clinicalEncounterFormUuid: 'e958f902-64df-4819-afd4-7fb061f59308',
46
47
  peerCalendarOutreactForm: '7492cffe-5874-4144-a1e6-c9e455472a35',
47
48
  autopsyFormUuid: '2b61a73-4971-4fc0-b20b-9a30176317e2',
49
+ htsClientTracingFormUuid: '15ed03d2-c972-11e9-a32f-2a2ae2dbcce4',
50
+ },
51
+ },
52
+ htsClientTracingConceptsUuids: {
53
+ _type: Type.Object,
54
+ _description: 'Concept Uuids for hts client tracing',
55
+ _default: {
56
+ modeOfClienttracingConceptUuid: 'a55f9516-ddb6-47ec-b10d-cb99d1d0bd41',
57
+ reasonNotContactedConceptUuid: '1779AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
58
+ tracingStatusConceptUuid: '159811AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
59
+ remarksConceptUuid: '163042AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
48
60
  },
49
61
  },
50
62
  defaulterTracingEncounterUuid: {
@@ -166,45 +178,54 @@ export const configSchema = {
166
178
  contactIPVOutcome: '49c543c2-a72a-4b0a-8cca-39c375c0726f',
167
179
  },
168
180
  },
169
- familyRelationshipsTypeList: {
181
+ relationshipTypesList: {
170
182
  _type: Type.Array,
171
- _description: 'List of Family relationship types (Used to list contacts)',
183
+ _description: 'List of Categorized relationship types',
172
184
  _default: [
173
185
  {
174
186
  uuid: '8d91a01c-c2cc-11de-8d13-0010c6dffd0f',
175
187
  display: 'Sibling/Sibling',
188
+ category: ['family'],
176
189
  },
177
190
  {
178
191
  uuid: '8d91a210-c2cc-11de-8d13-0010c6dffd0f',
179
192
  display: 'Parent/Child',
193
+ category: ['family'],
180
194
  },
181
195
  {
182
196
  uuid: '8d91a3dc-c2cc-11de-8d13-0010c6dffd0f',
183
197
  display: 'Aunt/Uncle/Niece/Nephew',
198
+ category: ['family'],
184
199
  },
185
200
  {
186
201
  uuid: '5f115f62-68b7-11e3-94ee-6bef9086de92',
187
202
  display: 'Guardian/Dependant',
203
+ category: ['other'],
188
204
  },
189
205
  {
190
206
  uuid: 'd6895098-5d8d-11e3-94ee-b35a4132a5e3',
191
207
  display: 'Spouse/Spouse',
208
+ category: ['sexual', 'pns', 'family'],
192
209
  },
193
210
  {
194
211
  uuid: '007b765f-6725-4ae9-afee-9966302bace4',
195
212
  display: 'Partner/Partner',
213
+ category: ['sexual', 'pns'],
196
214
  },
197
215
  {
198
216
  uuid: '2ac0d501-eadc-4624-b982-563c70035d46',
199
217
  display: 'Co-wife/Co-wife',
218
+ category: ['pns'],
200
219
  },
201
220
  {
202
221
  uuid: '58da0d1e-9c89-42e9-9412-275cef1e0429',
203
222
  display: 'Injectable-drug-user/Injectable-druguser',
223
+ category: ['pns'],
204
224
  },
205
225
  {
206
226
  uuid: '76edc1fe-c5ce-4608-b326-c8ecd1020a73',
207
227
  display: 'SNS/SNS',
228
+ category: ['other'],
208
229
  },
209
230
  ],
210
231
  },
@@ -213,32 +234,6 @@ export const configSchema = {
213
234
  _description: 'Peer Educator Relationship type',
214
235
  _default: '96adecc2-e7cd-41d0-b577-08eb4834abcb',
215
236
  },
216
- pnsRelationships: {
217
- _type: Type.Array,
218
- _description: 'List of Patner relationship (PNS - Patner Notification Service)',
219
- _default: [
220
- {
221
- uuid: 'd6895098-5d8d-11e3-94ee-b35a4132a5e3',
222
- display: 'Spouse/Spouse',
223
- sexual: true,
224
- },
225
- {
226
- uuid: '007b765f-6725-4ae9-afee-9966302bace4',
227
- display: 'Partner/Partner',
228
- sexual: true,
229
- },
230
- {
231
- uuid: '2ac0d501-eadc-4624-b982-563c70035d46',
232
- display: 'Co-wife/Co-wife',
233
- sexual: false,
234
- },
235
- {
236
- uuid: '58da0d1e-9c89-42e9-9412-275cef1e0429',
237
- display: 'Injectable-drug-user/Injectable-druguser',
238
- sexual: false,
239
- },
240
- ],
241
- },
242
237
  admissionLocationTagUuid: {
243
238
  _type: Type.UUID,
244
239
  _description:
@@ -290,7 +285,18 @@ export interface ConfigObject {
290
285
  morgueDischargeEncounterUuid: string;
291
286
  caseManagementForms: Array<{ id: string; title: string; formUuid: string; encounterTypeUuid: string }>;
292
287
  peerCalendarOutreactForm: string;
293
- encounterTypes: { mchMotherConsultation: string; hivTestingServices: string; kpPeerCalender: string };
288
+ htsClientTracingConceptsUuids: {
289
+ modeOfClienttracingConceptUuid: string;
290
+ reasonNotContactedConceptUuid: string;
291
+ tracingStatusConceptUuid: string;
292
+ remarksConceptUuid: string;
293
+ };
294
+ encounterTypes: {
295
+ mchMotherConsultation: string;
296
+ hivTestingServices: string;
297
+ kpPeerCalender: string;
298
+ htsEcounterUuid: string;
299
+ };
294
300
  formsList: {
295
301
  labourAndDelivery: string;
296
302
  antenatal: string;
@@ -302,6 +308,7 @@ export interface ConfigObject {
302
308
  clinicalEncounterFormUuid: string;
303
309
  peerCalendarOutreactForm: string;
304
310
  autopsyFormUuid: string;
311
+ htsClientTracingFormUuid: string;
305
312
  };
306
313
  defaulterTracingEncounterUuid: string;
307
314
  autopsyEncounterFormUuid: string;
@@ -327,8 +334,11 @@ export interface ConfigObject {
327
334
  livingWithContact: string;
328
335
  contactIPVOutcome: string;
329
336
  };
330
- familyRelationshipsTypeList: Array<{ uuid: string; display: string }>;
331
- pnsRelationships: Array<{ uuid: string; display: string; sexual: boolean }>;
337
+ relationshipTypesList: Array<{
338
+ uuid: string;
339
+ display: string;
340
+ category: Array<'sexual' | 'pns' | 'family' | 'other'>;
341
+ }>;
332
342
  admissionLocationTagUuid: {
333
343
  _type: Type.UUID;
334
344
  _description: 'UUID for the location tag of the `Admission Location`. Patients may only be admitted to inpatient care in a location with this tag';
@@ -3,17 +3,22 @@ import {
3
3
  DataTable,
4
4
  DataTableSkeleton,
5
5
  Layer,
6
+ OverflowMenu,
7
+ OverflowMenuItem,
6
8
  Pagination,
7
9
  Table,
8
10
  TableBody,
9
11
  TableCell,
10
12
  TableContainer,
13
+ TableExpandedRow,
14
+ TableExpandHeader,
15
+ TableExpandRow,
11
16
  TableHead,
12
17
  TableHeader,
13
18
  TableRow,
14
19
  Tile,
15
20
  } from '@carbon/react';
16
- import { Add, Edit, TrashCan } from '@carbon/react/icons';
21
+ import { Add } from '@carbon/react/icons';
17
22
  import {
18
23
  ConfigurableLink,
19
24
  ErrorState,
@@ -26,10 +31,13 @@ import {
26
31
  import { CardHeader, EmptyDataIllustration, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
27
32
  import React, { useState } from 'react';
28
33
  import { useTranslation } from 'react-i18next';
34
+ import { mutate } from 'swr';
35
+ import { ConfigObject } from '../config-schema';
29
36
  import useContacts from '../hooks/useContacts';
37
+ import { deleteRelationship } from '../relationships/relationship.resources';
30
38
  import styles from './contact-list.scss';
39
+ import ContactTracingHistory from './contact-tracing-history.component';
31
40
  import HIVStatus from './hiv-status.component';
32
- import { deleteRelationship } from '../relationships/relationship.resources';
33
41
 
34
42
  interface ContactListProps {
35
43
  patientUuid: string;
@@ -40,11 +48,13 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
40
48
  const [pageSize, setPageSize] = useState(10);
41
49
  const headerTitle = t('contactList', 'Contact list');
42
50
  const layout = useLayoutType();
43
-
51
+ const size = layout === 'tablet' ? 'lg' : 'md';
44
52
  const { contacts, error, isLoading } = useContacts(patientUuid);
45
53
  const { results, totalPages, currentPage, goTo } = usePagination(contacts, pageSize);
46
54
  const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, results.length);
47
-
55
+ const {
56
+ formsList: { htsClientTracingFormUuid },
57
+ } = useConfig<ConfigObject>();
48
58
  const headers = [
49
59
  {
50
60
  header: t('listingDate', 'Listing date'),
@@ -104,6 +114,19 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
104
114
  });
105
115
  };
106
116
 
117
+ const handleLaunchContactTracingForm = (contactUuid: string) => {
118
+ launchWorkspace('kenyaemr-cusom-form-entry-workspace', {
119
+ formUuid: htsClientTracingFormUuid,
120
+ patientUuid: contactUuid,
121
+ encounterUuid: '',
122
+ mutateForm: () => {
123
+ mutate((key) => true, undefined, {
124
+ revalidate: true,
125
+ });
126
+ },
127
+ });
128
+ };
129
+
107
130
  const handleEditRelationship = (relationShipUuid: string) => {
108
131
  launchWorkspace('relationship-update-form', {
109
132
  relationShipUuid,
@@ -137,20 +160,14 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
137
160
  ipvOutcome: relation.ipvOutcome ?? '--',
138
161
  actions: (
139
162
  <>
140
- <Button
141
- renderIcon={Edit}
142
- hasIconOnly
143
- kind="ghost"
144
- iconDescription="Edit"
145
- onClick={() => handleEditRelationship(relation.uuid)}
146
- />
147
- <Button
148
- renderIcon={TrashCan}
149
- hasIconOnly
150
- kind="ghost"
151
- iconDescription="Delete"
152
- onClick={() => deleteRelationship(relation.uuid)}
153
- />
163
+ <OverflowMenu size={size} flipped>
164
+ <OverflowMenuItem itemText={t('edit', 'Edit')} onClick={() => handleEditRelationship(relation.uuid)} />
165
+ <OverflowMenuItem
166
+ itemText={t('traceContact', 'Trace Contact')}
167
+ onClick={() => handleLaunchContactTracingForm(patientUuid)}
168
+ />
169
+ <OverflowMenuItem itemText={t('delete', 'Delete')} onClick={() => deleteRelationship(relation.uuid)} />
170
+ </OverflowMenu>
154
171
  </>
155
172
  ),
156
173
  };
@@ -191,11 +208,20 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
191
208
  <DataTable
192
209
  rows={tableRows ?? []}
193
210
  headers={headers}
194
- render={({ rows, headers, getHeaderProps, getTableProps, getTableContainerProps }) => (
211
+ render={({
212
+ rows,
213
+ headers,
214
+ getHeaderProps,
215
+ getTableProps,
216
+ getTableContainerProps,
217
+ getRowProps,
218
+ getExpandedRowProps,
219
+ }) => (
195
220
  <TableContainer {...getTableContainerProps()}>
196
221
  <Table {...getTableProps()}>
197
222
  <TableHead>
198
223
  <TableRow>
224
+ <TableExpandHeader aria-label="expand row" />
199
225
  {headers.map((header) => (
200
226
  <TableHeader
201
227
  {...getHeaderProps({
@@ -209,11 +235,25 @@ const ContactList: React.FC<ContactListProps> = ({ patientUuid }) => {
209
235
  </TableHead>
210
236
  <TableBody>
211
237
  {rows.map((row) => (
212
- <TableRow key={row.id}>
213
- {row.cells.map((cell) => (
214
- <TableCell key={cell.id}>{cell.value}</TableCell>
215
- ))}
216
- </TableRow>
238
+ <React.Fragment key={row.id}>
239
+ <TableExpandRow
240
+ {...getRowProps({
241
+ row,
242
+ })}>
243
+ {row.cells.map((cell) => (
244
+ <TableCell key={cell.id}>{cell.value}</TableCell>
245
+ ))}
246
+ </TableExpandRow>
247
+
248
+ <TableExpandedRow
249
+ colSpan={headers.length + 1}
250
+ className="demo-expanded-td"
251
+ {...getExpandedRowProps({
252
+ row,
253
+ })}>
254
+ <ContactTracingHistory patientUuid={results.find((r) => r.uuid === row.id)?.patientUuid} />
255
+ </TableExpandedRow>
256
+ </React.Fragment>
217
257
  ))}
218
258
  </TableBody>
219
259
  </Table>
@@ -59,8 +59,12 @@ const ContactListForm: React.FC<ContactListFormProps> = ({
59
59
 
60
60
  const config = useConfig<ConfigObject>();
61
61
  const { data } = useMappedRelationshipTypes();
62
+ const pnsRelationships = useMemo(
63
+ () => config.relationshipTypesList.filter((rl) => rl.category.some((c) => c === 'pns')),
64
+ [config],
65
+ );
62
66
  const pnsRelationshipTypes = data
63
- ? config.pnsRelationships.map((rel) => ({
67
+ ? pnsRelationships.map((rel) => ({
64
68
  ...rel,
65
69
  display: data!.find((r) => r.uuid === rel.uuid)?.display,
66
70
  }))
@@ -106,7 +110,8 @@ const ContactListForm: React.FC<ContactListFormProps> = ({
106
110
  const observableSexualAssault = form.watch('sexualAssault');
107
111
  const observableMode = form.watch('mode');
108
112
  const showIPVRelatedFields =
109
- config.pnsRelationships.findIndex((r) => r.uuid === observableRelationship && r.sexual) !== -1;
113
+ pnsRelationships.findIndex((r) => r.uuid === observableRelationship && r.category.some((c) => c === 'sexual')) !==
114
+ -1;
110
115
 
111
116
  useEffect(() => {
112
117
  if ([observablePhysicalAssault, observableThreatened, observableSexualAssault].includes(BOOLEAN_YES)) {
@@ -0,0 +1,158 @@
1
+ import {
2
+ Button,
3
+ DataTable,
4
+ Pagination,
5
+ Table,
6
+ TableBody,
7
+ TableCell,
8
+ TableContainer,
9
+ TableHead,
10
+ TableHeader,
11
+ TableRow,
12
+ } from '@carbon/react';
13
+ import { Edit } from '@carbon/react/icons';
14
+ import { launchWorkspace, useConfig, usePagination } from '@openmrs/esm-framework';
15
+ import { CardHeader, EmptyState, ErrorState } from '@openmrs/esm-patient-common-lib';
16
+ import React, { useMemo, useState } from 'react';
17
+ import { useTranslation } from 'react-i18next';
18
+ import { mutate } from 'swr';
19
+ import { ConfigObject } from '../config-schema';
20
+ import styles from './contact-list.scss';
21
+ import { PAGE_SIZE_OPTIONS, useContactTraceHistory } from './contact-tracing.resource';
22
+
23
+ type ContactTracingHistoryProps = {
24
+ patientUuid: string;
25
+ };
26
+
27
+ const ContactTracingHistory: React.FC<ContactTracingHistoryProps> = ({ patientUuid }) => {
28
+ const { t } = useTranslation();
29
+ const { contactTracesHistory, error, isLoading } = useContactTraceHistory(patientUuid);
30
+ const [pageSize, setPageSize] = useState(3);
31
+ const { results, totalPages, currentPage, goTo } = usePagination(contactTracesHistory, pageSize);
32
+ const {
33
+ formsList: { htsClientTracingFormUuid },
34
+ } = useConfig<ConfigObject>();
35
+
36
+ const handleLaunchContactTracingForm = (encounterUuid: string) => {
37
+ launchWorkspace('kenyaemr-cusom-form-entry-workspace', {
38
+ workspaceTitle: 'Contact tracing form',
39
+ formUuid: htsClientTracingFormUuid,
40
+ patientUuid,
41
+ encounterUuid,
42
+ mutateForm: () => {
43
+ mutate((key) => true, undefined, {
44
+ revalidate: true,
45
+ });
46
+ },
47
+ });
48
+ };
49
+
50
+ const headers = [
51
+ {
52
+ header: t('date', 'Date'),
53
+ key: 'date',
54
+ },
55
+ {
56
+ header: t('contactType', 'Contact Type'),
57
+ key: 'contactType',
58
+ },
59
+ {
60
+ header: t('status', 'Status'),
61
+ key: 'status',
62
+ },
63
+ {
64
+ header: t('reasonNotContacted', 'Reason Not Contacted'),
65
+ key: 'reasonNotContacted',
66
+ },
67
+ {
68
+ header: t('facilityLinkedTo', 'Facility Linked To'),
69
+ key: 'facilityLinkedTo',
70
+ },
71
+ {
72
+ header: t('remarks', 'Remarks'),
73
+ key: 'remarks',
74
+ },
75
+ {
76
+ header: t('actions', 'Actions'),
77
+ key: 'actions',
78
+ },
79
+ ];
80
+
81
+ const headerTitle = t('traceHistory', 'Trace History');
82
+ const tablerows = useMemo(
83
+ () =>
84
+ results.map((row) => ({
85
+ ...row,
86
+ id: row.encounterUuid,
87
+ actions: (
88
+ <Button
89
+ renderIcon={Edit}
90
+ hasIconOnly
91
+ kind="ghost"
92
+ iconDescription={t('editTracing', 'Edit tracing')}
93
+ onClick={() => handleLaunchContactTracingForm(row.encounterUuid)}
94
+ />
95
+ ),
96
+ })),
97
+ [results],
98
+ );
99
+
100
+ if (contactTracesHistory.length === 0) {
101
+ return <EmptyState headerTitle={headerTitle} displayText="tracing hosty" />;
102
+ }
103
+ if (error) {
104
+ return <ErrorState headerTitle={headerTitle} error={error} />;
105
+ }
106
+
107
+ return (
108
+ <div className={styles.widgetContainer}>
109
+ <CardHeader title={headerTitle}>
110
+ <></>
111
+ </CardHeader>
112
+ <DataTable
113
+ rows={tablerows ?? []}
114
+ headers={headers}
115
+ render={({ rows, headers, getHeaderProps, getTableProps, getTableContainerProps }) => (
116
+ <TableContainer {...getTableContainerProps()}>
117
+ <Table {...getTableProps()}>
118
+ <TableHead>
119
+ <TableRow>
120
+ {headers.map((header) => (
121
+ <TableHeader
122
+ {...getHeaderProps({
123
+ header,
124
+ isSortable: header.isSortable,
125
+ })}>
126
+ {header.header?.content ?? header.header}
127
+ </TableHeader>
128
+ ))}
129
+ </TableRow>
130
+ </TableHead>
131
+ <TableBody>
132
+ {rows.map((row) => (
133
+ <TableRow key={row.id}>
134
+ {row.cells.map((cell) => (
135
+ <TableCell key={cell.id}>{cell.value}</TableCell>
136
+ ))}
137
+ </TableRow>
138
+ ))}
139
+ </TableBody>
140
+ </Table>
141
+ </TableContainer>
142
+ )}
143
+ />
144
+ <Pagination
145
+ page={currentPage}
146
+ pageSize={pageSize}
147
+ pageSizes={PAGE_SIZE_OPTIONS}
148
+ totalItems={contactTracesHistory.length}
149
+ onChange={({ page, pageSize }) => {
150
+ goTo(page);
151
+ setPageSize(pageSize);
152
+ }}
153
+ />
154
+ </div>
155
+ );
156
+ };
157
+
158
+ export default ContactTracingHistory;
@@ -0,0 +1,108 @@
1
+ import { formatDate, openmrsFetch, parseDate, restBaseUrl, useConfig } from '@openmrs/esm-framework';
2
+ import useEncounters from '../hooks/useEncounters';
3
+ import { ConfigObject } from '../config-schema';
4
+ import { useMemo } from 'react';
5
+ import { Encounter } from '../types';
6
+
7
+ type ContactTrace = {
8
+ date: string;
9
+ contactType: string;
10
+ status: string;
11
+ reasonNotContacted?: string;
12
+ facilityLinkedTo?: string;
13
+ remarks?: string;
14
+ encounterUuid: string;
15
+ };
16
+
17
+ type TraceEncounter = Encounter & {
18
+ form: {
19
+ uuid: string;
20
+ display: string;
21
+ };
22
+ location: {
23
+ uuid: string;
24
+ display: string;
25
+ };
26
+ obs: Array<{
27
+ uuid: string;
28
+ display: string;
29
+ concept: {
30
+ uuid: string;
31
+ displat: string;
32
+ };
33
+ value:
34
+ | string
35
+ | {
36
+ uuid: string;
37
+ display: string;
38
+ };
39
+ }>;
40
+ };
41
+ const mapConcepts = (conceptUuid: string) => {
42
+ const mapping = {
43
+ '0c112728-17b5-4342-b603-ac6dd2acf9cd': 'Incorrect locator information',
44
+ 'ac1fcb25-f443-4a32-b638-193f04d897a9': 'No locator information',
45
+ '1567AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Calls not going through',
46
+ '1706AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Not found at home',
47
+ '160415AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Migrated',
48
+ '160034AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Died',
49
+ '5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Others',
50
+ '1118AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Not contacted',
51
+ '1066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Contacted but not linked',
52
+ '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Contacted and linked',
53
+ 'eb113c76-aef8-4890-a611-fe22ba003123': 'Physical tracing',
54
+ '1650AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': 'Phone tracing',
55
+ };
56
+ return mapping[conceptUuid];
57
+ };
58
+
59
+ const getObsValueByConceptUuid = (obs: TraceEncounter['obs'], conceptUuid: string) => {
60
+ const obsValue = (obs ?? []).find((obs) => obs.concept.uuid === conceptUuid)?.value;
61
+ if (typeof obsValue === 'string') {
62
+ return obsValue;
63
+ }
64
+ if (typeof obsValue === 'object') {
65
+ return mapConcepts(obsValue.uuid);
66
+ }
67
+ };
68
+ export const useContactTraceHistory = (patientUuid: string) => {
69
+ const customRep =
70
+ 'custom:(uuid,display,encounterDatetime,location:(uuid,display),form:(uuid,display),obs:(uuid,display,concept:(uuid,display),value:(uuid,display)))';
71
+ const {
72
+ encounterTypes: { htsEcounterUuid },
73
+ formsList: { htsClientTracingFormUuid },
74
+ htsClientTracingConceptsUuids: {
75
+ modeOfClienttracingConceptUuid,
76
+ reasonNotContactedConceptUuid,
77
+ remarksConceptUuid,
78
+ tracingStatusConceptUuid,
79
+ },
80
+ } = useConfig<ConfigObject>();
81
+
82
+ const { encounters, error, isLoading } = useEncounters(patientUuid, htsEcounterUuid, undefined, undefined, customRep);
83
+
84
+ const tracingHistory = useMemo(
85
+ () =>
86
+ encounters
87
+ .filter((encounter: TraceEncounter) => encounter.form.uuid === htsClientTracingFormUuid)
88
+ .map<ContactTrace>((encounter: TraceEncounter) => ({
89
+ encounterUuid: encounter.uuid,
90
+ contactType: getObsValueByConceptUuid(encounter.obs, modeOfClienttracingConceptUuid),
91
+ status: getObsValueByConceptUuid(encounter.obs, tracingStatusConceptUuid),
92
+ reasonNotContacted: getObsValueByConceptUuid(encounter.obs, reasonNotContactedConceptUuid),
93
+ date: encounter.encounterDatetime ? formatDate(parseDate(encounter.encounterDatetime)) : '--',
94
+ facilityLinkedTo: encounter?.location?.display ?? '--',
95
+ remarks: getObsValueByConceptUuid(encounter.obs, remarksConceptUuid) ?? '--',
96
+ })),
97
+ [
98
+ encounters,
99
+ htsClientTracingFormUuid,
100
+ modeOfClienttracingConceptUuid,
101
+ reasonNotContactedConceptUuid,
102
+ remarksConceptUuid,
103
+ tracingStatusConceptUuid,
104
+ ],
105
+ );
106
+ return { isLoading, error, contactTracesHistory: tracingHistory ?? ([] as Array<ContactTrace>) };
107
+ };
108
+ export const PAGE_SIZE_OPTIONS = [3, 5, 10, 20, 50, 100];