@kenyaemr/esm-active-visits-app 8.1.1-pre.129 → 8.1.2-pre.154

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 (74) hide show
  1. package/.turbo/turbo-build.log +17 -17
  2. package/dist/130.js +1 -1
  3. package/dist/130.js.map +1 -1
  4. package/dist/136.js +2 -0
  5. package/dist/136.js.map +1 -0
  6. package/dist/236.js +1 -0
  7. package/dist/240.js +1 -0
  8. package/dist/261.js +1 -0
  9. package/dist/271.js +1 -1
  10. package/dist/272.js +1 -0
  11. package/dist/319.js +1 -1
  12. package/dist/336.js +1 -0
  13. package/dist/378.js +1 -0
  14. package/dist/460.js +1 -1
  15. package/dist/539.js +1 -0
  16. package/dist/566.js +1 -0
  17. package/dist/6.js +1 -1
  18. package/dist/6.js.map +1 -1
  19. package/dist/652.js +1 -0
  20. package/dist/673.js +1 -0
  21. package/dist/705.js +1 -0
  22. package/dist/711.js +1 -0
  23. package/dist/725.js +1 -1
  24. package/dist/727.js +1 -0
  25. package/dist/737.js +1 -0
  26. package/dist/744.js +1 -0
  27. package/dist/899.js +1 -0
  28. package/dist/967.js +1 -1
  29. package/dist/kenyaemr-esm-active-visits-app.js +1 -1
  30. package/dist/kenyaemr-esm-active-visits-app.js.buildmanifest.json +389 -37
  31. package/dist/kenyaemr-esm-active-visits-app.js.map +1 -1
  32. package/dist/main.js +1 -1
  33. package/dist/main.js.map +1 -1
  34. package/dist/routes.json +1 -1
  35. package/package-lock.json +2028 -1668
  36. package/package.json +5 -5
  37. package/src/active-visits-widget/active-visits.component.tsx +156 -187
  38. package/src/active-visits-widget/active-visits.resource.tsx +202 -28
  39. package/src/active-visits-widget/active-visits.scss +18 -0
  40. package/src/active-visits-widget/active-visits.test.tsx +120 -83
  41. package/src/config-schema.ts +11 -1
  42. package/src/types/index.ts +156 -1
  43. package/src/visits-summary/visit-detail.component.tsx +3 -2
  44. package/src/visits-summary/visit-detail.test.tsx +27 -14
  45. package/src/visits-summary/visit.resource.ts +1 -135
  46. package/src/visits-summary/visits-components/encounter-list.component.tsx +9 -9
  47. package/src/visits-summary/visits-components/encounter-observations.component.tsx +1 -1
  48. package/src/visits-summary/visits-components/encounter-observations.test.tsx +1 -1
  49. package/src/visits-summary/visits-components/medications-summary.component.tsx +1 -1
  50. package/src/visits-summary/visits-components/notes-summary.component.tsx +1 -1
  51. package/src/visits-summary/visits-components/tests-summary.component.tsx +1 -1
  52. package/src/visits-summary/visits-components/visit-summary.component.tsx +4 -4
  53. package/translations/ar.json +6 -6
  54. package/translations/de.json +37 -0
  55. package/translations/es.json +11 -11
  56. package/translations/hi.json +37 -0
  57. package/translations/hi_IN.json +37 -0
  58. package/translations/id.json +37 -0
  59. package/translations/it.json +37 -0
  60. package/translations/ne.json +37 -0
  61. package/translations/pt.json +37 -0
  62. package/translations/pt_BR.json +37 -0
  63. package/translations/qu.json +37 -0
  64. package/translations/si.json +37 -0
  65. package/translations/sw.json +37 -0
  66. package/translations/sw_KE.json +37 -0
  67. package/translations/tr.json +37 -0
  68. package/translations/tr_TR.json +37 -0
  69. package/translations/uk.json +37 -0
  70. package/translations/vi.json +37 -0
  71. package/translations/zh.json +1 -1
  72. package/dist/586.js +0 -2
  73. package/dist/586.js.map +0 -1
  74. /package/dist/{586.js.LICENSE.txt → 136.js.LICENSE.txt} +0 -0
@@ -1,39 +1,24 @@
1
- import { useEffect } from 'react';
1
+ import { useEffect, useMemo, useState } from 'react';
2
2
  import useSWRInfinite from 'swr/infinite';
3
3
  import dayjs from 'dayjs';
4
4
  import isToday from 'dayjs/plugin/isToday';
5
5
  import last from 'lodash-es/last';
6
6
  import {
7
- openmrsFetch,
8
- type Visit,
9
- useSession,
10
7
  type FetchResponse,
11
8
  formatDatetime,
9
+ openmrsFetch,
10
+ type OpenmrsResource,
12
11
  parseDate,
13
- useConfig,
14
12
  restBaseUrl,
13
+ useConfig,
14
+ useSession,
15
+ type Visit,
15
16
  } from '@openmrs/esm-framework';
16
- dayjs.extend(isToday);
17
+ import useSWR from 'swr';
18
+ import { type ActiveVisit, type VisitResponse } from '../types';
19
+ import { useTranslation } from 'react-i18next';
17
20
 
18
- export interface ActiveVisit {
19
- age: string;
20
- id: string;
21
- idNumber: string;
22
- gender: string;
23
- location: string;
24
- name: string;
25
- patientUuid: string;
26
- visitStartTime: string;
27
- visitType: string;
28
- visitUuid: string;
29
- [identifier: string]: string;
30
- }
31
-
32
- interface VisitResponse {
33
- results: Array<Visit>;
34
- links: Array<{ rel: 'prev' | 'next' }>;
35
- totalCount: number;
36
- }
21
+ dayjs.extend(isToday);
37
22
 
38
23
  export function useActiveVisits() {
39
24
  const session = useSession();
@@ -41,8 +26,10 @@ export function useActiveVisits() {
41
26
  const sessionLocation = session?.sessionLocation?.uuid;
42
27
 
43
28
  const customRepresentation =
44
- 'custom:(uuid,patient:(uuid,identifiers:(identifier,uuid,identifierType:(name,uuid)),person:(age,display,gender,uuid,attributes:(value,attributeType:(uuid,display)))),' +
45
- 'visitType:(uuid,name,display),location:(uuid,name,display),startDatetime,stopDatetime)';
29
+ 'custom:(uuid,patient:(uuid,identifiers:(identifier,uuid,identifierType:(name,uuid)),' +
30
+ 'person:(age,display,gender,uuid,attributes:(value,attributeType:(uuid,display)))),' +
31
+ 'visitType:(uuid,name,display),location:(uuid,name,display),startDatetime,stopDatetime,' +
32
+ 'encounters:(encounterDatetime,obs:(uuid,concept:(uuid,display),value)))';
46
33
 
47
34
  const getUrl = (pageIndex, previousPageData: FetchResponse<VisitResponse>) => {
48
35
  if (pageIndex && !previousPageData?.data?.links?.some((link) => link.rel === 'next')) {
@@ -76,7 +63,7 @@ export function useActiveVisits() {
76
63
  if (data && data?.[pageNumber - 1]?.data?.links?.some((link) => link.rel === 'next')) {
77
64
  setSize((currentSize) => currentSize + 1);
78
65
  }
79
- }, [data, pageNumber]);
66
+ }, [data, pageNumber, setSize]);
80
67
 
81
68
  const mapVisitProperties = (visit: Visit): ActiveVisit => {
82
69
  // create base object
@@ -126,6 +113,23 @@ export function useActiveVisits() {
126
113
  activeVisits[header?.key] = personAttributes?.value ?? '--';
127
114
  });
128
115
 
116
+ // Add flattened observations
117
+ const allObs = visit.encounters.reduce((accumulator, encounter) => {
118
+ return [...accumulator, ...(encounter.obs || [])];
119
+ }, []);
120
+
121
+ activeVisits.observations = allObs.reduce((map, obs) => {
122
+ const key = obs.concept.uuid;
123
+ if (!map[key]) {
124
+ map[key] = [];
125
+ }
126
+ map[key].push({
127
+ value: obs.value,
128
+ uuid: obs.uuid,
129
+ });
130
+ return map;
131
+ }, {});
132
+
129
133
  return activeVisits;
130
134
  };
131
135
 
@@ -142,6 +146,176 @@ export function useActiveVisits() {
142
146
  };
143
147
  }
144
148
 
149
+ export function useObsConcepts(uuids: Array<string>): {
150
+ obsConcepts: Array<OpenmrsResource> | undefined;
151
+ isLoadingObsConcepts: boolean;
152
+ } {
153
+ const fetchConcept = async (uuid: string): Promise<OpenmrsResource | null> => {
154
+ try {
155
+ const response = await openmrsFetch(`${restBaseUrl}/concept/${uuid}?v=custom:(uuid,display)`);
156
+ return response?.data;
157
+ } catch (error) {
158
+ console.error(`Error fetching concept for UUID: ${uuid}`, error);
159
+ return null;
160
+ }
161
+ };
162
+
163
+ const { data, isLoading, error } = useSWR(uuids.length > 0 ? ['obs-concepts', uuids] : null, async () => {
164
+ const results = await Promise.all(uuids.map(fetchConcept));
165
+ return results.filter((concept) => concept !== null);
166
+ });
167
+
168
+ return useMemo(
169
+ () => ({
170
+ obsConcepts: data ?? [],
171
+ isLoadingObsConcepts: isLoading,
172
+ }),
173
+ [data, isLoading],
174
+ );
175
+ }
176
+
177
+ export function useActiveVisitsSorting(tableRows: Array<any>) {
178
+ const [sortParams, setSortParams] = useState<{
179
+ key: string;
180
+ sortDirection: 'ASC' | 'DESC' | 'NONE';
181
+ }>({ key: 'visitStartTime', sortDirection: 'DESC' });
182
+
183
+ const sortRow = (cellA, cellB, { key, sortDirection }) => {
184
+ setSortParams({ key, sortDirection });
185
+ };
186
+
187
+ const getSortValue = (item: any, key: string) => {
188
+ // For observation columns
189
+ if (key.startsWith('obs-')) {
190
+ const conceptUuid = key.replace('obs-', '');
191
+ const obsValue = item?.observations?.[conceptUuid]?.[0]?.value;
192
+
193
+ if (!obsValue) return null;
194
+ if (typeof obsValue === 'object' && obsValue.display) {
195
+ return obsValue.display.toLowerCase();
196
+ }
197
+ return obsValue;
198
+ }
199
+
200
+ const value = item[key];
201
+ if (value == null) return null;
202
+
203
+ if (key === 'visitStartTime') {
204
+ return new Date(value).getTime();
205
+ }
206
+
207
+ if (key === 'age' && !isNaN(value)) {
208
+ return Number(value);
209
+ }
210
+
211
+ return String(value).toLowerCase();
212
+ };
213
+
214
+ const sortedRows = useMemo(() => {
215
+ if (sortParams.sortDirection === 'NONE') {
216
+ return tableRows;
217
+ }
218
+
219
+ return [...tableRows].sort((a, b) => {
220
+ const valueA = getSortValue(a, sortParams.key);
221
+ const valueB = getSortValue(b, sortParams.key);
222
+
223
+ if (valueA === null && valueB === null) return 0;
224
+ if (valueA === null) return 1;
225
+ if (valueB === null) return -1;
226
+
227
+ if (typeof valueA === 'number' && typeof valueB === 'number') {
228
+ return sortParams.sortDirection === 'DESC' ? valueB - valueA : valueA - valueB;
229
+ }
230
+
231
+ const compareResult = String(valueA).localeCompare(String(valueB), undefined, {
232
+ numeric: true,
233
+ });
234
+
235
+ return sortParams.sortDirection === 'DESC' ? -compareResult : compareResult;
236
+ });
237
+ }, [sortParams, tableRows]);
238
+
239
+ return {
240
+ sortedRows,
241
+ sortRow,
242
+ };
243
+ }
244
+
245
+ export function useTableHeaders(obsConcepts: OpenmrsResource[]) {
246
+ const { t } = useTranslation();
247
+ const config = useConfig();
248
+ return useMemo(() => {
249
+ let headersIndex = 0;
250
+
251
+ const headers = [
252
+ {
253
+ id: headersIndex++,
254
+ header: t('visitStartTime', 'Visit Time'),
255
+ key: 'visitStartTime',
256
+ },
257
+ ];
258
+
259
+ config?.activeVisits?.identifiers?.forEach((identifier) => {
260
+ headers.push({
261
+ id: headersIndex++,
262
+ header: t(identifier?.header?.key, identifier?.header?.default),
263
+ key: identifier?.header?.key,
264
+ });
265
+ });
266
+
267
+ if (!config?.activeVisits?.identifiers) {
268
+ headers.push({
269
+ id: headersIndex++,
270
+ header: t('idNumber', 'ID Number'),
271
+ key: 'idNumber',
272
+ });
273
+ }
274
+
275
+ config?.activeVisits?.attributes?.forEach((attribute) => {
276
+ headers.push({
277
+ id: headersIndex++,
278
+ header: t(attribute?.header?.key, attribute?.header?.default),
279
+ key: attribute?.header?.key,
280
+ });
281
+ });
282
+
283
+ // Add headers for obs concepts
284
+ obsConcepts?.forEach((concept) => {
285
+ headers.push({
286
+ id: headersIndex++,
287
+ header: concept.display,
288
+ key: `obs-${concept.uuid}`,
289
+ });
290
+ });
291
+
292
+ headers.push(
293
+ {
294
+ id: headersIndex++,
295
+ header: t('name', 'Name'),
296
+ key: 'name',
297
+ },
298
+ {
299
+ id: headersIndex++,
300
+ header: t('gender', 'Gender'),
301
+ key: 'gender',
302
+ },
303
+ {
304
+ id: headersIndex++,
305
+ header: t('age', 'Age'),
306
+ key: 'age',
307
+ },
308
+ {
309
+ id: headersIndex++,
310
+ header: t('visitType', 'Visit Type'),
311
+ key: 'visitType',
312
+ },
313
+ );
314
+
315
+ return headers;
316
+ }, [t, config, obsConcepts]);
317
+ }
318
+
145
319
  export const getOriginFromPathName = (pathname = '') => {
146
320
  const from = pathname.split('/');
147
321
  return last(from);
@@ -24,6 +24,14 @@
24
24
  }
25
25
 
26
26
  .activeVisitsTable {
27
+ width: 100%;
28
+
29
+ th,
30
+ td {
31
+ white-space: nowrap;
32
+ text-align: left;
33
+ }
34
+
27
35
  tbody tr[data-parent-row] {
28
36
  // Don't show a bottom border on the last row so we don't end up with a double border from the activeVisitContainer
29
37
  &:nth-last-of-type(2) > td {
@@ -154,12 +162,14 @@ html[dir='rtl'] {
154
162
  .activeVisitsDetailHeaderContainer {
155
163
  padding: layout.$spacing-04 layout.$spacing-05 layout.$spacing-04 0;
156
164
  }
165
+
157
166
  .desktopHeading,
158
167
  .tabletHeading {
159
168
  h4 {
160
169
  text-align: right;
161
170
  }
162
171
  }
172
+
163
173
  div[role='search'] {
164
174
  & :first-child {
165
175
  svg {
@@ -167,21 +177,29 @@ html[dir='rtl'] {
167
177
  right: layout.$spacing-03;
168
178
  }
169
179
  }
180
+
170
181
  & :last-child {
171
182
  right: unset;
172
183
  left: 0;
173
184
  }
174
185
  }
186
+
175
187
  .tableContainer {
188
+ overflow-x: auto;
189
+ text-wrap: nowrap;
190
+
176
191
  th > div {
177
192
  text-align: right;
178
193
  }
194
+
179
195
  td {
180
196
  text-align: right;
197
+
181
198
  .serviceColor {
182
199
  margin-right: 0;
183
200
  margin-left: layout.$spacing-03;
184
201
  }
202
+
185
203
  button {
186
204
  text-align: right;
187
205
  }
@@ -1,41 +1,72 @@
1
1
  import React from 'react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
  import { render, screen } from '@testing-library/react';
4
- import { getDefaultsFromConfigSchema, useConfig } from '@openmrs/esm-framework';
5
- import { mockPatient, mockSession } from '__mocks__';
6
- import { configSchema, type SectionDefinition } from '../config-schema';
7
- import { useActiveVisits } from './active-visits.resource';
4
+ import { getDefaultsFromConfigSchema, type OpenmrsResource, useConfig } from '@openmrs/esm-framework';
5
+ import { mockSession } from '__mocks__';
6
+ import { type ActiveVisitsConfigSchema, configSchema } from '../config-schema';
7
+ import { useActiveVisits, useObsConcepts } from './active-visits.resource';
8
8
  import ActiveVisitsTable from './active-visits.component';
9
+ import { type ActiveVisit, type Observation } from '../types';
9
10
 
10
11
  const mockUseActiveVisits = jest.mocked(useActiveVisits);
11
- const mockUseConfig = jest.mocked(useConfig<SectionDefinition>);
12
+ const mockUseObsConcepts = jest.mocked(useObsConcepts);
13
+ const mockIsDesktop = jest.mocked(useObsConcepts);
14
+ const mockUseConfig = jest.mocked(useConfig<ActiveVisitsConfigSchema>);
12
15
 
13
16
  jest.mock('./active-visits.resource', () => ({
14
17
  ...jest.requireActual('./active-visits.resource'),
15
18
  useActiveVisits: jest.fn(),
19
+ useObsConcepts: jest.fn(),
16
20
  }));
17
21
 
22
+ const mockObsConcepts: Array<OpenmrsResource> = [
23
+ { uuid: '160225AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', display: 'Sickle cell screening test' },
24
+ { uuid: '5484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', display: 'Nutritional support' },
25
+ ];
26
+
27
+ const mockConfig: ActiveVisitsConfigSchema = {
28
+ activeVisits: {
29
+ ...getDefaultsFromConfigSchema(configSchema).activeVisits,
30
+ obs: ['160225AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', '5484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'],
31
+ },
32
+ };
33
+
34
+ const mockActiveVisits: ActiveVisit[] = [
35
+ {
36
+ age: '20',
37
+ gender: 'male',
38
+ id: '1',
39
+ idNumber: '000001A',
40
+ location: mockSession.data.sessionLocation.uuid,
41
+ name: 'John Doe',
42
+ patientUuid: 'uuid1',
43
+ visitStartTime: '',
44
+ visitType: 'Checkup',
45
+ visitUuid: 'visit-uuid-1',
46
+ },
47
+ {
48
+ age: '25',
49
+ gender: 'female',
50
+ id: '2',
51
+ idNumber: '000001B',
52
+ location: mockSession.data.sessionLocation.uuid,
53
+ name: 'Some One',
54
+ patientUuid: 'uuid2',
55
+ visitStartTime: '',
56
+ visitType: 'Checkup',
57
+ visitUuid: 'visit-uuid-2',
58
+ },
59
+ ];
60
+
18
61
  describe('ActiveVisitsTable', () => {
19
62
  beforeEach(() => {
20
- mockUseConfig.mockReturnValue({
21
- ...getDefaultsFromConfigSchema(configSchema),
63
+ mockUseConfig.mockReturnValue(mockConfig);
64
+ mockUseObsConcepts.mockReturnValue({
65
+ obsConcepts: mockObsConcepts,
66
+ isLoadingObsConcepts: false,
22
67
  });
23
-
24
68
  mockUseActiveVisits.mockReturnValue({
25
- activeVisits: [
26
- {
27
- age: '20',
28
- gender: 'male',
29
- id: '1',
30
- idNumber: mockPatient.uuid,
31
- location: mockSession.data.sessionLocation.uuid,
32
- name: 'John Doe',
33
- patientUuid: 'uuid1',
34
- visitStartTime: '',
35
- visitType: 'Checkup',
36
- visitUuid: 'visit-uuid-1',
37
- },
38
- ],
69
+ activeVisits: mockActiveVisits,
39
70
  isLoading: false,
40
71
  isValidating: false,
41
72
  error: undefined,
@@ -43,51 +74,82 @@ describe('ActiveVisitsTable', () => {
43
74
  });
44
75
  });
45
76
 
46
- it('renders data table with active visits', () => {
77
+ afterEach(() => {
78
+ jest.clearAllMocks();
79
+ });
80
+
81
+ it('renders data table with standard and observation columns', () => {
82
+ mockUseActiveVisits.mockReturnValue({
83
+ activeVisits: mockActiveVisits.map((visit) => ({
84
+ ...visit,
85
+ observations: {
86
+ '160225AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': [
87
+ {
88
+ value: { uuid: '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', display: 'Patient is sick' },
89
+ uuid: 'obs-uuid-1',
90
+ } as unknown as Observation,
91
+ ],
92
+ '5484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': [
93
+ {
94
+ value: 'Not done',
95
+ uuid: 'obs-uuid-2',
96
+ } as unknown as Observation,
97
+ ],
98
+ },
99
+ })),
100
+ isLoading: false,
101
+ isValidating: false,
102
+ error: undefined,
103
+ totalResults: 0,
104
+ });
105
+
47
106
  render(<ActiveVisitsTable />);
48
107
 
49
- expect(screen.getByText('Visit Time')).toBeInTheDocument();
50
- expect(screen.getByText('ID Number')).toBeInTheDocument();
51
- const expectedColumnHeaders = [/Visit Time/, /ID Number/, /Name/, /Gender/, /Age/, /Visit Type/];
52
- expectedColumnHeaders.forEach((header) => {
53
- expect(screen.getByRole('columnheader', { name: new RegExp(header, 'i') })).toBeInTheDocument();
108
+ const standardColumnHeaders = [/Visit Time/, /ID Number/, /Name/, /Gender/, /Age/, /Visit Type/];
109
+ standardColumnHeaders.forEach((header) => {
110
+ expect(screen.getByRole('columnheader', { name: header })).toBeInTheDocument();
54
111
  });
55
112
 
56
- const patientNameLink = screen.getByText('John Doe');
57
- expect(patientNameLink).toBeInTheDocument();
58
- expect(patientNameLink.tagName).toBe('A');
113
+ expect(screen.getByRole('columnheader', { name: /Sickle cell screening test/ })).toBeInTheDocument();
114
+ expect(screen.getByRole('columnheader', { name: /Nutritional support/ })).toBeInTheDocument();
115
+ });
116
+
117
+ it('displays observation values correctly', () => {
118
+ mockUseActiveVisits.mockReturnValue({
119
+ activeVisits: mockActiveVisits.map((visit) => ({
120
+ ...visit,
121
+ observations: {
122
+ '160225AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': [
123
+ {
124
+ value: { uuid: '1065AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', display: 'Patient is sick' },
125
+ uuid: 'obs-uuid-1',
126
+ } as unknown as Observation,
127
+ ],
128
+ '5484AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA': [
129
+ {
130
+ value: 'Not done',
131
+ uuid: 'obs-uuid-2',
132
+ } as unknown as Observation,
133
+ ],
134
+ },
135
+ })),
136
+ isLoading: false,
137
+ isValidating: false,
138
+ error: undefined,
139
+ totalResults: 0,
140
+ });
141
+
142
+ render(<ActiveVisitsTable />);
143
+
144
+ expect(screen.getAllByRole('cell', { name: /Patient is sick/ }).length).toBe(2);
145
+ expect(screen.getAllByRole('cell', { name: /Not done/ }).length).toBe(2);
59
146
  });
60
147
 
61
148
  it('filters active visits based on search input', async () => {
62
149
  const user = userEvent.setup();
63
150
 
64
151
  mockUseActiveVisits.mockReturnValue({
65
- activeVisits: [
66
- {
67
- age: '20',
68
- gender: 'male',
69
- id: '1',
70
- idNumber: '000001A',
71
- location: mockSession.data.sessionLocation.uuid,
72
- name: 'John Doe',
73
- patientUuid: 'uuid1',
74
- visitStartTime: '',
75
- visitType: 'Checkup',
76
- visitUuid: 'visit-uuid-1',
77
- },
78
- {
79
- age: '25',
80
- gender: 'female',
81
- id: '2',
82
- idNumber: '000001B',
83
- location: mockSession.data.sessionLocation.uuid,
84
- name: 'Some One',
85
- patientUuid: 'uuid2',
86
- visitStartTime: '',
87
- visitType: 'Checkup',
88
- visitUuid: 'visit-uuid-2',
89
- },
90
- ],
152
+ activeVisits: mockActiveVisits,
91
153
  isLoading: false,
92
154
  isValidating: false,
93
155
  error: undefined,
@@ -151,32 +213,7 @@ describe('ActiveVisitsTable', () => {
151
213
 
152
214
  it('should display the pagination when pagination is true', () => {
153
215
  mockUseActiveVisits.mockReturnValue({
154
- activeVisits: [
155
- {
156
- age: '20',
157
- gender: 'male',
158
- id: '1',
159
- idNumber: '000001A',
160
- location: mockSession.data.sessionLocation.uuid,
161
- name: 'John Doe',
162
- patientUuid: 'uuid1',
163
- visitStartTime: '',
164
- visitType: 'Checkup',
165
- visitUuid: 'visit-uuid-1',
166
- },
167
- {
168
- age: '25',
169
- gender: 'female',
170
- id: '2',
171
- idNumber: '000001B',
172
- location: mockSession.data.sessionLocation.uuid,
173
- name: 'Some One',
174
- patientUuid: 'uuid2',
175
- visitStartTime: '',
176
- visitType: 'Checkup',
177
- visitUuid: 'visit-uuid-2',
178
- },
179
- ],
216
+ activeVisits: mockActiveVisits,
180
217
  isLoading: false,
181
218
  isValidating: false,
182
219
  error: undefined,
@@ -1,10 +1,11 @@
1
1
  import { Type } from '@openmrs/esm-framework';
2
2
 
3
- export interface SectionDefinition {
3
+ export interface ActiveVisitsConfigSchema {
4
4
  activeVisits: {
5
5
  pageSize: Number;
6
6
  pageSizes: Array<Number>;
7
7
  identifiers: Array<IdentifiersDefinition>;
8
+ obs: Array<string>;
8
9
  };
9
10
  }
10
11
 
@@ -53,5 +54,14 @@ export const configSchema = {
53
54
  _description: 'Customizable page sizes that user can choose',
54
55
  _default: [10, 20, 50],
55
56
  },
57
+ obs: {
58
+ _type: Type.Array,
59
+ _description: 'Array of observation concept UUIDs to be displayed on the active visits table.',
60
+ _elements: {
61
+ _type: Type.UUID,
62
+ _description: 'UUID of an observation concept.',
63
+ },
64
+ _default: [],
65
+ },
56
66
  },
57
67
  };