@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
@@ -1,55 +0,0 @@
1
- import { FetchResponse, openmrsFetch, restBaseUrl, useFhirFetchAll } from '@openmrs/esm-framework';
2
- import { type Patient, type FHIREncounter } from '../types';
3
- import { useAdmissionLocation } from './useMortuaryAdmissionLocation';
4
- import useSWR from 'swr';
5
-
6
- export const useDischargedPatient = (dischargeEncounterTypeUuid: string) => {
7
- const url = dischargeEncounterTypeUuid
8
- ? `/ws/fhir2/R4/Encounter?_format=json&type=${dischargeEncounterTypeUuid}`
9
- : null;
10
- const { data, error, isLoading } = useFhirFetchAll<FHIREncounter>(url);
11
-
12
- const dischargedPatientUuids = data
13
- ?.map((encounter) => {
14
- const reference = encounter?.subject?.reference;
15
- if (reference && reference.startsWith('Patient/')) {
16
- return reference.split('/')[1];
17
- }
18
- return undefined;
19
- })
20
- .filter((uuid) => uuid);
21
-
22
- const { admissionLocation } = useAdmissionLocation();
23
-
24
- const admittedPatientUuids = admissionLocation?.bedLayouts
25
- ?.flatMap((bed) => bed.patients?.map((patient) => patient.uuid))
26
- .filter(Boolean);
27
-
28
- const filteredDischargedPatientUuids = dischargedPatientUuids?.filter(
29
- (uuid) => !admittedPatientUuids?.includes(uuid),
30
- );
31
-
32
- const uniqueDischargedPatientUuids = [...new Set(filteredDischargedPatientUuids)];
33
-
34
- return { dischargedPatientUuids: uniqueDischargedPatientUuids, error, isLoading };
35
- };
36
-
37
- export const usePatients = (uuids: string[]) => {
38
- const customRepresentation =
39
- 'custom:(uuid,display,identifiers:(uuid,display),person:(uuid,display,gender,birthdate,dead,age,deathDate,causeOfDeath:(uuid,display),attributes:(uuid,display,value,attributeType:(uuid,))))';
40
- const urls = uuids.map((uuid) => `${restBaseUrl}/patient/${uuid}?v=${customRepresentation}`);
41
-
42
- const { data, error, isLoading } = useSWR<FetchResponse<Patient>[]>(urls, (urls) =>
43
- Promise.all(urls.map((url) => openmrsFetch<Patient>(url))),
44
- );
45
-
46
- const deceasedPatients = data?.map((response) => response.data)?.filter((patient) => patient?.person?.dead === true);
47
-
48
- return {
49
- isLoading,
50
- error,
51
- patients: deceasedPatients,
52
- };
53
- };
54
-
55
- export default usePatients;
@@ -1,163 +0,0 @@
1
- import {
2
- FetchResponse,
3
- openmrsFetch,
4
- openmrsObservableFetch,
5
- OpenmrsResource,
6
- restBaseUrl,
7
- toDateObjectStrict,
8
- toOmrsIsoString,
9
- useConfig,
10
- useOpenmrsPagination,
11
- } from '@openmrs/esm-framework';
12
- import {
13
- DeceasedPatientResponse,
14
- PaymentMethod,
15
- VisitTypeResponse,
16
- Location,
17
- Patient,
18
- Visit,
19
- UseVisitQueueEntries,
20
- VisitQueueEntry,
21
- MappedVisitQueueEntry,
22
- UpdateVisitPayload,
23
- PaginatedResponse,
24
- } from '../types';
25
- import useSWR from 'swr';
26
- import { BillingConfig, ConfigObject } from '../config-schema';
27
- import { useEffect, useState } from 'react';
28
- import useSWRImmutable from 'swr/immutable';
29
- import { makeUrlUrl } from '../utils/utils';
30
- import type { Observable } from 'rxjs';
31
-
32
- export const useVisitType = () => {
33
- const customRepresentation = 'custom:(uuid,display,name)';
34
- const url = `${restBaseUrl}/visittype?v=${customRepresentation}`;
35
- const { data, error, isLoading } = useSWR<FetchResponse<{ results: VisitTypeResponse[] }>>(url, openmrsFetch);
36
- const visitType = data?.data?.results || null;
37
-
38
- return { data: visitType, error, isLoading };
39
- };
40
-
41
- export const usePaymentModes = (excludeWaiver: boolean = true) => {
42
- const { excludedPaymentMode } = useConfig<BillingConfig>();
43
- const url = `${restBaseUrl}/cashier/paymentMode?v=full`;
44
- const { data, isLoading, error, mutate } = useSWR<{ data: { results: Array<PaymentMethod> } }>(url, openmrsFetch, {
45
- errorRetryCount: 2,
46
- });
47
- const allowedPaymentModes =
48
- excludedPaymentMode?.length > 0
49
- ? data?.data?.results.filter((mode) => !excludedPaymentMode.some((excluded) => excluded.uuid === mode.uuid)) ?? []
50
- : data?.data?.results ?? [];
51
- return {
52
- paymentModes: excludeWaiver ? allowedPaymentModes : data?.data?.results,
53
- isLoading,
54
- mutate,
55
- error,
56
- };
57
- };
58
- export const useBillableItems = () => {
59
- const url = `${restBaseUrl}/cashier/billableService?v=custom:(uuid,name,shortName,serviceStatus,serviceType:(uuid,display),servicePrices:(uuid,name,price,paymentMode))`;
60
- const { data, isLoading, error } = useSWR<{ data: { results: Array<OpenmrsResource> } }>(url, openmrsFetch);
61
- const [searchTerm, setSearchTerm] = useState('');
62
- const filteredItems =
63
- data?.data?.results?.filter((item) => item.name.toLowerCase().includes(searchTerm.toLowerCase())) ?? [];
64
- return {
65
- lineItems: filteredItems,
66
- isLoading,
67
- error,
68
- searchTerm,
69
- setSearchTerm,
70
- };
71
- };
72
- // // Used
73
- export const createPatientBill = (payload) => {
74
- const postUrl = `${restBaseUrl}/cashier/bill`;
75
- return openmrsFetch(postUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: payload });
76
- };
77
- // Used
78
- export const useCashPoint = () => {
79
- const url = `/ws/rest/v1/cashier/cashPoint`;
80
- const { data, isLoading, error } = useSWR<{ data: { results: Array<OpenmrsResource> } }>(url, openmrsFetch);
81
-
82
- return { isLoading, error, cashPoints: data?.data?.results ?? [] };
83
- };
84
- // // Used
85
-
86
- export function useVisitQueueEntry(patientUuid, visitUuid): UseVisitQueueEntries {
87
- const apiUrl = `${restBaseUrl}/visit-queue-entry?v=full&patient=${patientUuid}`;
88
- const { data, error, isLoading, isValidating, mutate } = useSWR<{ data: { results: Array<VisitQueueEntry> } }, Error>(
89
- apiUrl,
90
- openmrsFetch,
91
- );
92
- const mapVisitQueueEntryProperties = (visitQueueEntry: VisitQueueEntry): MappedVisitQueueEntry => ({
93
- id: visitQueueEntry.uuid,
94
- name: visitQueueEntry.queueEntry.queue.display,
95
- patientUuid: visitQueueEntry.queueEntry.patient.uuid,
96
- priority:
97
- visitQueueEntry.queueEntry.priority.display === 'Urgent'
98
- ? 'Priority'
99
- : visitQueueEntry.queueEntry.priority.display,
100
- priorityUuid: visitQueueEntry.queueEntry.priority.uuid,
101
- service: visitQueueEntry.queueEntry.queue?.display,
102
- status: visitQueueEntry.queueEntry.status.display,
103
- statusUuid: visitQueueEntry.queueEntry.status.uuid,
104
- visitUuid: visitQueueEntry.visit?.uuid,
105
- visitType: visitQueueEntry.visit?.visitType?.display,
106
- queue: visitQueueEntry.queueEntry.queue,
107
- queueEntryUuid: visitQueueEntry.queueEntry.uuid,
108
- });
109
-
110
- const mappedVisitQueueEntry =
111
- data?.data?.results
112
- ?.map(mapVisitQueueEntryProperties)
113
- .filter((visitQueueEntry) => visitUuid !== undefined && visitUuid === visitQueueEntry.visitUuid)
114
- .shift() ?? null;
115
- return {
116
- queueEntry: mappedVisitQueueEntry,
117
- isLoading,
118
- error: error,
119
- isValidating,
120
- mutate,
121
- };
122
- }
123
- export const usePerson = (uuid: string) => {
124
- const customRepresentation = `custom:(uuid,display,gender,birthdate,dead,age,deathDate,causeOfDeath:(uuid,display))`;
125
- const url = `${restBaseUrl}/person/${uuid}?v=${customRepresentation}`;
126
- const { isLoading, error, data } = useSWR<FetchResponse<Patient['person']>>(url, openmrsFetch);
127
- const person = data?.data;
128
- return { isLoading, error, person };
129
- };
130
-
131
- // Used
132
- export function removeQueuedPatient(
133
- queueUuid: string,
134
- queueEntryUuid: string,
135
- abortController: AbortController,
136
- endedAt?: Date,
137
- ) {
138
- return openmrsFetch(`${restBaseUrl}/queue/${queueUuid}/entry/${queueEntryUuid}`, {
139
- method: 'POST',
140
- headers: {
141
- 'Content-Type': 'application/json',
142
- },
143
- body: {
144
- endedAt: toDateObjectStrict(toOmrsIsoString(endedAt) ?? toOmrsIsoString(new Date())),
145
- },
146
- signal: abortController.signal,
147
- });
148
- }
149
-
150
- export function updateVisit(
151
- uuid: string,
152
- payload: UpdateVisitPayload,
153
- abortController: AbortController,
154
- ): Observable<any> {
155
- return openmrsObservableFetch(`${restBaseUrl}/visit/${uuid}`, {
156
- signal: abortController.signal,
157
- method: 'POST',
158
- headers: {
159
- 'Content-type': 'application/json',
160
- },
161
- body: payload,
162
- });
163
- }
@@ -1,64 +0,0 @@
1
- import {
2
- type FetchResponse,
3
- openmrsFetch,
4
- restBaseUrl,
5
- useFeatureFlag,
6
- type Location,
7
- useSession,
8
- } from '@openmrs/esm-framework';
9
- import useSWR from 'swr';
10
- import useSWRImmutable from 'swr/immutable';
11
- import { useParams } from 'react-router-dom';
12
- import { type MortuaryLocationFetchResponse, type FHIREncounter } from '../types';
13
-
14
- export function useLocation(locationUuid: string, rep: string = 'custom:(display,uuid)') {
15
- return useSWRImmutable<FetchResponse<Location>>(
16
- locationUuid ? `${restBaseUrl}/location/${locationUuid}?v=${rep}` : null,
17
- openmrsFetch,
18
- );
19
- }
20
-
21
- export function useMortuaryLocation(): {
22
- location: Location | undefined;
23
- isLoadingLocation: boolean;
24
- errorFetchingLocation: Error | undefined;
25
- invalidLocation: boolean;
26
- } {
27
- const { locationUuid: locationUuidFromUrl } = useParams();
28
- const { sessionLocation } = useSession();
29
-
30
- const {
31
- data: locationResponse,
32
- isLoading: isLoadingLocation,
33
- error: errorFetchingLocation,
34
- } = useLocation(locationUuidFromUrl ?? null);
35
-
36
- const invalidLocation = !!locationUuidFromUrl && !!errorFetchingLocation;
37
-
38
- return {
39
- location: locationUuidFromUrl ? locationResponse?.data : sessionLocation,
40
- isLoadingLocation,
41
- errorFetchingLocation,
42
- invalidLocation,
43
- };
44
- }
45
-
46
- const requestRep =
47
- 'custom:(ward,totalBeds,occupiedBeds,bedLayouts:(rowNumber,columnNumber,bedNumber,bedId,bedUuid,status,location,patients:(person:full,identifiers,uuid)))';
48
-
49
- export function useAdmissionLocation(rep: string = requestRep) {
50
- const { location } = useMortuaryLocation();
51
- const isBedManagementModuleInstalled = useFeatureFlag('bedmanagement-module');
52
-
53
- const apiUrl = location?.uuid ? `${restBaseUrl}/admissionLocation/${location.uuid}?v=${rep}` : null;
54
-
55
- const { data, ...rest } = useSWR<FetchResponse<MortuaryLocationFetchResponse>, Error>(
56
- isBedManagementModuleInstalled ? apiUrl : null,
57
- openmrsFetch,
58
- );
59
-
60
- return {
61
- admissionLocation: data?.data,
62
- ...rest,
63
- };
64
- }
@@ -1,54 +0,0 @@
1
- import React, { useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { UserHasAccess } from '@openmrs/esm-framework';
4
- import DeceasedFilter from '../header/admitted-queue-header.component';
5
- import styles from './admitted-queue.scss';
6
- import CompartmentView from '../card/compartment-view.compartment';
7
- import { useAdmissionLocation } from '../hook/useMortuaryAdmissionLocation';
8
- import { InlineLoading } from '@carbon/react';
9
- import { CardHeader, ErrorState } from '@openmrs/esm-patient-common-lib';
10
- import EmptyMorgueAdmission from '../empty-state/empty-morgue-admission.component';
11
- import useEmrConfiguration from '../hook/useAdmitPatient';
12
- import { useDischargedPatient } from '../hook/useDischargedPatient';
13
-
14
- export const AdmittedQueue: React.FC = () => {
15
- const { t } = useTranslation();
16
- const [searchQuery, setSearchQuery] = useState('');
17
- const { admissionLocation, isLoading, error } = useAdmissionLocation();
18
- const handleSearchChange = (query: string) => {
19
- setSearchQuery(query);
20
- };
21
-
22
- if (isLoading) {
23
- return <InlineLoading description={t('loading', 'Loading...')} />;
24
- }
25
-
26
- if (error) {
27
- return <ErrorState headerTitle={t('errorLoadingData', 'Error loading data')} error={error} />;
28
- }
29
-
30
- const filteredBedLayouts = admissionLocation?.bedLayouts?.filter((bed) => {
31
- return bed.patients.some((patient) => patient?.person?.display?.toLowerCase().includes(searchQuery.toLowerCase()));
32
- });
33
-
34
- return (
35
- <div className={styles.layoutWrapper}>
36
- <CardHeader title={t('allocation', 'Allocation')} children={''} />
37
- <DeceasedFilter onSearchChange={handleSearchChange} />
38
- <div className={styles.patientCardContainer}>
39
- {filteredBedLayouts?.length === 0 ? (
40
- <EmptyMorgueAdmission
41
- title={t('allocations', 'Allocation')}
42
- subTitle={t('noAdmittedBodies', 'There are no admitted bodies matching your search')}
43
- />
44
- ) : (
45
- <UserHasAccess privilege="o3 : View Mortuary Compartments">
46
- <CompartmentView />
47
- </UserHasAccess>
48
- )}
49
- </div>
50
- </div>
51
- );
52
- };
53
-
54
- export default AdmittedQueue;
@@ -1,62 +0,0 @@
1
- @use '@carbon/layout';
2
- @use '@carbon/type';
3
- @use '@carbon/colors';
4
- // @use '~@openmrs/esm-styleguide/src/vars' as *;
5
-
6
- .container {
7
- display: flex;
8
- flex-wrap: wrap;
9
- justify-content: space-between;
10
- margin: layout.$spacing-04;
11
- }
12
-
13
- .column {
14
- width: calc(25% - 1rem);
15
- height: 776px;
16
- flex-grow: 0;
17
- display: flex;
18
- flex-direction: column;
19
- justify-content: flex-start;
20
- align-items: center;
21
- gap: layout.$spacing-03;
22
- padding: 0;
23
- margin: 0.5rem;
24
- }
25
-
26
- .tile {
27
- width: 340px;
28
- height: layout.$spacing-09;
29
- display: flex;
30
- justify-content: center;
31
- align-items: center;
32
- margin: layout.$spacing-03 0;
33
- }
34
-
35
- .tileContent {
36
- display: flex;
37
- justify-content: center;
38
- align-items: center;
39
- gap: layout.$spacing-04;
40
- }
41
-
42
- .label {
43
- width: layout.$spacing-07;
44
- height: layout.$spacing-07;
45
- display: flex;
46
- justify-content: center;
47
- align-items: center;
48
- font-size: layout.$spacing-01;
49
- font-weight: 600;
50
- line-height: 1.29;
51
- background-color: colors.$cool-gray-20;
52
- border: 1px solid colors.$cool-gray-20;
53
- border-radius: 50%;
54
- }
55
-
56
- .emptyunit {
57
- line-height: 1.38;
58
- }
59
- .layoutWrapper {
60
- border: 1px solid colors.$gray-30;
61
- padding: layout.$spacing-05 layout.$spacing-05;
62
- }
@@ -1,87 +0,0 @@
1
- import { DataTableSkeleton } from '@carbon/react';
2
- import { ConfigurableLink, ErrorState, formatDate, useConfig } from '@openmrs/esm-framework';
3
- import React from 'react';
4
- import { useTranslation } from 'react-i18next';
5
- import styles from './generic-table.scss';
6
- import GenericTable from './generic-table.component';
7
- import { ConfigObject } from '../config-schema';
8
- import usePatients from '../hook/useDischargedPatient';
9
-
10
- interface DischargedProps {
11
- dischargedPatientUuids: string[];
12
- isLoading: boolean;
13
- error: any;
14
- }
15
-
16
- export const DischargedBodies: React.FC<DischargedProps> = ({ isLoading, error, dischargedPatientUuids }) => {
17
- const { t } = useTranslation();
18
- const dischargedInLine = t('dischargeBodies', 'Discharged bodies');
19
- const patientChartUrl = '${openmrsSpaBase}/patient/${patientUuid}/chart/deceased-panel';
20
- const { patients, isLoading: isLoadingPatients, error: patientsError } = usePatients(dischargedPatientUuids);
21
-
22
- const { nextOfKinAddressUuid, nextOfKinNameUuid, nextOfKinPhoneUuid, nextOfKinRelationshipUuid } =
23
- useConfig<ConfigObject>();
24
-
25
- const genericTableHeader = [
26
- { header: 'Patient Name', key: 'name' },
27
- { header: 'Gender', key: 'gender' },
28
- { header: 'Identifier', key: 'identifier' },
29
- { header: 'Age', key: 'age' },
30
- { header: 'Date of Death', key: 'deathDate' },
31
- { header: 'Cause of Death', key: 'causeOfDeath' },
32
- ];
33
-
34
- if (isLoading) {
35
- return (
36
- <div className={styles.table}>
37
- <DataTableSkeleton
38
- headers={genericTableHeader}
39
- aria-label="discharged-datatable"
40
- showToolbar={false}
41
- showHeader={false}
42
- rowCount={10}
43
- zebra
44
- columnCount={7}
45
- />
46
- </div>
47
- );
48
- }
49
-
50
- if (error) {
51
- return <ErrorState error={error} headerTitle={t('dischargeBodies', 'Discharged bodies')} />;
52
- }
53
-
54
- const getAttributeValue = (patient, uuid) => {
55
- return patient?.person?.attributes?.find((attr) => attr?.attributeType?.uuid === uuid)?.value || '--';
56
- };
57
-
58
- const rows = patients?.map((patient) => {
59
- const openmrsID = patient?.identifiers?.find((id) => id.display.startsWith('OpenMRS ID'))?.display.split(' = ')[1];
60
-
61
- const nextOfKin = {
62
- name: getAttributeValue(patient, nextOfKinNameUuid),
63
- phone: getAttributeValue(patient, nextOfKinPhoneUuid),
64
- address: getAttributeValue(patient, nextOfKinAddressUuid),
65
- relationship: getAttributeValue(patient, nextOfKinRelationshipUuid),
66
- };
67
-
68
- return {
69
- id: patient?.uuid,
70
- name: (
71
- <ConfigurableLink
72
- style={{ textDecoration: 'none', maxWidth: '50%' }}
73
- to={patientChartUrl}
74
- templateParams={{ patientUuid: patient?.uuid }}>
75
- {patient?.person?.display?.toUpperCase()}
76
- </ConfigurableLink>
77
- ),
78
- gender: patient?.person?.gender || '--',
79
- age: patient?.person?.age || '--',
80
- identifier: openmrsID || '--',
81
- deathDate: formatDate(new Date(patient?.person?.deathDate)) || '--',
82
- causeOfDeath: patient?.person?.causeOfDeath?.display || '--',
83
- nextOfKin: nextOfKin, // Ensure nextOfKin is included in the row
84
- };
85
- });
86
- return <GenericTable rows={rows} headers={genericTableHeader} title={dischargedInLine} />;
87
- };
@@ -1,140 +0,0 @@
1
- import React, { useState } from 'react';
2
- import classNames from 'classnames';
3
- import { useTranslation } from 'react-i18next';
4
- import {
5
- DataTable,
6
- Table,
7
- TableCell,
8
- TableContainer,
9
- TableBody,
10
- TableHead,
11
- TableHeader,
12
- TableRow,
13
- TableExpandRow,
14
- TableExpandedRow,
15
- Search,
16
- TableExpandHeader,
17
- } from '@carbon/react';
18
- import { CardHeader, PatientChartPagination } from '@openmrs/esm-patient-common-lib';
19
- import { useLayoutType, usePagination } from '@openmrs/esm-framework';
20
- import styles from './generic-table.scss';
21
- import EmptyDeceasedSearch from '../empty-state/empty-morgue-admission.component';
22
- import { Patient } from '../types';
23
- import NextOfKinDetails from '../component/next-of-kin-details/nextOfKinDetails.component';
24
-
25
- interface GenericTableProps {
26
- rows: any[];
27
- headers: { header: string; key: string }[];
28
- actionColumn?: (row: any) => React.ReactNode;
29
- title?: string;
30
- }
31
-
32
- const GenericTable: React.FC<GenericTableProps> = ({ rows, headers, actionColumn, title }) => {
33
- const { t } = useTranslation();
34
- const pageSize = 10;
35
- const isTablet = useLayoutType() === 'tablet';
36
-
37
- const [searchTerm, setSearchTerm] = useState('');
38
-
39
- const filteredRows = rows?.filter((row) =>
40
- headers.some((header) => row[header.key]?.toString().toLowerCase().includes(searchTerm.toLowerCase())),
41
- );
42
-
43
- const { results: paginatedData, currentPage, goTo } = usePagination(filteredRows, pageSize);
44
-
45
- return (
46
- <div className={styles.table}>
47
- <CardHeader title={title} children={''} />
48
- <div className={styles.searchContainer}>
49
- <Search
50
- size="sm"
51
- placeholder="Search for deceased"
52
- labelText="Search"
53
- closeButtonLabelText="Clear search input"
54
- id="search-deceased"
55
- value={searchTerm}
56
- onChange={(e) => setSearchTerm(e.target.value)}
57
- className={styles.searchInput}
58
- />
59
- </div>
60
-
61
- {rows?.length === 0 ? (
62
- <EmptyDeceasedSearch
63
- title={t('noWaitingList', 'Waiting List')}
64
- subTitle={t('noDeceasedPersons', 'There are no deceased persons on the waiting list')}
65
- />
66
- ) : searchTerm && filteredRows?.length === 0 ? (
67
- <EmptyDeceasedSearch
68
- title={t('noResultFound', 'Sorry, no results found')}
69
- subTitle={t('searchForADeceased', "Try to search again using the deceased patient's unique ID number")}
70
- />
71
- ) : (
72
- <div className={styles.genericTable}>
73
- <DataTable rows={paginatedData} headers={headers} isSortable size={isTablet ? 'lg' : 'sm'} useZebraStyles>
74
- {({
75
- rows: tableRows,
76
- headers,
77
- getHeaderProps,
78
- getTableProps,
79
- getRowProps,
80
- getTableContainerProps,
81
- getExpandHeaderProps,
82
- }) => (
83
- <TableContainer {...getTableContainerProps()} className={styles.tableContainer}>
84
- <Table {...getTableProps()}>
85
- <TableHead>
86
- <TableRow>
87
- <TableExpandHeader enableToggle {...getExpandHeaderProps()} />
88
- {headers?.map((header, i) => (
89
- <TableHeader
90
- key={i}
91
- {...getHeaderProps({
92
- header,
93
- })}>
94
- {header.header}
95
- </TableHeader>
96
- ))}
97
- {actionColumn && <TableHeader>Action</TableHeader>}
98
- </TableRow>
99
- </TableHead>
100
- <TableBody>
101
- {tableRows?.map((row, i) => {
102
- const originalRow = rows.find((r) => r.id === row.id);
103
-
104
- return (
105
- <React.Fragment key={row.id}>
106
- <TableExpandRow {...getRowProps({ row })}>
107
- {row.cells.map((cell) => (
108
- <TableCell key={cell.id}>{cell.value}</TableCell>
109
- ))}
110
- {actionColumn && <TableCell>{actionColumn(row)}</TableCell>}
111
- </TableExpandRow>
112
- {row.isExpanded && (
113
- <TableExpandedRow colSpan={headers.length + 1}>
114
- <div className={styles.expandedRowContent}>
115
- {originalRow && <NextOfKinDetails nextOfKin={originalRow.nextOfKin} />}
116
- </div>
117
- </TableExpandedRow>
118
- )}
119
- </React.Fragment>
120
- );
121
- })}
122
- </TableBody>
123
- </Table>
124
- </TableContainer>
125
- )}
126
- </DataTable>
127
- <PatientChartPagination
128
- currentItems={paginatedData?.length}
129
- totalItems={filteredRows?.length}
130
- onPageNumberChange={({ page }) => goTo(page)}
131
- pageNumber={currentPage}
132
- pageSize={pageSize}
133
- />
134
- </div>
135
- )}
136
- </div>
137
- );
138
- };
139
-
140
- export default GenericTable;
@@ -1,37 +0,0 @@
1
- @use '@carbon/layout';
2
- @use '@carbon/type';
3
- @use '@carbon/colors';
4
-
5
- .genericTable {
6
- margin: 0 auto;
7
- }
8
-
9
- .searchContainer {
10
- margin-bottom: layout.$spacing-05;
11
- border: solid colors.$gray-30 0.1rem;
12
- margin-left: layout.$spacing-06;
13
- margin-right: layout.$spacing-06;
14
- }
15
-
16
- .tableContainer {
17
- margin: 0 layout.$spacing-05;
18
- }
19
-
20
- .actionBtn {
21
- --cds-layout-size-height-context: var(--cds-layout-size-height-sm, 2rem);
22
- --cds-layout-size-height: var(--cds-layout-size-height-context);
23
- display: flex;
24
- align-items: center;
25
- justify-content: center;
26
- text-align: center;
27
- padding: 0 layout.$spacing-04;
28
- }
29
- .table {
30
- border: 1px solid colors.$gray-30;
31
- width: 98%;
32
- margin: 0 auto;
33
- }
34
- .groupButtons {
35
- display: flex;
36
- gap: layout.$spacing-05;
37
- }