@kenyaemr/esm-bed-management-app 1.0.1-pre.11

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 (137) hide show
  1. package/.editorconfig +12 -0
  2. package/.eslintignore +2 -0
  3. package/.eslintrc +37 -0
  4. package/.husky/pre-commit +4 -0
  5. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  6. package/.idea/modules.xml +8 -0
  7. package/.idea/vcs.xml +6 -0
  8. package/.prettierignore +14 -0
  9. package/.turbo.json +18 -0
  10. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
  11. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +550 -0
  12. package/.yarn/versions/3d353a50.yml +0 -0
  13. package/LICENSE +373 -0
  14. package/README.md +40 -0
  15. package/dist/207.js +1 -0
  16. package/dist/207.js.map +1 -0
  17. package/dist/26.js +2 -0
  18. package/dist/26.js.LICENSE.txt +32 -0
  19. package/dist/26.js.map +1 -0
  20. package/dist/283.js +1 -0
  21. package/dist/283.js.map +1 -0
  22. package/dist/294.js +2 -0
  23. package/dist/294.js.LICENSE.txt +9 -0
  24. package/dist/294.js.map +1 -0
  25. package/dist/330.js +2 -0
  26. package/dist/330.js.LICENSE.txt +44 -0
  27. package/dist/330.js.map +1 -0
  28. package/dist/404.js +1 -0
  29. package/dist/404.js.map +1 -0
  30. package/dist/455.js +2 -0
  31. package/dist/455.js.LICENSE.txt +9 -0
  32. package/dist/455.js.map +1 -0
  33. package/dist/558.js +2 -0
  34. package/dist/558.js.LICENSE.txt +14 -0
  35. package/dist/558.js.map +1 -0
  36. package/dist/574.js +1 -0
  37. package/dist/629.js +1 -0
  38. package/dist/629.js.map +1 -0
  39. package/dist/637.js +1 -0
  40. package/dist/637.js.map +1 -0
  41. package/dist/707.js +1 -0
  42. package/dist/707.js.map +1 -0
  43. package/dist/800.js +2 -0
  44. package/dist/800.js.LICENSE.txt +3 -0
  45. package/dist/800.js.map +1 -0
  46. package/dist/850.js +1 -0
  47. package/dist/850.js.map +1 -0
  48. package/dist/884.js +1 -0
  49. package/dist/884.js.map +1 -0
  50. package/dist/933.js +1 -0
  51. package/dist/933.js.map +1 -0
  52. package/dist/esm-kenyaemr-bed-management-app.js +1 -0
  53. package/dist/esm-kenyaemr-bed-management-app.js.buildmanifest.json +506 -0
  54. package/dist/esm-kenyaemr-bed-management-app.js.map +1 -0
  55. package/dist/main.js +1 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/routes.json +1 -0
  58. package/i18next-parser.config.js +89 -0
  59. package/jest.config.js +0 -0
  60. package/package.json +112 -0
  61. package/src/__mocks__/react-i18next.js +55 -0
  62. package/src/admin-card-link.component.tsx +27 -0
  63. package/src/assets/landing-page.png +0 -0
  64. package/src/assets/logo.svg +1 -0
  65. package/src/bed-administration/bed-administration-form.component.tsx +326 -0
  66. package/src/bed-administration/bed-administration-form.scss +0 -0
  67. package/src/bed-administration/bed-administration-table.component.tsx +317 -0
  68. package/src/bed-administration/bed-administration-table.scss +112 -0
  69. package/src/bed-administration/bed-administration-types.ts +20 -0
  70. package/src/bed-administration/bed-administration.resource.ts +59 -0
  71. package/src/bed-administration/edit-bed-form.component.tsx +100 -0
  72. package/src/bed-administration/new-bed-form.component.tsx +112 -0
  73. package/src/bed-admission/active-patients/active-patients-table.component.tsx +299 -0
  74. package/src/bed-admission/active-patients/active-visits.resource.ts +171 -0
  75. package/src/bed-admission/active-patients/admission-action-button-styles.scss +0 -0
  76. package/src/bed-admission/active-patients/admission-action-button.component.tsx +26 -0
  77. package/src/bed-admission/active-patients/index.tsx +15 -0
  78. package/src/bed-admission/active-patients/patient-queues.resource.ts +136 -0
  79. package/src/bed-admission/active-patients/styles.scss +284 -0
  80. package/src/bed-admission/active-patients/view-action-menu.component.tsx +33 -0
  81. package/src/bed-admission/admitted-patients/active-admissions.resource.ts +125 -0
  82. package/src/bed-admission/admitted-patients/admitted-patients-table.component.tsx +280 -0
  83. package/src/bed-admission/admitted-patients/admitted-patients.component.tsx +22 -0
  84. package/src/bed-admission/admitted-patients/location-combo-box.component.tsx +55 -0
  85. package/src/bed-admission/admitted-patients/styles.scss +284 -0
  86. package/src/bed-admission/bed-admission-tabs-styles.scss +30 -0
  87. package/src/bed-admission/bed-admission-tabs.component.tsx +69 -0
  88. package/src/bed-admission/bed-admission.component.tsx +15 -0
  89. package/src/bed-admission/bed-admission.resource.ts +52 -0
  90. package/src/bed-admission/bed-layout/bed-layout-list.component.tsx +101 -0
  91. package/src/bed-admission/bed-layout/bed-layout.component.tsx +64 -0
  92. package/src/bed-admission/bed-layout/bed-layout.scss +118 -0
  93. package/src/bed-admission/bed-layout/min-bed-layout.component.tsx +26 -0
  94. package/src/bed-admission/bed-tag/bed-tag-administration-table.component.tsx +217 -0
  95. package/src/bed-admission/bed-tag/bed-tags-admin-form.component.tsx +131 -0
  96. package/src/bed-admission/bed-tag/edit-tag-form.component.tsx +80 -0
  97. package/src/bed-admission/bed-tag/new-tag-form.component.tsx +83 -0
  98. package/src/bed-admission/bed-type/bed-type-admin-form.component.tsx +173 -0
  99. package/src/bed-admission/bed-type/bed-type-administration-table.component.tsx +222 -0
  100. package/src/bed-admission/bed-type/edit-bed-type.component.tsx +80 -0
  101. package/src/bed-admission/bed-type/new-bed-type-form.component.tsx +87 -0
  102. package/src/bed-admission/createDashboardLink.tsx +47 -0
  103. package/src/bed-admission/discharged-patients/discharged-patients.componet.tsx +19 -0
  104. package/src/bed-admission/helpers/functions.ts +102 -0
  105. package/src/bed-admission/types.ts +133 -0
  106. package/src/config-schema.ts +31 -0
  107. package/src/declarations.d.ts +7 -0
  108. package/src/empty-state/empty-state.component.tsx +69 -0
  109. package/src/empty-state/empty-state.scss +62 -0
  110. package/src/header/header.component.tsx +51 -0
  111. package/src/header/header.scss +72 -0
  112. package/src/header/illustration.component.tsx +13 -0
  113. package/src/home.component.tsx +15 -0
  114. package/src/home.scss +5 -0
  115. package/src/index.ts +78 -0
  116. package/src/left-panel/left-panel.component.tsx +33 -0
  117. package/src/left-panel/left-panel.scss +41 -0
  118. package/src/left-panel-link.component.tsx +49 -0
  119. package/src/root.component.tsx +39 -0
  120. package/src/root.scss +11 -0
  121. package/src/routes.json +56 -0
  122. package/src/setup-tests.ts +1 -0
  123. package/src/summary/summary.component.tsx +74 -0
  124. package/src/summary/summary.resource.ts +211 -0
  125. package/src/summary/summary.scss +72 -0
  126. package/src/types.ts +163 -0
  127. package/src/ward-card/ward-card.component.tsx +41 -0
  128. package/src/ward-card/ward-card.scss +51 -0
  129. package/src/ward-with-beds/ward-with-beds.component.tsx +186 -0
  130. package/src/ward-with-beds/ward-with-beds.scss +27 -0
  131. package/src/workspace/allocate-bed-workspace.component.tsx +188 -0
  132. package/src/workspace/allocate-bed.scss +124 -0
  133. package/src/workspace/overlay.component.tsx +55 -0
  134. package/src/workspace/overlay.scss +96 -0
  135. package/translations/en.json +7 -0
  136. package/tsconfig.json +23 -0
  137. package/webpack.config.js +1 -0
@@ -0,0 +1,112 @@
1
+ import React, { useCallback } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import { showToast, showNotification, useConfig } from "@openmrs/esm-framework";
4
+
5
+ import type { InitialData, Mutator } from "../types";
6
+ import { useBedType, saveBed } from "./bed-administration.resource";
7
+ import BedAdministrationForm from "./bed-administration-form.component";
8
+ import { useLocationsByTag } from "../summary/summary.resource";
9
+ import { BedAdministrationData } from "./bed-administration-types";
10
+
11
+ interface NewBedFormProps {
12
+ showModal: boolean;
13
+ onModalChange: (showModal: boolean) => void;
14
+ mutate: Mutator;
15
+ }
16
+
17
+ const NewBedForm: React.FC<NewBedFormProps> = ({
18
+ showModal,
19
+ onModalChange,
20
+ mutate,
21
+ }) => {
22
+ const { t } = useTranslation();
23
+ const { admissionLocationTagUuid } = useConfig();
24
+ const { data: admissionLocations } = useLocationsByTag(
25
+ admissionLocationTagUuid
26
+ );
27
+ const headerTitle = t("createNewBed", "Create a new bed");
28
+ const occupancyStatuses = ["Available", "Occupied"];
29
+ const { bedTypes } = useBedType();
30
+ const availableBedTypes = bedTypes ? bedTypes : [];
31
+
32
+ const initialData: InitialData = {
33
+ uuid: "",
34
+ bedNumber: "",
35
+ status: "",
36
+ description: "",
37
+ row: 0,
38
+ column: 0,
39
+ location: {
40
+ display: "",
41
+ uuid: "",
42
+ },
43
+ bedType: {
44
+ name: "",
45
+ },
46
+ };
47
+
48
+ const handleCreateQuestion = useCallback(
49
+ (formData: BedAdministrationData) => {
50
+ const {
51
+ bedId,
52
+ description,
53
+ occupancyStatus,
54
+ bedRow,
55
+ bedColumn,
56
+ location,
57
+ bedType,
58
+ } = formData;
59
+
60
+ const bedObject = {
61
+ bedNumber: bedId,
62
+ bedType,
63
+ description,
64
+ status: occupancyStatus.toUpperCase(),
65
+ row: parseInt(bedRow.toString()),
66
+ column: parseInt(bedColumn.toString()),
67
+ locationUuid: location.uuid,
68
+ };
69
+
70
+ saveBed({ bedPayload: bedObject })
71
+ .then(() => {
72
+ showToast({
73
+ title: t("formCreated", "New bed created"),
74
+ kind: "success",
75
+ critical: true,
76
+ description: `Bed ${bedId} was created successfully.`,
77
+ });
78
+
79
+ mutate();
80
+ onModalChange(false);
81
+ })
82
+ .catch((error) => {
83
+ showNotification({
84
+ title: t("errorCreatingForm", "Error creating bed"),
85
+ kind: "error",
86
+ critical: true,
87
+ description: error?.message,
88
+ });
89
+ onModalChange(false);
90
+ });
91
+ onModalChange(false);
92
+ },
93
+ [onModalChange, mutate, t]
94
+ );
95
+
96
+ return (
97
+ <>
98
+ <BedAdministrationForm
99
+ onModalChange={onModalChange}
100
+ allLocations={admissionLocations}
101
+ availableBedTypes={availableBedTypes}
102
+ showModal={showModal}
103
+ handleCreateQuestion={handleCreateQuestion}
104
+ headerTitle={headerTitle}
105
+ occupancyStatuses={occupancyStatuses}
106
+ initialData={initialData}
107
+ />
108
+ </>
109
+ );
110
+ };
111
+
112
+ export default NewBedForm;
@@ -0,0 +1,299 @@
1
+ import {
2
+ DataTable,
3
+ DataTableSkeleton,
4
+ DefinitionTooltip,
5
+ Pagination,
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableContainer,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ Tag,
14
+ Layer,
15
+ TableToolbar,
16
+ TableToolbarContent,
17
+ TableToolbarSearch,
18
+ TableExpandedRow,
19
+ TableExpandHeader,
20
+ TableExpandRow,
21
+ } from "@carbon/react";
22
+
23
+ import {
24
+ isDesktop,
25
+ useConfig,
26
+ useLayoutType,
27
+ usePagination,
28
+ useSession,
29
+ } from "@openmrs/esm-framework";
30
+ import React, { useCallback, useMemo, useState } from "react";
31
+ import { useTranslation } from "react-i18next";
32
+ import {
33
+ formatWaitTime,
34
+ getOriginFromPathName,
35
+ getTagColor,
36
+ getTagType,
37
+ trimVisitNumber,
38
+ } from "../helpers/functions";
39
+ import styles from "./styles.scss";
40
+ import { usePatientQueuesList } from "./patient-queues.resource";
41
+ import { useActiveVisits } from "./active-visits.resource";
42
+ import EmptyState from "../../empty-state/empty-state.component";
43
+ import AssignBedWorkSpace from "../../workspace/allocate-bed-workspace.component";
44
+ import AdmissionActionButton from "./admission-action-button.component";
45
+ import { patientDetailsProps } from "../types";
46
+ import ViewActionsMenu from "./view-action-menu.component";
47
+
48
+ interface ActiveVisitsTableProps {
49
+ status: string;
50
+ setPatientCount?: (value: number) => void;
51
+ }
52
+
53
+ const ActivePatientsTable: React.FC<ActiveVisitsTableProps> = ({
54
+ status,
55
+ setPatientCount,
56
+ }) => {
57
+ const { t } = useTranslation();
58
+ const session = useSession();
59
+ const currentPathName: string = window.location.pathname;
60
+ const fromPage: string = getOriginFromPathName(currentPathName);
61
+ const pageSizes = [10, 20, 30, 40, 50];
62
+ const [currentPageSize, setPageSize] = useState(10);
63
+ const [showOverlay, setShowOverlay] = useState(false);
64
+ const [selectedPatientDetails, setSelectedPatientDetails] =
65
+ useState<patientDetailsProps>();
66
+
67
+ const layout = useLayoutType();
68
+
69
+ const { patientQueueEntries, isLoading } = useActiveVisits();
70
+ const { restrictWardAdministrationToLoginLocation } = useConfig();
71
+
72
+ const handleBedAssigmentModal = useCallback(
73
+ (entry) => {
74
+ setSelectedPatientDetails({
75
+ name: entry.name,
76
+ patientUuid: entry.patientUuid,
77
+ encounter: entry.encounter,
78
+ locationUuid: session?.sessionLocation?.uuid,
79
+ locationTo: entry.locationTo,
80
+ locationFrom: entry.locationFrom,
81
+ queueUuid: entry.uuid,
82
+ });
83
+ setShowOverlay(true);
84
+ },
85
+ [session?.sessionLocation?.uuid]
86
+ );
87
+
88
+ const renderActionButton = useCallback(
89
+ (entry) => {
90
+ const buttonTexts = {
91
+ pending: "Assign Bed",
92
+ completed: "Transfer",
93
+ };
94
+ const buttonText = buttonTexts[status] || "Un-assign";
95
+
96
+ return (
97
+ <AdmissionActionButton
98
+ entry={entry}
99
+ handleBedAssigmentModal={handleBedAssigmentModal}
100
+ buttonText={buttonText}
101
+ />
102
+ );
103
+ },
104
+ [handleBedAssigmentModal, status]
105
+ );
106
+
107
+ const {
108
+ goTo,
109
+ results: paginatedQueueEntries,
110
+ currentPage,
111
+ } = usePagination(patientQueueEntries, currentPageSize);
112
+
113
+ const tableHeaders = useMemo(
114
+ () => [
115
+ {
116
+ id: 0,
117
+ header: t("name", "Name"),
118
+ key: "name",
119
+ },
120
+ {
121
+ id: 1,
122
+ header: t("idNumber", "Identifier"),
123
+ key: "idNumber",
124
+ },
125
+ {
126
+ id: 2,
127
+ header: t("gender", "Gender"),
128
+ key: "gender",
129
+ },
130
+ {
131
+ id: 3,
132
+ header: t("age", "Age"),
133
+ key: "age",
134
+ },
135
+ {
136
+ id: 4,
137
+ header: t("visitType", "Visit type"),
138
+ key: "visitType",
139
+ },
140
+ {
141
+ id: 5,
142
+ header: t("visitStartTime", "Visit start date/time"),
143
+ key: "visitStartTime",
144
+ },
145
+ {
146
+ id: 6,
147
+ header: t("action", "Action"),
148
+ key: "actions",
149
+ },
150
+ ],
151
+ [t]
152
+ );
153
+
154
+ const tableRows = useMemo(() => {
155
+ return paginatedQueueEntries?.map((entry) => ({
156
+ ...entry,
157
+ actions: {
158
+ content: (
159
+ <div className={styles.displayFlex}>{renderActionButton(entry)}</div>
160
+ ),
161
+ },
162
+ }));
163
+ }, [paginatedQueueEntries, renderActionButton]);
164
+
165
+ if (isLoading) {
166
+ return <DataTableSkeleton role="progressbar" />;
167
+ }
168
+
169
+ if (
170
+ (!isLoading && patientQueueEntries && status === "pending") ||
171
+ status === "completed" ||
172
+ status === ""
173
+ ) {
174
+ setPatientCount(patientQueueEntries.length);
175
+ }
176
+
177
+ if (patientQueueEntries?.length) {
178
+ return (
179
+ <div className={styles.container}>
180
+ <div className={styles.headerBtnContainer}></div>
181
+
182
+ <DataTable
183
+ data-floating-menu-container
184
+ headers={tableHeaders}
185
+ overflowMenuOnHover={isDesktop(layout) ? true : false}
186
+ rows={tableRows}
187
+ isSortable
188
+ size="xs"
189
+ useZebraStyles
190
+ >
191
+ {({ rows, headers, getTableProps, getRowProps, onInputChange }) => (
192
+ <TableContainer className={styles.tableContainer}>
193
+ <TableToolbar
194
+ style={{
195
+ position: "static",
196
+ height: "3rem",
197
+ overflow: "visible",
198
+ backgroundColor: "color",
199
+ }}
200
+ >
201
+ <TableToolbarContent className={styles.toolbarContent}>
202
+ <Layer>
203
+ <TableToolbarSearch
204
+ className={styles.search}
205
+ onChange={onInputChange}
206
+ placeholder={t("searchThisList", "Search this list")}
207
+ size="sm"
208
+ />
209
+ </Layer>
210
+ </TableToolbarContent>
211
+ </TableToolbar>
212
+ <Table {...getTableProps()} className={styles.activeVisitsTable}>
213
+ <TableHead>
214
+ <TableRow>
215
+ <TableExpandHeader />
216
+ {headers.map((header) => (
217
+ <TableHeader>
218
+ {header.header?.content ?? header.header}
219
+ </TableHeader>
220
+ ))}
221
+ </TableRow>
222
+ </TableHead>
223
+ <TableBody>
224
+ {rows.map((row, index) => {
225
+ return (
226
+ <>
227
+ <TableExpandRow {...getRowProps({ row })} key={row.id}>
228
+ {row.cells.map((cell) => (
229
+ <TableCell key={cell.id}>
230
+ {cell.value?.content ?? cell.value}
231
+ </TableCell>
232
+ ))}
233
+ </TableExpandRow>
234
+
235
+ {row.isExpanded ? (
236
+ <TableExpandedRow
237
+ className={styles.expandedLabQueueVisitRow}
238
+ colSpan={headers.length + 2}
239
+ >
240
+ <>
241
+ {/* <span>{tableRows[index]?.comment ?? ""}</span> */}
242
+ </>
243
+ </TableExpandedRow>
244
+ ) : (
245
+ <TableExpandedRow
246
+ className={styles.hiddenRow}
247
+ colSpan={headers.length + 2}
248
+ />
249
+ )}
250
+ </>
251
+ );
252
+ })}
253
+ </TableBody>
254
+ </Table>
255
+ <Pagination
256
+ forwardText="Next page"
257
+ backwardText="Previous page"
258
+ page={currentPage}
259
+ pageSize={currentPageSize}
260
+ pageSizes={pageSizes}
261
+ totalItems={patientQueueEntries?.length}
262
+ className={styles.pagination}
263
+ onChange={({ pageSize, page }) => {
264
+ if (pageSize !== currentPageSize) {
265
+ setPageSize(pageSize);
266
+ }
267
+ if (page !== currentPage) {
268
+ goTo(page);
269
+ }
270
+ }}
271
+ />
272
+ </TableContainer>
273
+ )}
274
+ </DataTable>
275
+ {showOverlay && (
276
+ <AssignBedWorkSpace
277
+ patientDetails={selectedPatientDetails}
278
+ closePanel={() => setShowOverlay(false)}
279
+ queueStatus={status}
280
+ headerTitle={t(
281
+ "assignBedToPatient",
282
+ restrictWardAdministrationToLoginLocation === true
283
+ ? `Assign Bed to Patient ${selectedPatientDetails.name} in the ${session?.sessionLocation?.display} Ward`
284
+ : `Assign Bed to Patient ${selectedPatientDetails.name}`
285
+ )}
286
+ />
287
+ )}
288
+ </div>
289
+ );
290
+ }
291
+
292
+ return (
293
+ <EmptyState
294
+ msg={t("noQueueItems", "No queue items to display")}
295
+ helper=""
296
+ />
297
+ );
298
+ };
299
+ export default ActivePatientsTable;
@@ -0,0 +1,171 @@
1
+ import { useEffect } from "react";
2
+ import useSWRInfinite from "swr/infinite";
3
+ import dayjs from "dayjs";
4
+ import isToday from "dayjs/plugin/isToday";
5
+ import last from "lodash-es/last";
6
+ import {
7
+ openmrsFetch,
8
+ type Visit,
9
+ useSession,
10
+ type FetchResponse,
11
+ formatDatetime,
12
+ parseDate,
13
+ useConfig,
14
+ } from "@openmrs/esm-framework";
15
+
16
+ dayjs.extend(isToday);
17
+
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
+ }
37
+
38
+ export function useActiveVisits() {
39
+ const session = useSession();
40
+ const config = useConfig();
41
+ const { inpatientVisitUuid } = useConfig();
42
+ const sessionLocation = session?.sessionLocation?.uuid;
43
+
44
+ const customRepresentation =
45
+ "custom:(uuid,patient:(uuid,identifiers:(identifier,uuid,identifierType:(name,uuid)),person:(age,display,gender,uuid,attributes:(value,attributeType:(uuid,display))))," +
46
+ "visitType:(uuid,name,display),location:(uuid,name,display),startDatetime,stopDatetime)";
47
+
48
+ const getUrl = (
49
+ pageIndex,
50
+ previousPageData: FetchResponse<VisitResponse>
51
+ ) => {
52
+ if (
53
+ pageIndex &&
54
+ !previousPageData?.data?.links?.some((link) => link.rel === "next")
55
+ ) {
56
+ return null;
57
+ }
58
+
59
+ const url = `/ws/rest/v1/visit?v=${customRepresentation}&`;
60
+ const urlSearchParams = new URLSearchParams();
61
+
62
+ urlSearchParams.append("includeInactive", "false");
63
+ urlSearchParams.append("visitType", `${inpatientVisitUuid}`);
64
+ urlSearchParams.append("totalCount", "true");
65
+ //urlSearchParams.append("location", `${sessionLocation}`);
66
+
67
+ if (pageIndex) {
68
+ urlSearchParams.append("startIndex", `${pageIndex * 50}`);
69
+ }
70
+
71
+ return url + urlSearchParams.toString();
72
+ };
73
+
74
+ const {
75
+ data,
76
+ error,
77
+ isLoading,
78
+ isValidating,
79
+ size: pageNumber,
80
+ setSize,
81
+ mutate,
82
+ } = useSWRInfinite<FetchResponse<VisitResponse>, Error>(
83
+ sessionLocation ? getUrl : null,
84
+ openmrsFetch
85
+ );
86
+
87
+ useEffect(() => {
88
+ if (
89
+ data &&
90
+ data?.[pageNumber - 1]?.data?.links?.some((link) => link.rel === "next")
91
+ ) {
92
+ setSize((currentSize) => currentSize + 1);
93
+ }
94
+ }, [data, pageNumber, setSize]);
95
+
96
+ const mapVisitProperties = (visit: Visit): ActiveVisit => {
97
+ // create base object
98
+ const activeVisits: ActiveVisit = {
99
+ age: visit?.patient?.person?.age,
100
+ id: visit.uuid,
101
+ idNumber: null,
102
+ gender: visit?.patient?.person?.gender,
103
+ location: visit?.location?.uuid,
104
+ name: visit?.patient?.person?.display,
105
+ patientUuid: visit?.patient?.uuid,
106
+ visitStartTime: formatDatetime(parseDate(visit?.startDatetime)),
107
+ visitType: visit?.visitType?.display,
108
+ visitUuid: visit.uuid,
109
+ };
110
+
111
+ // in case no configuration is given the previous behavior remains the same
112
+ if (!config?.activeVisits?.identifiers) {
113
+ activeVisits.idNumber =
114
+ visit?.patient?.identifiers[0]?.identifier ?? "--";
115
+ } else {
116
+ // map identifiers on config
117
+ config?.activeVisits?.identifiers?.map((configIdentifier) => {
118
+ // check if in the current visit the patient has in his identifiers the current identifierType name
119
+ const visitIdentifier = visit?.patient?.identifiers.find(
120
+ (visitIdentifier) =>
121
+ visitIdentifier?.identifierType?.name ===
122
+ configIdentifier?.identifierName
123
+ );
124
+
125
+ // add the new identifier or rewrite existing one to activeVisit object
126
+ // the parameter will corresponds to the name of the key value of the configuration
127
+ // and the respective value is the visit identifier
128
+ // If there isn't a identifier we display this default text '--'
129
+ activeVisits[configIdentifier.header?.key] =
130
+ visitIdentifier?.identifier ?? "--";
131
+ });
132
+ }
133
+
134
+ // map attributes on config
135
+ config?.activeVisits?.attributes?.map(({ display, header }) => {
136
+ // check if in the current visit the person has in his attributes the current display
137
+ const personAttributes = visit?.patient?.person?.attributes.find(
138
+ (personAttributes) =>
139
+ personAttributes?.attributeType?.display === display
140
+ );
141
+
142
+ // add the new attribute or rewrite existing one to activeVisit object
143
+ // the parameter will correspond to the name of the key value of the configuration
144
+ // and the respective value is the persons value
145
+ // If there isn't a attribute we display this default text '--'
146
+ activeVisits[header?.key] = personAttributes?.value ?? "--";
147
+ });
148
+
149
+ return activeVisits;
150
+ };
151
+
152
+ const formattedActiveVisits: Array<ActiveVisit> = data
153
+ ? [].concat(
154
+ ...data?.map((res) => res?.data?.results?.map(mapVisitProperties))
155
+ )
156
+ : [];
157
+
158
+ return {
159
+ patientQueueEntries: formattedActiveVisits,
160
+ isError: error,
161
+ isLoading,
162
+ isValidating,
163
+ patientQueueCount: data?.[0]?.data?.totalCount ?? 0,
164
+ mutate,
165
+ };
166
+ }
167
+
168
+ export const getOriginFromPathName = (pathname = "") => {
169
+ const from = pathname.split("/");
170
+ return last(from);
171
+ };
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import { Button, Tooltip } from "@carbon/react";
3
+ import { HospitalBed } from "@carbon/react/icons";
4
+ import { useTranslation } from "react-i18next";
5
+ import styles from "./admission-action-button-styles.scss";
6
+
7
+ const AdmissionActionButton = ({
8
+ entry,
9
+ handleBedAssigmentModal,
10
+ buttonText,
11
+ }) => {
12
+ const { t } = useTranslation();
13
+ return (
14
+ <Tooltip align="bottom" label={t("buttonTooltip", buttonText)}>
15
+ <Button
16
+ className={styles.actionButton}
17
+ kind="ghost"
18
+ renderIcon={HospitalBed}
19
+ onClick={() => handleBedAssigmentModal(entry)}
20
+ iconDescription={t("buttonText", buttonText)}
21
+ ></Button>
22
+ </Tooltip>
23
+ );
24
+ };
25
+
26
+ export default AdmissionActionButton;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import Header from "../../header/header.component";
3
+ import styles from "./styles.scss";
4
+ import BedAdmissionTabs from "../bed-admission-tabs.component";
5
+
6
+ const ActivePatientsHome: React.FC = () => {
7
+ return (
8
+ <section className={styles.section}>
9
+ <Header route="In Patient" headerTitle="" />
10
+ <BedAdmissionTabs />
11
+ </section>
12
+ );
13
+ };
14
+
15
+ export default ActivePatientsHome;