Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

UHM-7439, add queue table metrics #1118

Merged
merged 7 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/esm-service-queues-app/src/hooks/useQueueEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,28 @@ export function useQueueEntries(searchCriteria?: QueueEntrySearchCriteria, rep:
...rest,
};
}

export function useQueueEntriesMetrics(searchCriteria?: QueueEntrySearchCriteria) {
const searchParam = new URLSearchParams();
for (let [key, value] of Object.entries(searchCriteria)) {
if (value != null) {
searchParam.append(key, value?.toString());
}
}
const apiUrl = `${restBaseUrl}/queue-entry-metrics?` + searchParam.toString();

const { data } = useSWR<
{
data: {
count: number;
averageWaitTime: number;
};
},
Error
>(apiUrl, openmrsFetch);

return {
count: data ? data?.data?.count : 0,
averageWaitTime: data?.data?.averageWaitTime,
};
}
2 changes: 1 addition & 1 deletion packages/esm-service-queues-app/src/hooks/useQueues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { type Queue } from '../types';

export function useQueues(locationUuid?: string) {
const customRepresentation =
'custom:(uuid,display,name,description,allowedPriorities:(uuid,display),allowedStatuses:(uuid,display),location:(uuid,display))';
'custom:(uuid,display,name,description,service:(uuid,display),allowedPriorities:(uuid,display),allowedStatuses:(uuid,display),location:(uuid,display))';
const apiUrl = `${restBaseUrl}/queue?v=${customRepresentation}` + (locationUuid ? `&location=${locationUuid}` : '');

const { data, ...rest } = useSWRImmutable<{ data: { results: Array<Queue> } }, Error>(apiUrl, openmrsFetch);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React from 'react';
import classNames from 'classnames';
import { useTranslation } from 'react-i18next';
import { Layer, Tile } from '@carbon/react';
import { useQueueEntriesMetrics } from '../hooks/useQueueEntries';
import styles from './queue-table-metrics-card.scss';

interface QueueTableMetricsCardProps {
value?: number;
queueUuid?: string;
status?: string;
headerLabel: string;
children?: React.ReactNode;
}

const QueueTableMetricsCard: React.FC<QueueTableMetricsCardProps> = ({
value,
queueUuid,
status,
headerLabel,
children,
}) => {
const { t } = useTranslation();
const { count } = useQueueEntriesMetrics({
queue: queueUuid,
status: status,
isEnded: false,
});

return (
<Layer
className={classNames(styles.container, {
[styles.cardWithChildren]: children,
})}>
<Tile className={styles.tileContainerWithoutBorder}>
<div className={styles.tileHeader}>
<div className={styles.headerLabelContainer}>
<label className={styles.headerLabel}>{headerLabel}</label>
{children}
</div>
</div>
<div>
<label className={styles.valueLabel}>{!isNaN(value) ? value : count}</label>
</div>
</Tile>
</Layer>
);
};

export default QueueTableMetricsCard;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@use '@carbon/styles/scss/spacing';
@use '@carbon/styles/scss/type';
@import '~@openmrs/esm-styleguide/src/vars';

.container {
flex-grow: 1;
}

/* Tablet viewport */
:global(.omrs-breakpoint-lt-desktop) {
// The card containing the dropdown element should be the first to overflow on tablet
.cardWithChildren {
order: 3;
}
}

.tileContainerWithoutBorder {
height: 4.875rem;
}

.tileHeader {
display: flex;
justify-content: space-between;
align-items: baseline;
}

.headerLabel {
@include type.type-style('heading-compact-01');
color: $text-02;
}

.valueLabel {
font-size: x-large;
}

.headerLabelContainer {
display: flex;
height: spacing.$spacing-07;

:global(.cds--dropdown__wrapper--inline) {
gap: 0;
margin-top: -0.75rem;
}

:global(.cds--list-box__menu-icon) {
height: 1rem;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useQueueEntries, useQueueEntriesMetrics } from '../hooks/useQueueEntries';
import QueueTableMetricsCard from './queue-table-metrics-card.component';
import styles from './queue-table-metrics.scss';
import { type Queue } from '../types';

interface QueueTableMetricsProps {
selectedQueue: Queue;
}

function QueueTableMetrics({ selectedQueue }: QueueTableMetricsProps) {
const { t } = useTranslation();

const allowedStatuses = selectedQueue.allowedStatuses;
const { count } = useQueueEntriesMetrics({ queue: selectedQueue.uuid, isEnded: false });

return (
<div className={styles.metricsBorder}>
<QueueTableMetricsCard value={count} headerLabel={t('totalPatients', 'Total Patients')} />
{allowedStatuses?.map((status) => {
return (
<QueueTableMetricsCard queueUuid={selectedQueue.uuid} status={status.uuid} headerLabel={status.display} />
);
})}
</div>
);
}

export default QueueTableMetrics;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@use '@carbon/styles/scss/spacing';
@import '~@openmrs/esm-styleguide/src/vars';

.metricsBorder {
border: 0.0625rem solid $ui-03;
background-color: $ui-02;
display: flex;
justify-content: space-between;
flex-flow: row wrap;
margin-top: -(spacing.$spacing-03);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { queueTableActionColumn } from '../queue-table/cells/queue-table-action-
import PatientSearch from '../patient-search/patient-search.component';
import { Add } from '@carbon/react/icons';
import { Search } from '@carbon/react';
import QueueTableMetrics from '../queue-table/queue-table-metrics.component';

interface QueueTablesForAllStatusesProps {
selectedQueue: Queue; // the selected queue
Expand Down Expand Up @@ -83,6 +84,9 @@ const QueueTablesForAllStatuses: React.FC<QueueTablesForAllStatusesProps> = ({ s
<div className={isDesktop(layout) ? styles.desktopHeading : styles.tabletHeading}>
<h3>{selectedQueue.display}</h3>
</div>
<div>
<QueueTableMetrics selectedQueue={selectedQueue} />
</div>
<div className={styles.headerButtons}>
<ExtensionSlot
name="patient-search-button-slot"
Expand Down
1 change: 1 addition & 0 deletions packages/esm-service-queues-app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@
"time": "Time",
"tirageNotYetCompleted": "Triage has not yet been completed",
"today": "Today",
"totalPatients": "Total Patients",
"transfer": "Transfer",
"transition": "Transition",
"transitionPatient": "Transition patient",
Expand Down