@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,648 @@
1
+ import React, { useEffect, useMemo, useState } from 'react';
2
+ import {
3
+ type DefaultWorkspaceProps,
4
+ ResponsiveWrapper,
5
+ useLayoutType,
6
+ showSnackbar,
7
+ useConfig,
8
+ restBaseUrl,
9
+ ExtensionSlot,
10
+ } from '@openmrs/esm-framework';
11
+ import { useTranslation } from 'react-i18next';
12
+ import { Controller, useForm } from 'react-hook-form';
13
+ import {
14
+ ButtonSet,
15
+ Button,
16
+ InlineLoading,
17
+ TextInput,
18
+ FormGroup,
19
+ Stack,
20
+ Form,
21
+ FilterableMultiSelect,
22
+ DatePicker,
23
+ Column,
24
+ DatePickerInput,
25
+ TimePicker,
26
+ TimePickerSelect,
27
+ SelectItem,
28
+ Search,
29
+ RadioButton,
30
+ RadioButtonGroup,
31
+ Tag,
32
+ Layer,
33
+ Tile,
34
+ Dropdown,
35
+ ComboBox,
36
+ InlineNotification,
37
+ } from '@carbon/react';
38
+ import classNames from 'classnames';
39
+ import { z } from 'zod';
40
+ import fuzzy from 'fuzzy';
41
+ import styles from './admit-deceased-person.scss';
42
+ import {
43
+ createPatientBill,
44
+ useBillableItems,
45
+ useCashPoint,
46
+ useMortuaryOperation,
47
+ usePaymentModes,
48
+ useVisitType,
49
+ } from './admit-deceased-person.resource';
50
+ import { getCurrentTime } from '../../utils/utils';
51
+ import { deceasedPatientAdmitSchema } from '../../schemas';
52
+ import { ConfigObject } from '../../config-schema';
53
+ import { DeceasedPatientHeader } from '../../deceased-patient-header/deceased-patient-header.component';
54
+ import { type MortuaryLocationResponse, type MortuaryPatient } from '../../types';
55
+ import { zodResolver } from '@hookform/resolvers/zod';
56
+ import { EmptyDataIllustration } from '@openmrs/esm-patient-common-lib';
57
+ import { PENDING_PAYMENT_STATUS } from '../../constants';
58
+ import { mutate } from 'swr';
59
+
60
+ type AdmitDeceasedPersonProps = DefaultWorkspaceProps & {
61
+ patientData: MortuaryPatient;
62
+ mortuaryLocation: MortuaryLocationResponse;
63
+ mutated;
64
+ deceasedPatientUuid?: string;
65
+ };
66
+
67
+ const MAX_RESULTS = 5;
68
+
69
+ const AdmitDeceasedPerson: React.FC<AdmitDeceasedPersonProps> = ({
70
+ closeWorkspace,
71
+ patientData,
72
+ mortuaryLocation,
73
+ mutated,
74
+ deceasedPatientUuid,
75
+ }) => {
76
+ const { t } = useTranslation();
77
+ const isTablet = useLayoutType() === 'tablet';
78
+ const [searchTerm, setSearchTerm] = useState('');
79
+ const [isPoliceCase, setIsPoliceCase] = useState<string | null>(null);
80
+
81
+ const { data: visitTypes, isLoading: isLoadingVisitTypes } = useVisitType();
82
+ const { lineItems, isLoading: isLoadingLineItems, error: lineError } = useBillableItems();
83
+ const { time: defaultTime, period: defaultPeriod } = getCurrentTime();
84
+ const { admitBody, errorFetchingEmrConfiguration, isLoadingEmrConfiguration } = useMortuaryOperation(
85
+ mortuaryLocation?.ward?.uuid,
86
+ );
87
+
88
+ const { cashPoints } = useCashPoint();
89
+ const cashPointUuid = cashPoints?.[0]?.uuid ?? '';
90
+
91
+ const patientUuid = patientData?.patient?.uuid || deceasedPatientUuid;
92
+
93
+ const { insuranceSchemes } = useConfig({ externalModuleName: '@kenyaemr/esm-billing-app' });
94
+
95
+ const { paymentModes, isLoading: isLoadingPaymentModes } = usePaymentModes();
96
+
97
+ const { morgueVisitTypeUuid, morgueDepartmentServiceTypeUuid, insurancepaymentModeUuid } = useConfig<ConfigObject>();
98
+ const handleMutation = () => {
99
+ const url = `${restBaseUrl}/morgue`;
100
+
101
+ mutate((key) => typeof key === 'string' && key.startsWith(url), undefined, {
102
+ revalidate: true,
103
+ });
104
+ };
105
+
106
+ const handlePoliceCaseChange = (selectedItem: string | null) => {
107
+ setIsPoliceCase(selectedItem);
108
+ };
109
+
110
+ const {
111
+ control,
112
+ watch,
113
+ handleSubmit,
114
+ formState: { errors, isDirty, isSubmitting },
115
+ } = useForm<z.infer<typeof deceasedPatientAdmitSchema>>({
116
+ resolver: zodResolver(deceasedPatientAdmitSchema),
117
+ defaultValues: {
118
+ dateOfAdmission: new Date(),
119
+ timeOfDeath: defaultTime,
120
+ period: defaultPeriod,
121
+ tagNumber: '',
122
+ obNumber: '',
123
+ policeName: '',
124
+ policeIDNo: '',
125
+ visitType: morgueVisitTypeUuid,
126
+ paymentMethod: '',
127
+ insuranceScheme: '',
128
+ dischargeArea: '',
129
+ policyNumber: '',
130
+ services: [],
131
+ availableCompartment: 0,
132
+ },
133
+ });
134
+
135
+ const currentVisitType = visitTypes?.find((vt) => vt.uuid === morgueVisitTypeUuid);
136
+ const paymentMethodObservable = watch('paymentMethod');
137
+
138
+ const filteredBeds = useMemo(() => {
139
+ if (!mortuaryLocation?.bedLayouts) {
140
+ return [];
141
+ }
142
+
143
+ if (!searchTerm) {
144
+ return mortuaryLocation.bedLayouts;
145
+ }
146
+
147
+ return mortuaryLocation.bedLayouts.filter(
148
+ (bed) =>
149
+ bed.bedNumber.toLowerCase().includes(searchTerm.toLowerCase()) ||
150
+ bed.bedType?.displayName?.toLowerCase().includes(searchTerm.toLowerCase()) ||
151
+ bed.status?.toLowerCase().includes(searchTerm.toLowerCase()),
152
+ );
153
+ }, [mortuaryLocation?.bedLayouts, searchTerm]);
154
+
155
+ const onSubmit = async (data: z.infer<typeof deceasedPatientAdmitSchema>) => {
156
+ const serviceUuid = data.services;
157
+
158
+ const linesItems = lineItems
159
+ .filter((item) => serviceUuid.includes(item.uuid))
160
+ .map((item, index) => {
161
+ const priceForPaymentMode =
162
+ item.servicePrices.find((p) => p.paymentMode?.uuid === paymentModes) || item?.servicePrices[0];
163
+
164
+ return {
165
+ billableService: item.uuid,
166
+ quantity: 1,
167
+ price: priceForPaymentMode ? priceForPaymentMode.price : '0.000',
168
+ priceName: 'Default',
169
+ priceUuid: priceForPaymentMode ? priceForPaymentMode.uuid : '',
170
+ lineItemOrder: index,
171
+ paymentStatus: PENDING_PAYMENT_STATUS,
172
+ };
173
+ });
174
+
175
+ const { admissionEncounter, compartment } = await admitBody(patientUuid, data);
176
+
177
+ if (admissionEncounter && compartment) {
178
+ showSnackbar({
179
+ title: t('admissionSuccess', 'Deceased Admission'),
180
+ subtitle: t('admissionSuccessMessage', 'Patient has been admitted to the mortuary successfully'),
181
+ kind: 'success',
182
+ });
183
+ } else {
184
+ showSnackbar({
185
+ title: t('admissionError', 'Deceased Admission Error'),
186
+ subtitle: t(
187
+ 'admissionError',
188
+ 'An error has occurred while admitting deceased patient to the mortuary, Contact system administrator',
189
+ ),
190
+ kind: 'error',
191
+ isLowContrast: true,
192
+ });
193
+ }
194
+
195
+ const billPayload = {
196
+ lineItems: linesItems,
197
+ cashPoint: cashPointUuid,
198
+ patient: patientUuid,
199
+ status: PENDING_PAYMENT_STATUS,
200
+ payments: [],
201
+ };
202
+
203
+ await createPatientBill(billPayload).then(
204
+ () => {
205
+ showSnackbar({
206
+ title: t('patientBill', 'Patient Bill'),
207
+ subtitle: t('patientBillSuccess', 'Patient has been billed successfully'),
208
+ kind: 'success',
209
+ });
210
+ },
211
+ (error) => {
212
+ const errorMessage = JSON.stringify(error?.responseBody?.error?.message?.replace(/\[/g, '').replace(/\]/g, ''));
213
+ showSnackbar({
214
+ title: 'Patient Bill Error',
215
+ subtitle: `An error has occurred while creating patient bill, Contact system administrator quoting this error ${errorMessage}`,
216
+ kind: 'error',
217
+ isLowContrast: true,
218
+ });
219
+ },
220
+ );
221
+ mutated();
222
+ handleMutation();
223
+ closeWorkspace();
224
+ };
225
+ return (
226
+ <Form onSubmit={handleSubmit(onSubmit)} className={styles.form}>
227
+ <div className={styles.formContainer}>
228
+ <Stack gap={3}>
229
+ <DeceasedPatientHeader patientData={patientData} />
230
+ <ResponsiveWrapper>
231
+ <FormGroup legendText="">
232
+ <Column></Column>
233
+ <Column>
234
+ <Controller
235
+ name="dateOfAdmission"
236
+ control={control}
237
+ render={({ field }) => (
238
+ <DatePicker
239
+ datePickerType="single"
240
+ className={styles.formAdmissionDatepicker}
241
+ onChange={(event) => {
242
+ if (event.length) {
243
+ field.onChange(event[0]);
244
+ }
245
+ }}
246
+ value={field.value ? new Date(field.value) : null}>
247
+ <DatePickerInput
248
+ id="date-of-admission"
249
+ placeholder="mm/dd/yyyy"
250
+ labelText={t('dateOfAdmission', 'Date of admission')}
251
+ invalid={!!errors.dateOfAdmission}
252
+ invalidText={errors.dateOfAdmission?.message}
253
+ />
254
+ </DatePicker>
255
+ )}
256
+ />
257
+ </Column>
258
+ </FormGroup>
259
+ </ResponsiveWrapper>
260
+ <ResponsiveWrapper>
261
+ <FormGroup legendText="">
262
+ <Column>
263
+ <div className={styles.dateTimeSection}>
264
+ <ResponsiveWrapper>
265
+ <Controller
266
+ name="timeOfDeath"
267
+ control={control}
268
+ render={({ field }) => {
269
+ return (
270
+ <TimePicker
271
+ {...field}
272
+ id="time-of-death-picker"
273
+ labelText={t('timeAdmission', 'Time of admission*')}
274
+ className={styles.formAdmissionTimepicker}
275
+ invalid={!!errors.timeOfDeath}
276
+ invalidText={errors.timeOfDeath?.message}
277
+ />
278
+ );
279
+ }}
280
+ />
281
+ <Controller
282
+ name="period"
283
+ control={control}
284
+ render={({ field }) => (
285
+ <TimePickerSelect
286
+ {...field}
287
+ className={styles.formDeathTimepickerSelector}
288
+ id="time-picker-select">
289
+ <SelectItem value="AM" text="AM" />
290
+ <SelectItem value="PM" text="PM" />
291
+ </TimePickerSelect>
292
+ )}
293
+ />
294
+ </ResponsiveWrapper>
295
+ </div>
296
+ </Column>
297
+ </FormGroup>
298
+ </ResponsiveWrapper>
299
+ <ResponsiveWrapper>
300
+ <FormGroup legendText="">
301
+ <Controller
302
+ control={control}
303
+ name="visitType"
304
+ render={({ field }) => (
305
+ <TextInput
306
+ {...field}
307
+ className={styles.sectionField}
308
+ id="visit-type"
309
+ type="text"
310
+ labelText={t('visitType', 'Visit type')}
311
+ value={currentVisitType?.display || ''}
312
+ invalid={!!errors.visitType}
313
+ invalidText={errors.visitType?.message}
314
+ disabled={isLoadingVisitTypes}
315
+ readOnly
316
+ />
317
+ )}
318
+ />
319
+ </FormGroup>
320
+ </ResponsiveWrapper>
321
+ <ResponsiveWrapper>
322
+ <FormGroup legendText="">
323
+ <div className={classNames(styles.visitTypeOverviewWrapper)}>
324
+ <ResponsiveWrapper>
325
+ <Search
326
+ onChange={(event) => setSearchTerm(event.target.value)}
327
+ placeholder={t('searchForCompartments', 'Search for a compartment')}
328
+ labelText=""
329
+ value={searchTerm}
330
+ />
331
+ <div className={styles.compartmentListContainer}>
332
+ {filteredBeds.length > 0 ? (
333
+ <>
334
+ <Controller
335
+ control={control}
336
+ name="availableCompartment"
337
+ render={({ field }) => (
338
+ <RadioButtonGroup
339
+ className={styles.radioButtonGroup}
340
+ orientation="vertical"
341
+ name="availableCompartment"
342
+ valueSelected={field.value}
343
+ onChange={field.onChange}>
344
+ {filteredBeds.map((bed, index) => (
345
+ <div key={index} className={styles.compartmentOption}>
346
+ <div className={styles.radioButtonWrapper}>
347
+ <RadioButton
348
+ className={styles.radioButton}
349
+ id={`compartment-${index}`}
350
+ labelText={bed.bedNumber}
351
+ value={bed.bedId}
352
+ />
353
+ </div>
354
+ <div className={styles.compartmentTags}>
355
+ <Tag type={bed.bedType?.display === 'VIP' ? 'green' : 'blue'} size="sm">
356
+ {bed.bedType?.displayName || ''}
357
+ </Tag>
358
+ <Tag type={bed.status === 'AVAILABLE' ? 'green' : 'red'} size="sm">
359
+ {bed?.status || ''}
360
+ </Tag>
361
+ </div>
362
+ </div>
363
+ ))}
364
+ </RadioButtonGroup>
365
+ )}
366
+ />
367
+ </>
368
+ ) : (
369
+ <Layer>
370
+ <Tile className={styles.emptyStateTile}>
371
+ <EmptyDataIllustration />
372
+ <p className={styles.emptyStateContent}>
373
+ {t('noCompartmentsFound', 'No compartments found')}
374
+ </p>
375
+ </Tile>
376
+ </Layer>
377
+ )}
378
+ </div>
379
+ </ResponsiveWrapper>
380
+ {errors.availableCompartment && (
381
+ <div className={styles.invalidText}>{errors.availableCompartment.message}</div>
382
+ )}
383
+ </div>
384
+ </FormGroup>
385
+ </ResponsiveWrapper>
386
+
387
+ <ResponsiveWrapper>
388
+ <FormGroup legendText="">
389
+ <Column>
390
+ <div className={styles.sectionFieldLayer}>
391
+ <Controller
392
+ control={control}
393
+ name="paymentMethod"
394
+ render={({ field }) => (
395
+ <Dropdown
396
+ {...field}
397
+ initialSelectedItem={field.value}
398
+ className={styles.sectionField}
399
+ onChange={({ selectedItem }) => field.onChange(selectedItem)}
400
+ id="paymentMethods"
401
+ items={paymentModes.map((mode) => mode.uuid)}
402
+ itemToString={(item) => paymentModes.find((mode) => mode.uuid === item)?.name ?? ''}
403
+ titleText={t('selectPaymentMethod', 'Select payment method')}
404
+ label={t('selectPaymentMethod', 'Select payment method')}
405
+ />
406
+ )}
407
+ />
408
+ </div>
409
+ </Column>
410
+ </FormGroup>
411
+ </ResponsiveWrapper>
412
+ {paymentMethodObservable === insurancepaymentModeUuid && (
413
+ <>
414
+ <Column>
415
+ <Controller
416
+ control={control}
417
+ name="insuranceScheme"
418
+ render={({ field }) => (
419
+ <ComboBox
420
+ className={styles.sectionField}
421
+ onChange={({ selectedItem }) => field.onChange(selectedItem)}
422
+ id="insurance-scheme"
423
+ items={insuranceSchemes}
424
+ itemToString={(item) => (item ? item.toString() : '')}
425
+ titleText={t('insuranceScheme', 'Insurance scheme')}
426
+ invalid={!!errors.insuranceScheme}
427
+ invalidText={errors.insuranceScheme?.message}
428
+ />
429
+ )}
430
+ />
431
+ </Column>
432
+ <Column>
433
+ <Controller
434
+ control={control}
435
+ name="policyNumber"
436
+ render={({ field }) => (
437
+ <TextInput
438
+ className={styles.sectionField}
439
+ onChange={(e) => field.onChange(e.target.value)}
440
+ id="policy-number"
441
+ type="text"
442
+ labelText={t('policyNumber', 'Policy number')}
443
+ placeholder={t('enterPolicyNumber', 'Enter policy number')}
444
+ invalid={!!errors.policyNumber}
445
+ invalidText={errors.policyNumber?.message}
446
+ />
447
+ )}
448
+ />
449
+ </Column>
450
+ </>
451
+ )}
452
+ {paymentMethodObservable && (
453
+ <Column>
454
+ <Controller
455
+ control={control}
456
+ name="services"
457
+ render={({ field }) => {
458
+ const availableServices = lineItems.filter(
459
+ (service) => service?.serviceType?.uuid === morgueDepartmentServiceTypeUuid,
460
+ );
461
+ return (
462
+ <>
463
+ {availableServices.length > 0 ? (
464
+ <FilterableMultiSelect
465
+ id="billing-service"
466
+ className={styles.formAdmissionDatepicker}
467
+ titleText={t('searchServices', 'Search services')}
468
+ items={availableServices.map((service) => service.uuid)}
469
+ itemToString={(item) => availableServices.find((i) => i.uuid === item)?.name ?? ''}
470
+ onChange={({ selectedItems }) => {
471
+ field.onChange(selectedItems);
472
+ }}
473
+ placeholder={t('Service', 'Service')}
474
+ initialSelectedItems={field.value}
475
+ invalid={!!errors.services}
476
+ invalidText={errors.services?.message}
477
+ />
478
+ ) : (
479
+ <InlineNotification
480
+ kind="warning"
481
+ title={t(
482
+ 'noServicesAvailable',
483
+ 'No service price has been configured for the mortuary department.',
484
+ )}
485
+ lowContrast
486
+ />
487
+ )}
488
+ </>
489
+ );
490
+ }}
491
+ />
492
+ </Column>
493
+ )}
494
+ <ResponsiveWrapper>
495
+ <FormGroup legendText="">
496
+ <Column>
497
+ <Controller
498
+ name="tagNumber"
499
+ control={control}
500
+ render={({ field }) => (
501
+ <TextInput
502
+ {...field}
503
+ id="tagNumber"
504
+ className={styles.sectionField}
505
+ placeholder={t('tagNumber', 'Tag Number*')}
506
+ labelText={t('tagNumber', 'Tag Number*')}
507
+ invalid={!!errors.tagNumber}
508
+ invalidText={errors.tagNumber?.message}
509
+ />
510
+ )}
511
+ />
512
+ </Column>
513
+ </FormGroup>
514
+ </ResponsiveWrapper>
515
+ <ResponsiveWrapper>
516
+ <FormGroup legendText="">
517
+ <Column>
518
+ <Controller
519
+ name="dischargeArea"
520
+ control={control}
521
+ render={({ field }) => (
522
+ <TextInput
523
+ {...field}
524
+ id="dischargeArea"
525
+ className={styles.sectionField}
526
+ placeholder={t('dischargeArea', 'Discharge Area')}
527
+ labelText={t('dischargeArea', 'Discharge Area')}
528
+ invalid={!!errors.dischargeArea}
529
+ invalidText={errors.dischargeArea?.message}
530
+ />
531
+ )}
532
+ />
533
+ </Column>
534
+ </FormGroup>
535
+ </ResponsiveWrapper>
536
+ <ResponsiveWrapper>
537
+ <FormGroup legendText="">
538
+ <Column>
539
+ <Dropdown
540
+ onChange={(e) => handlePoliceCaseChange(e.selectedItem)}
541
+ id="morgue-combobox"
542
+ className={styles.formAdmissionDatepicker}
543
+ items={['Yes', 'No']}
544
+ itemToString={(item) => (item ? item : '')}
545
+ label={t('ChooseOptions', 'Choose option')}
546
+ titleText={t(
547
+ 'isPoliceCase',
548
+ 'Is the body anextIDNo: z.sssociated with a police case? If so, can you provide the OB number?*',
549
+ )}
550
+ />
551
+ </Column>
552
+ </FormGroup>
553
+ </ResponsiveWrapper>
554
+ <ResponsiveWrapper>
555
+ <FormGroup legendText="">
556
+ {isPoliceCase === 'Yes' && (
557
+ <>
558
+ <Column>
559
+ <Controller
560
+ name="obNumber"
561
+ control={control}
562
+ render={({ field }) => (
563
+ <TextInput
564
+ {...field}
565
+ id="obNumber"
566
+ className={styles.formAdmissionDatepicker}
567
+ placeholder={t('obNos', 'OB Number')}
568
+ labelText={t('obNumber', 'OB Number')}
569
+ invalid={!!errors.obNumber}
570
+ invalidText={errors.obNumber?.message}
571
+ />
572
+ )}
573
+ />
574
+ </Column>
575
+ <Column>
576
+ <Controller
577
+ name="policeName"
578
+ control={control}
579
+ render={({ field }) => (
580
+ <TextInput
581
+ {...field}
582
+ id="policeName"
583
+ className={styles.sectionField}
584
+ placeholder={t('policeNames', 'Police Name')}
585
+ labelText={t('policeName', 'Police name')}
586
+ invalid={!!errors.policeName}
587
+ invalidText={errors.policeName?.message}
588
+ />
589
+ )}
590
+ />
591
+ </Column>
592
+ <Column>
593
+ <Controller
594
+ name="policeIDNo"
595
+ control={control}
596
+ render={({ field }) => (
597
+ <TextInput
598
+ {...field}
599
+ id="policeIDNo"
600
+ className={styles.sectionField}
601
+ placeholder={t('policeID', 'Police ID number')}
602
+ labelText={t('policeIDNo', 'Police ID number')}
603
+ invalid={!!errors.policeIDNo}
604
+ invalidText={errors.policeIDNo?.message}
605
+ />
606
+ )}
607
+ />
608
+ </Column>
609
+ <ResponsiveWrapper>
610
+ <ExtensionSlot
611
+ name="patient-chart-attachments-dashboard-slot"
612
+ className={styles.sectionField}
613
+ state={{
614
+ patientUuid,
615
+ }}
616
+ />{' '}
617
+ </ResponsiveWrapper>
618
+ </>
619
+ )}
620
+ </FormGroup>
621
+ </ResponsiveWrapper>
622
+ </Stack>
623
+ </div>
624
+
625
+ <ButtonSet
626
+ className={classNames({
627
+ [styles.tablet]: isTablet,
628
+ [styles.desktop]: !isTablet,
629
+ })}>
630
+ <Button className={styles.buttonContainer} kind="secondary" onClick={() => closeWorkspace()}>
631
+ {t('cancel', 'Cancel')}
632
+ </Button>
633
+ <Button className={styles.buttonContainer} disabled={isSubmitting || !isDirty} kind="primary" type="submit">
634
+ {isSubmitting ? (
635
+ <span className={styles.inlineLoading}>
636
+ {t('submitting', 'Submitting' + '...')}
637
+ <InlineLoading status="active" iconDescription="Loading" />
638
+ </span>
639
+ ) : (
640
+ t('saveAndClose', 'Save & close')
641
+ )}
642
+ </Button>
643
+ </ButtonSet>
644
+ </Form>
645
+ );
646
+ };
647
+
648
+ export default AdmitDeceasedPerson;
@@ -1,6 +1,6 @@
1
1
  import { FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
- import { Patient, PatientInfo } from '../types';
3
2
  import useSWR from 'swr';
3
+ import { Patient, PatientInfo } from '../../types';
4
4
 
5
5
  export const usePersonAttributes = (personUuid: string) => {
6
6
  const { data, error, isLoading } = useSWR<FetchResponse<{ results: Patient['person']['attributes'] }>>(