@digihmis/esm-administration-app 1.0.0

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 (206) hide show
  1. package/README.md +4 -0
  2. package/dist/101.js +1 -0
  3. package/dist/101.js.map +1 -0
  4. package/dist/117.js +1 -0
  5. package/dist/117.js.map +1 -0
  6. package/dist/132.js +1 -0
  7. package/dist/132.js.map +1 -0
  8. package/dist/15.js +1 -0
  9. package/dist/15.js.map +1 -0
  10. package/dist/152.js +1 -0
  11. package/dist/152.js.map +1 -0
  12. package/dist/153.js +1 -0
  13. package/dist/153.js.map +1 -0
  14. package/dist/190.js +1 -0
  15. package/dist/190.js.map +1 -0
  16. package/dist/209.js +1 -0
  17. package/dist/209.js.map +1 -0
  18. package/dist/266.js +1 -0
  19. package/dist/266.js.map +1 -0
  20. package/dist/317.js +1 -0
  21. package/dist/317.js.map +1 -0
  22. package/dist/349.js +1 -0
  23. package/dist/349.js.map +1 -0
  24. package/dist/371.js +1 -0
  25. package/dist/371.js.map +1 -0
  26. package/dist/378.js +1 -0
  27. package/dist/378.js.map +1 -0
  28. package/dist/394.js +1 -0
  29. package/dist/394.js.map +1 -0
  30. package/dist/442.js +1 -0
  31. package/dist/442.js.map +1 -0
  32. package/dist/45.js +1 -0
  33. package/dist/45.js.map +1 -0
  34. package/dist/454.js +1 -0
  35. package/dist/454.js.map +1 -0
  36. package/dist/466.js +1 -0
  37. package/dist/466.js.map +1 -0
  38. package/dist/482.js +1 -0
  39. package/dist/482.js.map +1 -0
  40. package/dist/501.js +1 -0
  41. package/dist/501.js.map +1 -0
  42. package/dist/508.js +1 -0
  43. package/dist/508.js.map +1 -0
  44. package/dist/578.js +1 -0
  45. package/dist/578.js.map +1 -0
  46. package/dist/598.js +1 -0
  47. package/dist/598.js.map +1 -0
  48. package/dist/606.js +1 -0
  49. package/dist/606.js.map +1 -0
  50. package/dist/61.js +1 -0
  51. package/dist/61.js.map +1 -0
  52. package/dist/640.js +1 -0
  53. package/dist/640.js.map +1 -0
  54. package/dist/685.js +1 -0
  55. package/dist/685.js.map +1 -0
  56. package/dist/689.js +1 -0
  57. package/dist/689.js.map +1 -0
  58. package/dist/709.js +1 -0
  59. package/dist/709.js.map +1 -0
  60. package/dist/712.js +1 -0
  61. package/dist/712.js.map +1 -0
  62. package/dist/720.js +1 -0
  63. package/dist/720.js.map +1 -0
  64. package/dist/737.js +12 -0
  65. package/dist/737.js.map +1 -0
  66. package/dist/742.js +1 -0
  67. package/dist/742.js.map +1 -0
  68. package/dist/747.js +1 -0
  69. package/dist/747.js.map +1 -0
  70. package/dist/771.js +1 -0
  71. package/dist/771.js.map +1 -0
  72. package/dist/806.js +1 -0
  73. package/dist/806.js.map +1 -0
  74. package/dist/912.js +1 -0
  75. package/dist/912.js.map +1 -0
  76. package/dist/913.js +1 -0
  77. package/dist/913.js.map +1 -0
  78. package/dist/916.js +15 -0
  79. package/dist/916.js.map +1 -0
  80. package/dist/940.js +1 -0
  81. package/dist/940.js.map +1 -0
  82. package/dist/digihmis-esm-administration-app.js +6 -0
  83. package/dist/digihmis-esm-administration-app.js.buildmanifest.json +1100 -0
  84. package/dist/digihmis-esm-administration-app.js.map +1 -0
  85. package/dist/main.js +17 -0
  86. package/dist/main.js.map +1 -0
  87. package/dist/routes.json +1 -0
  88. package/increment-version.js +17 -0
  89. package/jest.config.js +26 -0
  90. package/package.json +51 -0
  91. package/release-version.js +16 -0
  92. package/rspack.config.js +1 -0
  93. package/src/bed-management/bed-management.component.tsx +19 -0
  94. package/src/bed-management/bed-management.scss +0 -0
  95. package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.modal.tsx +79 -0
  96. package/src/billing-management/billing-charge-items/billing-charge-items-modal/billing-charge-items.resource.ts +11 -0
  97. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-item.workspace.tsx +212 -0
  98. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-items.resource.ts +51 -0
  99. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/billing-charge-service.workspace.tsx +296 -0
  100. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/concept-search.component.tsx +67 -0
  101. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/price.component.tsx +81 -0
  102. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/components/stock-search.component.tsx +107 -0
  103. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-commodity.scss +61 -0
  104. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/global/billing-charge-items.scss +59 -0
  105. package/src/billing-management/billing-charge-items/billing-charge-items-workspace/schemas/form-schemas.ts +33 -0
  106. package/src/billing-management/billing-charge-items/billing-charge-items.component.tsx +222 -0
  107. package/src/billing-management/billing-charge-items/billing-charge-items.resource.ts +20 -0
  108. package/src/billing-management/billing-charge-items/billing-charge-items.scss +84 -0
  109. package/src/billing-management/billing-charge-items/type/index.ts +88 -0
  110. package/src/billing-management/billing-charge-items/utils/index.ts +96 -0
  111. package/src/billing-management/billing-management.component.tsx +21 -0
  112. package/src/billing-management/billing-management.scss +0 -0
  113. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.scss +28 -0
  114. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/billing-delete-payment-modes.modal.tsx +67 -0
  115. package/src/billing-management/billing-payment-modes/billing-payment-modes-modal/delete-payment-mode.test.tsx +56 -0
  116. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes-form-schema.ts +52 -0
  117. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.resource.ts +35 -0
  118. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.scss +33 -0
  119. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.test.tsx +239 -0
  120. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/billing-payment-modes.workspace.tsx +218 -0
  121. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.component.tsx +156 -0
  122. package/src/billing-management/billing-payment-modes/billing-payment-modes-workspace/payment-attributes/payment-mode-attributes.scss +10 -0
  123. package/src/billing-management/billing-payment-modes/billing-payment-modes.component.tsx +243 -0
  124. package/src/billing-management/billing-payment-modes/billing-payment-modes.resource.ts +23 -0
  125. package/src/billing-management/billing-payment-modes/billing-payment-modes.scss +140 -0
  126. package/src/billing-management/billing-payment-modes/type/index.ts +42 -0
  127. package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-modes.modal.scss +28 -0
  128. package/src/billing-management/billing-payment-points/billing-payment-point-modal/billing-delete-payment-point.modal.tsx +72 -0
  129. package/src/billing-management/billing-payment-points/billing-payment-point-modal/delete-payment-point.test.tsx +56 -0
  130. package/src/billing-management/billing-payment-points/billing-payment-point.component.tsx +202 -0
  131. package/src/billing-management/billing-payment-points/billing-payment-point.resource.ts +16 -0
  132. package/src/billing-management/billing-payment-points/billing-payment-point.scss +0 -0
  133. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.resource.ts +39 -0
  134. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-point.workspace.scss +33 -0
  135. package/src/billing-management/billing-payment-points/billing-payment-points-workspace/billing-payment-points.workspace.tsx +194 -0
  136. package/src/billing-management/billing-payment-points/type/index.ts +35 -0
  137. package/src/billing-management/billing-tabs/billing-tabs.component.scss +15 -0
  138. package/src/billing-management/billing-tabs/billing-tabs.component.tsx +36 -0
  139. package/src/components/custom-icon-wrapper/custom-icon-wrapper.component.tsx +17 -0
  140. package/src/components/custom-page-header/custom-page-header.component.tsx +38 -0
  141. package/src/components/custom-page-header/custom-page-header.scss +76 -0
  142. package/src/config-schema.ts +142 -0
  143. package/src/constant/index.ts +1 -0
  144. package/src/dashboard.meta.ts +47 -0
  145. package/src/declarations.d.ts +6 -0
  146. package/src/form-builder/form-builder.component.tsx +19 -0
  147. package/src/form-builder/form-builder.scss +0 -0
  148. package/src/hooks/useConcept.ts +13 -0
  149. package/src/hooks/useQueues.ts +22 -0
  150. package/src/hooks/useSystemSetting.ts +18 -0
  151. package/src/index.ts +133 -0
  152. package/src/left-panel/left-panel.component.tsx +49 -0
  153. package/src/left-panel/left-panel.scss +13 -0
  154. package/src/location-management/components/auto-suggest/autosuggest.component.tsx +149 -0
  155. package/src/location-management/components/auto-suggest/autosuggest.scss +61 -0
  156. package/src/location-management/components/auto-suggest/location-autosuggest.component.tsx +97 -0
  157. package/src/location-management/components/auto-suggest/location-autosuggest.scss +48 -0
  158. package/src/location-management/components/custom-results-tile/results-tile.component.tsx +43 -0
  159. package/src/location-management/components/custom-results-tile/results-tile.scss +86 -0
  160. package/src/location-management/forms/add-location/add-location.workspace.scss +71 -0
  161. package/src/location-management/forms/add-location/add-location.workspace.tsx +199 -0
  162. package/src/location-management/forms/search-location/search-location.workspace.scss +71 -0
  163. package/src/location-management/forms/search-location/search-location.workspace.tsx +214 -0
  164. package/src/location-management/helpers/index.ts +33 -0
  165. package/src/location-management/hooks/UseFacilityLocations.ts +12 -0
  166. package/src/location-management/hooks/useLocation.ts +18 -0
  167. package/src/location-management/hooks/useLocationTags.ts +15 -0
  168. package/src/location-management/location-management-dashboard.component.tsx +21 -0
  169. package/src/location-management/location-management-dashboard.scss +3 -0
  170. package/src/location-management/tables/locations-table.component.tsx +242 -0
  171. package/src/location-management/tables/locations-table.resource.ts +26 -0
  172. package/src/location-management/tables/locations-table.scss +114 -0
  173. package/src/location-management/types/index.ts +120 -0
  174. package/src/queue-management/queue-management-dashboard.component.tsx +23 -0
  175. package/src/queue-management/queue-management-dashboard.scss +8 -0
  176. package/src/queue-management/queue-management-table/queue-management-table.component.tsx +296 -0
  177. package/src/queue-management/queue-management-table/queue-management-table.scss +78 -0
  178. package/src/queue-management/queue-management-table/queue-management.resource.ts +39 -0
  179. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.scss +56 -0
  180. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.test.tsx +82 -0
  181. package/src/queue-management/queue-management-workspace/queue-room/queue-room-form.workspace.tsx +169 -0
  182. package/src/queue-management/queue-management-workspace/queue-room/queue-room.resource.ts +20 -0
  183. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.scss +61 -0
  184. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.test.tsx +127 -0
  185. package/src/queue-management/queue-management-workspace/queue-service/queue-service-form.workspace.tsx +178 -0
  186. package/src/queue-management/queue-management-workspace/queue-service/queue-service.resource.ts +55 -0
  187. package/src/queue-management/queue-types/index.ts +33 -0
  188. package/src/routes.json +157 -0
  189. package/src/setup-tests.ts +1 -0
  190. package/src/system-info/system-info.component.tsx +338 -0
  191. package/src/system-info/system-info.resource.ts +40 -0
  192. package/src/system-info/system-info.scss +622 -0
  193. package/src/type/index.ts +6 -0
  194. package/translations/am.json +111 -0
  195. package/translations/ar.json +115 -0
  196. package/translations/en.json +111 -0
  197. package/translations/es.json +112 -0
  198. package/translations/fr.json +112 -0
  199. package/translations/he.json +112 -0
  200. package/translations/km.json +110 -0
  201. package/translations/pt.json +112 -0
  202. package/translations/sw.json +111 -0
  203. package/translations/vi.json +110 -0
  204. package/translations/zh.json +110 -0
  205. package/tsconfig.json +5 -0
  206. package/version.js +27 -0
@@ -0,0 +1,296 @@
1
+ import React, { useMemo, useState } from 'react';
2
+ import {
3
+ Button,
4
+ DataTable,
5
+ DataTableSkeleton,
6
+ Table,
7
+ TableBody,
8
+ TableCell,
9
+ TableContainer,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ Layer,
14
+ Pagination,
15
+ Tile,
16
+ } from '@carbon/react';
17
+ import { Add } from '@carbon/react/icons';
18
+ import { launchWorkspace, useLayoutType, ErrorState } from '@openmrs/esm-framework';
19
+ import { useTranslation } from 'react-i18next';
20
+ import styles from './queue-management-table.scss';
21
+ import { useQueueRooms, useQueuesMutable } from './queue-management.resource';
22
+ import { CardHeader } from '@openmrs/esm-patient-common-lib';
23
+ const QueueManagementTable = () => {
24
+ const { t } = useTranslation();
25
+ const layout = useLayoutType();
26
+ const isTablet = layout === 'tablet';
27
+ const responsiveSize = isTablet ? 'lg' : 'sm';
28
+
29
+ const { queues, isLoading: isLoadingQueues, error: queuesError } = useQueuesMutable();
30
+ const { queueRooms, isLoading: isLoadingQueueRooms, error: queueRoomsError } = useQueueRooms();
31
+
32
+ const [currentPage, setCurrentPage] = useState(1);
33
+ const [currentPageSize, setCurrentPageSize] = useState(10);
34
+ const pageSizes = [10, 20, 30, 40, 50];
35
+
36
+ const [currentRoomPage, setCurrentRoomPage] = useState(1);
37
+ const [currentRoomPageSize, setCurrentRoomPageSize] = useState(10);
38
+
39
+ const queueTableHeaders = [
40
+ {
41
+ key: 'name',
42
+ header: t('name', 'Name'),
43
+ },
44
+ {
45
+ key: 'description',
46
+ header: t('description', 'Description'),
47
+ },
48
+ {
49
+ key: 'service',
50
+ header: t('service', 'Service'),
51
+ },
52
+ {
53
+ key: 'location',
54
+ header: t('location', 'Location'),
55
+ },
56
+ ];
57
+
58
+ const queueRoomTableHeaders = [
59
+ {
60
+ key: 'name',
61
+ header: t('name', 'Name'),
62
+ },
63
+ {
64
+ key: 'description',
65
+ header: t('description', 'Description'),
66
+ },
67
+ {
68
+ key: 'queue',
69
+ header: t('queue', 'Queue'),
70
+ },
71
+ ];
72
+
73
+ const queueTableRows = useMemo(() => {
74
+ return (
75
+ queues?.map((queue) => ({
76
+ id: queue.uuid,
77
+ name: queue.name || queue.display,
78
+ description: queue.description || '--',
79
+ service: queue.service?.display || '--',
80
+ location: queue.location?.display || '--',
81
+ })) || []
82
+ );
83
+ }, [queues]);
84
+
85
+ const queueRoomTableRows = useMemo(() => {
86
+ return (
87
+ queueRooms?.map((room) => ({
88
+ id: room.uuid,
89
+ name: room.name || room.display,
90
+ description: room.description || '--',
91
+ queue: (room as any).queue?.display || '--',
92
+ })) || []
93
+ );
94
+ }, [queueRooms]);
95
+
96
+ // Paginated queue rows
97
+ const paginatedQueueRows = useMemo(() => {
98
+ const startIndex = (currentPage - 1) * currentPageSize;
99
+ const endIndex = startIndex + currentPageSize;
100
+ return queueTableRows.slice(startIndex, endIndex);
101
+ }, [queueTableRows, currentPage, currentPageSize]);
102
+
103
+ // Paginated queue room rows
104
+ const paginatedQueueRoomRows = useMemo(() => {
105
+ const startIndex = (currentRoomPage - 1) * currentRoomPageSize;
106
+ const endIndex = startIndex + currentRoomPageSize;
107
+ return queueRoomTableRows.slice(startIndex, endIndex);
108
+ }, [queueRoomTableRows, currentRoomPage, currentRoomPageSize]);
109
+
110
+ const handleAddQueue = () => {
111
+ launchWorkspace('service-queues-service-form');
112
+ };
113
+
114
+ const handleAddQueueRoom = () => {
115
+ launchWorkspace('service-queues-room-workspace');
116
+ };
117
+
118
+ if (isLoadingQueues || isLoadingQueueRooms) {
119
+ return (
120
+ <div className={styles.adminPage}>
121
+ <div className={styles.section}>
122
+ <h3>{t('queues', 'Queues')}</h3>
123
+ <DataTableSkeleton role="progressbar" compact={!isTablet} zebra />
124
+ </div>
125
+ <div className={styles.section}>
126
+ <h3>{t('queueRooms', 'Queue Rooms')}</h3>
127
+ <DataTableSkeleton role="progressbar" compact={!isTablet} zebra />
128
+ </div>
129
+ </div>
130
+ );
131
+ }
132
+
133
+ if (queuesError) {
134
+ return (
135
+ <div className={styles.adminPage}>
136
+ <ErrorState error={queuesError} headerTitle={t('queues', 'Queues')} />
137
+ </div>
138
+ );
139
+ }
140
+
141
+ if (queueRoomsError) {
142
+ return (
143
+ <div className={styles.adminPage}>
144
+ <ErrorState error={queueRoomsError} headerTitle={t('queueRooms', 'Queue Rooms')} />
145
+ </div>
146
+ );
147
+ }
148
+
149
+ return (
150
+ <div className={styles.adminPage}>
151
+ <div className={styles.section}>
152
+ <CardHeader title={t('queues', 'Queues')}>
153
+ <Button kind="ghost" renderIcon={(props) => <Add size={16} {...props} />} onClick={handleAddQueue}>
154
+ {t('addQueue', 'Add Queue')}
155
+ </Button>
156
+ </CardHeader>
157
+ <Layer>
158
+ <DataTable
159
+ rows={paginatedQueueRows}
160
+ headers={queueTableHeaders}
161
+ isSortable
162
+ size={responsiveSize}
163
+ useZebraStyles>
164
+ {({ rows, headers, getTableProps }) => (
165
+ <TableContainer>
166
+ <Table {...getTableProps()}>
167
+ <TableHead>
168
+ <TableRow>
169
+ {headers.map((header) => (
170
+ <TableHeader key={header.key}>{header.header}</TableHeader>
171
+ ))}
172
+ </TableRow>
173
+ </TableHead>
174
+ <TableBody>
175
+ {rows.map((row) => (
176
+ <TableRow key={row.id}>
177
+ {row.cells.map((cell) => (
178
+ <TableCell key={cell.id}>{cell.value}</TableCell>
179
+ ))}
180
+ </TableRow>
181
+ ))}
182
+ </TableBody>
183
+ </Table>
184
+ {queueTableRows.length === 0 ? (
185
+ <div className={styles.tileContainer}>
186
+ <Tile className={styles.tile}>
187
+ <div className={styles.tileContent}>
188
+ <p className={styles.content}>{t('noQueuesFound', 'No queues found')}</p>
189
+ <p className={styles.emptyStateHelperText}>
190
+ {t('checkFilters', 'Please check the filters above and try again')}
191
+ </p>
192
+ </div>
193
+ </Tile>
194
+ </div>
195
+ ) : null}
196
+ {queueTableRows.length > 0 && (
197
+ <Pagination
198
+ forwardText={t('nextPage', 'Next page')}
199
+ backwardText={t('previousPage', 'Previous page')}
200
+ page={currentPage}
201
+ pageSize={currentPageSize}
202
+ pageSizes={pageSizes}
203
+ totalItems={queueTableRows.length}
204
+ className={styles.pagination}
205
+ onChange={({ pageSize, page }) => {
206
+ if (pageSize !== currentPageSize) {
207
+ setCurrentPageSize(pageSize);
208
+ setCurrentPage(1);
209
+ }
210
+ if (page !== currentPage) {
211
+ setCurrentPage(page);
212
+ }
213
+ }}
214
+ />
215
+ )}
216
+ </TableContainer>
217
+ )}
218
+ </DataTable>
219
+ </Layer>
220
+ </div>
221
+
222
+ <div className={styles.section}>
223
+ <CardHeader title={t('queueRooms', 'Queue Rooms')}>
224
+ <Button kind="ghost" renderIcon={(props) => <Add size={16} {...props} />} onClick={handleAddQueueRoom}>
225
+ {t('addQueueRoom', 'Add Queue Room')}
226
+ </Button>
227
+ </CardHeader>
228
+ <Layer>
229
+ <DataTable
230
+ rows={paginatedQueueRoomRows}
231
+ headers={queueRoomTableHeaders}
232
+ isSortable
233
+ size={responsiveSize}
234
+ useZebraStyles>
235
+ {({ rows, headers, getTableProps }) => (
236
+ <TableContainer>
237
+ <Table {...getTableProps()}>
238
+ <TableHead>
239
+ <TableRow>
240
+ {headers.map((header) => (
241
+ <TableHeader key={header.key}>{header.header}</TableHeader>
242
+ ))}
243
+ </TableRow>
244
+ </TableHead>
245
+ <TableBody>
246
+ {rows.map((row) => (
247
+ <TableRow key={row.id}>
248
+ {row.cells.map((cell) => (
249
+ <TableCell key={cell.id}>{cell.value}</TableCell>
250
+ ))}
251
+ </TableRow>
252
+ ))}
253
+ </TableBody>
254
+ </Table>
255
+ {queueRoomTableRows.length === 0 ? (
256
+ <div className={styles.tileContainer}>
257
+ <Tile className={styles.tile}>
258
+ <div className={styles.tileContent}>
259
+ <p className={styles.content}>{t('noQueueRoomsFound', 'No queue rooms found')}</p>
260
+ <p className={styles.emptyStateHelperText}>
261
+ {t('checkFilters', 'Please check the filters above and try again')}
262
+ </p>
263
+ </div>
264
+ </Tile>
265
+ </div>
266
+ ) : null}
267
+ {queueRoomTableRows.length > 0 && (
268
+ <Pagination
269
+ forwardText={t('nextPage', 'Next page')}
270
+ backwardText={t('previousPage', 'Previous page')}
271
+ page={currentRoomPage}
272
+ pageSize={currentRoomPageSize}
273
+ pageSizes={pageSizes}
274
+ totalItems={queueRoomTableRows.length}
275
+ className={styles.pagination}
276
+ onChange={({ pageSize, page }) => {
277
+ if (pageSize !== currentRoomPageSize) {
278
+ setCurrentRoomPageSize(pageSize);
279
+ setCurrentRoomPage(1);
280
+ }
281
+ if (page !== currentRoomPage) {
282
+ setCurrentRoomPage(page);
283
+ }
284
+ }}
285
+ />
286
+ )}
287
+ </TableContainer>
288
+ )}
289
+ </DataTable>
290
+ </Layer>
291
+ </div>
292
+ </div>
293
+ );
294
+ };
295
+
296
+ export default QueueManagementTable;
@@ -0,0 +1,78 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@carbon/colors';
4
+
5
+ .adminPage {
6
+ padding: layout.$spacing-05;
7
+ background: var(--cds-field);
8
+ }
9
+
10
+ .section {
11
+ margin-bottom: layout.$spacing-07;
12
+
13
+ &:last-child {
14
+ margin-bottom: 0;
15
+ }
16
+ }
17
+
18
+ .sectionHeader {
19
+ display: flex;
20
+ justify-content: space-between;
21
+ align-items: center;
22
+ margin-bottom: layout.$spacing-05;
23
+ padding-bottom: layout.$spacing-03;
24
+ border-bottom: 1px solid var(--cds-border-subtle);
25
+
26
+ h3 {
27
+ margin: 0;
28
+ color: var(--cds-text-primary);
29
+ font-size: 1.25rem;
30
+ font-weight: 600;
31
+ }
32
+ }
33
+
34
+ @media (max-width: 768px) {
35
+ .adminPage {
36
+ padding: layout.$spacing-03;
37
+ }
38
+
39
+ .sectionHeader {
40
+ flex-direction: column;
41
+ align-items: flex-start;
42
+ gap: layout.$spacing-03;
43
+
44
+ h3 {
45
+ font-size: 1.125rem;
46
+ }
47
+ }
48
+ }
49
+ .tileContainer {
50
+ border-top: 1px solid colors.$gray-20;
51
+ padding: 3rem 0;
52
+ }
53
+
54
+ .tile {
55
+ margin: auto;
56
+ width: fit-content;
57
+ background: colors.$gray-20;
58
+ }
59
+
60
+ .tileContent {
61
+ display: flex;
62
+ flex-direction: column;
63
+ align-items: center;
64
+ }
65
+
66
+ .content {
67
+ @include type.type-style('heading-compact-02');
68
+ color: colors.$gray-70;
69
+ margin-bottom: layout.$spacing-03;
70
+ }
71
+
72
+ .singleLineDisplay {
73
+ white-space: nowrap;
74
+ }
75
+
76
+ .emptyStateHelperText {
77
+ @include type.type-style('helper-text-02');
78
+ }
@@ -0,0 +1,39 @@
1
+ import { useMemo } from 'react';
2
+ import useSWR from 'swr';
3
+ import { getLocale, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
4
+ import { type QueueRoom, type Queue } from '../queue-types';
5
+
6
+ export function useQueuesMutable() {
7
+ const customRepresentation =
8
+ 'custom:(uuid,display,name,description,service:(uuid,display),allowedPriorities:(uuid,display),allowedStatuses:(uuid,display),location:(uuid,display))';
9
+ const apiUrl = `${restBaseUrl}/queue?v=${customRepresentation}`;
10
+
11
+ const { data, ...rest } = useSWR<{ data: { results: Array<Queue> } }, Error>(apiUrl, openmrsFetch);
12
+
13
+ const queues = useMemo(
14
+ () => data?.data?.results.sort((a, b) => a.display.localeCompare(b.display, getLocale())) ?? [],
15
+ [data?.data?.results],
16
+ );
17
+
18
+ return {
19
+ queues,
20
+ ...rest,
21
+ };
22
+ }
23
+
24
+ export function useQueueRooms() {
25
+ const customRepresentation = 'custom:(uuid,display,name,description,queue:(uuid,display))';
26
+ const apiUrl = `${restBaseUrl}/queue-room?v=${customRepresentation}`;
27
+
28
+ const { data, ...rest } = useSWR<{ data: { results: Array<QueueRoom> } }, Error>(apiUrl, openmrsFetch);
29
+
30
+ const queueRooms = useMemo(
31
+ () => data?.data?.results.sort((a, b) => a.display.localeCompare(b.display, getLocale())) ?? [],
32
+ [data?.data?.results],
33
+ );
34
+
35
+ return {
36
+ queueRooms,
37
+ ...rest,
38
+ };
39
+ }
@@ -0,0 +1,56 @@
1
+ @use '@carbon/layout';
2
+ @use '@carbon/type';
3
+ @use '@openmrs/esm-styleguide/src/vars' as *;
4
+
5
+ $overlay-header-height: 5.5rem;
6
+
7
+ .heading {
8
+ @include type.type-style('heading-compact-01');
9
+ margin: layout.$spacing-05 0 layout.$spacing-05;
10
+ }
11
+
12
+ .warningContainer {
13
+ background-color: $carbon--red-50;
14
+ padding: layout.$spacing-04;
15
+ margin: layout.$spacing-03 0 layout.$spacing-03;
16
+ display: flex;
17
+ justify-content: space-between;
18
+ .warning {
19
+ @include type.type-style('heading-compact-01');
20
+ color: $ui-05;
21
+ }
22
+ }
23
+
24
+ .form {
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: space-between;
28
+ height: 100%;
29
+ }
30
+
31
+ .grid {
32
+ margin: 0 layout.$spacing-05;
33
+ padding: 0;
34
+ }
35
+
36
+ .input {
37
+ margin-top: layout.$spacing-04;
38
+ }
39
+
40
+ .button {
41
+ height: layout.$spacing-10;
42
+ display: flex;
43
+ align-content: flex-start;
44
+ align-items: baseline;
45
+ min-width: 50%;
46
+ }
47
+
48
+ .tablet {
49
+ padding: layout.$spacing-06 layout.$spacing-05;
50
+ background-color: $ui-02;
51
+ }
52
+
53
+ .desktop {
54
+ padding: 0;
55
+ margin-top: layout.$spacing-05;
56
+ }
@@ -0,0 +1,82 @@
1
+ import React from 'react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { render, screen } from '@testing-library/react';
4
+ import { useLayoutType } from '@openmrs/esm-framework';
5
+ import QueueRoomForm from './queue-room-form.workspace';
6
+
7
+ const mockUseLayoutType = jest.mocked(useLayoutType);
8
+
9
+ jest.mock('../../queue-management-workspace/queue-service/queue-service.resource.ts', () => ({
10
+ ...jest.requireActual('../../queue-management-workspace/queue-service/queue-service.resource.ts'),
11
+ useQueueLocations: jest.fn(() => ({
12
+ queueLocations: { uuid: 'e7786d9a-ab62-11ec-b909-0242ac120002', display: 'Location Test' },
13
+ })),
14
+ }));
15
+
16
+ const workspaceProps = {
17
+ closeWorkspace: jest.fn(),
18
+ promptBeforeClosing: jest.fn(),
19
+ closeWorkspaceWithSavedChanges: jest.fn(),
20
+ setTitle: jest.fn(),
21
+ };
22
+
23
+ jest.mock('./queue-room.resource', () => ({
24
+ saveQueueRoom: jest.fn(() => Promise.resolve({ status: 201 })),
25
+ }));
26
+
27
+ describe('QueueRoomForm', () => {
28
+ beforeEach(() => {
29
+ mockUseLayoutType.mockReturnValue('tablet');
30
+ });
31
+
32
+ it('renders the form with queue room elements', () => {
33
+ render(<QueueRoomForm {...workspaceProps} />);
34
+
35
+ expect(screen.getByLabelText('Queue room name')).toBeInTheDocument();
36
+ expect(screen.getByLabelText('Select a service')).toBeInTheDocument();
37
+ expect(screen.getByLabelText('Select a queue location')).toBeInTheDocument();
38
+ expect(screen.getByText('Cancel')).toBeInTheDocument();
39
+ expect(screen.getByText('Save')).toBeInTheDocument();
40
+ });
41
+
42
+ it('displays error notification if queue room name is missing on submission', async () => {
43
+ const user = userEvent.setup();
44
+
45
+ render(<QueueRoomForm {...workspaceProps} />);
46
+
47
+ await user.click(screen.getByText('Save'));
48
+ expect(screen.getByText('Missing queue room name')).toBeInTheDocument();
49
+ });
50
+
51
+ it('displays error notification if queue room service is missing on submission', async () => {
52
+ const user = userEvent.setup();
53
+
54
+ render(<QueueRoomForm {...workspaceProps} />);
55
+
56
+ const queueRoomNameInput = screen.getByLabelText('Queue room name');
57
+
58
+ await user.type(queueRoomNameInput, 'Room 123');
59
+ await user.click(screen.getByText('Save'));
60
+ expect(screen.getByText('Missing queue room service')).toBeInTheDocument();
61
+ });
62
+
63
+ it('calls closePanel when Cancel button is clicked', async () => {
64
+ const user = userEvent.setup();
65
+
66
+ const closeWorkspace = jest.fn();
67
+ render(<QueueRoomForm {...{ ...workspaceProps, closeWorkspace }} />);
68
+
69
+ await user.click(screen.getByText('Cancel'));
70
+ expect(closeWorkspace).toHaveBeenCalledTimes(1);
71
+ });
72
+
73
+ it('updates queue room name state when a value is entered', async () => {
74
+ const user = userEvent.setup();
75
+
76
+ render(<QueueRoomForm {...workspaceProps} />);
77
+
78
+ const queueRoomNameInput = screen.getByLabelText('Queue room name');
79
+ await user.type(queueRoomNameInput, 'Room 123');
80
+ expect(queueRoomNameInput).toHaveValue('Room 123');
81
+ });
82
+ });