@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,69 @@
1
+ import { Tab, TabList, TabPanel, TabPanels, Tabs } from "@carbon/react";
2
+ import React, { useState } from "react";
3
+ import styles from "./bed-admission-tabs-styles.scss";
4
+ import { useTranslation } from "react-i18next";
5
+ import ActivePatientsTable from "./active-patients/active-patients-table.component";
6
+ import AdmittedPatientsList from "./admitted-patients/admitted-patients.component";
7
+ import DischargedPatientsList from "./discharged-patients/discharged-patients.componet";
8
+ import WardCard from "../ward-card/ward-card.component";
9
+
10
+ const BedAdmissionTabs: React.FC = () => {
11
+ const { t } = useTranslation();
12
+ const [admittedCount, setAdmittedCount] = useState(0);
13
+ const [toAdmitCount, setToAdmitCount] = useState(0);
14
+ const [toDischargeCount, setToDischargeCount] = useState(0);
15
+
16
+ return (
17
+ <>
18
+ <div className={styles.cardContainer}>
19
+ <WardCard
20
+ label="patients"
21
+ headerLabel="To Admit"
22
+ value={admittedCount}
23
+ />
24
+ <WardCard
25
+ label="patients"
26
+ headerLabel="Admitted"
27
+ value={toAdmitCount}
28
+ />
29
+ <WardCard
30
+ label="patients"
31
+ headerLabel="To Discharge"
32
+ value={toDischargeCount}
33
+ />
34
+ </div>
35
+ <div className={styles.container}>
36
+ <Tabs>
37
+ <TabList contained fullWidth className={styles.tabsContainer}>
38
+ <Tab className={styles.tab}>
39
+ {t("toAdmit", `To Admit (${admittedCount})`)}
40
+ </Tab>
41
+ <Tab className={styles.tab}>
42
+ {t("admitted", `Admitted (${toAdmitCount})`)}
43
+ </Tab>
44
+ <Tab className={styles.tab}>
45
+ {t("discharged", `To Discharge (0)`)}
46
+ </Tab>
47
+ </TabList>
48
+ <TabPanels>
49
+ <TabPanel>
50
+ <ActivePatientsTable
51
+ status="pending"
52
+ setPatientCount={setAdmittedCount}
53
+ />
54
+ </TabPanel>
55
+ <TabPanel>
56
+ <AdmittedPatientsList
57
+ status="completed"
58
+ setPatientCount={setToAdmitCount}
59
+ />
60
+ </TabPanel>
61
+ <TabPanel></TabPanel>
62
+ </TabPanels>
63
+ </Tabs>
64
+ </div>
65
+ </>
66
+ );
67
+ };
68
+
69
+ export default BedAdmissionTabs;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import { BrowserRouter, Route, Routes } from "react-router-dom";
3
+ import ActivePatientsHome from "./active-patients";
4
+
5
+ const BedAdmission: React.FC = () => {
6
+ return (
7
+ <BrowserRouter basename={window.getOpenmrsSpaBase()}>
8
+ <Routes>
9
+ <Route path="/home/bed-admission" element={<ActivePatientsHome />} />
10
+ </Routes>
11
+ </BrowserRouter>
12
+ );
13
+ };
14
+
15
+ export default BedAdmission;
@@ -0,0 +1,52 @@
1
+ import { FetchResponse, openmrsFetch, useConfig } from "@openmrs/esm-framework";
2
+ import { useMemo } from "react";
3
+ import useSWR from "swr";
4
+
5
+ export async function assignPatientBed(
6
+ requestPayload,
7
+ bedId
8
+ ): Promise<FetchResponse> {
9
+ const abortController = new AbortController();
10
+ abortController.abort();
11
+ const response: FetchResponse = await openmrsFetch(
12
+ `/ws/rest/v1/beds/${bedId}`,
13
+ {
14
+ method: "POST",
15
+ headers: { "Content-Type": "application/json" },
16
+ body: requestPayload,
17
+ }
18
+ );
19
+ return response;
20
+ }
21
+
22
+ export async function endPatientQueue(
23
+ queueStatus,
24
+ queueUuid
25
+ ): Promise<FetchResponse> {
26
+ const abortController = new AbortController();
27
+ abortController.abort();
28
+ const response: FetchResponse = await openmrsFetch(
29
+ `/ws/rest/v1/patientqueue/${queueUuid}`,
30
+ {
31
+ method: "POST",
32
+ headers: { "Content-Type": "application/json" },
33
+ body: queueStatus,
34
+ }
35
+ );
36
+ return response;
37
+ }
38
+
39
+ export function findLatestClinicalEncounter(
40
+ patientUuid: string,
41
+ encounterTypeUuid: string,
42
+ data,
43
+ admissionFormUuid
44
+ ) {
45
+ const clinicalEncounters =
46
+ data?.data?.results?.filter(
47
+ (enc) => enc?.form?.uuid === admissionFormUuid
48
+ ) ?? [];
49
+ const encounterUuid = clinicalEncounters?.[0]?.uuid ?? "";
50
+
51
+ return { data: encounterUuid };
52
+ }
@@ -0,0 +1,101 @@
1
+ import React, { useState } from "react";
2
+ import { Column, InlineLoading, Grid } from "@carbon/react";
3
+ import { ErrorState } from "@openmrs/esm-patient-common-lib";
4
+ import { useTranslation } from "react-i18next";
5
+ import BedLayout from "./bed-layout.component";
6
+ import styles from "./bed-layout.scss";
7
+ import EmptyState from "../../empty-state/empty-state.component";
8
+ import MinBedLayout from "./min-bed-layout.component";
9
+ import { useAdmissionLocationBedLayout } from "../../summary/summary.resource";
10
+ import { patientDetailsProps } from "../types";
11
+ interface BedLayoutListProps {
12
+ locationUuid: string;
13
+ handleClick: (e) => void;
14
+ patientDetails: patientDetailsProps;
15
+ }
16
+
17
+ const BedLayoutList: React.FC<BedLayoutListProps> = React.memo(
18
+ ({ locationUuid, handleClick, patientDetails }) => {
19
+ const { t } = useTranslation();
20
+ const [selectedBed, setSelectedBed] = useState(null);
21
+ const {
22
+ data: bedData,
23
+ isLoading,
24
+ error,
25
+ } = useAdmissionLocationBedLayout(locationUuid);
26
+
27
+ const getLayoutClass = (status: string) =>
28
+ status === "AVAILABLE" ? styles.available : styles.occupied;
29
+
30
+ if (isLoading) {
31
+ return (
32
+ <div className={styles.loadingContainer}>
33
+ <InlineLoading
34
+ status="active"
35
+ iconDescription={t("loading", "Loading")}
36
+ description={t("loading", "Loading...")}
37
+ />
38
+ </div>
39
+ );
40
+ }
41
+
42
+ if (error) {
43
+ return (
44
+ <div className={styles.errorContainer}>
45
+ <ErrorState
46
+ headerTitle={t(
47
+ "errorFetchingbedInformation",
48
+ "Error fetching bed information"
49
+ )}
50
+ error={error}
51
+ />
52
+ </div>
53
+ );
54
+ }
55
+
56
+ if (locationUuid === "") {
57
+ return (
58
+ <div className={styles.errorContainer}>
59
+ <EmptyState
60
+ msg={t("noWardSelected", "No ward has been selected")}
61
+ helper=""
62
+ />
63
+ </div>
64
+ );
65
+ }
66
+ if (locationUuid !== "" && !bedData?.length) {
67
+ return (
68
+ <div className={styles.errorContainer}>
69
+ <EmptyState
70
+ msg={t("noBedItems", "No bed to display in this ward")}
71
+ helper=""
72
+ />
73
+ </div>
74
+ );
75
+ }
76
+ return (
77
+ <>
78
+ <MinBedLayout />
79
+ <Grid>
80
+ {bedData?.map((bed) => (
81
+ <Column key={bed.bedNumber} lg={5} md={5} sm={5}>
82
+ <BedLayout
83
+ handleBedAssignment={() => {
84
+ setSelectedBed(bed.bedId);
85
+ handleClick(bed);
86
+ }}
87
+ bedPillowStyles={styles.pillow}
88
+ layOutStyles={`${styles.bed} ${getLayoutClass(bed.status)}`}
89
+ isBedSelected={selectedBed === bed.bedId}
90
+ patientDetails={patientDetails}
91
+ bedDetails={bed}
92
+ />
93
+ </Column>
94
+ ))}
95
+ </Grid>
96
+ </>
97
+ );
98
+ }
99
+ );
100
+
101
+ export default BedLayoutList;
@@ -0,0 +1,64 @@
1
+ import React, { useRef } from "react";
2
+ import classnames from "classnames";
3
+ import styles from "./bed-layout.scss";
4
+ import { patientDetailsProps } from "../types";
5
+ import { BedDetails } from "../../types";
6
+
7
+ interface BedProps {
8
+ handleBedAssignment?: () => void;
9
+ isBedSelected?: boolean;
10
+ layOutStyles?: string;
11
+ bedPillowStyles?: string;
12
+ patientDetails?: patientDetailsProps;
13
+ bedDetails?: BedDetails;
14
+ }
15
+
16
+ const BedLayout: React.FC<BedProps> = ({
17
+ layOutStyles,
18
+ bedPillowStyles,
19
+ handleBedAssignment,
20
+ isBedSelected,
21
+ bedDetails,
22
+ patientDetails,
23
+ }) => {
24
+ const bedRef = useRef(null);
25
+
26
+ return (
27
+ <>
28
+ <div
29
+ ref={bedRef}
30
+ role="button"
31
+ tabIndex={0}
32
+ onClick={() => handleBedAssignment()}
33
+ className={classnames(styles.bedLayout, {
34
+ [layOutStyles]: layOutStyles,
35
+ [styles.bedLayoutSelected]:
36
+ isBedSelected ||
37
+ (bedDetails &&
38
+ bedDetails.patient &&
39
+ bedDetails.patient.uuid === patientDetails.patientUuid),
40
+ })}
41
+ >
42
+ <div
43
+ className={classnames(styles.bedPillow, {
44
+ [bedPillowStyles]: bedPillowStyles,
45
+ })}
46
+ ></div>
47
+ <div style={{ display: "grid" }}>
48
+ <span className={styles.bedNumber}>
49
+ {bedDetails && bedDetails.bedNumber}
50
+ </span>
51
+ <span className={styles.bedNumber}>
52
+ {bedDetails &&
53
+ bedDetails.patient &&
54
+ bedDetails.patient.uuid === patientDetails.patientUuid
55
+ ? bedDetails.patient.identifiers[0].identifier
56
+ : ""}
57
+ </span>
58
+ </div>
59
+ </div>
60
+ </>
61
+ );
62
+ };
63
+
64
+ export default BedLayout;
@@ -0,0 +1,118 @@
1
+ @use '@carbon/type';
2
+ @use '@carbon/colors';
3
+ @use '@carbon/styles/scss/spacing';
4
+ @import '~@openmrs/esm-styleguide/src/vars';
5
+
6
+ .bedLayout {
7
+ position: relative;
8
+ margin: 20px;
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: space-between;
12
+ padding: 0 20px;
13
+ border-radius: 8px;
14
+ border: 1px solid #42be65;
15
+
16
+ .bedPillow {
17
+ background-color: #fff;
18
+ border-radius: 3rem;
19
+ border: 1px solid #42be65;
20
+ }
21
+
22
+ .bedNumber {
23
+ font-weight: bold;
24
+ }
25
+
26
+ &:hover {
27
+ cursor: pointer;
28
+ }
29
+ }
30
+
31
+ .bedLayoutSelected {
32
+ background-color: #42be65 !important;
33
+ color: #fff !important;
34
+ border: 5px solid #e4e1c9 !important;
35
+ opacity:1 !important;
36
+ }
37
+
38
+ ;
39
+
40
+ .bedInfoMain {
41
+ display: flex;
42
+ align-self: center;
43
+ }
44
+
45
+ .bedInfoContainer {
46
+ display: flex;
47
+ justify-content: flex-end;
48
+ padding-right: 4rem;
49
+ border-bottom: 1px solid #a8a8a8;
50
+ }
51
+
52
+ .bedInfoText {
53
+ align-self: center;
54
+ }
55
+
56
+ .disabled {
57
+ opacity: 0.8;
58
+ pointer-events: none;
59
+ }
60
+
61
+ .errorContainer {
62
+ width: 90%;
63
+ position: absolute;
64
+ }
65
+
66
+ .loadingContainer {
67
+ position: absolute;
68
+ margin: spacing.$spacing-02 spacing.$spacing-05 0;
69
+ }
70
+
71
+ .bed {
72
+ height: 60px;
73
+ width: 8rem;
74
+ }
75
+
76
+ .pillow {
77
+ width: 10px;
78
+ height: 40px;
79
+ }
80
+
81
+ .available {
82
+ background-color: #fff;
83
+ color: #525252;
84
+ opacity: 1;
85
+ pointer-events: auto;
86
+ }
87
+
88
+ .occupied {
89
+ background-color: #42be65;
90
+ color: #fff;
91
+ opacity: 0.5;
92
+ pointer-events: none;
93
+ }
94
+
95
+ .minOccupied {
96
+ height: 1.5rem;
97
+ width: 2.5rem;
98
+ color: #fff;
99
+ background-color: rgb(66, 190, 101);
100
+ padding: 0 6px;
101
+ border-radius: 5px;
102
+ pointer-events: none;
103
+ }
104
+
105
+ .minAvailable {
106
+ height: 1.5rem;
107
+ width: 2.5rem;
108
+ color: none;
109
+ background-color: #fff;
110
+ padding: 0 6px;
111
+ border-radius: 5px;
112
+ pointer-events: none;
113
+ }
114
+
115
+ .minPillow {
116
+ width: 7px;
117
+ height: 1rem;
118
+ }
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import styles from "./bed-layout.scss";
3
+ import BedLayout from "./bed-layout.component";
4
+
5
+ const MinBedLayout: React.FC = () => {
6
+ return (
7
+ <div className={styles.bedInfoContainer}>
8
+ <div className={styles.bedInfoMain}>
9
+ <BedLayout
10
+ bedPillowStyles={styles.minPillow}
11
+ layOutStyles={styles.minOccupied}
12
+ />{" "}
13
+ <span className={styles.bedInfoText}>Occupied</span>
14
+ </div>
15
+ <div className={styles.bedInfoMain}>
16
+ <BedLayout
17
+ bedPillowStyles={styles.minPillow}
18
+ layOutStyles={styles.minAvailable}
19
+ />{" "}
20
+ <span className={styles.bedInfoText}>Available</span>
21
+ </div>
22
+ </div>
23
+ );
24
+ };
25
+
26
+ export default MinBedLayout;
@@ -0,0 +1,217 @@
1
+ import React, { useMemo, useState } from "react";
2
+ import { useTranslation } from "react-i18next";
3
+ import {
4
+ Button,
5
+ DataTable,
6
+ DataTableSkeleton,
7
+ InlineLoading,
8
+ Pagination,
9
+ Table,
10
+ TableBody,
11
+ TableCell,
12
+ TableContainer,
13
+ TableHead,
14
+ TableHeader,
15
+ TableRow,
16
+ Tile,
17
+ } from "@carbon/react";
18
+ import { Add, Edit } from "@carbon/react/icons";
19
+ import {
20
+ isDesktop as desktopLayout,
21
+ useLayoutType,
22
+ } from "@openmrs/esm-framework";
23
+ import { CardHeader, ErrorState } from "@openmrs/esm-patient-common-lib";
24
+ import type { BedTagData } from "../../types";
25
+ import { useBedTag } from "../../summary/summary.resource";
26
+ import Header from "../../header/header.component";
27
+ import styles from "../../bed-administration/bed-administration-table.scss";
28
+ import BedTagForm from "./new-tag-form.component";
29
+ import EditBedTagForm from "./edit-tag-form.component";
30
+
31
+ const BedTagAdministrationTable: React.FC = () => {
32
+ const { t } = useTranslation();
33
+ const headerTitle = t("bedTag", "Bed Tag");
34
+ const layout = useLayoutType();
35
+ const isTablet = layout === "tablet";
36
+ const responsiveSize = isTablet ? "lg" : "sm";
37
+ const isDesktop = desktopLayout(layout);
38
+ const [isBedDataLoading] = useState(false);
39
+ const [showBedTagsModal, setAddBedTagsModal] = useState(false);
40
+ const [showEditBedModal, setShowEditBedModal] = useState(false);
41
+ const [editData, setEditData] = useState<BedTagData>();
42
+ const [currentPage, setCurrentPage] = useState(1);
43
+ const [pageSize] = useState(10);
44
+ const { bedTypeData, isError, loading, validate, mutate } = useBedTag();
45
+ const [currentPageSize, setPageSize] = useState(10);
46
+ const pageSizes = [10, 20, 30, 40, 50];
47
+
48
+ const tableHeaders = [
49
+ {
50
+ header: t("ids", "Id"),
51
+ key: "ids",
52
+ },
53
+ {
54
+ header: t("name", "Name"),
55
+ key: "name",
56
+ },
57
+ {
58
+ header: t("actions", "Actions"),
59
+ key: "actions",
60
+ },
61
+ ];
62
+
63
+ const tableRows = useMemo(() => {
64
+ return bedTypeData?.map((entry) => ({
65
+ id: entry.uuid,
66
+ ids: entry.id,
67
+ name: entry?.name,
68
+ actions: (
69
+ <>
70
+ <Button
71
+ enterDelayMs={300}
72
+ renderIcon={Edit}
73
+ onClick={(e) => {
74
+ e.preventDefault();
75
+ setEditData(entry);
76
+ setShowEditBedModal(true);
77
+ setAddBedTagsModal(false);
78
+ }}
79
+ kind={"ghost"}
80
+ iconDescription={t("editBedTag", "Edit Bed Tag")}
81
+ hasIconOnly
82
+ size={responsiveSize}
83
+ tooltipAlignment="start"
84
+ />
85
+ </>
86
+ ),
87
+ }));
88
+ }, [responsiveSize, bedTypeData, t]);
89
+
90
+ if (isBedDataLoading || loading) {
91
+ return (
92
+ <>
93
+ <Header route="Bed Tag" />
94
+ <div className={styles.widgetCard}>
95
+ <DataTableSkeleton role="progressbar" compact={isDesktop} zebra />
96
+ </div>
97
+ </>
98
+ );
99
+ }
100
+
101
+ if (isError) {
102
+ return (
103
+ <>
104
+ <Header route="Bed Tag" />
105
+ <div className={styles.widgetCard}>
106
+ <ErrorState error={isError} headerTitle={headerTitle} />
107
+ </div>
108
+ </>
109
+ );
110
+ }
111
+
112
+ return (
113
+ <>
114
+ <Header route="Bed Tag" />
115
+
116
+ <div className={styles.widgetCard}>
117
+ {showBedTagsModal ? (
118
+ <BedTagForm
119
+ onModalChange={setAddBedTagsModal}
120
+ showModal={showBedTagsModal}
121
+ mutate={mutate}
122
+ />
123
+ ) : null}
124
+ {showEditBedModal ? (
125
+ <EditBedTagForm
126
+ onModalChange={setShowEditBedModal}
127
+ showModal={showEditBedModal}
128
+ editData={editData}
129
+ mutate={mutate}
130
+ />
131
+ ) : null}
132
+ <CardHeader title={headerTitle}>
133
+ <span className={styles.backgroundDataFetchingIndicator}>
134
+ <span>{validate ? <InlineLoading /> : null}</span>
135
+ </span>
136
+ {bedTypeData?.length ? (
137
+ <Button
138
+ kind="ghost"
139
+ renderIcon={(props) => <Add size={16} {...props} />}
140
+ onClick={() => setAddBedTagsModal(true)}
141
+ >
142
+ {t("addBedTag", "Add Bed Tag")}
143
+ </Button>
144
+ ) : null}
145
+ </CardHeader>
146
+ <DataTable
147
+ rows={tableRows}
148
+ headers={tableHeaders}
149
+ isSortable
150
+ size={isTablet ? "lg" : "sm"}
151
+ useZebraStyles
152
+ >
153
+ {({ rows, headers, getTableProps }) => (
154
+ <TableContainer>
155
+ <Table {...getTableProps()}>
156
+ <TableHead>
157
+ <TableRow>
158
+ {headers.map((header) => (
159
+ <TableHeader>
160
+ {header.header?.content ?? header.header}
161
+ </TableHeader>
162
+ ))}
163
+ </TableRow>
164
+ </TableHead>
165
+ <TableBody>
166
+ {rows.map((row) => (
167
+ <TableRow key={row.id}>
168
+ {row.cells.map((cell) => (
169
+ <TableCell key={cell.id}>
170
+ {cell.value?.content ?? cell.value}
171
+ </TableCell>
172
+ ))}
173
+ </TableRow>
174
+ ))}
175
+ </TableBody>
176
+ </Table>
177
+ {rows.length === 0 ? (
178
+ <div className={styles.tileContainer}>
179
+ <Tile className={styles.tile}>
180
+ <div className={styles.tileContent}>
181
+ <p className={styles.content}>
182
+ {t("No data", "No data to display")}
183
+ </p>
184
+ <p className={styles.helper}>
185
+ {t("checkFilters", "Check the filters above")}
186
+ </p>
187
+ </div>
188
+ <p className={styles.separator}>{t("or", "or")}</p>
189
+ <Button
190
+ kind="ghost"
191
+ size="sm"
192
+ renderIcon={(props) => <Add size={16} {...props} />}
193
+ onClick={() => setAddBedTagsModal(true)}
194
+ >
195
+ {t("bedTag", "Add Bed Tag")}
196
+ </Button>
197
+ </Tile>
198
+ </div>
199
+ ) : null}
200
+ <Pagination
201
+ page={currentPage}
202
+ pageSize={pageSize}
203
+ pageSizes={[10, 20, 30, 40, 50]}
204
+ totalItems={bedTypeData.length}
205
+ onChange={({ page, pageSize }) => {
206
+ setCurrentPage(page);
207
+ setPageSize(pageSize);
208
+ }}
209
+ />
210
+ </TableContainer>
211
+ )}
212
+ </DataTable>
213
+ </div>
214
+ </>
215
+ );
216
+ };
217
+ export default BedTagAdministrationTable;