@kenyaemr/esm-patient-clinical-view-app 5.4.2-pre.2724 → 5.4.2-pre.2726

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.
@@ -0,0 +1,121 @@
1
+ import React from 'react';
2
+ import { ErrorState, isDesktop, useConfig, useLayoutType } from '@openmrs/esm-framework';
3
+ import { CardHeader, EmptyState, usePaginationInfo } from '@openmrs/esm-patient-common-lib';
4
+ import { useTranslation } from 'react-i18next';
5
+ import {
6
+ DataTable,
7
+ Table,
8
+ TableHead,
9
+ TableRow,
10
+ TableHeader,
11
+ TableBody,
12
+ TableCell,
13
+ DataTableSkeleton,
14
+ Pagination,
15
+ } from '@carbon/react';
16
+
17
+ import { useForm, usePaginatedEncounters, extractComplaintsFromObservations } from './complaints.resource';
18
+ import { ConfigObject } from '../config-schema';
19
+
20
+ import styles from './patient-complaints.scss';
21
+
22
+ const pageSize = 5;
23
+
24
+ type PatientComplaintsComponentProps = {
25
+ patientUuid: string;
26
+ };
27
+
28
+ const PatientComplaintsComponent = ({ patientUuid }: PatientComplaintsComponentProps) => {
29
+ const { t } = useTranslation();
30
+ const layout = useLayoutType();
31
+ const config = useConfig<ConfigObject>();
32
+ const {
33
+ data = [],
34
+ isLoading: isLoadingEncounters,
35
+ error: errorEncounters,
36
+ currentPage,
37
+ goTo,
38
+ totalPages,
39
+ } = usePaginatedEncounters(patientUuid, config.encounterTypes.triage, pageSize);
40
+ const responsiveSize = isDesktop(layout) ? 'sm' : 'lg';
41
+ const { conceptLabelMap, isLoading: isLoadingForm, error: errorForm } = useForm(config.formsList.complaintsFormUuid);
42
+ const { pageSizes } = usePaginationInfo(pageSize, totalPages, currentPage, data?.length);
43
+ if (isLoadingEncounters || isLoadingForm) {
44
+ return <DataTableSkeleton />;
45
+ }
46
+
47
+ if (errorEncounters || errorForm) {
48
+ return <ErrorState error={errorEncounters || errorForm} headerTitle={t('complaints', 'Complaints')} />;
49
+ }
50
+
51
+ const complaintsTableHeaders = [
52
+ {
53
+ key: 'complaint',
54
+ header: t('complaint', 'Complaint'),
55
+ },
56
+ {
57
+ key: 'duration',
58
+ header: t('duration', 'Duration'),
59
+ },
60
+ {
61
+ key: 'onset',
62
+ header: t('onset', 'Onset'),
63
+ },
64
+ ];
65
+
66
+ const observations = data?.map((encounter) => encounter.obs) ?? [];
67
+ const complaints = extractComplaintsFromObservations(
68
+ observations.flatMap((observation) => observation),
69
+ config,
70
+ conceptLabelMap,
71
+ );
72
+
73
+ if (complaints.length === 0) {
74
+ return <EmptyState displayText={t('Complaints', 'Complaints')} headerTitle={t('complaints', 'Complaints')} />;
75
+ }
76
+
77
+ return (
78
+ <div className={styles.patientComplaintsContainer}>
79
+ <CardHeader title="Complaints">
80
+ <></>
81
+ </CardHeader>
82
+ <DataTable size={responsiveSize} useZebraStyles rows={complaints} headers={complaintsTableHeaders}>
83
+ {({ rows, headers, getTableProps, getHeaderProps, getRowProps, getCellProps }) => (
84
+ <Table {...getTableProps()}>
85
+ <TableHead>
86
+ <TableRow>
87
+ {headers.map((header) => (
88
+ <TableHeader {...getHeaderProps({ header })}>{header.header}</TableHeader>
89
+ ))}
90
+ </TableRow>
91
+ </TableHead>
92
+ <TableBody>
93
+ {rows.map((row) => (
94
+ <TableRow {...getRowProps({ row })}>
95
+ {row.cells.map((cell) => (
96
+ <TableCell {...getCellProps({ cell })}>{cell.value}</TableCell>
97
+ ))}
98
+ </TableRow>
99
+ ))}
100
+ </TableBody>
101
+ </Table>
102
+ )}
103
+ </DataTable>
104
+ <Pagination
105
+ className={styles.pagination}
106
+ backwardText={t('previousPage', 'Previous page')}
107
+ forwardText={t('nextPage', 'Next page')}
108
+ page={currentPage}
109
+ pageSize={pageSize}
110
+ pageSizeInputDisabled={true}
111
+ pageSizes={pageSizes}
112
+ totalItems={complaints.length}
113
+ onChange={({ page }) => {
114
+ goTo(page);
115
+ }}
116
+ />
117
+ </div>
118
+ );
119
+ };
120
+
121
+ export default PatientComplaintsComponent;
@@ -0,0 +1,11 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+
5
+ .patientComplaintsContainer {
6
+ border: 1px solid colors.$gray-20;
7
+ }
8
+
9
+ .pagination {
10
+ border-top: none;
11
+ }
@@ -2,6 +2,21 @@ import { Type } from '@openmrs/esm-framework';
2
2
  import _default from 'react-hook-form/dist/logic/appendErrors';
3
3
 
4
4
  export const configSchema = {
5
+ complaintsConceptUuids: {
6
+ _type: Type.Array,
7
+ _description: 'List of complaint concept UUIDs',
8
+ _default: ['160531AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'],
9
+ },
10
+ complaints: {
11
+ _type: Type.Object,
12
+ _description: 'Complaints configuration',
13
+ _default: {
14
+ chiefComplaintConceptUuid: '160531AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
15
+ complaintMemberConceptUuid: '5219AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
16
+ durationConceptUuid: '159368AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
17
+ onsetConceptUuid: 'd7a3441d-6aeb-49be-b7d6-b2a3bb39e78d',
18
+ },
19
+ },
5
20
  requireMaritalStatusOnAgeGreaterThanOrEqualTo: {
6
21
  _type: Type.Number,
7
22
  _description: 'Age in years',
@@ -15,6 +30,7 @@ export const configSchema = {
15
30
  hivTestingServices: '9c0a7a57-62ff-4f75-babe-5835b0e921b7',
16
31
  kpPeerCalender: 'c4f9db39-2c18-49a6-bf9b-b243d673c64d',
17
32
  htsEcounterUuid: '9c0a7a57-62ff-4f75-babe-5835b0e921b7', // Used with Contact tracing
33
+ triage: 'd1059fb9-a079-4feb-a749-eedd709ae542',
18
34
  },
19
35
  },
20
36
  caseManagementForms: {
@@ -53,6 +69,7 @@ export const configSchema = {
53
69
  peerCalendarOutreactForm: '7492cffe-5874-4144-a1e6-c9e455472a35',
54
70
  autopsyFormUuid: '2b61a73-4971-4fc0-b20b-9a30176317e2',
55
71
  htsClientTracingFormUuid: '15ed03d2-c972-11e9-a32f-2a2ae2dbcce4',
72
+ complaintsFormUuid: '37f6bd8d-586a-4169-95fa-5781f987fe62',
56
73
  },
57
74
  },
58
75
  htsClientTracingConceptsUuids: {
@@ -489,6 +506,7 @@ export interface ConfigObject {
489
506
  hivTestingServices: string;
490
507
  kpPeerCalender: string;
491
508
  htsEcounterUuid: string;
509
+ triage: string;
492
510
  };
493
511
  formsList: {
494
512
  labourAndDelivery: string;
@@ -503,6 +521,7 @@ export interface ConfigObject {
503
521
  peerCalendarOutreactForm: string;
504
522
  autopsyFormUuid: string;
505
523
  htsClientTracingFormUuid: string;
524
+ complaintsFormUuid: string;
506
525
  };
507
526
  defaulterTracingEncounterUuid: string;
508
527
  autopsyEncounterFormUuid: string;
@@ -569,6 +588,13 @@ export interface ConfigObject {
569
588
  };
570
589
  };
571
590
  caseManagerRelationshipType: string;
591
+ complaintsConceptUuids: Array<string>;
592
+ complaints: {
593
+ chiefComplaintConceptUuid: string;
594
+ complaintMemberConceptUuid: string;
595
+ durationConceptUuid: string;
596
+ onsetConceptUuid: string;
597
+ };
572
598
  }
573
599
 
574
600
  export interface PartograpyComponents {
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { defineConfigSchema, getSyncLifecycle } from '@openmrs/esm-framework';
1
+ import { defineConfigSchema, getAsyncLifecycle, getSyncLifecycle } from '@openmrs/esm-framework';
2
2
  import { createDashboardLink } from '@openmrs/esm-patient-common-lib';
3
3
 
4
4
  import { inPatientClinicalEncounterDashboardMeta } from './clinical-encounter/clinical-encounter-dashboard-meta';
@@ -116,6 +116,7 @@ export const specialClinicsDashboardLink = getSyncLifecycle(
116
116
  );
117
117
  export const specialClinicsDashboard = getSyncLifecycle(SpecialClinicDashboard, options);
118
118
 
119
+ export const patientComplaints = getAsyncLifecycle(() => import('./complaints/patient-complaints.component'), options);
119
120
  export function startupApp() {
120
121
  defineConfigSchema(moduleName, configSchema);
121
122
  }
package/src/routes.json CHANGED
@@ -195,6 +195,14 @@
195
195
  "order": 0,
196
196
  "online": true,
197
197
  "offline": false
198
+ },
199
+ {
200
+ "name": "patient-complaints",
201
+ "slot": "ewf-patient-summary-slot",
202
+ "component": "patientComplaints",
203
+ "order": 0,
204
+ "online": true,
205
+ "offline": false
198
206
  }
199
207
  ],
200
208
  "modals": [
@@ -56,6 +56,9 @@
56
56
  "clearLiquor": "Clear liquor",
57
57
  "clientEligibility": "ብቁ",
58
58
  "clinicalEncounter": "ክሊኒካዊ ግኝት",
59
+ "complaint": "ቅሬታ",
60
+ "complaints": "ቅሬታዎች",
61
+ "Complaints": "ቅሬታዎች",
59
62
  "completed": "ተጠናቋል",
60
63
  "completedDocumentations": "የተጠናቀቀ ሰነድ",
61
64
  "contact": "እውቂያ",
@@ -99,6 +102,7 @@
99
102
  "drugsAndIVFluidsGiven": "Drugs given and IV fluids",
100
103
  "drugsIVFluids": "Drugs and IV Fluids Given",
101
104
  "duplicateTimeEntry": "This time already exists",
105
+ "duration": "Duration",
102
106
  "edit": "አስተካክል",
103
107
  "editContactList": "የእውቂያ ዝርዝር አስተካክል",
104
108
  "editEncounter": "አስተካክል",
@@ -190,6 +194,7 @@
190
194
  "neonatalAbnormalities": "የጨቅላ ህፃናት ያልተለመዱ ሁኔታዎች",
191
195
  "neonatalProblems": "የጨቅላ ህፃናት ችግሮች",
192
196
  "neonatalSummary": "የጨቅላ ህፃናት ማጠቃለያ",
197
+ "nextPage": "Next page",
193
198
  "nextVisitDate": "የሚቀጥለው የጉብኝት ቀን",
194
199
  "no": "አይ",
195
200
  "noContactToDisplay": "ለዚህ ታካሚ የሚታይ የእውቂያ ዳታ የለም።",
@@ -205,6 +210,7 @@
205
210
  "noPatientSelected": "No patient selected",
206
211
  "noPulseBPData": "No pulse and BP data available",
207
212
  "oneContraction": "1 contraction",
213
+ "onset": "Onset",
208
214
  "operatingDoctor": "የሚያሰራ ሀኪም",
209
215
  "otherSubstanceAbuse": "ሌላ የሱስ አላግባብ መጠቀም",
210
216
  "oxytocin": "Oxytocin",
@@ -228,6 +234,7 @@
228
234
  "postOperativeDiagnosis": "ከቀዶ ጥገና በኋላ ምርመራ",
229
235
  "pphCondition": "PPH አለ",
230
236
  "preferedPNSAproach": "የተመረጠ የPNS አካሄድ",
237
+ "previousPage": "Previous page",
231
238
  "primaryDiagnosis": "ዋና ምርመራ",
232
239
  "priorityOfAdmission": "የመግቢያ ቅድሚያ",
233
240
  "protein": "Protein",
@@ -56,6 +56,9 @@
56
56
  "clearLiquor": "Clear liquor",
57
57
  "clientEligibility": "Eligible",
58
58
  "clinicalEncounter": "Clinical Encounter",
59
+ "complaint": "Complaint",
60
+ "complaints": "Complaints",
61
+ "Complaints": "Complaints",
59
62
  "completed": "Completed",
60
63
  "completedDocumentations": "Completed Documentation",
61
64
  "contact": "Contact",
@@ -99,6 +102,7 @@
99
102
  "drugsAndIVFluidsGiven": "Drugs given and IV fluids",
100
103
  "drugsIVFluids": "Drugs and IV Fluids Given",
101
104
  "duplicateTimeEntry": "This time already exists",
105
+ "duration": "Duration",
102
106
  "edit": "Edit",
103
107
  "editContactList": "Edit contact list",
104
108
  "editEncounter": "Edit",
@@ -190,6 +194,7 @@
190
194
  "neonatalAbnormalities": "Neonatal Abnormalities",
191
195
  "neonatalProblems": "Neonatal Problems",
192
196
  "neonatalSummary": "Neonatal Summary",
197
+ "nextPage": "Next page",
193
198
  "nextVisitDate": "Next visit date",
194
199
  "no": "No",
195
200
  "noContactToDisplay": "There is no contact data to display for this patient.",
@@ -205,6 +210,7 @@
205
210
  "noPatientSelected": "No patient selected",
206
211
  "noPulseBPData": "No pulse and BP data available",
207
212
  "oneContraction": "1 contraction",
213
+ "onset": "Onset",
208
214
  "operatingDoctor": "Operating Doctor",
209
215
  "otherSubstanceAbuse": "Other Substance Abuse",
210
216
  "oxytocin": "Oxytocin",
@@ -228,6 +234,7 @@
228
234
  "postOperativeDiagnosis": "Post Operative Diagnosis",
229
235
  "pphCondition": "PPH present",
230
236
  "preferedPNSAproach": "Prefered PNS Aproach",
237
+ "previousPage": "Previous page",
231
238
  "primaryDiagnosis": "Primary Diagnosis",
232
239
  "priorityOfAdmission": "Priority Of Admission",
233
240
  "protein": "Protein",
@@ -56,6 +56,9 @@
56
56
  "clearLiquor": "Clear liquor",
57
57
  "clientEligibility": "Eligible",
58
58
  "clinicalEncounter": "Clinical Encounter",
59
+ "complaint": "Complaint",
60
+ "complaints": "Complaints",
61
+ "Complaints": "Complaints",
59
62
  "completed": "Completed",
60
63
  "completedDocumentations": "Completed Documentation",
61
64
  "contact": "Contact",
@@ -99,6 +102,7 @@
99
102
  "drugsAndIVFluidsGiven": "Drugs given and IV fluids",
100
103
  "drugsIVFluids": "Drugs and IV Fluids Given",
101
104
  "duplicateTimeEntry": "This time already exists",
105
+ "duration": "Duration",
102
106
  "edit": "Edit",
103
107
  "editContactList": "Edit contact list",
104
108
  "editEncounter": "Edit",
@@ -190,6 +194,7 @@
190
194
  "neonatalAbnormalities": "Neonatal Abnormalities",
191
195
  "neonatalProblems": "Neonatal Problems",
192
196
  "neonatalSummary": "Neonatal Summary",
197
+ "nextPage": "Next page",
193
198
  "nextVisitDate": "Next visit date",
194
199
  "no": "No",
195
200
  "noContactToDisplay": "There is no contact data to display for this patient.",
@@ -205,6 +210,7 @@
205
210
  "noPatientSelected": "No patient selected",
206
211
  "noPulseBPData": "No pulse and BP data available",
207
212
  "oneContraction": "1 contraction",
213
+ "onset": "Onset",
208
214
  "operatingDoctor": "Operating Doctor",
209
215
  "otherSubstanceAbuse": "Other Substance Abuse",
210
216
  "oxytocin": "Oxytocin",
@@ -228,6 +234,7 @@
228
234
  "postOperativeDiagnosis": "Post Operative Diagnosis",
229
235
  "pphCondition": "PPH present",
230
236
  "preferedPNSAproach": "Prefered PNS Aproach",
237
+ "previousPage": "Previous page",
231
238
  "primaryDiagnosis": "Primary Diagnosis",
232
239
  "priorityOfAdmission": "Priority Of Admission",
233
240
  "protein": "Protein",