@kenyaemr/esm-morgue-app 5.4.2-pre.2279 → 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 +67 -25
  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,256 @@
1
+ // DischargedBedLineListView.tsx
2
+ import React, { useState, useMemo } from 'react';
3
+ import { useTranslation } from 'react-i18next';
4
+ import {
5
+ DataTable,
6
+ InlineLoading,
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableContainer,
11
+ TableHead,
12
+ TableHeader,
13
+ TableRow,
14
+ Button,
15
+ Pagination,
16
+ OverflowMenu,
17
+ OverflowMenuItem,
18
+ DataTableSkeleton,
19
+ } from '@carbon/react';
20
+ import { useConfig } from '@openmrs/esm-framework';
21
+ import styles from '../bed-linelist-view.scss';
22
+ import { formatDateTime } from '../../utils/utils';
23
+ import { type MortuaryLocationResponse } from '../../types';
24
+ import { ConfigObject } from '../../config-schema';
25
+ import usePatients, { useMortuaryDischargeEncounter } from '../../bed-layout/discharged/discharged-bed-layout.resource';
26
+ import { EmptyState } from '@openmrs/esm-patient-common-lib';
27
+
28
+ interface DischargedBedLineListViewProps {
29
+ AdmittedDeceasedPatient: MortuaryLocationResponse | null;
30
+ isLoading: boolean;
31
+ paginated?: boolean;
32
+ initialPageSize?: number;
33
+ pageSizes?: number[];
34
+ onPrintGatePass?: (patientUuid: string) => void;
35
+ onPrintPostmortem?: (patientUuid: string) => void;
36
+ mutate?: () => void;
37
+ }
38
+
39
+ const DischargedBedLineListView: React.FC<DischargedBedLineListViewProps> = ({
40
+ AdmittedDeceasedPatient,
41
+ isLoading,
42
+ paginated = true,
43
+ initialPageSize = 10,
44
+ pageSizes = [10, 20, 30, 40, 50],
45
+ onPrintGatePass,
46
+ onPrintPostmortem,
47
+ mutate,
48
+ }) => {
49
+ const { t } = useTranslation();
50
+ const { morgueDischargeEncounterTypeUuid } = useConfig<ConfigObject>();
51
+
52
+ const [currentPage, setCurrentPage] = useState(1);
53
+ const [currPageSize, setCurrPageSize] = useState(initialPageSize);
54
+
55
+ const {
56
+ dischargedPatientUuids,
57
+ isLoading: encountersLoading,
58
+ error: encountersError,
59
+ } = useMortuaryDischargeEncounter(morgueDischargeEncounterTypeUuid, AdmittedDeceasedPatient);
60
+
61
+ const {
62
+ patients: dischargedPatients,
63
+ isLoading: patientsLoading,
64
+ error: patientsError,
65
+ } = usePatients(dischargedPatientUuids || []);
66
+
67
+ const headers = [
68
+ { key: 'name', header: t('name', 'Name') },
69
+ { key: 'idNumber', header: t('idNumber', 'ID Number') },
70
+ { key: 'gender', header: t('gender', 'Gender') },
71
+ { key: 'age', header: t('age', 'Age') },
72
+ { key: 'causeOfDeath', header: t('causeOfDeath', 'Cause of Death') },
73
+ { key: 'dateOfDeath', header: t('dateOfDeath', 'Date of Death') },
74
+ { key: 'daysSinceDeath', header: t('daysSinceDeath', 'Days Since Death') },
75
+ { key: 'action', header: t('action', 'Action') },
76
+ ];
77
+
78
+ const calculateDaysSinceDeath = (dateOfDeath: string): number => {
79
+ if (!dateOfDeath) {
80
+ return 0;
81
+ }
82
+ const deathDate = new Date(dateOfDeath);
83
+ const currentDate = new Date();
84
+ const timeDiff = currentDate.getTime() - deathDate.getTime();
85
+ return Math.floor(timeDiff / (1000 * 3600 * 24));
86
+ };
87
+
88
+ const handlePrintGatePass = (patientUuid: string) => {
89
+ if (onPrintGatePass) {
90
+ onPrintGatePass(patientUuid);
91
+ }
92
+ };
93
+
94
+ const handlePrintPostmortem = (patientUuid: string) => {
95
+ if (onPrintPostmortem) {
96
+ onPrintPostmortem(patientUuid);
97
+ }
98
+ };
99
+
100
+ const allRows = useMemo(() => {
101
+ if (!dischargedPatients || dischargedPatients.length === 0) {
102
+ return [];
103
+ }
104
+
105
+ const rows = dischargedPatients.map((patient, index) => {
106
+ const patientUuid = patient?.uuid || `patient-${index}`;
107
+ const patientName = patient?.person?.display || '-';
108
+ const gender = patient?.person?.gender || '-';
109
+ const age = patient?.person?.age || '-';
110
+ const causeOfDeath = patient?.person?.causeOfDeath?.display || '-';
111
+ const dateOfDeath = patient?.person?.deathDate;
112
+ const daysSinceDeath = calculateDaysSinceDeath(dateOfDeath);
113
+
114
+ return {
115
+ id: patientUuid,
116
+ idNumber:
117
+ patient?.identifiers
118
+ ?.find((id) => id.display?.includes('OpenMRS ID'))
119
+ ?.display?.split('=')?.[1]
120
+ ?.trim() || '-',
121
+ name: patientName,
122
+ gender: gender,
123
+ age: age.toString(),
124
+ causeOfDeath: causeOfDeath,
125
+ dateOfDeath: formatDateTime(dateOfDeath),
126
+ daysSinceDeath: daysSinceDeath.toString(),
127
+ action: patientUuid,
128
+ };
129
+ });
130
+
131
+ return rows;
132
+ }, [dischargedPatients]);
133
+
134
+ const totalCount = allRows.length;
135
+ const startIndex = (currentPage - 1) * currPageSize;
136
+ const endIndex = startIndex + currPageSize;
137
+ const paginatedRows = paginated ? allRows.slice(startIndex, endIndex) : allRows;
138
+
139
+ const goTo = (page: number) => {
140
+ setCurrentPage(page);
141
+ };
142
+
143
+ const handlePaginationChange = ({ page: newPage, pageSize }: { page: number; pageSize: number }) => {
144
+ if (newPage !== currentPage) {
145
+ goTo(newPage);
146
+ }
147
+ if (pageSize !== currPageSize) {
148
+ setCurrPageSize(pageSize);
149
+ setCurrentPage(1);
150
+ }
151
+ };
152
+
153
+ const isLoadingData = isLoading || encountersLoading || patientsLoading;
154
+
155
+ if (isLoadingData) {
156
+ return (
157
+ <div className={styles.loadingContainer}>
158
+ <DataTableSkeleton columnCount={headers.length} rowCount={5} />
159
+ </div>
160
+ );
161
+ }
162
+
163
+ if (encountersError || patientsError) {
164
+ return (
165
+ <div className={styles.emptyState}>
166
+ <EmptyState
167
+ headerTitle={t('noDischargedPatients', 'No discharged patients found')}
168
+ displayText={t('noDischargedPatientsDescription', 'There are currently no discharged patients to display.')}
169
+ />{' '}
170
+ </div>
171
+ );
172
+ }
173
+
174
+ if (!dischargedPatients || dischargedPatients.length === 0) {
175
+ return (
176
+ <div className={styles.emptyState}>
177
+ <EmptyState
178
+ headerTitle={t('noDischargedPatients', 'No discharged patients found')}
179
+ displayText={t('noDischargedPatientsDescription', 'There are currently no discharged patients to display.')}
180
+ />
181
+ </div>
182
+ );
183
+ }
184
+
185
+ return (
186
+ <div className={styles.bedLayoutWrapper}>
187
+ <DataTable rows={paginatedRows} headers={headers} isSortable useZebraStyles>
188
+ {({ rows, headers, getHeaderProps, getRowProps, getTableProps, getCellProps }) => (
189
+ <TableContainer>
190
+ <Table {...getTableProps()} aria-label="discharged patients table">
191
+ <TableHead>
192
+ <TableRow>
193
+ {headers.map((header) => (
194
+ <TableHeader
195
+ key={header.key}
196
+ {...getHeaderProps({
197
+ header,
198
+ })}>
199
+ {header.header}
200
+ </TableHeader>
201
+ ))}
202
+ </TableRow>
203
+ </TableHead>
204
+ <TableBody>
205
+ {rows.map((row) => {
206
+ const patientData = dischargedPatients.find((patient) => patient?.uuid === row.id);
207
+ const patientName = patientData?.person?.display || '';
208
+
209
+ return (
210
+ <TableRow key={row.id} {...getRowProps({ row })}>
211
+ {row.cells.map((cell) => (
212
+ <TableCell key={cell.id} {...getCellProps({ cell })}>
213
+ {cell.info.header === 'action' ? (
214
+ <div className={styles.actionButtons}>
215
+ <OverflowMenu flipped>
216
+ <OverflowMenuItem
217
+ onClick={() => handlePrintGatePass(row.id)}
218
+ itemText={t('printGatePass', 'Gate Pass')}
219
+ disabled={!patientData}
220
+ />
221
+ <OverflowMenuItem
222
+ onClick={() => handlePrintPostmortem(row.id)}
223
+ itemText={t('printPostmortem', 'Postmortem')}
224
+ disabled={!patientData}
225
+ />
226
+ </OverflowMenu>
227
+ </div>
228
+ ) : (
229
+ cell.value
230
+ )}
231
+ </TableCell>
232
+ ))}
233
+ </TableRow>
234
+ );
235
+ })}
236
+ </TableBody>
237
+ </Table>
238
+ </TableContainer>
239
+ )}
240
+ </DataTable>
241
+
242
+ {paginated && !isLoadingData && totalCount > 0 && (
243
+ <Pagination
244
+ page={currentPage}
245
+ pageSize={currPageSize}
246
+ pageSizes={pageSizes}
247
+ totalItems={totalCount}
248
+ size={'sm'}
249
+ onChange={handlePaginationChange}
250
+ />
251
+ )}
252
+ </div>
253
+ );
254
+ };
255
+
256
+ export default DischargedBedLineListView;
@@ -1,6 +1,12 @@
1
1
  import { Type } from '@openmrs/esm-framework';
2
+ import _default from 'react-hook-form/dist/utils/createSubject';
2
3
 
3
4
  export const configSchema = {
5
+ mortuaryLocationTagUuid: {
6
+ _type: Type.String,
7
+ _description: 'UUID for mortuary location tag',
8
+ _default: '1dbbfe22-d21f-499c-bf33-cc9f75b6c7e8',
9
+ },
4
10
  morgueVisitTypeUuid: {
5
11
  _type: Type.String,
6
12
  _description: ' UUID for morgue visit',
@@ -16,23 +22,19 @@ export const configSchema = {
16
22
  _description: ' UUID for insurance payment mode',
17
23
  _default: 'beac329b-f1dc-4a33-9e7c-d95821a137a6',
18
24
  },
19
- morgueCompartmentTagUuid: {
20
- _type: Type.String,
21
- _description: 'UUID for morgue compartment tag',
22
- _default: 'a69f6810-fa6a-4423-a3e4-f88e8ac032dd',
23
- },
25
+
24
26
  tagNumberUuid: {
25
27
  _type: Type.String,
26
28
  _description: 'UUID for tag number concept',
27
29
  _default: 'f2b35679-7ba9-4619-92cb-6872b0c6bf57',
28
30
  },
29
- morgueAdmissionEncounterType: {
31
+ morgueAdmissionEncounterTypeUuid: {
30
32
  _type: Type.String,
31
33
  _description: 'Encounter type for morgue admission',
32
34
  _default: '3d2df845-6f3c-45e7-b91a-d828a1f9c2e8',
33
35
  },
34
36
  morgueDischargeEncounterTypeUuid: {
35
- type: Type.String,
37
+ _type: Type.String,
36
38
  _description: 'Encounter type for morgue discharge',
37
39
  _default: '3d618f40b-b5a3-4f17-81c8-2f04e2aad58e',
38
40
  },
@@ -96,6 +98,31 @@ export const configSchema = {
96
98
  _description: 'UUID for admin user',
97
99
  _default: 'e02c40e5-04e7-11e5-ae3c-a0b3cc4f922f',
98
100
  },
101
+ autopsyFormUuid: {
102
+ _type: Type.String,
103
+ _description: 'UUID for autopsy form',
104
+ _default: '2b61a73-4971-4fc0-b20b-9a30176317e2',
105
+ },
106
+ autopsyEncounterFormUuid: {
107
+ _type: Type.String,
108
+ _description: 'Encounter UUID for autopsy',
109
+ _default: '32b61a73-4971-4fc0-b20b-9a30176317e2',
110
+ },
111
+ nextOfKinNamesUuid: {
112
+ _type: Type.String,
113
+ _description: 'UUID for next of kin names concept',
114
+ _default: '830bef6d-b01f-449d-9f8d-ac0fede8dbd3',
115
+ },
116
+ courtOrderCaseNumberUuid: {
117
+ _type: Type.String,
118
+ _description: 'UUID for court order case number concept',
119
+ _default: '26e0da6c-3e53-4f7d-9a3a-1c2f634450f7',
120
+ },
121
+ serialNumberUuid: {
122
+ _type: Type.String,
123
+ _description: 'UUID for serial number concept',
124
+ _default: '1646AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
125
+ },
99
126
  };
100
127
 
101
128
  export interface BillingConfig {
@@ -124,9 +151,9 @@ export type ConfigObject = {
124
151
  morgueVisitTypeUuid: string;
125
152
  morgueDepartmentServiceTypeUuid: string;
126
153
  insurancepaymentModeUuid: string;
127
- morgueCompartmentTagUuid: string;
154
+ mortuaryLocationTagUuid: string;
128
155
  tagNumberUuid: string;
129
- morgueAdmissionEncounterType: string;
156
+ morgueAdmissionEncounterTypeUuid: string;
130
157
  nextOfKinNameUuid: string;
131
158
  nextOfKinRelationshipUuid: string;
132
159
  nextOfKinAddressUuid: string;
@@ -141,4 +168,9 @@ export type ConfigObject = {
141
168
  dischargeAreaUuid: string;
142
169
  morgueDischargeEncounterTypeUuid: string;
143
170
  adminUuid: string;
171
+ autopsyFormUuid: string;
172
+ autopsyEncounterFormUuid: string;
173
+ nextOfKinNamesUuid: string;
174
+ courtOrderCaseNumberUuid: string;
175
+ serialNumberUuid: string;
144
176
  };
package/src/constants.ts CHANGED
@@ -1 +1,58 @@
1
1
  export const PENDING_PAYMENT_STATUS = 'PENDING';
2
+
3
+ export const customRepProps = [
4
+ ['metadataSourceName', 'ref'],
5
+ ['orderingProviderEncounterRole', 'ref'],
6
+ ['supportsTransferLocationTag', '(uuid,display,name,links)'],
7
+ ['unknownLocation', 'ref'],
8
+ ['denyAdmissionConcept', 'ref'],
9
+ ['admissionForm', 'ref'],
10
+ ['exitFromInpatientEncounterType', 'ref'],
11
+ ['extraPatientIdentifierTypes', 'ref'],
12
+ ['consultFreeTextCommentsConcept', 'ref'],
13
+ ['sameAsConceptMapType', 'ref'],
14
+ ['testPatientPersonAttributeType', 'ref'],
15
+ ['admissionDecisionConcept', 'ref'],
16
+ ['supportsAdmissionLocationTag', '(uuid,display,name,links)'],
17
+ ['checkInEncounterType', 'ref'],
18
+ ['transferWithinHospitalEncounterType', 'ref'],
19
+ ['suppressedDiagnosisConcepts', 'ref'],
20
+ ['primaryIdentifierType', 'ref'],
21
+ ['nonDiagnosisConceptSets', 'ref'],
22
+ ['fullPrivilegeLevel', 'ref'],
23
+ ['unknownProvider', 'ref'],
24
+ ['diagnosisSets', 'ref'],
25
+ ['personImageDirectory', 'ref'],
26
+ ['visitNoteEncounterType', 'ref'],
27
+ ['inpatientNoteEncounterType', 'ref'],
28
+ ['transferRequestEncounterType', 'ref'],
29
+ ['consultEncounterType', 'ref'],
30
+ ['diagnosisMetadata', 'ref'],
31
+ ['narrowerThanConceptMapType', 'ref'],
32
+ ['clinicianEncounterRole', 'ref'],
33
+ ['conceptSourcesForDiagnosisSearch', 'ref'],
34
+ ['patientDiedConcept', 'ref'],
35
+ ['emrApiConceptSource', 'ref'],
36
+ ['lastViewedPatientSizeLimit', 'ref'],
37
+ ['identifierTypesToSearch', 'ref'],
38
+ ['telephoneAttributeType', 'ref'],
39
+ ['checkInClerkEncounterRole', 'ref'],
40
+ ['dischargeForm', 'ref'],
41
+ ['unknownCauseOfDeathConcept', 'ref'],
42
+ ['visitAssignmentHandlerAdjustEncounterTimeOfDayIfNecessary', 'ref'],
43
+ ['atFacilityVisitType', 'ref'],
44
+ ['visitExpireHours', 'ref'],
45
+ ['admissionEncounterType', 'ref'],
46
+ ['motherChildRelationshipType', 'ref'],
47
+ ['dispositions', 'ref'],
48
+ ['dispositionDescriptor', 'ref'],
49
+ ['highPrivilegeLevel', 'ref'],
50
+ ['supportsLoginLocationTag', '(uuid,display,name,links)'],
51
+ ['unknownPatientPersonAttributeType', 'ref'],
52
+ ['supportsVisitsLocationTag', '(uuid,display,name,links)'],
53
+ ['transferForm', 'ref'],
54
+ ['bedAssignmentEncounterType', 'ref'],
55
+ ['cancelADTRequestEncounterType', 'ref'],
56
+ ['admissionDecisionConcept', 'ref'],
57
+ ['denyAdmissionConcept', 'ref'],
58
+ ];
@@ -0,0 +1,31 @@
1
+ import { Tile } from '@carbon/react';
2
+ import { PatientPhoto, usePatient } from '@openmrs/esm-framework';
3
+ import React from 'react';
4
+ import { useTranslation } from 'react-i18next';
5
+ import { formatDeceasedName } from '../utils/utils';
6
+ import styles from './deceased-patient-header.scss';
7
+ import { type MortuaryPatient } from '../types';
8
+
9
+ interface DeceasedPatientHeaderProps {
10
+ patientData: MortuaryPatient;
11
+ }
12
+ export const DeceasedPatientHeader: React.FC<DeceasedPatientHeaderProps> = ({ patientData }) => {
13
+ const { t } = useTranslation();
14
+
15
+ return (
16
+ <Tile>
17
+ <div className={styles.patientHeader}>
18
+ <PatientPhoto patientUuid={patientData?.patient?.uuid} patientName={patientData?.person?.person?.display} />
19
+ <div className={styles.patientInfo}>
20
+ <span className={styles.patientName}>{patientData?.person?.person?.display}</span>
21
+ <div className={styles.patientDetails}>
22
+ <span className={styles.gender}>{patientData?.person?.person?.gender}</span>
23
+ <span className={styles.middot}>•</span>
24
+ <span className={styles.age}>{patientData?.person?.person?.age}</span>
25
+ <span className={styles.ageUnit}>{t('yearsOld', 'Yrs old')}</span>
26
+ </div>
27
+ </div>
28
+ </div>
29
+ </Tile>
30
+ );
31
+ };
@@ -0,0 +1,50 @@
1
+ @use '@carbon/colors';
2
+ @use '@carbon/layout';
3
+ @use '@carbon/type';
4
+
5
+ .patientHeader {
6
+ display: flex;
7
+ gap: layout.$spacing-05;
8
+ align-items: flex-start;
9
+ }
10
+
11
+ .patientInfo {
12
+ display: flex;
13
+ flex-direction: column;
14
+ gap: layout.$spacing-02;
15
+ }
16
+
17
+ .patientDetails {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: layout.$spacing-03;
21
+ flex-wrap: wrap;
22
+ }
23
+
24
+ .middot {
25
+ color: colors.$gray-70;
26
+ font-weight: bold;
27
+ }
28
+
29
+ .gender {
30
+ @include type.type-style('body-01');
31
+ color: colors.$gray-70;
32
+ font-weight: 500;
33
+ }
34
+
35
+ .age {
36
+ @include type.type-style('body-01');
37
+ color: colors.$gray-70;
38
+ font-weight: 500;
39
+ }
40
+
41
+ .ageUnit {
42
+ @include type.type-style('body-01');
43
+ color: colors.$gray-70;
44
+ margin-left: layout.$spacing-01;
45
+ }
46
+
47
+ .patientName {
48
+ @include type.type-style('body-01');
49
+ margin-bottom: layout.$spacing-01;
50
+ }
@@ -4,7 +4,7 @@ import React from 'react';
4
4
  import styles from './deceased-info.scss';
5
5
  import { formatDeceasedName } from '../../utils/utils';
6
6
  import { useTranslation } from 'react-i18next';
7
- import { usePerson } from '../../hook/useMorgue.resource';
7
+ import { usePerson } from './deceased-info.resource';
8
8
 
9
9
  const DeceasedInfo: React.FC<{ patientUuid: string }> = ({ patientUuid }) => {
10
10
  const { isLoading, patient, error } = usePatient(patientUuid);
@@ -0,0 +1,11 @@
1
+ import { FetchResponse, openmrsFetch, restBaseUrl } from '@openmrs/esm-framework';
2
+ import { Patient } from '../../types';
3
+ import useSWR from 'swr';
4
+
5
+ export const usePerson = (uuid: string) => {
6
+ const customRepresentation = `custom:(uuid,display,gender,birthdate,dead,age,deathDate,causeOfDeath:(uuid,display))`;
7
+ const url = `${restBaseUrl}/person/${uuid}?v=${customRepresentation}`;
8
+ const { isLoading, error, data } = useSWR<FetchResponse<Patient['person']>>(url, openmrsFetch);
9
+ const person = data?.data;
10
+ return { isLoading, error, person };
11
+ };
@@ -3,8 +3,9 @@ import { useTranslation } from 'react-i18next';
3
3
  import { launchWorkspace, navigate, UserHasAccess } from '@openmrs/esm-framework';
4
4
  import { Movement, Return, ShareKnowledge } from '@carbon/react/icons';
5
5
  import React from 'react';
6
- import { useAdmissionLocation } from '../hook/useMortuaryAdmissionLocation';
6
+
7
7
  import styles from './actionButton.scss';
8
+ import { useParams } from 'react-router-dom';
8
9
 
9
10
  interface ActionButtonProps {
10
11
  patientUuid: string;
@@ -12,73 +13,18 @@ interface ActionButtonProps {
12
13
 
13
14
  const ActionButton: React.FC<ActionButtonProps> = ({ patientUuid }) => {
14
15
  const { t } = useTranslation();
15
- const { admissionLocation, isLoading, error } = useAdmissionLocation();
16
-
17
- const isPatientInAdmissionLocation = admissionLocation?.bedLayouts?.some((bed) =>
18
- bed.patients.some((patient) => patient.uuid === patientUuid),
19
- );
20
-
21
- const bedId = admissionLocation?.bedLayouts?.find((bed) =>
22
- bed.patients.some((patient) => patient.uuid === patientUuid),
23
- )?.bedId;
24
-
25
- const personUuid = admissionLocation?.bedLayouts
26
- ?.find((bed) => bed.patients.some((patient) => patient.uuid === patientUuid))
27
- ?.patients.find((patient) => patient.uuid === patientUuid)?.person?.uuid;
28
-
29
- const handleNavigateToAllocationPage = () =>
16
+ const handleNavigateToHomePage = () =>
30
17
  navigate({
31
- to: window.getOpenmrsSpaBase() + `home/morgue/allocation`,
18
+ to: window.getOpenmrsSpaBase() + `home/morgue`,
32
19
  });
33
20
 
34
- const handleDischargeForm = (uuid: string, bedId: number) => {
35
- launchWorkspace('discharge-body-form', {
36
- workspaceTitle: t('dischargeForm', 'Discharge form'),
37
- patientUuid: uuid,
38
- bedId,
39
- personUuid,
40
- });
41
- };
42
-
43
- const handleSwapForm = (uuid: string, bedId: number) => {
44
- launchWorkspace('swap-unit-form', {
45
- workspaceTitle: t('swapCompartment', 'Swap compartment'),
46
- patientUuid: uuid,
47
- bedId,
48
- });
49
- };
50
-
51
21
  return (
52
22
  <div className={styles.actionButton}>
53
23
  <UserHasAccess privilege="o3 : View Mortuary Dashboard">
54
- <Button kind="primary" size="sm" renderIcon={Return} onClick={handleNavigateToAllocationPage}>
24
+ <Button kind="primary" size="sm" renderIcon={Return} onClick={handleNavigateToHomePage}>
55
25
  {t('allocation', 'Allocation View')}
56
26
  </Button>
57
27
  </UserHasAccess>
58
-
59
- {isPatientInAdmissionLocation && (
60
- <>
61
- <UserHasAccess privilege="o3: Swap Mortuary Compartments">
62
- <Button
63
- kind="secondary"
64
- size="sm"
65
- renderIcon={ShareKnowledge}
66
- onClick={() => handleSwapForm(patientUuid, bedId)}>
67
- {t('swapCompartment', 'Swap compartment')}
68
- </Button>
69
- </UserHasAccess>
70
-
71
- <UserHasAccess privilege="o3: Discharge Body from Mortuary">
72
- <Button
73
- kind="danger"
74
- size="sm"
75
- renderIcon={Movement}
76
- onClick={() => handleDischargeForm(patientUuid, bedId)}>
77
- {t('discharge', 'Discharge body')}
78
- </Button>
79
- </UserHasAccess>
80
- </>
81
- )}
82
28
  </div>
83
29
  );
84
30
  };
@@ -3,28 +3,24 @@ import { useTranslation } from 'react-i18next';
3
3
  import { launchWorkspace, navigate, usePatient, useVisit } from '@openmrs/esm-framework';
4
4
  import { Movement, Return, ShareKnowledge } from '@carbon/react/icons';
5
5
  import React from 'react';
6
- import { useAdmissionLocation } from '../hook/useMortuaryAdmissionLocation';
7
6
  import styles from './actionButton.scss';
8
7
  import { convertDateToDays, formatDateTime } from '../utils/utils';
9
8
  import { Console } from '@carbon/pictograms-react';
9
+ import { type Visit } from '../types';
10
10
 
11
11
  interface BannerInfoProps {
12
12
  patientUuid: string;
13
+ visit: Visit;
14
+ bedNumber?: string;
13
15
  }
14
16
 
15
- const BannerInfo: React.FC<BannerInfoProps> = ({ patientUuid }) => {
17
+ const BannerInfo: React.FC<BannerInfoProps> = ({ patientUuid, visit, bedNumber }) => {
16
18
  const { t } = useTranslation();
17
- const { admissionLocation, isLoading, error } = useAdmissionLocation();
18
19
  const { patient } = usePatient(patientUuid);
19
- const { currentVisit } = useVisit(patientUuid);
20
-
21
- const bedNumber =
22
- admissionLocation?.bedLayouts?.find((bed) => bed.patients.some((patient) => patient.uuid === patientUuid))
23
- ?.bedNumber || t('discharged', 'Discharged');
24
20
 
25
21
  const timeAndDateOfDeath = patient?.deceasedDateTime;
26
22
 
27
- const startDate = currentVisit?.startDatetime;
23
+ const startDate = visit?.startDatetime;
28
24
 
29
25
  const lengthOfStay = `${convertDateToDays(startDate)} ${
30
26
  convertDateToDays(startDate) === 1 ? t('day', 'Day') : t('days', 'Days')