@kenyaemr/esm-morgue-app 5.4.2-pre.2283 → 5.4.2-pre.2288

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 (193) hide show
  1. package/.turbo/turbo-build.log +19 -19
  2. package/dist/109.js +2 -0
  3. package/dist/109.js.map +1 -0
  4. package/dist/201.js +1 -0
  5. package/dist/201.js.map +1 -0
  6. package/dist/293.js +1 -0
  7. package/dist/293.js.map +1 -0
  8. package/dist/300.js +1 -1
  9. package/dist/347.js +1 -2
  10. package/dist/347.js.map +1 -1
  11. package/dist/373.js +2 -0
  12. package/dist/373.js.map +1 -0
  13. package/dist/38.js +1 -0
  14. package/dist/38.js.map +1 -0
  15. package/dist/389.js +1 -0
  16. package/dist/389.js.map +1 -0
  17. package/dist/398.js +1 -0
  18. package/dist/398.js.map +1 -0
  19. package/dist/4.js +2 -0
  20. package/dist/4.js.map +1 -0
  21. package/dist/410.js +1 -0
  22. package/dist/410.js.map +1 -0
  23. package/dist/420.js +2 -0
  24. package/dist/420.js.map +1 -0
  25. package/dist/467.js +1 -0
  26. package/dist/467.js.map +1 -0
  27. package/dist/632.js +1 -0
  28. package/dist/632.js.map +1 -0
  29. package/dist/798.js +1 -0
  30. package/dist/798.js.map +1 -0
  31. package/dist/811.js +1 -0
  32. package/dist/811.js.map +1 -0
  33. package/dist/824.js +1 -0
  34. package/dist/824.js.map +1 -0
  35. package/dist/827.js +1 -0
  36. package/dist/827.js.map +1 -0
  37. package/dist/842.js +2 -0
  38. package/dist/842.js.LICENSE.txt +5 -0
  39. package/dist/842.js.map +1 -0
  40. package/dist/918.js +1 -1
  41. package/dist/918.js.map +1 -1
  42. package/dist/kenyaemr-esm-morgue-app.js +1 -1
  43. package/dist/kenyaemr-esm-morgue-app.js.buildmanifest.json +218 -291
  44. package/dist/kenyaemr-esm-morgue-app.js.map +1 -1
  45. package/dist/main.js +2 -1
  46. package/dist/main.js.LICENSE.txt +15 -0
  47. package/dist/main.js.map +1 -1
  48. package/dist/routes.json +1 -1
  49. package/package.json +1 -1
  50. package/src/bed/bed.component.tsx +164 -0
  51. package/src/bed/bed.scss +192 -0
  52. package/src/bed/divider/divider.component.tsx +18 -0
  53. package/src/bed/empty-bed.component.tsx +47 -0
  54. package/src/bed-layout/admitted/admitted-bed-layout.component.tsx +189 -0
  55. package/src/bed-layout/awaiting/awaiting-bed-layout.component.tsx +86 -0
  56. package/src/bed-layout/bed-layout.resource.ts +72 -0
  57. package/src/bed-layout/bed-layout.scss +55 -0
  58. package/src/bed-layout/discharged/discharged-bed-layout.component.tsx +109 -0
  59. package/src/bed-layout/discharged/discharged-bed-layout.resource.ts +99 -0
  60. package/src/bed-linelist-view/admitted/admitted-bed-linelist-view.component.tsx +420 -0
  61. package/src/bed-linelist-view/awaiting/awaiting-bed-linelist-view.component.tsx +224 -0
  62. package/src/bed-linelist-view/bed-linelist-view.scss +5 -0
  63. package/src/bed-linelist-view/discharged/discharged-bed-line-view.component.tsx +256 -0
  64. package/src/config-schema.ts +41 -9
  65. package/src/constants.ts +57 -0
  66. package/src/deceased-patient-header/deceased-patient-header.component.tsx +31 -0
  67. package/src/deceased-patient-header/deceased-patient-header.scss +50 -0
  68. package/src/{component → deceased-patient-header}/deceasedInfo/deceased-info.component.tsx +1 -1
  69. package/src/deceased-patient-header/deceasedInfo/deceased-info.resource.ts +11 -0
  70. package/src/extension/actionButton.component.tsx +5 -59
  71. package/src/extension/deceasedInfoBanner.component.tsx +5 -9
  72. package/src/{hook/useAdmitPatient.ts → forms/admit-deceased-person-workspace/admit-deceased-person.resource.ts} +177 -46
  73. package/src/forms/admit-deceased-person-workspace/admit-deceased-person.scss +143 -0
  74. package/src/forms/admit-deceased-person-workspace/admit-deceased-person.workspace.tsx +648 -0
  75. package/src/{hook/usePersonAttributes.ts → forms/discharge-deceased-person-workspace/discharge-body.resource.ts} +1 -1
  76. package/src/forms/discharge-deceased-person-workspace/discharge-body.scss +56 -0
  77. package/src/forms/discharge-deceased-person-workspace/discharge-body.workspace.tsx +362 -0
  78. package/src/forms/dispose-deceased-person-workspace/dispose-deceased-person.resource.ts +18 -0
  79. package/src/{workspaces/patientAdditionalInfoForm.scss → forms/dispose-deceased-person-workspace/dispose-deceased-person.scss} +46 -66
  80. package/src/forms/dispose-deceased-person-workspace/dispose-deceased-person.workspace.tsx +401 -0
  81. package/src/forms/form-entry-workspace/form-entry-workspace.workspace.tsx +62 -0
  82. package/src/forms/swap-compartment-workspace/swap-unit.scss +144 -0
  83. package/src/forms/swap-compartment-workspace/swap-unit.workspace.tsx +280 -0
  84. package/src/header/header.component.tsx +41 -0
  85. package/src/header/header.scss +58 -0
  86. package/src/home/home.component.tsx +87 -0
  87. package/src/home/home.resource.ts +261 -0
  88. package/src/home/home.scss +5 -0
  89. package/src/index.ts +18 -12
  90. package/src/metrics/metrics-card.component.tsx +31 -0
  91. package/src/metrics/metrics-card.scss +51 -0
  92. package/src/root.component.tsx +7 -3
  93. package/src/routes.json +25 -1
  94. package/src/schemas/index.ts +66 -0
  95. package/src/summary/summary.component.tsx +42 -0
  96. package/src/summary/summary.scss +10 -0
  97. package/src/switcher/content-switcher.component.tsx +220 -0
  98. package/src/switcher/content-switcher.scss +30 -0
  99. package/src/types/index.ts +336 -359
  100. package/src/utils/utils.ts +20 -2
  101. package/src/view-details/main/main.component.tsx +34 -0
  102. package/src/view-details/main/main.scss +45 -0
  103. package/src/view-details/panels/attachement.component.tsx +21 -0
  104. package/src/view-details/panels/autopsy.component.tsx +215 -0
  105. package/src/view-details/panels/billing-history.component.tsx +13 -0
  106. package/src/view-details/panels/observations/observation.component.tsx +57 -0
  107. package/src/view-details/panels/observations/observation.scss +24 -0
  108. package/src/view-details/panels/panels.scss +46 -0
  109. package/src/view-details/view-details.component.tsx +65 -0
  110. package/src/view-details/view-details.resource.ts +65 -0
  111. package/src/view-details/views-details.scss +82 -0
  112. package/translations/en.json +74 -21
  113. package/tsconfig.json +1 -1
  114. package/dist/113.js +0 -1
  115. package/dist/113.js.map +0 -1
  116. package/dist/160.js +0 -1
  117. package/dist/160.js.map +0 -1
  118. package/dist/299.js +0 -1
  119. package/dist/299.js.map +0 -1
  120. package/dist/433.js +0 -2
  121. package/dist/433.js.map +0 -1
  122. package/dist/441.js +0 -1
  123. package/dist/441.js.map +0 -1
  124. package/dist/496.js +0 -1
  125. package/dist/496.js.map +0 -1
  126. package/dist/511.js +0 -1
  127. package/dist/511.js.map +0 -1
  128. package/dist/603.js +0 -1
  129. package/dist/603.js.map +0 -1
  130. package/dist/610.js +0 -1
  131. package/dist/610.js.map +0 -1
  132. package/dist/612.js +0 -1
  133. package/dist/612.js.map +0 -1
  134. package/dist/656.js +0 -2
  135. package/dist/656.js.map +0 -1
  136. package/dist/752.js +0 -1
  137. package/dist/752.js.map +0 -1
  138. package/dist/754.js +0 -1
  139. package/dist/754.js.map +0 -1
  140. package/dist/781.js +0 -1
  141. package/dist/781.js.map +0 -1
  142. package/dist/801.js +0 -2
  143. package/dist/801.js.map +0 -1
  144. package/dist/817.js +0 -1
  145. package/dist/817.js.map +0 -1
  146. package/dist/877.js +0 -1
  147. package/dist/877.js.map +0 -1
  148. package/dist/924.js +0 -1
  149. package/dist/924.js.map +0 -1
  150. package/src/autosuggest/autosuggest.component.tsx +0 -162
  151. package/src/autosuggest/autosuggest.scss +0 -61
  152. package/src/autosuggest/patient-search-info.component.tsx +0 -75
  153. package/src/autosuggest/patient-search-info.scss +0 -62
  154. package/src/autosuggest/search-empty-state.component.tsx +0 -21
  155. package/src/autosuggest/search-empty-state.scss +0 -18
  156. package/src/card/avail-compartment.compartment.tsx +0 -94
  157. package/src/card/compartment-view.compartment.tsx +0 -62
  158. package/src/card/compartment.scss +0 -128
  159. package/src/card/compartmentSharing.component.tsx +0 -21
  160. package/src/card/compartmentSharing.scss +0 -24
  161. package/src/card/empty-compartment.component.tsx +0 -28
  162. package/src/card/empty-compartment.scss +0 -61
  163. package/src/component/main.component.tsx +0 -17
  164. package/src/component/next-of-kin-details/nextOfKinDetails.component.tsx +0 -50
  165. package/src/component/next-of-kin-details/nextOfKinDetails.scss +0 -37
  166. package/src/header/admitted-queue-header.component.tsx +0 -30
  167. package/src/header/admitted-queue-header.scss +0 -32
  168. package/src/header/morgue-header.component.tsx +0 -38
  169. package/src/header/morgue-header.scss +0 -95
  170. package/src/header/morgue-illustration.component.tsx +0 -13
  171. package/src/hook/useDeceasedPatients.ts +0 -12
  172. package/src/hook/useDischargedPatient.ts +0 -55
  173. package/src/hook/useMorgue.resource.ts +0 -163
  174. package/src/hook/useMortuaryAdmissionLocation.ts +0 -64
  175. package/src/tables/admitted-queue.component.tsx +0 -54
  176. package/src/tables/admitted-queue.scss +0 -62
  177. package/src/tables/discharge-queue.component.tsx +0 -87
  178. package/src/tables/generic-table.component.tsx +0 -140
  179. package/src/tables/generic-table.scss +0 -37
  180. package/src/tabs/tabs.component.tsx +0 -82
  181. package/src/tabs/tabs.scss +0 -15
  182. package/src/workspaces/admit-body.scss +0 -46
  183. package/src/workspaces/admit-body.workspace.tsx +0 -79
  184. package/src/workspaces/discharge-body.scss +0 -67
  185. package/src/workspaces/discharge-body.workspace.tsx +0 -329
  186. package/src/workspaces/patientAdditionalInfoForm.workspace.tsx +0 -562
  187. package/src/workspaces/swap-unit.scss +0 -46
  188. package/src/workspaces/swap-unit.workspace.tsx +0 -168
  189. /package/dist/{347.js.LICENSE.txt → 109.js.LICENSE.txt} +0 -0
  190. /package/dist/{656.js.LICENSE.txt → 373.js.LICENSE.txt} +0 -0
  191. /package/dist/{801.js.LICENSE.txt → 4.js.LICENSE.txt} +0 -0
  192. /package/dist/{433.js.LICENSE.txt → 420.js.LICENSE.txt} +0 -0
  193. /package/src/{component → deceased-patient-header}/deceasedInfo/deceased-info.scss +0 -0
@@ -0,0 +1,280 @@
1
+ import {
2
+ Button,
3
+ ButtonSet,
4
+ Form,
5
+ Stack,
6
+ Column,
7
+ InlineLoading,
8
+ InlineNotification,
9
+ Search,
10
+ RadioButton,
11
+ RadioButtonGroup,
12
+ Tag,
13
+ Layer,
14
+ Tile,
15
+ FormGroup,
16
+ } from '@carbon/react';
17
+ import React, { useState, useMemo } from 'react';
18
+ import { useTranslation } from 'react-i18next';
19
+ import DeceasedInfo from '../../deceased-patient-header/deceasedInfo/deceased-info.component';
20
+ import styles from './swap-unit.scss';
21
+ import { Controller, useForm } from 'react-hook-form';
22
+ import { z } from 'zod';
23
+ import { zodResolver } from '@hookform/resolvers/zod';
24
+ import {
25
+ useVisit,
26
+ showSnackbar,
27
+ navigate,
28
+ restBaseUrl,
29
+ ResponsiveWrapper,
30
+ useLayoutType,
31
+ } from '@openmrs/esm-framework';
32
+ import { EmptyDataIllustration } from '@openmrs/esm-patient-common-lib';
33
+ import classNames from 'classnames';
34
+ import { type MortuaryLocationResponse } from '../../types';
35
+ import { useMortuaryOperation } from '../admit-deceased-person-workspace/admit-deceased-person.resource';
36
+
37
+ interface SwapFormProps {
38
+ closeWorkspace: () => void;
39
+ patientUuid: string;
40
+ mortuaryLocation: MortuaryLocationResponse;
41
+ mutate?: () => void;
42
+ }
43
+
44
+ const schema = z.object({
45
+ availableCompartment: z
46
+ .union([z.number(), z.string()])
47
+ .refine((val) => {
48
+ if (typeof val === 'string') {
49
+ return val.length > 0 && !isNaN(Number(val)) && Number(val) > 0;
50
+ }
51
+ return typeof val === 'number' && !isNaN(val) && val > 0;
52
+ }, 'Please select an available compartment')
53
+ .transform((val) => (typeof val === 'string' ? Number(val) : val)),
54
+ });
55
+
56
+ const SwapForm: React.FC<SwapFormProps> = ({ closeWorkspace, patientUuid, mortuaryLocation, mutate }) => {
57
+ const { t } = useTranslation();
58
+ const isTablet = useLayoutType() === 'tablet';
59
+ const { currentVisit } = useVisit(patientUuid);
60
+ const { assignDeceasedToCompartment, removeDeceasedFromCompartment, createEncounterForCompartmentSwap } =
61
+ useMortuaryOperation();
62
+
63
+ const [searchTerm, setSearchTerm] = useState('');
64
+
65
+ const {
66
+ control,
67
+ handleSubmit,
68
+ formState: { errors, isSubmitting, isDirty },
69
+ } = useForm({
70
+ resolver: zodResolver(schema),
71
+ defaultValues: {
72
+ availableCompartment: '',
73
+ },
74
+ });
75
+
76
+ const currentBed = mortuaryLocation?.bedLayouts?.find((bed) =>
77
+ bed.patients?.some((patient) => patient.uuid === patientUuid),
78
+ );
79
+
80
+ const currentBedNumber = currentBed?.bedNumber;
81
+
82
+ const filteredBeds = useMemo(() => {
83
+ if (!mortuaryLocation?.bedLayouts) {
84
+ return [];
85
+ }
86
+
87
+ let beds = mortuaryLocation.bedLayouts;
88
+
89
+ if (searchTerm) {
90
+ beds = beds.filter(
91
+ (bed) =>
92
+ bed.bedNumber.toLowerCase().includes(searchTerm.toLowerCase()) ||
93
+ bed.bedType?.displayName?.toLowerCase().includes(searchTerm.toLowerCase()) ||
94
+ bed.status?.toLowerCase().includes(searchTerm.toLowerCase()) ||
95
+ bed.patients?.some((patient) => patient.person?.display?.toLowerCase().includes(searchTerm.toLowerCase())),
96
+ );
97
+ }
98
+
99
+ return beds;
100
+ }, [mortuaryLocation?.bedLayouts, searchTerm]);
101
+
102
+ const onSubmit = async (data: any) => {
103
+ const { availableCompartment } = data;
104
+ const bedSelected = mortuaryLocation?.bedLayouts?.find((bed) => bed.bedId === availableCompartment);
105
+ const bedAssignedToPatient = mortuaryLocation?.bedLayouts?.find((bed) =>
106
+ bed.patients?.some((patient) => patient.uuid === patientUuid),
107
+ );
108
+
109
+ try {
110
+ const encounterResponse = await createEncounterForCompartmentSwap(patientUuid, currentVisit?.uuid);
111
+
112
+ if (encounterResponse.ok) {
113
+ if (bedSelected) {
114
+ const compartmentResponse = await assignDeceasedToCompartment(
115
+ patientUuid,
116
+ availableCompartment,
117
+ encounterResponse.data.uuid,
118
+ );
119
+
120
+ if (compartmentResponse.ok) {
121
+ showSnackbar({
122
+ kind: 'success',
123
+ title: t('deceasedPatientAssignedNewBed', 'Deceased patient assigned to new compartment'),
124
+ subtitle: t(
125
+ 'deceasedPatientAssignedNewBedDetail',
126
+ '{{patientName}} assigned to compartment {{bedNumber}}',
127
+ {
128
+ patientName: currentVisit?.patient?.person?.display,
129
+ bedNumber: bedSelected.bedNumber,
130
+ },
131
+ ),
132
+ });
133
+ }
134
+ } else if (bedAssignedToPatient) {
135
+ const unassignResponse = await removeDeceasedFromCompartment(patientUuid, bedAssignedToPatient.bedId);
136
+
137
+ if (unassignResponse.ok) {
138
+ showSnackbar({
139
+ kind: 'success',
140
+ title: t('patientUnassignedFromBed', 'Deceased patient unassigned from bed'),
141
+ subtitle: t('patientUnassignedFromBedDetail', '{{patientName}} is now unassigned from bed', {
142
+ patientName: currentVisit?.patient?.person?.display,
143
+ }),
144
+ });
145
+ }
146
+ }
147
+
148
+ mutate();
149
+ navigate({ to: window.getOpenmrsSpaBase() + `home/morgue` });
150
+ closeWorkspace();
151
+ } else {
152
+ showSnackbar({
153
+ kind: 'error',
154
+ title: t('errorCreatingEncounter', 'Error assigning deceased to compartment'),
155
+ subtitle: t('errorCreatingEncounterDetail', 'Please try again or contact system administrator'),
156
+ });
157
+ }
158
+ } catch (error) {
159
+ showSnackbar({
160
+ kind: 'error',
161
+ title: t('errorChangingPatientBedAssignment', 'Error changing patient bed assignment'),
162
+ subtitle: error?.message,
163
+ });
164
+ }
165
+ };
166
+
167
+ return (
168
+ <Form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
169
+ <div className={styles.formContainer}>
170
+ <Stack gap={3}>
171
+ <DeceasedInfo patientUuid={patientUuid} />
172
+ <ResponsiveWrapper>
173
+ <Column>
174
+ <FormGroup legendText="">
175
+ <div className={classNames(styles.visitTypeOverviewWrapper)}>
176
+ <Search
177
+ onChange={(event) => setSearchTerm(event.target.value)}
178
+ placeholder={t('searchForCompartments', 'Search for a compartment')}
179
+ labelText=""
180
+ value={searchTerm}
181
+ className={styles.searchInput}
182
+ />
183
+ <div className={styles.compartmentListContainer}>
184
+ {filteredBeds.length > 0 ? (
185
+ <Controller
186
+ control={control}
187
+ name="availableCompartment"
188
+ render={({ field }) => (
189
+ <RadioButtonGroup
190
+ className={styles.radioButtonGroup}
191
+ orientation="vertical"
192
+ name="availableCompartment"
193
+ valueSelected={field.value ? field.value.toString() : ''}
194
+ onChange={(value) => {
195
+ field.onChange(value);
196
+ }}>
197
+ {filteredBeds.map((bed, index) => {
198
+ const isCurrentBed = bed.bedId === currentBed?.bedId;
199
+ const isOccupied = bed.status === 'OCCUPIED';
200
+
201
+ return (
202
+ <div key={index} className={styles.compartmentOption}>
203
+ <div className={styles.radioButtonWrapper}>
204
+ <RadioButton
205
+ className={styles.radioButton}
206
+ id={`compartment-${index}`}
207
+ labelText={bed.bedNumber}
208
+ value={bed.bedId.toString()}
209
+ disabled={isCurrentBed}
210
+ />
211
+ </div>
212
+ <div className={styles.compartmentInfo}>
213
+ <div className={styles.compartmentTags}>
214
+ <Tag type={bed.bedType?.displayName === 'VIP' ? 'green' : 'blue'} size="sm">
215
+ {bed.bedType?.displayName || 'Standard'}
216
+ </Tag>
217
+ <Tag type={bed.status === 'AVAILABLE' ? 'green' : 'red'} size="sm">
218
+ {bed.status || 'Unknown'}
219
+ </Tag>
220
+ {isCurrentBed && (
221
+ <Tag type="purple" size="sm">
222
+ {t('current', 'Current')}
223
+ </Tag>
224
+ )}
225
+ </div>
226
+ </div>
227
+ </div>
228
+ );
229
+ })}
230
+ </RadioButtonGroup>
231
+ )}
232
+ />
233
+ ) : (
234
+ <Layer>
235
+ <Tile className={styles.emptyStateTile}>
236
+ <EmptyDataIllustration />
237
+ <p className={styles.emptyStateContent}>
238
+ {t('noCompartmentsFound', 'No compartments found')}
239
+ </p>
240
+ </Tile>
241
+ </Layer>
242
+ )}
243
+ </div>
244
+ </div>
245
+ {errors.availableCompartment && (
246
+ <div className={styles.invalidText}>
247
+ {typeof errors.availableCompartment?.message === 'string'
248
+ ? errors.availableCompartment.message
249
+ : ''}
250
+ </div>
251
+ )}
252
+ </FormGroup>
253
+ </Column>
254
+ </ResponsiveWrapper>
255
+ </Stack>
256
+ </div>
257
+ <ButtonSet
258
+ className={classNames({
259
+ [styles.tablet]: isTablet,
260
+ [styles.desktop]: !isTablet,
261
+ })}>
262
+ <Button className={styles.buttonContainer} kind="secondary" onClick={() => closeWorkspace()}>
263
+ {t('cancel', 'Cancel')}
264
+ </Button>
265
+ <Button className={styles.buttonContainer} disabled={isSubmitting || !isDirty} kind="primary" type="submit">
266
+ {isSubmitting ? (
267
+ <span className={styles.inlineLoading}>
268
+ {t('submitting', 'Submitting' + '...')}
269
+ <InlineLoading status="active" iconDescription="Loading" />
270
+ </span>
271
+ ) : (
272
+ t('saveAndClose', 'Save & close')
273
+ )}
274
+ </Button>
275
+ </ButtonSet>
276
+ </Form>
277
+ );
278
+ };
279
+
280
+ export default SwapForm;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import { Calendar, Location } from '@carbon/react/icons';
4
+ import { ConfigurableLink, formatDate, PageHeader, PageHeaderContent, useSession } from '@openmrs/esm-framework';
5
+ import styles from './header.scss';
6
+ import { TwoPersonLift } from '@carbon/pictograms-react';
7
+
8
+ type HeaderProps = {
9
+ title: string;
10
+ };
11
+
12
+ const Header: React.FC<HeaderProps> = ({ title }) => {
13
+ const { t } = useTranslation();
14
+ const userSession = useSession();
15
+ const userLocation = userSession?.sessionLocation?.display;
16
+
17
+ return (
18
+ <PageHeader className={styles.header}>
19
+ <PageHeaderContent
20
+ illustration={
21
+ <ConfigurableLink to={`${window.getOpenmrsSpaBase()}home/morgue`}>
22
+ <TwoPersonLift className={styles.mortuaryPictogram} />
23
+ </ConfigurableLink>
24
+ }
25
+ title={title}
26
+ className={styles.leftJustifiedItems}
27
+ />
28
+ <div className={styles.rightJustifiedItems}>
29
+ <div className={styles.dateAndLocation}>
30
+ <Location size={16} />
31
+ <span className={styles.value}>{userLocation}</span>
32
+ <span className={styles.middot}>&middot;</span>
33
+ <Calendar size={16} />
34
+ <span className={styles.value}>{formatDate(new Date(), { mode: 'standard' })}</span>
35
+ </div>
36
+ </div>
37
+ </PageHeader>
38
+ );
39
+ };
40
+
41
+ export default Header;
@@ -0,0 +1,58 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+
5
+ .header {
6
+ @include type.type-style('body-compact-02');
7
+ color: colors.$gray-70;
8
+ height: layout.$spacing-12;
9
+ background-color: colors.$white-0;
10
+ display: flex;
11
+ padding-left: layout.$spacing-03;
12
+ justify-content: space-between;
13
+ border-bottom: 1px solid colors.$gray-20;
14
+ }
15
+
16
+ .leftJustifiedItems {
17
+ display: flex;
18
+ flex-direction: row;
19
+ align-items: center;
20
+ cursor: pointer;
21
+
22
+ & > div:nth-child(2) {
23
+ margin: layout.$spacing-05;
24
+
25
+ & > p:last-child {
26
+ white-space: nowrap;
27
+ @include type.type-style('heading-04');
28
+ }
29
+ }
30
+ }
31
+
32
+ .mortuaryPictogram {
33
+ width: 4.5rem;
34
+ height: 4.5rem;
35
+ fill: var(--brand-03);
36
+ }
37
+
38
+ .rightJustifiedItems {
39
+ @include type.type-style('body-compact-02');
40
+ color: colors.$gray-70;
41
+ margin: layout.$spacing-03;
42
+ padding-top: layout.$spacing-04;
43
+ }
44
+
45
+ .dateAndLocation {
46
+ display: flex;
47
+ justify-content: flex-end;
48
+ align-items: center;
49
+ margin-right: layout.$spacing-05;
50
+ }
51
+
52
+ .value {
53
+ margin-left: layout.$spacing-02;
54
+ }
55
+
56
+ .middot {
57
+ margin: 0 layout.$spacing-03;
58
+ }
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import { useTranslation } from 'react-i18next';
3
+ import Header from '../header/header.component';
4
+ import styles from './home.scss';
5
+ import Summary from '../summary/summary.component';
6
+ import CustomContentSwitcher from '../switcher/content-switcher.component';
7
+ import { useAwaitingPatients, useAwaitingQueuePatients } from './home.resource';
8
+ import { useLocation, useMortuaryAdmissionLocation } from '../bed-layout/bed-layout.resource';
9
+
10
+ const HomeViewComponent: React.FC = () => {
11
+ const { t } = useTranslation();
12
+
13
+ const [selectedLocation, setSelectedLocation] = React.useState<string>('');
14
+
15
+ const { locations, isLoading: isLoadingLocation, error: locationError } = useLocation();
16
+
17
+ const {
18
+ admissionLocation,
19
+ isLoading: isLoadingAdmission,
20
+ error: admissionError,
21
+ mutate,
22
+ } = useMortuaryAdmissionLocation(selectedLocation);
23
+
24
+ const {
25
+ awaitingQueueDeceasedPatients,
26
+ admittedPatients,
27
+ dischargedPatients,
28
+ dischargedPatientsCount,
29
+ isLoadingAwaitingQueuePatients,
30
+ isLoadingDischarge,
31
+ isLoadingAll,
32
+ errorFetchingAwaitingQueuePatients,
33
+ mutateAwaitingQueuePatients,
34
+ mutateAll,
35
+ } = useAwaitingQueuePatients(admissionLocation);
36
+
37
+ const locationItems = React.useMemo(() => {
38
+ return locations.map((location) => ({
39
+ id: location.ward.uuid,
40
+ text: location.ward.display,
41
+ ...location,
42
+ }));
43
+ }, [locations]);
44
+
45
+ React.useEffect(() => {
46
+ if (locationItems.length === 1 && !selectedLocation) {
47
+ setSelectedLocation(locationItems[0].id);
48
+ }
49
+ }, [locationItems, selectedLocation]);
50
+
51
+ const trulyAwaitingPatients = useAwaitingPatients(awaitingQueueDeceasedPatients);
52
+
53
+ const handleLocationChange = React.useCallback((data: { selectedItem: { id: string; text: string } }) => {
54
+ if (data.selectedItem) {
55
+ setSelectedLocation(data.selectedItem.id);
56
+ }
57
+ }, []);
58
+
59
+ return (
60
+ <section className={styles.section}>
61
+ <Header title={t('mortuary', 'Mortuary')} />
62
+ <Summary
63
+ awaitingQueueCount={trulyAwaitingPatients.length}
64
+ admittedCount={admittedPatients.length}
65
+ dischargedCount={dischargedPatientsCount}
66
+ isLoading={isLoadingAll}
67
+ />
68
+ <CustomContentSwitcher
69
+ awaitingQueueDeceasedPatients={trulyAwaitingPatients}
70
+ isLoading={isLoadingAwaitingQueuePatients}
71
+ locationItems={locationItems}
72
+ selectedLocation={selectedLocation}
73
+ admissionLocation={admissionLocation}
74
+ isLoadingLocation={isLoadingLocation}
75
+ isLoadingAdmission={isLoadingAdmission}
76
+ locationError={locationError}
77
+ admissionError={admissionError}
78
+ onLocationChange={handleLocationChange}
79
+ mutate={mutate}
80
+ dischargedPatients={dischargedPatients}
81
+ isLoadingDischarge={isLoadingDischarge}
82
+ />
83
+ </section>
84
+ );
85
+ };
86
+
87
+ export default HomeViewComponent;