@openmrs/esm-generic-patient-widgets-app 11.3.1-patch.9310 → 11.3.1-patch.9508

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 (124) hide show
  1. package/.turbo/turbo-build.log +21 -24
  2. package/dist/1119.js +1 -1
  3. package/dist/1197.js +1 -1
  4. package/dist/1936.js +1 -0
  5. package/dist/1936.js.map +1 -0
  6. package/dist/2146.js +1 -1
  7. package/dist/2606.js +2 -0
  8. package/dist/2606.js.map +1 -0
  9. package/dist/2690.js +1 -1
  10. package/dist/3099.js +1 -1
  11. package/dist/3584.js +1 -1
  12. package/dist/4055.js +1 -1
  13. package/dist/4132.js +1 -1
  14. package/dist/4300.js +1 -1
  15. package/dist/4335.js +1 -1
  16. package/dist/439.js +1 -0
  17. package/dist/4618.js +1 -1
  18. package/dist/4652.js +1 -1
  19. package/dist/4944.js +1 -1
  20. package/dist/5173.js +1 -1
  21. package/dist/5241.js +1 -1
  22. package/dist/5442.js +1 -1
  23. package/dist/5661.js +1 -1
  24. package/dist/5670.js +1 -1
  25. package/dist/6022.js +1 -1
  26. package/dist/6468.js +1 -1
  27. package/dist/6589.js +1 -0
  28. package/dist/6679.js +1 -1
  29. package/dist/6840.js +1 -1
  30. package/dist/6859.js +1 -1
  31. package/dist/7097.js +1 -1
  32. package/dist/7159.js +1 -1
  33. package/dist/723.js +1 -1
  34. package/dist/7545.js +2 -0
  35. package/dist/7545.js.map +1 -0
  36. package/dist/7617.js +1 -1
  37. package/dist/795.js +1 -1
  38. package/dist/8163.js +1 -1
  39. package/dist/8349.js +1 -1
  40. package/dist/8371.js +1 -0
  41. package/dist/8618.js +1 -1
  42. package/dist/8803.js +1 -0
  43. package/dist/8803.js.map +1 -0
  44. package/dist/890.js +1 -1
  45. package/dist/9214.js +1 -1
  46. package/dist/9538.js +1 -1
  47. package/dist/9569.js +1 -1
  48. package/dist/986.js +1 -1
  49. package/dist/9879.js +1 -1
  50. package/dist/9895.js +1 -1
  51. package/dist/9900.js +1 -1
  52. package/dist/9913.js +1 -1
  53. package/dist/main.js +1 -1
  54. package/dist/main.js.map +1 -1
  55. package/dist/openmrs-esm-generic-patient-widgets-app.js +1 -1
  56. package/dist/openmrs-esm-generic-patient-widgets-app.js.buildmanifest.json +244 -178
  57. package/dist/openmrs-esm-generic-patient-widgets-app.js.map +1 -1
  58. package/dist/routes.json +1 -1
  59. package/package.json +3 -3
  60. package/src/config-schema-obs-horizontal.ts +12 -0
  61. package/src/config-schema-obs-switchable.ts +7 -1
  62. package/src/obs-graph/obs-graph.component.tsx +9 -9
  63. package/src/obs-switchable/obs-switchable.component.tsx +5 -9
  64. package/src/obs-switchable/obs-switchable.test.tsx +110 -23
  65. package/src/obs-table/obs-table.component.tsx +99 -17
  66. package/src/obs-table-horizontal/obs-table-horizontal.component.tsx +466 -56
  67. package/src/obs-table-horizontal/obs-table-horizontal.resource.ts +67 -0
  68. package/src/obs-table-horizontal/obs-table-horizontal.scss +47 -0
  69. package/src/obs-table-horizontal/obs-table-horizontal.test.tsx +923 -0
  70. package/src/resources/useConcepts.ts +14 -4
  71. package/src/resources/useEncounterTypes.ts +34 -0
  72. package/src/resources/useObs.ts +29 -47
  73. package/translations/am.json +6 -1
  74. package/translations/ar.json +6 -1
  75. package/translations/ar_SY.json +6 -1
  76. package/translations/bn.json +6 -1
  77. package/translations/cs.json +10 -0
  78. package/translations/de.json +6 -1
  79. package/translations/en.json +6 -1
  80. package/translations/en_US.json +6 -1
  81. package/translations/es.json +6 -1
  82. package/translations/es_MX.json +6 -1
  83. package/translations/fr.json +6 -1
  84. package/translations/he.json +6 -1
  85. package/translations/hi.json +6 -1
  86. package/translations/hi_IN.json +6 -1
  87. package/translations/id.json +6 -1
  88. package/translations/it.json +6 -1
  89. package/translations/ka.json +6 -1
  90. package/translations/km.json +6 -1
  91. package/translations/ku.json +6 -1
  92. package/translations/ky.json +6 -1
  93. package/translations/lg.json +6 -1
  94. package/translations/ne.json +6 -1
  95. package/translations/pl.json +6 -1
  96. package/translations/pt.json +6 -1
  97. package/translations/pt_BR.json +6 -1
  98. package/translations/qu.json +6 -1
  99. package/translations/ro_RO.json +6 -1
  100. package/translations/ru_RU.json +6 -1
  101. package/translations/si.json +6 -1
  102. package/translations/sq.json +10 -0
  103. package/translations/sw.json +6 -1
  104. package/translations/sw_KE.json +6 -1
  105. package/translations/tr.json +6 -1
  106. package/translations/tr_TR.json +6 -1
  107. package/translations/uk.json +6 -1
  108. package/translations/uz.json +6 -1
  109. package/translations/uz@Latn.json +6 -1
  110. package/translations/uz_UZ.json +6 -1
  111. package/translations/vi.json +6 -1
  112. package/translations/zh.json +6 -1
  113. package/translations/zh_CN.json +6 -1
  114. package/translations/zh_TW.json +10 -0
  115. package/dist/2499.js +0 -2
  116. package/dist/2499.js.map +0 -1
  117. package/dist/251.js +0 -2
  118. package/dist/251.js.map +0 -1
  119. package/dist/4341.js +0 -1
  120. package/dist/4341.js.map +0 -1
  121. package/dist/9351.js +0 -1
  122. package/dist/9351.js.map +0 -1
  123. /package/dist/{251.js.LICENSE.txt → 2606.js.LICENSE.txt} +0 -0
  124. /package/dist/{2499.js.LICENSE.txt → 7545.js.LICENSE.txt} +0 -0
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useMemo, useState, useCallback } from 'react';
2
2
  import {
3
3
  DataTable,
4
4
  Table,
@@ -8,6 +8,7 @@ import {
8
8
  TableHead,
9
9
  TableHeader,
10
10
  TableRow,
11
+ type DataTableSortState,
11
12
  } from '@carbon/react';
12
13
  import { usePagination, useConfig, formatDatetime, formatDate, formatTime } from '@openmrs/esm-framework';
13
14
  import { PatientChartPagination } from '@openmrs/esm-patient-common-lib';
@@ -20,35 +21,77 @@ interface ObsTableProps {
20
21
  patientUuid: string;
21
22
  }
22
23
 
24
+ interface Row {
25
+ id: string;
26
+ date: string;
27
+ rawDate: string;
28
+ encounter: string;
29
+ [conceptUuid: string]: string | number;
30
+ }
31
+
32
+ interface Header {
33
+ key: string;
34
+ header: string;
35
+ sortFunc: (rowA: Row, rowB: Row) => number;
36
+ }
37
+
23
38
  const ObsTable: React.FC<ObsTableProps> = ({ patientUuid }) => {
24
39
  const { t } = useTranslation();
25
40
  const config = useConfig<ConfigObjectSwitchable>();
26
41
  const {
27
42
  data: { observations, concepts },
28
43
  } = useObs(patientUuid);
44
+
29
45
  const uniqueEncounterReferences = [...new Set(observations.map((o) => o.encounter.reference))].sort();
30
46
  const obssGroupedByEncounters = uniqueEncounterReferences.map((reference) =>
31
47
  observations.filter((o) => o.encounter.reference === reference),
32
48
  );
33
49
 
34
- const tableHeaders = [
35
- { key: 'date', header: t('dateAndTime', 'Date and time'), isSortable: true },
36
- ...config.data.map(({ concept, label }) => ({
37
- key: concept,
38
- header: label || concepts.find((c) => c.uuid == concept)?.display,
39
- })),
40
- ];
41
-
42
- if (config.showEncounterType) {
43
- tableHeaders.splice(1, 0, { key: 'encounter', header: t('encounterType', 'Encounter type'), isSortable: true });
44
- }
50
+ const tableHeaders: Array<Header> = useMemo(() => {
51
+ const headers: Array<Header> = [
52
+ {
53
+ key: 'date',
54
+ header: t('dateAndTime', 'Date and time'),
55
+ sortFunc: (rowA: Row, rowB: Row) => new Date(rowB.rawDate).getTime() - new Date(rowA.rawDate).getTime(),
56
+ },
57
+ ];
58
+ if (config.showEncounterType) {
59
+ headers.splice(1, 0, {
60
+ key: 'encounter',
61
+ header: t('encounterType', 'Encounter type'),
62
+ sortFunc: (rowA: Row, rowB: Row) => rowA.encounter.localeCompare(rowB.encounter) as 1 | -1,
63
+ });
64
+ }
65
+ headers.push(
66
+ ...config.data.map(({ concept, label }) => ({
67
+ key: concept,
68
+ header: label || concepts.find((c) => c.uuid == concept)?.display,
69
+ sortFunc: (rowA: Row, rowB: Row) => {
70
+ const a = rowA[concept];
71
+ const b = rowB[concept];
72
+ if (a === b) {
73
+ return 0;
74
+ }
75
+ if (a == null) {
76
+ return 1;
77
+ }
78
+ if (b == null) {
79
+ return -1;
80
+ }
81
+ return a < b ? 1 : -1;
82
+ },
83
+ })),
84
+ );
85
+ return headers;
86
+ }, [t, config.data, config.showEncounterType, concepts]);
45
87
 
46
- const tableRows = React.useMemo(
88
+ const tableRows: Array<Row> = React.useMemo(
47
89
  () =>
48
90
  obssGroupedByEncounters?.map((obss, index) => {
49
91
  const rowData = {
50
92
  id: `${index}`,
51
93
  date: formatDatetime(new Date(obss[0].effectiveDateTime), { mode: 'wide' }),
94
+ rawDate: obss[0].effectiveDateTime,
52
95
  encounter: obss[0].encounter.name,
53
96
  };
54
97
 
@@ -58,7 +101,7 @@ const ObsTable: React.FC<ObsTableProps> = ({ patientUuid }) => {
58
101
  rowData[obs.conceptUuid] = obs.valueString;
59
102
  break;
60
103
 
61
- case 'Number': {
104
+ case 'Numeric': {
62
105
  const decimalPlaces: number | undefined = config.data.find(
63
106
  (ele: any) => ele.concept === obs.conceptUuid,
64
107
  )?.decimalPlaces;
@@ -100,11 +143,50 @@ const ObsTable: React.FC<ObsTableProps> = ({ patientUuid }) => {
100
143
  [config.data, config?.dateFormat, obssGroupedByEncounters],
101
144
  );
102
145
 
103
- const { results, goTo, currentPage } = usePagination(tableRows, config.table.pageSize);
146
+ const [sortParams, setSortParams] = useState<{ key: string; sortDirection: 'ASC' | 'DESC' | 'NONE' }>({
147
+ key: 'date',
148
+ sortDirection: config.tableSortOldestFirst ? 'ASC' : 'DESC',
149
+ });
150
+
151
+ const handleSorting = useCallback(
152
+ (cellA: any, cellB: any, { key, sortDirection }: { key: string; sortDirection: DataTableSortState }) => {
153
+ // Use setTimeout to avoid setState during render
154
+ setTimeout(() => {
155
+ if (sortDirection === 'NONE') {
156
+ setSortParams({ key: '', sortDirection });
157
+ } else {
158
+ setSortParams({ key, sortDirection });
159
+ }
160
+ }, 0);
161
+ return 0;
162
+ },
163
+ [],
164
+ );
165
+
166
+ const sortedData: Array<any> = useMemo(() => {
167
+ if (sortParams.sortDirection === 'NONE') {
168
+ return tableRows;
169
+ }
170
+
171
+ const header = tableHeaders.find((header) => header.key === sortParams.key);
172
+
173
+ if (!header) {
174
+ return tableRows;
175
+ }
176
+
177
+ const sortedRows = tableRows.slice().sort((rowA, rowB) => {
178
+ const sortingNum = header.sortFunc(rowA, rowB);
179
+ return sortParams.sortDirection === 'DESC' ? sortingNum : -sortingNum;
180
+ });
181
+
182
+ return sortedRows;
183
+ }, [tableHeaders, tableRows, sortParams]);
184
+
185
+ const { results, goTo, currentPage } = usePagination(sortedData, config.table.pageSize);
104
186
 
105
187
  return (
106
188
  <div>
107
- <DataTable rows={results} headers={tableHeaders} isSortable size="sm" useZebraStyles>
189
+ <DataTable rows={results} headers={tableHeaders} isSortable sortRow={handleSorting} size="sm" useZebraStyles>
108
190
  {({ rows, headers, getHeaderProps, getTableProps }) => (
109
191
  <TableContainer>
110
192
  <Table {...getTableProps()} className={styles.customRow}>
@@ -137,7 +219,7 @@ const ObsTable: React.FC<ObsTableProps> = ({ patientUuid }) => {
137
219
  </DataTable>
138
220
  <PatientChartPagination
139
221
  pageNumber={currentPage}
140
- totalItems={tableRows.length}
222
+ totalItems={sortedData.length}
141
223
  currentItems={results.length}
142
224
  pageSize={config.table.pageSize}
143
225
  onPageNumberChange={({ page }) => goTo(page)}