@kenyaemr/esm-express-workflow-app 5.4.3 → 5.4.4-pre.10

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.
@@ -1,12 +1,14 @@
1
+ import React, { useCallback, useMemo, useState } from 'react';
1
2
  import { IconButton, InlineLoading } from '@carbon/react';
2
3
  import { Renew } from '@carbon/react/icons';
3
4
  import { useConfig } from '@openmrs/esm-framework';
4
5
  import { EmptyState } from '@openmrs/esm-patient-common-lib';
5
- import React, { useCallback, useMemo, useState } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
+
7
8
  import { ExpressWorkflowConfig } from '../../config-schema';
8
9
  import { useQueues } from '../../hooks/useServiceQueues';
9
10
  import QueueTab from '../../shared/queue/queue-tab.component';
11
+ import QueueSummaryCards, { QueueSummaryCard } from '../../shared/queue/queue-summary-cards.component';
10
12
  import { Queue, QueueFilter } from '../../types';
11
13
  import {
12
14
  useConsultationQueueMetrics,
@@ -17,7 +19,7 @@ import styles from '../consultation/consultation.scss';
17
19
 
18
20
  const MCHConsultation: React.FC = () => {
19
21
  const { t } = useTranslation();
20
- const { queues, isLoading, error } = useQueues();
22
+ const { queues, isLoading: isLoadingQueues } = useQueues();
21
23
  const [currQueue, setCurrQueue] = useState<Queue>();
22
24
  const [filters, setFilters] = useState<Array<QueueFilter>>([]);
23
25
  const [isRefreshing, setIsRefreshing] = useState(false);
@@ -26,7 +28,12 @@ const MCHConsultation: React.FC = () => {
26
28
  priorities: { emergencyPriorityConceptUuid, urgentPriorityConceptUuid, notUrgentPriorityConceptUuid },
27
29
  queueServiceConceptUuids,
28
30
  } = useConfig<ExpressWorkflowConfig>();
29
- const { data: totalVisits, isLoading: isLoadingTotalVisits } = useTotalVisits();
31
+ const {
32
+ data: totalVisits,
33
+ isLoading: isLoadingTotalVisits,
34
+ isValidating: isValidatingTotalVisits,
35
+ } = useTotalVisits();
36
+
30
37
  const consultationQueues = queues.filter(
31
38
  (queue) =>
32
39
  queue.service.uuid === queueServiceConceptUuids.consultationService &&
@@ -38,21 +45,21 @@ const MCHConsultation: React.FC = () => {
38
45
  const {
39
46
  waitingEntries,
40
47
  isLoading: isLoadingQueueMetrics,
41
- error: waitingError,
42
48
  emergencyEntries,
43
49
  urgentEntries,
44
50
  notUrgentEntries,
51
+ isValidating: isValidatingQueueMetrics,
45
52
  } = useConsultationQueueMetrics(activeQueue);
46
53
  const {
47
54
  awaitingCount,
48
55
  completedCount,
49
- totalCount,
50
56
  lab,
51
57
  radiology,
52
58
  procedures,
53
59
  isLoading: isLoadingInvestigations,
54
60
  refresh: refreshInvestigations,
55
61
  investigationCategorizedEntries,
62
+ isValidating: isValidatingInvestigations,
56
63
  } = useInvestigationStats(activeQueue);
57
64
  // Single refresh handler for all investigations
58
65
  const handleRefresh = useCallback(async () => {
@@ -66,7 +73,7 @@ const MCHConsultation: React.FC = () => {
66
73
  }
67
74
  }, [refreshInvestigations]);
68
75
 
69
- const cards = useMemo(
76
+ const cards: Array<QueueSummaryCard> = useMemo(
70
77
  () => [
71
78
  {
72
79
  title: t('awaitingConsultation', 'Awaiting consultation'),
@@ -258,7 +265,10 @@ const MCHConsultation: React.FC = () => {
258
265
  ],
259
266
  );
260
267
 
261
- if (isLoading || isLoadingTotalVisits || isLoadingInvestigations || isLoadingQueueMetrics) {
268
+ const isLoading = isLoadingQueues || isLoadingTotalVisits || isLoadingInvestigations || isLoadingQueueMetrics;
269
+ const isValidating = isValidatingTotalVisits || isValidatingInvestigations || isValidatingQueueMetrics;
270
+
271
+ if (isLoading && !isValidating) {
262
272
  return <InlineLoading description={t('loadingQueues', 'Loading queues...')} />;
263
273
  }
264
274
 
@@ -271,14 +281,16 @@ const MCHConsultation: React.FC = () => {
271
281
  );
272
282
  }
273
283
  return (
274
- <QueueTab
275
- queues={consultationQueues}
276
- navigatePath="mch"
277
- cards={cards}
278
- usePatientChart
279
- filters={filters}
280
- onFiltersChanged={setFilters}
281
- />
284
+ <>
285
+ <QueueSummaryCards cards={cards} />
286
+ <QueueTab
287
+ queues={consultationQueues}
288
+ navigatePath="mch"
289
+ usePatientChart
290
+ filters={filters}
291
+ onFiltersChanged={setFilters}
292
+ />
293
+ </>
282
294
  );
283
295
  };
284
296
 
@@ -5,13 +5,14 @@ import { ErrorState, useConfig } from '@openmrs/esm-framework';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { useQueues } from '../../hooks/useServiceQueues';
7
7
  import QueueTab from '../../shared/queue/queue-tab.component';
8
+ import QueueSummaryCards, { QueueSummaryCard } from '../../shared/queue/queue-summary-cards.component';
8
9
  import { Queue, QueueFilter } from '../../types';
9
10
  import { useTriageQueuesMetrics } from '../triage/triage.resource';
10
11
  import { ExpressWorkflowConfig } from '../../config-schema';
11
12
 
12
13
  const MCHTriage: React.FC = () => {
13
14
  const { t } = useTranslation();
14
- const { queues, isLoading, error } = useQueues();
15
+ const { queues, isLoading: isLoadingQueues, error } = useQueues();
15
16
  const [currQueue, setCurrQueue] = useState<Queue>();
16
17
  const [filters, setFilters] = useState<Array<QueueFilter>>([]);
17
18
  const {
@@ -31,11 +32,15 @@ const MCHTriage: React.FC = () => {
31
32
  const {
32
33
  error: metricsError,
33
34
  isLoading: isLoadingMetrics,
34
- attendedtoEntries,
35
+ attendedToEntries,
35
36
  waitingEntries,
37
+ isValidating: isValidatingMetrics,
36
38
  } = useTriageQueuesMetrics(activeQueue);
37
39
 
38
- if (isLoading || isLoadingMetrics) {
40
+ const isLoading = isLoadingQueues || isLoadingMetrics;
41
+ const isValidating = isValidatingMetrics;
42
+
43
+ if (isLoading && !isValidating) {
39
44
  return <InlineLoading description={t('loadingQueues', 'Loading queues...')} />;
40
45
  }
41
46
 
@@ -43,37 +48,41 @@ const MCHTriage: React.FC = () => {
43
48
  return <ErrorState error={error ?? metricsError} headerTitle={t('errorLoadingQueues', 'Error loading queues')} />;
44
49
  }
45
50
 
51
+ const cards: Array<QueueSummaryCard> = [
52
+ {
53
+ title: t('patientsAwaiting', 'Patient awaiting'),
54
+ value: waitingEntries?.length?.toString(),
55
+ onClick: () => {
56
+ setFilters((prevFilters) => [
57
+ ...prevFilters.filter((f) => f.key !== 'status'),
58
+ { key: 'status', value: waitingStatus, label: t('waiting', 'Waiting') },
59
+ ]);
60
+ },
61
+ },
62
+ {
63
+ title: t('patientAttended', 'Patient attended to'),
64
+ value: attendedToEntries?.length?.toString(),
65
+ onClick: () => {
66
+ setFilters((prevFilters) => [
67
+ ...prevFilters.filter((f) => f.key !== 'status'),
68
+ { key: 'status', value: `${finishedStatus},${inServiceStatus}`, label: t('attendedTo', 'Attended to') },
69
+ ]);
70
+ },
71
+ },
72
+ ];
73
+
46
74
  return (
47
- <QueueTab
48
- queues={triageQueues}
49
- navigatePath="mch"
50
- cards={[
51
- {
52
- title: t('patientsAwaiting', 'Patient awaiting'),
53
- value: waitingEntries?.length?.toString(),
54
- onClick: () => {
55
- setFilters((prevFilters) => [
56
- ...prevFilters.filter((f) => f.key !== 'status'),
57
- { key: 'status', value: waitingStatus, label: t('waiting', 'Waiting') },
58
- ]);
59
- },
60
- },
61
- {
62
- title: t('patientAttended', 'Patient attended to'),
63
- value: attendedtoEntries?.length?.toString(),
64
- onClick: () => {
65
- setFilters((prevFilters) => [
66
- ...prevFilters.filter((f) => f.key !== 'status'),
67
- { key: 'status', value: `${finishedStatus},${inServiceStatus}`, label: t('attendedTo', 'Attended to') },
68
- ]);
69
- },
70
- },
71
- ]}
72
- onTabChanged={setCurrQueue}
73
- usePatientChart
74
- filters={filters}
75
- onFiltersChanged={setFilters}
76
- />
75
+ <>
76
+ <QueueSummaryCards cards={cards} />
77
+ <QueueTab
78
+ queues={triageQueues}
79
+ navigatePath="mch"
80
+ onTabChanged={setCurrQueue}
81
+ usePatientChart
82
+ filters={filters}
83
+ onFiltersChanged={setFilters}
84
+ />
85
+ </>
77
86
  );
78
87
  };
79
88
 
@@ -13,6 +13,7 @@ import { InlineLoading } from '@carbon/react';
13
13
 
14
14
  import { useQueues } from '../../hooks/useServiceQueues';
15
15
  import QueueTab from '../../shared/queue/queue-tab.component';
16
+ import QueueSummaryCards, { QueueSummaryCard } from '../../shared/queue/queue-summary-cards.component';
16
17
  import styles from './triage.scss';
17
18
  import { Queue, QueueFilter } from '../../types';
18
19
  import { useTriageQueuesMetrics } from './triage.resource';
@@ -38,13 +39,19 @@ export default Triage;
38
39
 
39
40
  const TriageQueueTab: React.FC = () => {
40
41
  const { t } = useTranslation();
41
- const [currQueue, setCurrQueue] = useState<Queue>();
42
- const { queues, isLoading, error } = useQueues();
43
- const [filters, setFilters] = useState<Array<QueueFilter>>([]);
44
42
  const {
45
43
  queueStatusConceptUuids: { finishedStatus, waitingStatus, inServiceStatus },
46
44
  queueServiceConceptUuids,
47
45
  } = useConfig<ExpressWorkflowConfig>();
46
+ const [currQueue, setCurrQueue] = useState<Queue>();
47
+ const [filters, setFilters] = useState<Array<QueueFilter>>([]);
48
+
49
+ const {
50
+ queues,
51
+ isLoading: isLoadingQueues,
52
+ error: errorLoadingQueues,
53
+ isValidating: isValidatingQueues,
54
+ } = useQueues();
48
55
 
49
56
  const triageQueues = queues
50
57
  .filter(
@@ -60,17 +67,25 @@ const TriageQueueTab: React.FC = () => {
60
67
  error: metricsError,
61
68
  isLoading: isLoadingMetrics,
62
69
  waitingEntries,
63
- attendedtoEntries,
70
+ attendedToEntries,
71
+ isValidating: isValidatingMetrics,
64
72
  } = useTriageQueuesMetrics(activeQueue);
65
73
 
66
- if (isLoadingMetrics) {
74
+ const isLoading = (isLoadingQueues || isLoadingMetrics) && !isValidatingQueues && !isValidatingMetrics;
75
+
76
+ if (isLoading) {
67
77
  return <InlineLoading description={t('loadingQueues', 'Loading queues...')} />;
68
78
  }
69
79
 
70
- if (metricsError) {
71
- return <ErrorState error={metricsError} headerTitle={t('errorLoadingQueues', 'Error loading queues')} />;
80
+ if (metricsError || errorLoadingQueues) {
81
+ return (
82
+ <ErrorState
83
+ error={metricsError ?? errorLoadingQueues}
84
+ headerTitle={t('errorLoadingQueues', 'Error loading queues')}
85
+ />
86
+ );
72
87
  }
73
- const cards = [
88
+ const cards: Array<QueueSummaryCard> = [
74
89
  {
75
90
  title: t('clientsPatientsWaiting', 'Clients/Patients waiting'),
76
91
  value: waitingEntries.length.toString(),
@@ -83,7 +98,7 @@ const TriageQueueTab: React.FC = () => {
83
98
  },
84
99
  {
85
100
  title: t('clientsPatientsAttendedTo', 'Clients/Patients attended to'),
86
- value: attendedtoEntries.length.toString(),
101
+ value: attendedToEntries.length.toString(),
87
102
  onClick: () => {
88
103
  setFilters((prevFilters) => [
89
104
  ...prevFilters.filter((f) => f.key !== 'status'),
@@ -94,14 +109,16 @@ const TriageQueueTab: React.FC = () => {
94
109
  ];
95
110
 
96
111
  return (
97
- <QueueTab
98
- queues={triageQueues}
99
- navigatePath="triage"
100
- usePatientChart
101
- cards={cards}
102
- onTabChanged={setCurrQueue}
103
- filters={filters}
104
- onFiltersChanged={setFilters}
105
- />
112
+ <>
113
+ <QueueSummaryCards cards={cards} />
114
+ <QueueTab
115
+ queues={triageQueues}
116
+ navigatePath="triage"
117
+ usePatientChart
118
+ onTabChanged={setCurrQueue}
119
+ filters={filters}
120
+ onFiltersChanged={setFilters}
121
+ />
122
+ </>
106
123
  );
107
124
  };
@@ -1,62 +1,68 @@
1
- import { useConfig } from '@openmrs/esm-framework';
2
1
  import { useMemo } from 'react';
3
- import { ExpressWorkflowConfig } from '../../config-schema';
2
+ import dayjs from 'dayjs';
3
+ import { useConfig } from '@openmrs/esm-framework';
4
+
5
+ import { type ExpressWorkflowConfig } from '../../config-schema';
4
6
  import { useQueueEntries } from '../../hooks/useServiceQueues';
5
- import { Queue } from '../../types';
7
+ import { type Queue } from '../../types';
6
8
 
7
9
  export const useTriageQueuesMetrics = (queue?: Queue) => {
8
- const { queueServiceConceptUuids, queueStatusConceptUuids } = useConfig<ExpressWorkflowConfig>();
9
- const {
10
- queueEntries: waitingEntries,
11
- isLoading: isLoadingWaiting,
12
- error: waitingError,
13
- } = useQueueEntries({
14
- service: [queueServiceConceptUuids.triageService],
15
- statuses: [queueStatusConceptUuids.waitingStatus],
16
- location: queue?.location?.uuid ? [queue.location.uuid] : undefined,
17
- });
18
- const {
19
- queueEntries: inServiceEntries,
20
- isLoading: isLoadingInService,
21
- error: inServiceError,
22
- } = useQueueEntries({
23
- service: [queueServiceConceptUuids.triageService],
24
- statuses: [queueStatusConceptUuids.inServiceStatus],
25
- location: queue?.location?.uuid ? [queue.location.uuid] : undefined,
26
- });
10
+ const { queueStatusConceptUuids } = useConfig<ExpressWorkflowConfig>();
11
+
27
12
  const {
28
- queueEntries: finishedEntries,
29
- isLoading: isLoadingFinished,
30
- error: finishedError,
13
+ queueEntries: allTriageEntries,
14
+ isLoading,
15
+ error,
16
+ isValidating: isValidatingQueueEntries,
31
17
  } = useQueueEntries({
32
- service: [queueServiceConceptUuids.triageService],
33
- statuses: [queueStatusConceptUuids.finishedStatus],
34
- location: queue?.location?.uuid ? [queue.location.uuid] : undefined,
35
- });
36
- const { queueEntries: attendedtoEntries } = useQueueEntries({
37
- service: [queueServiceConceptUuids.triageService],
38
- statuses: [queueStatusConceptUuids.inServiceStatus, queueStatusConceptUuids.finishedStatus],
39
18
  location: queue?.location?.uuid ? [queue.location.uuid] : undefined,
19
+ startedOnOrAfter: dayjs().subtract(24, 'hour').format('YYYY-MM-DD HH:mm:ss'),
40
20
  });
41
21
 
22
+ const queueUuid = queue?.uuid;
23
+
24
+ const waitingEntries = useMemo(
25
+ () =>
26
+ allTriageEntries.filter(
27
+ (entry) => entry?.queue?.uuid === queueUuid && entry?.status?.uuid === queueStatusConceptUuids.waitingStatus,
28
+ ),
29
+ [allTriageEntries, queueUuid, queueStatusConceptUuids.waitingStatus],
30
+ );
31
+
32
+ const inServiceEntries = useMemo(
33
+ () =>
34
+ allTriageEntries.filter(
35
+ (entry) => entry?.queue?.uuid === queueUuid && entry?.status?.uuid === queueStatusConceptUuids.inServiceStatus,
36
+ ),
37
+ [allTriageEntries, queueUuid, queueStatusConceptUuids.inServiceStatus],
38
+ );
39
+
40
+ const finishedEntries = useMemo(
41
+ () =>
42
+ allTriageEntries.filter(
43
+ (entry) => entry?.queue?.uuid === queueUuid && entry?.status?.uuid === queueStatusConceptUuids.finishedStatus,
44
+ ),
45
+ [allTriageEntries, queueUuid, queueStatusConceptUuids.finishedStatus],
46
+ );
47
+
48
+ const attendedToEntries = useMemo(
49
+ () =>
50
+ allTriageEntries.filter(
51
+ (entry) =>
52
+ entry?.queue?.uuid === queueUuid &&
53
+ (entry?.status?.uuid === queueStatusConceptUuids.inServiceStatus ||
54
+ entry?.status?.uuid === queueStatusConceptUuids.finishedStatus),
55
+ ),
56
+ [allTriageEntries, queueUuid, queueStatusConceptUuids.inServiceStatus, queueStatusConceptUuids.finishedStatus],
57
+ );
58
+
42
59
  return {
43
- isLoading: isLoadingFinished || isLoadingInService || isLoadingWaiting,
44
- waitingEntries: useMemo(
45
- () => waitingEntries.filter((entry) => entry?.queue?.uuid === queue?.uuid),
46
- [waitingEntries, queue],
47
- ),
48
- inServiceEntries: useMemo(
49
- () => inServiceEntries.filter((entry) => entry?.queue?.uuid === queue?.uuid),
50
- [inServiceEntries, queue],
51
- ),
52
- finishedEntries: useMemo(
53
- () => finishedEntries.filter((entry) => entry?.queue?.uuid === queue?.uuid),
54
- [finishedEntries, queue],
55
- ),
56
- attendedtoEntries: useMemo(
57
- () => attendedtoEntries.filter((entry) => entry?.queue?.uuid === queue?.uuid),
58
- [attendedtoEntries, queue],
59
- ),
60
- error: finishedError ?? inServiceError ?? waitingError,
60
+ isLoading,
61
+ waitingEntries,
62
+ inServiceEntries,
63
+ finishedEntries,
64
+ attendedToEntries,
65
+ error,
66
+ isValidating: isValidatingQueueEntries,
61
67
  };
62
68
  };
@@ -1,68 +1,136 @@
1
- import { openmrsFetch, restBaseUrl, useConfig } from '@openmrs/esm-framework';
2
- import dayjs from 'dayjs';
3
1
  import { useMemo } from 'react';
4
- import useSWR from 'swr';
5
- import { ExpressWorkflowConfig } from '../config-schema';
6
- import { Queue, QueueEntry, QueueEntryFilters } from '../types/index';
2
+ import useSWRImmutable from 'swr/immutable';
3
+ import dayjs from 'dayjs';
4
+ import { openmrsFetch, restBaseUrl, useConfig, useOpenmrsPagination } from '@openmrs/esm-framework';
5
+
6
+ import { type ExpressWorkflowConfig } from '../config-schema';
7
+ import { QueueEntriesPagination, type Queue, type QueueEntry, type QueueEntryFilters } from '../types/index';
8
+
9
+ const QUEUE_LIST_REP =
10
+ 'custom:(uuid,display,name,location:(uuid,display),service:(uuid,display),queueRooms:(uuid,display))';
11
+
12
+ const SWR_QUEUE_OPTIONS = {
13
+ dedupingInterval: 5000,
14
+ revalidateOnFocus: false,
15
+ } as const;
7
16
 
8
17
  export const useQueues = () => {
9
- const { data, isLoading, error } = useSWR<{ data: { results: Array<Queue> } }>(
10
- '/ws/rest/v1/queue?v=full',
18
+ const queueListKey = `/ws/rest/v1/queue?v=${encodeURIComponent(QUEUE_LIST_REP)}`;
19
+ const { data, isLoading, error, isValidating } = useSWRImmutable<{ data: { results: Array<Queue> } }>(
20
+ queueListKey,
11
21
  openmrsFetch,
22
+ SWR_QUEUE_OPTIONS,
12
23
  );
13
24
 
14
25
  return {
15
26
  queues: data?.data?.results || [],
16
27
  isLoading,
17
28
  error,
29
+ isValidating,
18
30
  };
19
31
  };
20
32
 
21
- export const useQueueEntries = (filters?: QueueEntryFilters) => {
33
+ export const useQueueEntries = (filters?: QueueEntryFilters, defaultPageSize: number = 100) => {
22
34
  const { outpatientVisitTypeUuid } = useConfig<ExpressWorkflowConfig>();
23
35
  const repString =
24
- 'custom:(uuid,display,queue,status,patient:(uuid,display,person,identifiers:(uuid,display,identifier,identifierType)),visit:(uuid,display,startDatetime,visitType:(uuid,display),encounters:(uuid,display,diagnoses,encounterDatetime,encounterType,obs,encounterProviders,voided),attributes:(uuid,display,value,attributeType)),priority,priorityComment,sortWeight,startedAt,endedAt,locationWaitingFor,queueComingFrom,providerWaitingFor,previousQueueEntry)';
36
+ 'custom:(uuid,queue:(uuid,display,name,location:(uuid,display)),status:(uuid,display),patient:(uuid,person:(uuid,display),identifiers),visit:(uuid,visitType:(uuid),attributes:(uuid,value,attributeType:(uuid))),priority:(uuid,display),priorityComment,startedAt,previousQueueEntry:(uuid,queue:(uuid,display)))';
25
37
 
26
- const buildQueryParams = (filters?: QueueEntryFilters & { status: string[] }): string => {
38
+ const queryString = useMemo(() => {
27
39
  const params = new URLSearchParams();
28
40
  params.append('v', repString);
29
41
 
30
- if (filters) {
31
- Object.entries(filters).forEach(([key, value]) => {
32
- if (value !== undefined && value !== null) {
33
- if (Array.isArray(value)) {
34
- value.forEach((v) => params.append(key, v));
35
- } else {
36
- params.append(key, String(value));
37
- }
42
+ const merged = {
43
+ ...filters,
44
+ status: filters?.statuses ?? [],
45
+ statuses: undefined,
46
+ startedOnOrAfter: filters?.startedOnOrAfter ?? undefined,
47
+ startedOnOrBefore: filters?.startedOnOrBefore ?? undefined,
48
+ };
49
+ if (merged) {
50
+ Object.entries(merged).forEach(([key, value]) => {
51
+ if (key === 'statuses' || value === undefined || value === null) {
52
+ return;
53
+ }
54
+ if (Array.isArray(value)) {
55
+ [...value].sort((a, b) => String(a).localeCompare(String(b))).forEach((v) => params.append(key, v));
56
+ } else {
57
+ params.append(key, String(value));
38
58
  }
39
59
  });
40
60
  }
41
61
 
42
- if (!filters || filters.isEnded === undefined || filters.isEnded === null) {
62
+ if (filters?.isEnded == null) {
43
63
  params.append('isEnded', 'false');
44
64
  }
45
65
 
46
66
  return params.toString();
47
- };
67
+ }, [
68
+ filters?.location?.join(','),
69
+ filters?.service?.join(','),
70
+ [...(filters?.statuses ?? [])].sort((a, b) => String(a).localeCompare(String(b))).join(','),
71
+ filters?.priorities?.join(','),
72
+ filters?.patient,
73
+ filters?.visit,
74
+ filters?.hasVisit,
75
+ filters?.isEnded,
76
+ filters?.locationsWaitingFor?.join(','),
77
+ filters?.providersWaitingFor?.join(','),
78
+ filters?.queuesComingFrom?.join(','),
79
+ ]);
48
80
 
49
- const queryString = buildQueryParams({ ...filters, status: filters?.statuses ?? [], statuses: [] });
50
- const url = `/ws/rest/v1/queue-entry${queryString ? `?${queryString}` : ''}`;
81
+ const url = queryString ? `/ws/rest/v1/queue-entry?${queryString}` : '/ws/rest/v1/queue-entry';
82
+
83
+ const {
84
+ data,
85
+ isLoading,
86
+ isValidating,
87
+ error,
88
+ totalPages,
89
+ totalCount,
90
+ currentPage,
91
+ currentPageSize,
92
+ paginated,
93
+ showNextButton,
94
+ showPreviousButton,
95
+ goTo,
96
+ goToNext,
97
+ goToPrevious,
98
+ } = useOpenmrsPagination<QueueEntry>(url, defaultPageSize, {
99
+ swrConfig: {
100
+ dedupingInterval: 2000,
101
+ revalidateOnFocus: false,
102
+ keepPreviousData: true,
103
+ },
104
+ });
51
105
 
52
- const { data, isLoading, error } = useSWR<{ data: { results: Array<QueueEntry> } }>(url, openmrsFetch);
53
106
  const queueEntries = useMemo(() => {
54
- return (data?.data?.results ?? [])?.filter((entry) => {
107
+ return (data ?? [])?.filter((entry) => {
55
108
  return (
56
109
  dayjs(entry.startedAt).isAfter(dayjs().subtract(24, 'hour')) &&
57
110
  entry?.visit?.visitType?.uuid === outpatientVisitTypeUuid
58
111
  );
59
112
  });
60
- }, [data?.data?.results, outpatientVisitTypeUuid]);
113
+ }, [data, outpatientVisitTypeUuid]);
114
+
115
+ const pagination: QueueEntriesPagination = {
116
+ totalPages,
117
+ totalCount,
118
+ currentPage,
119
+ currentPageSize,
120
+ paginated,
121
+ showNextButton,
122
+ showPreviousButton,
123
+ goTo,
124
+ goToNext,
125
+ goToPrevious,
126
+ };
61
127
 
62
128
  return {
63
129
  queueEntries,
64
130
  isLoading,
131
+ isValidating,
65
132
  error,
133
+ pagination,
66
134
  };
67
135
  };
68
136
  export function serveQueueEntry(servicePointName: string, ticketNumber: string, status: string, locationUuid?: string) {