@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,211 @@
1
+ import useSWR from "swr";
2
+ import { FetchResponse, openmrsFetch } from "@openmrs/esm-framework";
3
+ import type { AdmissionLocation, Bed, MappedBedData } from "../types";
4
+
5
+ export const useLocationsByTag = (locationUuid: string) => {
6
+ const locationsUrl = `/ws/rest/v1/location?tag=${locationUuid}&v=full`;
7
+
8
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
9
+ { data },
10
+ Error
11
+ >(locationUuid ? locationsUrl : null, openmrsFetch);
12
+
13
+ return {
14
+ data: data?.data?.results ?? [],
15
+ error,
16
+ isLoading,
17
+ isValidating,
18
+ mutate,
19
+ };
20
+ };
21
+
22
+ export const getBedsForLocation = (locationUuid: string) => {
23
+ const locationsUrl = `/ws/rest/v1/bed?locationUuid=${locationUuid}`;
24
+
25
+ return openmrsFetch(locationsUrl, {
26
+ method: "GET",
27
+ }).then((res) => res?.data?.results ?? []);
28
+ };
29
+
30
+ export const useBedsForLocation = (locationUuid: string) => {
31
+ const apiUrl = `/ws/rest/v1/bed?locationUuid=${locationUuid}&v=full`;
32
+
33
+ const { data, isLoading, error } = useSWR<
34
+ { data: { results: Array<Bed> } },
35
+ Error
36
+ >(locationUuid ? apiUrl : null, openmrsFetch);
37
+
38
+ const mappedBedData: MappedBedData = (data?.data?.results ?? []).map(
39
+ (bed) => ({
40
+ id: bed.id,
41
+ number: bed.bedNumber,
42
+ name: bed.bedType?.displayName,
43
+ description: bed.bedType?.description,
44
+ status: bed.status,
45
+ uuid: bed.uuid,
46
+ })
47
+ );
48
+
49
+ return {
50
+ bedData: mappedBedData,
51
+ isLoading,
52
+ error,
53
+ };
54
+ };
55
+
56
+ export const useLocationName = (locationUuid: string) => {
57
+ const apiUrl = `/ws/rest/v1/location/${locationUuid}`;
58
+
59
+ const { data, isLoading } = useSWR<{ data }, Error>(
60
+ locationUuid ? apiUrl : null,
61
+ openmrsFetch
62
+ );
63
+
64
+ return {
65
+ name: data?.data?.display ?? null,
66
+ isLoadingLocationData: isLoading,
67
+ };
68
+ };
69
+
70
+ export const findBedByLocation = (locationUuid: string) => {
71
+ const locationsUrl = `/ws/rest/v1/bed?locationUuid=${locationUuid}`;
72
+ return openmrsFetch(locationsUrl, {
73
+ method: "GET",
74
+ });
75
+ };
76
+
77
+ export const useWards = (locationUuid: string) => {
78
+ const locationsUrl = `/ws/rest/v1/location?tag=${locationUuid}&v=full`;
79
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
80
+ { data },
81
+ Error
82
+ >(locationUuid ? locationsUrl : null, openmrsFetch);
83
+
84
+ return {
85
+ data,
86
+ error,
87
+ isLoading,
88
+ isValidating,
89
+ mutate,
90
+ };
91
+ };
92
+
93
+ export const useAdmissionLocations = () => {
94
+ const locationsUrl = `/ws/rest/v1/admissionLocation?v=full`;
95
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
96
+ { data: { results: Array<AdmissionLocation> } },
97
+ Error
98
+ >(locationsUrl, openmrsFetch);
99
+
100
+ return {
101
+ data: data?.data?.results ?? [],
102
+ error,
103
+ isLoading,
104
+ isValidating,
105
+ mutate,
106
+ };
107
+ };
108
+
109
+ export const useAdmissionLocationBedLayout = (locationUuid: string) => {
110
+ const locationsUrl = `/ws/rest/v1/admissionLocation/${locationUuid}?v=full`;
111
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
112
+ { data: AdmissionLocation },
113
+ Error
114
+ >(locationsUrl, openmrsFetch);
115
+
116
+ return {
117
+ data: data?.data?.bedLayouts ?? [],
118
+ error,
119
+ isLoading,
120
+ isValidating,
121
+ mutate,
122
+ };
123
+ };
124
+ export const useBedType = () => {
125
+ const url = `/ws/rest/v1/bedtype/`;
126
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
127
+ { data },
128
+ Error
129
+ >(url, openmrsFetch);
130
+ const results = data?.data?.results ? data?.data?.results : [];
131
+ return {
132
+ bedTypeData: results,
133
+ isError: error,
134
+ loading: isLoading,
135
+ validate: isValidating,
136
+ mutate,
137
+ };
138
+ };
139
+
140
+ export const useBedTag = () => {
141
+ const url = `/ws/rest/v1/bedTag/`;
142
+ const { data, error, isLoading, isValidating, mutate } = useSWR<
143
+ { data },
144
+ Error
145
+ >(url, openmrsFetch);
146
+ const results = data?.data?.results ? data?.data?.results : [];
147
+ return {
148
+ bedTypeData: results,
149
+ isError: error,
150
+ loading: isLoading,
151
+ validate: isValidating,
152
+ mutate,
153
+ };
154
+ };
155
+ interface BedType {
156
+ name: string;
157
+ displayName: string;
158
+ description: string;
159
+ }
160
+ interface BedTag {
161
+ name: string;
162
+ }
163
+ export async function saveBedType({
164
+ bedPayload,
165
+ }): Promise<FetchResponse<BedType>> {
166
+ const response: FetchResponse = await openmrsFetch(`/ws/rest/v1/bedtype`, {
167
+ method: "POST",
168
+ headers: { "Content-Type": "application/json" },
169
+ body: bedPayload,
170
+ });
171
+ return response;
172
+ }
173
+
174
+ export async function saveBedTag({
175
+ bedPayload,
176
+ }): Promise<FetchResponse<BedTag>> {
177
+ const response: FetchResponse = await openmrsFetch(`/ws/rest/v1/bedTag/`, {
178
+ method: "POST",
179
+ headers: { "Content-Type": "application/json" },
180
+ body: bedPayload,
181
+ });
182
+ return response;
183
+ }
184
+ export async function editBedType({
185
+ bedPayload,
186
+ bedTypeId,
187
+ }): Promise<FetchResponse<BedType>> {
188
+ const response: FetchResponse = await openmrsFetch(
189
+ `/ws/rest/v1/bedtype/${bedTypeId}`,
190
+ {
191
+ method: "POST",
192
+ headers: { "Content-Type": "application/json" },
193
+ body: bedPayload,
194
+ }
195
+ );
196
+ return response;
197
+ }
198
+ export async function editBedTag({
199
+ bedPayload,
200
+ bedTagId,
201
+ }): Promise<FetchResponse<BedType>> {
202
+ const response: FetchResponse = await openmrsFetch(
203
+ `/ws/rest/v1/bedTag/${bedTagId}`,
204
+ {
205
+ method: "POST",
206
+ headers: { "Content-Type": "application/json" },
207
+ body: bedPayload,
208
+ }
209
+ );
210
+ return response;
211
+ }
@@ -0,0 +1,72 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+
4
+ .cardContainer {
5
+ background-color: colors.$white-0;
6
+ display: grid;
7
+ grid-template-columns: repeat(3, minmax(0, 1fr));
8
+ justify-content: space-between;
9
+ padding: 1rem;
10
+ }
11
+
12
+ .buttonMain {
13
+ background-color: colors.$white-0;
14
+ color: colors.$teal-60;
15
+ cursor: text;
16
+ }
17
+
18
+ .sectionLoader {
19
+ text-align: center;
20
+ }
21
+
22
+ .buttonMain {
23
+ &:active, &:focus, &:hover {
24
+ color: colors.$teal-60 !important;
25
+ background-color: colors.$white-0 !important;
26
+ }
27
+ }
28
+
29
+ .inactiveMain {
30
+ margin-bottom: 4rem;
31
+ }
32
+
33
+ .buttonContainer {
34
+ display: flex;
35
+ }
36
+
37
+ .buttonItems {
38
+ flex: auto;
39
+ }
40
+
41
+ .pageHeaderContainer {
42
+ display: flex;
43
+ justify-content: space-between;
44
+ align-items: center;
45
+ padding: layout.$spacing-05;
46
+ background-color: #ededed;
47
+ }
48
+
49
+ .pageHeader {
50
+ text-overflow: ellipsis;
51
+ overflow: hidden;
52
+ white-space: nowrap;
53
+ font-size: 1.25rem;
54
+ font-weight: 400;
55
+ line-height: 1.4;
56
+ letter-spacing: 0;
57
+ }
58
+
59
+ .link {
60
+ text-decoration: none;
61
+ display: flex;
62
+ align-items: center;
63
+ color: colors.$blue-60;
64
+
65
+ svg {
66
+ margin-left: layout.$spacing-03;
67
+ }
68
+ }
69
+
70
+ .loader {
71
+ margin: 2rem;
72
+ }
package/src/types.ts ADDED
@@ -0,0 +1,163 @@
1
+ import type { KeyedMutator } from "swr";
2
+
3
+ export type Tag = {
4
+ uuid: string;
5
+ display: string;
6
+ name: string;
7
+ description?: string;
8
+ retired: boolean;
9
+ links: Array<{
10
+ rel: string;
11
+ uri: string;
12
+ resourceAlias: string;
13
+ }>;
14
+ resourceVersion: string;
15
+ };
16
+
17
+ export type Location = {
18
+ uuid: string;
19
+ display: string;
20
+ name: string;
21
+ description: string | null;
22
+ address1: string | null;
23
+ address2: string | null;
24
+ cityVillage: string | null;
25
+ stateProvince: string | null;
26
+ country: string | null;
27
+ postalCode: string | null;
28
+ latitude: string | null;
29
+ longitude: string | null;
30
+ countyDistrict: string | null;
31
+ address3: string | null;
32
+ address4: string | null;
33
+ address5: string | null;
34
+ address6: string | null;
35
+ tags: Tag[];
36
+ parentLocation: Location;
37
+ childLocations: Location[];
38
+ retired: boolean;
39
+ auditInfo: {
40
+ creator: {
41
+ uuid: string;
42
+ display: string;
43
+ links: Array<{
44
+ rel: string;
45
+ uri: string;
46
+ resourceAlias: string;
47
+ }>;
48
+ };
49
+ dateCreated: string;
50
+ changedBy: null;
51
+ dateChanged: null;
52
+ };
53
+ address7: string | null;
54
+ address8: string | null;
55
+ address9: string | null;
56
+ address10: string | null;
57
+ address11: string | null;
58
+ address12: string | null;
59
+ address13: string | null;
60
+ address14: string | null;
61
+ address15: string | null;
62
+ links: Array<{
63
+ rel: string;
64
+ uri: string;
65
+ resourceAlias: string;
66
+ }>;
67
+ resourceVersion: string;
68
+ beds: Bed[];
69
+ };
70
+
71
+ export interface Bed {
72
+ id: number;
73
+ bedId: number;
74
+ uuid: string;
75
+ bedNumber: string;
76
+ bedType: {
77
+ uuid: string;
78
+ name: string;
79
+ displayName: string;
80
+ description: string;
81
+ resourceVersion: string;
82
+ };
83
+ row: number;
84
+ column: number;
85
+ status: "AVAILABLE" | string;
86
+ location: string;
87
+ }
88
+
89
+ export interface BedType {
90
+ uuid: string;
91
+ name: string;
92
+ displayName: string;
93
+ description: string;
94
+ }
95
+
96
+ export interface InitialData {
97
+ uuid: string;
98
+ bedNumber: string;
99
+ status: string;
100
+ description: string;
101
+ row: number;
102
+ column: number;
103
+ location: {
104
+ display: string;
105
+ uuid: string;
106
+ };
107
+ bedType: {
108
+ name: string;
109
+ };
110
+ }
111
+
112
+ export type Mutator = KeyedMutator<{
113
+ data: {
114
+ results: Array<Location>;
115
+ };
116
+ }>;
117
+
118
+ export type AdmissionLocation = {
119
+ ward: {
120
+ uuid: string;
121
+ display: string;
122
+ name: string;
123
+ description: string;
124
+ };
125
+ totalBeds: number;
126
+ occupiedBeds: number;
127
+ bedLayouts: Array<BedDetails>;
128
+ };
129
+
130
+ export type MappedBedData = Array<{
131
+ id: number;
132
+ number: string;
133
+ name: string;
134
+ description: string;
135
+ status: string;
136
+ uuid: string;
137
+ }>;
138
+
139
+ export interface BedDetails extends Bed {
140
+ patient: null | {
141
+ uuid: string;
142
+ person: {
143
+ gender: string;
144
+ age: number;
145
+ preferredName: {
146
+ givenName: string;
147
+ familyName: string;
148
+ };
149
+ };
150
+ identifiers: Array<{ identifier: string }>;
151
+ };
152
+ }
153
+ export interface BedTypeData {
154
+ uuid: string;
155
+ name: string;
156
+ displayName: string;
157
+ description: string;
158
+ }
159
+
160
+ export interface BedTagData {
161
+ uuid: string;
162
+ name: string;
163
+ }
@@ -0,0 +1,41 @@
1
+ import React from "react";
2
+ import { Layer, Tile } from "@carbon/react";
3
+ import styles from "./ward-card.scss";
4
+
5
+ interface WardCardProps {
6
+ label: string;
7
+ value: number | string;
8
+ headerLabel: string;
9
+ children?: React.ReactNode;
10
+ service?: string;
11
+ serviceUuid?: string;
12
+ locationUuid?: string;
13
+ }
14
+
15
+ const WardCard: React.FC<WardCardProps> = ({
16
+ children,
17
+ headerLabel,
18
+ label,
19
+ value,
20
+ }) => {
21
+ return (
22
+ <Layer
23
+ className={`${children && styles.cardWithChildren} ${styles.container}`}
24
+ >
25
+ <Tile className={styles.tileContainer}>
26
+ <div className={styles.tileHeader}>
27
+ <div className={styles.headerLabelContainer}>
28
+ <label className={styles.headerLabel}>{headerLabel}</label>
29
+ </div>
30
+ {children}
31
+ </div>
32
+ <div>
33
+ <label className={styles.totalsLabel}>{label}</label>
34
+ <p className={styles.totalsValue}>{value}</p>
35
+ </div>
36
+ </Tile>
37
+ </Layer>
38
+ );
39
+ };
40
+
41
+ export default WardCard;
@@ -0,0 +1,51 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use "@carbon/type";
4
+
5
+ .container {
6
+ flex-grow: 1;
7
+ }
8
+
9
+ .tileContainer {
10
+ border: 1px solid colors.$gray-20;
11
+ height: 7.875rem;
12
+ padding: layout.$spacing-05;
13
+ margin: layout.$spacing-03 layout.$spacing-03;
14
+ }
15
+
16
+ .tileHeader {
17
+ display: flex;
18
+ justify-content: space-between;
19
+ align-items: baseline;
20
+ margin-bottom: layout.$spacing-03;
21
+ }
22
+
23
+ .headerLabel {
24
+ @include type.type-style('heading-compact-01');
25
+ color: colors.$gray-70;
26
+ }
27
+
28
+ .totalsLabel {
29
+ @include type.type-style('label-01');
30
+ color: colors.$gray-70;
31
+ }
32
+
33
+ .totalsValue {
34
+ @include type.type-style('heading-04');
35
+ color: colors.$gray-100;
36
+ }
37
+
38
+ .headerLabelContainer {
39
+ margin-bottom: 1rem;
40
+ }
41
+
42
+ .link {
43
+ text-decoration: none;
44
+ display: flex;
45
+ align-items: center;
46
+ color: colors.$blue-60;
47
+
48
+ svg {
49
+ margin-left: layout.$spacing-03;
50
+ }
51
+ }
@@ -0,0 +1,186 @@
1
+ import React, { useMemo, useState } from "react";
2
+ import { useParams } from "react-router-dom";
3
+ import { useTranslation } from "react-i18next";
4
+ import {
5
+ Button,
6
+ DataTable,
7
+ DataTableSkeleton,
8
+ Pagination,
9
+ TableContainer,
10
+ Table,
11
+ TableHead,
12
+ TableRow,
13
+ TableHeader,
14
+ TableBody,
15
+ TableCell,
16
+ Tag,
17
+ } from "@carbon/react";
18
+ import { ArrowLeft } from "@carbon/react/icons";
19
+ import { navigate, usePagination } from "@openmrs/esm-framework";
20
+ import Header from "../header/header.component";
21
+ import {
22
+ useBedsForLocation,
23
+ useLocationName,
24
+ } from "../summary/summary.resource";
25
+ import styles from "./ward-with-beds.scss";
26
+
27
+ type RouteParams = { location: string };
28
+
29
+ const WardWithBeds: React.FC = () => {
30
+ const { location } = useParams<RouteParams>();
31
+ const { isLoading, bedData } = useBedsForLocation(location);
32
+
33
+ const { name } = useLocationName(location);
34
+
35
+ const [pageSize, setPageSize] = useState(10);
36
+ const {
37
+ results: paginatedData,
38
+ goTo,
39
+ currentPage,
40
+ } = usePagination(bedData, pageSize);
41
+
42
+ if (isLoading) {
43
+ <p>Loading...</p>;
44
+ }
45
+
46
+ const tableHeaders = [
47
+ {
48
+ id: 0,
49
+ header: "ID",
50
+ key: "id",
51
+ },
52
+ {
53
+ id: 1,
54
+ header: "Number",
55
+ key: "number",
56
+ },
57
+ {
58
+ id: 2,
59
+ header: "Name",
60
+ key: "name",
61
+ },
62
+ {
63
+ id: 3,
64
+ header: "Description",
65
+ key: "description",
66
+ },
67
+ {
68
+ id: 4,
69
+ header: "Occupied",
70
+ key: "occupied",
71
+ },
72
+ ];
73
+
74
+ const CustomTag = ({ condition }: { condition: boolean }) => {
75
+ const { t } = useTranslation();
76
+
77
+ if (condition) {
78
+ return (
79
+ <Tag type="green" size="md">
80
+ {t("yes", "Yes")}
81
+ </Tag>
82
+ );
83
+ }
84
+
85
+ return (
86
+ <Tag type="red" size="md">
87
+ {t("no", "No")}
88
+ </Tag>
89
+ );
90
+ };
91
+
92
+ const tableRows = useMemo(() => {
93
+ return paginatedData?.map((bed) => ({
94
+ id: bed.id,
95
+ number: bed.number,
96
+ name: bed.name,
97
+ description: bed.description,
98
+ occupied: <CustomTag condition={bed?.status === "OCCUPIED"} />,
99
+ }));
100
+ }, [paginatedData]);
101
+
102
+ return (
103
+ <>
104
+ <Header route={name ? name : "--"} />
105
+ {isLoading && (
106
+ <div className={styles.container}>
107
+ <DataTableSkeleton role="progressbar" zebra />
108
+ </div>
109
+ )}
110
+
111
+ {bedData?.length ? (
112
+ <>
113
+ <div className={styles.backButton}>
114
+ <Button
115
+ kind="ghost"
116
+ renderIcon={(props) => <ArrowLeft size={24} {...props} />}
117
+ iconDescription="Return to summary"
118
+ onClick={() =>
119
+ navigate({
120
+ to: `${window.getOpenmrsSpaBase()}bed-management`,
121
+ })
122
+ }
123
+ >
124
+ <span>Return to summary</span>
125
+ </Button>
126
+ </div>
127
+ <div className={styles.container}>
128
+ <DataTable rows={tableRows} headers={tableHeaders} useZebraStyles>
129
+ {({
130
+ rows,
131
+ headers,
132
+ getHeaderProps,
133
+ getRowProps,
134
+ getTableProps,
135
+ }) => (
136
+ <TableContainer>
137
+ <Table {...getTableProps()}>
138
+ <TableHead>
139
+ <TableRow>
140
+ {headers.map((header) => (
141
+ <TableHeader
142
+ key={header.key}
143
+ {...getHeaderProps({ header })}
144
+ >
145
+ {header.header}
146
+ </TableHeader>
147
+ ))}
148
+ </TableRow>
149
+ </TableHead>
150
+ <TableBody>
151
+ {rows.map((row) => (
152
+ <TableRow key={row.id} {...getRowProps({ row })}>
153
+ {row.cells.map((cell) => (
154
+ <TableCell key={cell.id}>
155
+ {cell.value?.content ?? cell.value}
156
+ </TableCell>
157
+ ))}
158
+ </TableRow>
159
+ ))}
160
+ </TableBody>
161
+ </Table>
162
+ </TableContainer>
163
+ )}
164
+ </DataTable>
165
+ <Pagination
166
+ backwardText="Previous page"
167
+ forwardText="Next page"
168
+ itemsPerPageText="Items per page:"
169
+ page={currentPage}
170
+ pageNumberText="Page Number"
171
+ pageSize={pageSize}
172
+ onChange={({ page, pageSize }) => {
173
+ goTo(page);
174
+ setPageSize(pageSize);
175
+ }}
176
+ pageSizes={[10, 20, 30, 40, 50]}
177
+ totalItems={paginatedData?.length}
178
+ />
179
+ </div>
180
+ </>
181
+ ) : null}
182
+ </>
183
+ );
184
+ };
185
+
186
+ export default WardWithBeds;