Skip to content

Commit 258d068

Browse files
authored
Ft/board/queuing (#103)
* fix: remove unused details * ft: queue board Signed-off-by: Isaac Obella <wizlif@users.noreply.github.com> * ft: ticket announcer --------- Signed-off-by: Isaac Obella <wizlif@users.noreply.github.com>
1 parent beae02b commit 258d068

21 files changed

+346
-30
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"base-64": "^1.0.0",
2626
"buffer": "^6.0.3",
2727
"dayjs": "^1.11.6",
28+
"react-full-screen": "^1.1.1",
2829
"react-grid-layout": "^1.3.4",
2930
"react-to-print": "^2.14.13",
3031
"recharts": "^2.7.2",

packages/esm-patient-queues-app/src/active-visits-print/active-visits-print.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
tr td:first-child {
3636
font-weight: bold;
37+
padding-right: spacing.$spacing-03;
3738
}
3839

3940
tr td:nth-child(2) {

packages/esm-patient-queues-app/src/active-visits-print/patient-queue-details-table.component.tsx

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,16 @@ const PatientQueueDetailsTable: React.FC<PrintTableProps> = ({ queueEntry }) =>
1212
<table>
1313
<tbody>
1414
<tr className={styles.name}>
15-
<td align="right">Check In Date:&nbsp;</td>
16-
<td>{queueEntry.dateCreated}</td>
17-
</tr>
18-
<tr className={styles.name}>
19-
<td align="right">Patient Name:&nbsp;</td>
20-
<td>{queueEntry.name}</td>
21-
</tr>
22-
<tr className={styles.name}>
23-
<td align="right">Visit No:&nbsp;</td>
15+
<td align="right">Visit No:</td>
2416
<td>{trimVisitNumber(queueEntry.visitNumber)}</td>
2517
</tr>
2618
<tr className={styles.name}>
27-
<td align="right">Gender:&nbsp;</td>
28-
<td>{queueEntry.patientSex}</td>
29-
</tr>
30-
<tr className={styles.name}>
31-
<td align="right">Entry Point:&nbsp;</td>
19+
<td align="right">Entry Point:</td>
3220
<td>{queueEntry.creatorDisplay}</td>
3321
</tr>
3422

3523
<tr className={styles.name}>
36-
<td align="right">Attendant:&nbsp;</td>
24+
<td align="right">Attendant:</td>
3725
<td>{queueEntry.creatorUsername}</td>
3826
</tr>
3927
</tbody>

packages/esm-patient-queues-app/src/active-visits/active-visits-table.component.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import {
77
Layer,
88
Pagination,
99
Tab,
10-
TabList,
11-
TabPanel,
12-
TabPanels,
1310
Table,
1411
TableBody,
1512
TableCell,
1613
TableContainer,
14+
TableExpandedRow,
1715
TableExpandHeader,
1816
TableExpandRow,
19-
TableExpandedRow,
2017
TableHead,
2118
TableHeader,
2219
TableRow,
2320
TableToolbar,
2421
TableToolbarContent,
2522
TableToolbarSearch,
23+
TabList,
24+
TabPanel,
25+
TabPanels,
2626
Tabs,
2727
Tag,
2828
Tile,
@@ -31,30 +31,22 @@ import { Add, Dashboard } from '@carbon/react/icons';
3131

3232
import {
3333
ConfigObject,
34-
ConfigurableLink,
3534
ExtensionSlot,
36-
UserHasAccess,
3735
interpolateUrl,
3836
isDesktop,
3937
navigate,
4038
useConfig,
4139
useLayoutType,
4240
usePagination,
41+
UserHasAccess,
4342
useSession,
4443
} from '@openmrs/esm-framework';
4544
import React, { AnchorHTMLAttributes, MouseEvent, useMemo, useState } from 'react';
4645
import { useTranslation } from 'react-i18next';
4746
import { PRIVILEGE_CHECKIN } from '../constants';
4847
import { buildStatusString, formatWaitTime, getTagColor, getTagType, trimVisitNumber } from '../helpers/functions';
49-
import {
50-
useSelectedQueueLocationUuid,
51-
useSelectedQueueRoomLocationName,
52-
useSelectedQueueRoomLocationUuid,
53-
} from '../helpers/helpers';
5448
import PastVisit from '../past-visit/past-visit.component';
55-
import { useQueueRoomLocations } from '../patient-search/hooks/useQueueRooms';
5649
import PatientSearch from '../patient-search/patient-search.component';
57-
import ActionsMenu from '../queue-entry-table-components/actions-menu.component';
5850
import StatusIcon from '../queue-entry-table-components/status-icon.component';
5951
import { SearchTypes } from '../types';
6052
import { getOriginFromPathName } from './active-visits-table.resource';

packages/esm-patient-queues-app/src/active-visits/patient-queues.resource.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface MappedPatientQueueEntry {
1616
status: string;
1717
waitTime: string;
1818
locationFrom?: string;
19+
locationToName?: string;
1920
visitNumber: string;
2021
identifiers: Array<UuidDisplay>;
2122
dateCreated: string;
@@ -24,8 +25,12 @@ export interface MappedPatientQueueEntry {
2425
creatorDisplay: string;
2526
}
2627

27-
export function usePatientQueuesList(currentQueueLocationUuid: string, status: string) {
28-
const apiUrl = `/ws/rest/v1/patientqueue?v=full&location=${currentQueueLocationUuid}&status=${status}`;
28+
export function usePatientQueuesList(currentQueueRoomLocationUuid: string, status: string) {
29+
const apiUrl = `/ws/rest/v1/patientqueue?v=full&room=${currentQueueRoomLocationUuid}&status=${status}`;
30+
return usePatientQueueRequest(apiUrl);
31+
}
32+
33+
export function usePatientQueueRequest(apiUrl: string) {
2934
const { data, error, isLoading, isValidating, mutate } = useSWR<{ data: { results: Array<PatientQueue> } }, Error>(
3035
apiUrl,
3136
openmrsFetch,
@@ -50,6 +55,7 @@ export function usePatientQueuesList(currentQueueLocationUuid: string, status: s
5055
identifiers: queue.patient?.identifiers,
5156
locationFrom: queue.locationFrom?.uuid,
5257
locationTo: queue.locationTo?.uuid,
58+
locationToName: queue.locationTo?.name,
5359
queueRoom: queue.locationTo?.display,
5460
visitNumber: queue.visitNumber,
5561
dateCreated: queue.dateCreated ? formatDate(parseDate(queue.dateCreated), { time: false }) : '--',

packages/esm-patient-queues-app/src/home.component.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ import {
99
} from './constants';
1010
import PatientQueueHeader from './patient-queue-header/patient-queue-header.component';
1111
import ClinicMetrics from './patient-queue-metrics/clinic-metrics.component';
12+
import QueueLauncher from './queue-launcher/queue-launcher.component';
1213

1314
interface HomeProps {}
1415

1516
const Home: React.FC<HomeProps> = (props) => {
1617
return (
1718
<div>
1819
<PatientQueueHeader />
20+
<UserHasAccess privilege={PRIVILEGE_RECEPTION_QUEUE_LIST}>
21+
<QueueLauncher />
22+
</UserHasAccess>
1923
<ClinicMetrics />
2024
<UserHasAccess privilege={PRIVILEGE_RECEPTION_QUEUE_LIST}>
2125
<ActiveVisitsReceptionTable />

packages/esm-patient-queues-app/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const options = {
1010
featureName: 'patient queues',
1111
moduleName,
1212
};
13+
1314
export function startupApp() {
1415
defineConfigSchema(moduleName, configSchema);
1516
}
@@ -119,3 +120,5 @@ export const queuePatientsWorkspace = getAsyncLifecycle(
119120
moduleName,
120121
},
121122
);
123+
124+
export const queueScreen = getAsyncLifecycle(() => import('./queue-board/queue-board.component'), options);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React from 'react';
2+
import { usePatientQueuesByParentLocation } from '../queue-board.resource';
3+
import { SkeletonPlaceholder, SkeletonText } from '@carbon/react';
4+
import styles from './base-board.scss';
5+
import { TicketCard } from './ticket-card.component';
6+
7+
interface BaseBoardProps {
8+
title: string;
9+
status: string;
10+
hasBorder?: boolean;
11+
isFullScreen: boolean;
12+
}
13+
14+
const BaseBoardComponent: React.FC<BaseBoardProps> = ({ title, status, hasBorder, isFullScreen }) => {
15+
const { patientQueues, isLoading, isError } = usePatientQueuesByParentLocation(status);
16+
17+
if (isLoading || isError || !patientQueues)
18+
return (
19+
<div>
20+
<SkeletonText />
21+
<div className={styles.gridFlow}>
22+
{[...Array(hasBorder ? 5 : 1).keys()].map(() => (
23+
<SkeletonPlaceholder
24+
style={{
25+
width: '30%',
26+
margin: '1.5rem',
27+
padding: '1.3rem',
28+
}}
29+
/>
30+
))}
31+
</div>
32+
</div>
33+
);
34+
35+
return (
36+
<div
37+
style={{
38+
borderRight: hasBorder ? '1px solid grey' : '',
39+
height: isFullScreen ? '100vh' : 'calc(100vh - 50px)',
40+
overflow: 'scroll',
41+
paddingRight: hasBorder ? '20px' : '',
42+
}}
43+
>
44+
<h1 className={styles.heading}>{title}</h1>
45+
<div className={styles.gridFlow}>
46+
{patientQueues
47+
.sort((a, b) => (a.dateCreated < b.dateCreated ? 0 : 1))
48+
.map((queueEntry) => {
49+
return <TicketCard queue={queueEntry} />;
50+
})}
51+
</div>
52+
</div>
53+
);
54+
};
55+
56+
export default BaseBoardComponent;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
@use '@carbon/styles/scss/colors';
2+
@use "@carbon/styles/scss/spacing";
3+
@import '~@openmrs/esm-styleguide/src/vars';
4+
5+
.tile-text {
6+
font-size: 3rem;
7+
padding: 1rem;
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
color: $brand-primary-50;
12+
}
13+
14+
.heading {
15+
padding-bottom: spacing.$spacing-08;
16+
text-align: center;
17+
text-transform: uppercase;
18+
}
19+
20+
.tile {
21+
display: flex;
22+
justify-content: center;
23+
align-items: center;
24+
flex-direction: column;
25+
margin-bottom: spacing.$spacing-03;
26+
padding: 1.5rem;
27+
}
28+
29+
.gridFlow {
30+
display: flex;
31+
flex-direction: row;
32+
padding: 2rem;
33+
flex-wrap: wrap;
34+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import styles from '../../queue-screen/queue-screen.scss';
2+
import React from 'react';
3+
import { useTranslation } from 'react-i18next';
4+
import { PatientQueue } from '../../types/patient-queues';
5+
import { trimVisitNumber } from '../../helpers/functions';
6+
7+
interface TicketCardProp {
8+
queue: PatientQueue;
9+
}
10+
11+
export const TicketCard: React.FC<TicketCardProp> = ({ queue }) => {
12+
const { t } = useTranslation();
13+
return (
14+
<div className={styles.card}>
15+
<p className={styles.subHeader}>{t('ticketNumber', 'Ticket number')}</p>
16+
<p className={queue.status === 'picked' ? styles.headerBlinking : styles.header}>
17+
{trimVisitNumber(queue.visitNumber)}
18+
</p>
19+
<p className={styles.subHeader}>
20+
{t('room', 'Room')} &nbsp; : &nbsp; {queue.locationTo?.name}
21+
</p>
22+
</div>
23+
);
24+
};

0 commit comments

Comments
 (0)