@kenyaemr/esm-ward-app 8.1.2-pre.214 → 8.5.1-pre.13
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.
- package/.turbo/turbo-build.log +25 -35
- package/README.md +38 -0
- package/dist/1119.js +1 -0
- package/dist/1197.js +1 -0
- package/dist/1663.js +1 -0
- package/dist/1663.js.map +1 -0
- package/dist/1741.js +1 -0
- package/dist/1741.js.map +1 -0
- package/dist/1776.js +1 -0
- package/dist/1776.js.map +1 -0
- package/dist/1899.js +1 -0
- package/dist/1899.js.map +1 -0
- package/dist/2146.js +1 -0
- package/dist/2372.js +1 -0
- package/dist/2372.js.map +1 -0
- package/dist/2470.js +1 -0
- package/dist/2470.js.map +1 -0
- package/dist/2499.js +2 -0
- package/dist/{372.js.LICENSE.txt → 2499.js.LICENSE.txt} +2 -2
- package/dist/2499.js.map +1 -0
- package/dist/2537.js +1 -0
- package/dist/2537.js.map +1 -0
- package/dist/2557.js +1 -0
- package/dist/2557.js.map +1 -0
- package/dist/2690.js +1 -0
- package/dist/2728.js +2 -0
- package/dist/{649.js.LICENSE.txt → 2728.js.LICENSE.txt} +2 -2
- package/dist/2728.js.map +1 -0
- package/dist/2775.js +2 -0
- package/dist/2775.js.LICENSE.txt +59 -0
- package/dist/2775.js.map +1 -0
- package/dist/2904.js +2 -0
- package/dist/2904.js.LICENSE.txt +15 -0
- package/dist/2904.js.map +1 -0
- package/dist/2913.js +2 -0
- package/dist/2913.js.map +1 -0
- package/dist/2932.js +1 -0
- package/dist/2932.js.map +1 -0
- package/dist/2941.js +1 -0
- package/dist/2941.js.map +1 -0
- package/dist/2948.js +1 -0
- package/dist/2948.js.map +1 -0
- package/dist/3099.js +1 -0
- package/dist/3103.js +1 -0
- package/dist/3103.js.map +1 -0
- package/dist/3296.js +2 -0
- package/dist/3296.js.LICENSE.txt +9 -0
- package/dist/3296.js.map +1 -0
- package/dist/3365.js +1 -0
- package/dist/3365.js.map +1 -0
- package/dist/3373.js +2 -0
- package/dist/3373.js.LICENSE.txt +5 -0
- package/dist/3373.js.map +1 -0
- package/dist/3399.js +1 -0
- package/dist/3399.js.map +1 -0
- package/dist/3413.js +1 -0
- package/dist/3413.js.map +1 -0
- package/dist/3584.js +1 -0
- package/dist/3737.js +1 -0
- package/dist/3737.js.map +1 -0
- package/dist/3982.js +1 -0
- package/dist/3982.js.map +1 -0
- package/dist/4041.js +2 -0
- package/dist/4041.js.map +1 -0
- package/dist/4055.js +1 -0
- package/dist/4132.js +1 -0
- package/dist/4300.js +1 -0
- package/dist/4335.js +1 -0
- package/dist/4430.js +2 -0
- package/dist/4430.js.LICENSE.txt +29 -0
- package/dist/4430.js.map +1 -0
- package/dist/4618.js +1 -0
- package/dist/4652.js +1 -0
- package/dist/4701.js +2 -0
- package/dist/4701.js.LICENSE.txt +9 -0
- package/dist/4701.js.map +1 -0
- package/dist/4944.js +1 -0
- package/dist/5173.js +1 -0
- package/dist/5241.js +1 -0
- package/dist/5442.js +1 -0
- package/dist/559.js +1 -1
- package/dist/559.js.map +1 -1
- package/dist/5661.js +1 -0
- package/dist/6012.js +2 -0
- package/dist/6012.js.LICENSE.txt +5 -0
- package/dist/6012.js.map +1 -0
- package/dist/6022.js +1 -0
- package/dist/6468.js +1 -0
- package/dist/6679.js +1 -0
- package/dist/6840.js +1 -0
- package/dist/6859.js +1 -0
- package/dist/7097.js +1 -0
- package/dist/7159.js +1 -0
- package/dist/7179.js +2 -0
- package/dist/7179.js.LICENSE.txt +9 -0
- package/dist/7179.js.map +1 -0
- package/dist/723.js +1 -0
- package/dist/7232.js +2 -0
- package/dist/7232.js.LICENSE.txt +9 -0
- package/dist/7232.js.map +1 -0
- package/dist/7524.js +1 -0
- package/dist/7524.js.map +1 -0
- package/dist/7617.js +1 -0
- package/dist/7661.js +1 -0
- package/dist/7661.js.map +1 -0
- package/dist/7886.js +1 -0
- package/dist/7886.js.map +1 -0
- package/dist/795.js +1 -0
- package/dist/8163.js +1 -0
- package/dist/8205.js +1 -0
- package/dist/8205.js.map +1 -0
- package/dist/8349.js +1 -0
- package/dist/8501.js +1 -0
- package/dist/8501.js.map +1 -0
- package/dist/8522.js +1 -0
- package/dist/8522.js.map +1 -0
- package/dist/8618.js +1 -0
- package/dist/8622.js +1 -0
- package/dist/8622.js.map +1 -0
- package/dist/89.js +1 -0
- package/dist/89.js.map +1 -0
- package/dist/890.js +1 -0
- package/dist/9045.js +1 -0
- package/dist/9045.js.map +1 -0
- package/dist/9117.js +1 -0
- package/dist/9117.js.map +1 -0
- package/dist/9214.js +1 -0
- package/dist/9538.js +1 -0
- package/dist/9569.js +1 -0
- package/dist/986.js +1 -0
- package/dist/9876.js +2 -0
- package/dist/9876.js.LICENSE.txt +9 -0
- package/dist/9876.js.map +1 -0
- package/dist/9879.js +1 -0
- package/dist/9880.js +1 -0
- package/dist/9880.js.map +1 -0
- package/dist/9895.js +1 -0
- package/dist/9900.js +1 -0
- package/dist/9913.js +1 -0
- package/dist/kenyaemr-esm-ward-app.js +1 -1
- package/dist/kenyaemr-esm-ward-app.js.buildmanifest.json +1457 -237
- package/dist/kenyaemr-esm-ward-app.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.LICENSE.txt +0 -35
- package/dist/main.js.map +1 -1
- package/dist/routes.json +1 -1
- package/mock.tsx +15 -2
- package/package.json +10 -5
- package/src/beds/{empty-bed-skeleton.tsx → empty-bed-skeleton.component.tsx} +2 -2
- package/src/config-schema.ts +48 -0
- package/src/declarations.d.ts +8 -0
- package/src/hooks/useAdmissionLocation.ts +22 -1
- package/src/hooks/useInpatientAdmission.ts +12 -8
- package/src/hooks/useInpatientAdmissionByPatients.ts +29 -0
- package/src/hooks/useInpatientRequest.ts +3 -0
- package/src/hooks/useInpatientRequestByPatients.ts +34 -0
- package/src/hooks/useIpdDischargeEncounter.ts +137 -0
- package/src/hooks/usePatientPendingOrders.ts +1 -1
- package/src/hooks/useRestPatient.ts +11 -3
- package/src/hooks/useWardLocation.test.ts +1 -1
- package/src/hooks/useWardLocation.ts +15 -2
- package/src/hooks/useWardPatientGrouping.ts +60 -7
- package/src/index.ts +24 -4
- package/src/location-selector/location-selector.component.tsx +38 -5
- package/src/root.component.tsx +2 -2
- package/src/routes.json +60 -26
- package/src/types/index.ts +17 -6
- package/src/ward-patient-card/card-rows/admission-request-note-row.component.tsx +1 -1
- package/src/ward-patient-card/card-rows/coded-obs-tags-row.component.tsx +4 -4
- package/src/ward-patient-card/card-rows/mother-child-row.component.tsx +6 -6
- package/src/ward-patient-card/card-rows/pending-items-row.component.tsx +2 -3
- package/src/ward-patient-card/row-elements/{ward-patient-coded-obs-tags.tsx → ward-patient-coded-obs-tags.component.tsx} +5 -5
- package/src/ward-patient-card/row-elements/{ward-patient-header-address.tsx → ward-patient-header-address.component.tsx} +2 -2
- package/src/ward-patient-card/row-elements/{ward-patient-identifier.tsx → ward-patient-identifier.component.tsx} +7 -1
- package/src/ward-patient-card/row-elements/ward-patient-identifier.scss +3 -0
- package/src/ward-patient-card/row-elements/{ward-patient-obs.tsx → ward-patient-obs.component.tsx} +5 -5
- package/src/ward-patient-card/row-elements/{ward-patient-pending-transfer.tsx → ward-patient-pending-transfer.component.tsx} +3 -5
- package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.component.tsx +73 -0
- package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.component.tsx +29 -0
- package/src/ward-patient-card/ward-patient-card.component.tsx +5 -5
- package/src/ward-patient-card/ward-patient-card.scss +2 -6
- package/src/ward-patients/admitted-patients.tsx +218 -0
- package/src/ward-patients/awaiting-admission-patients.tsx +158 -0
- package/src/ward-patients/discharge-in-patients.tsx +183 -0
- package/src/ward-patients/discharge-patients.tsx +129 -0
- package/src/ward-patients/patient-cells.tsx +75 -0
- package/src/ward-patients/table-state-components.tsx +40 -0
- package/src/ward-patients/ward-patient.scss +24 -0
- package/src/ward-patients/ward-patients-table.tsx +38 -0
- package/src/ward-view/default-ward/default-ward-patient-card-header.component.tsx +8 -8
- package/src/ward-view/default-ward/default-ward-pending-patients.component.tsx +3 -3
- package/src/ward-view/default-ward/default-ward-view.component.tsx +31 -6
- package/src/ward-view/linelist-wards/Filters.tsx +25 -0
- package/src/ward-view/linelist-wards/Header.tsx +27 -0
- package/src/ward-view/linelist-wards/LineListTable.tsx +147 -0
- package/src/ward-view/linelist-wards/Metrics.tsx +21 -0
- package/src/ward-view/linelist-wards/WardsLineList.tsx +29 -0
- package/src/ward-view/linelist-wards/linelist-wards.scss +100 -0
- package/src/ward-view/materal-ward/maternal-ward-patient-card-header.component.tsx +8 -8
- package/src/ward-view/materal-ward/maternal-ward-patient-card.component.tsx +2 -2
- package/src/ward-view/materal-ward/maternal-ward-patient-card.test.tsx +1 -1
- package/src/ward-view/materal-ward/maternal-ward-pending-patients.component.tsx +1 -1
- package/src/ward-view/materal-ward/maternal-ward-view.component.tsx +4 -4
- package/src/ward-view/ward-view-content-wrapper.tsx +36 -0
- package/src/ward-view/ward-view.resource.ts +26 -8
- package/src/ward-view/ward-view.scss +15 -8
- package/src/ward-view/ward-view.test.tsx +8 -8
- package/src/ward-view/ward.component.tsx +2 -2
- package/src/ward-view-header/admission-requests-bar.component.tsx +18 -8
- package/src/ward-view-header/admission-requests-bar.test.tsx +3 -3
- package/src/ward-view-header/ward-metric.component.tsx +2 -3
- package/src/ward-workspace/admission-request-card/admission-request-card-actions.component.tsx +12 -14
- package/src/ward-workspace/admission-request-card/admission-request-card-header.component.tsx +5 -5
- package/src/ward-workspace/admission-request-card/admission-request-card.component.tsx +1 -1
- package/src/ward-workspace/admission-request-workspace/admission-requests-action-button.extension.tsx +18 -0
- package/src/ward-workspace/admission-request-workspace/admission-requests-context.ts +20 -0
- package/src/ward-workspace/admission-request-workspace/admission-requests-workspace.test.tsx +7 -6
- package/src/ward-workspace/admission-request-workspace/admission-requests.workspace.tsx +15 -25
- package/src/ward-workspace/admit-patient-button.component.tsx +41 -18
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.test.tsx +14 -16
- package/src/ward-workspace/admit-patient-form-workspace/admit-patient-form.workspace.tsx +2 -2
- package/src/ward-workspace/bed-selector.component.tsx +1 -1
- package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.test.tsx +1 -1
- package/src/ward-workspace/cancel-admission-request-workspace/cancel-admission-request.workspace.tsx +4 -6
- package/src/ward-workspace/create-admission-encounter/create-admission-encounter-action-button.extension.tsx +46 -0
- package/src/ward-workspace/create-admission-encounter/create-admission-encounter.test.tsx +241 -0
- package/src/ward-workspace/create-admission-encounter/create-admission-encounter.workspace.tsx +152 -0
- package/src/ward-workspace/kenya-emr-patient-discharge/discharge-workspace-siderail.component.tsx +23 -0
- package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.resource.tsx +123 -0
- package/src/ward-workspace/kenya-emr-patient-discharge/patient-discharge.workspace.tsx +101 -0
- package/src/ward-workspace/patient-discharge/patient-discharge.workspace.tsx +6 -15
- package/src/ward-workspace/patient-transfer-bed-swap/{patient-transfer-request-form.component.tsx → patient-admit-or-transfer-request-form.component.tsx} +56 -37
- package/src/ward-workspace/patient-transfer-bed-swap/patient-bed-swap-form.component.tsx +13 -3
- package/src/ward-workspace/patient-transfer-bed-swap/patient-transfer-swap.workspace.tsx +11 -5
- package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.scss +5 -0
- package/src/ward-workspace/patient-transfer-request-workspace/patient-transfer-request.workspace.tsx +20 -6
- package/src/ward-workspace/ward-patient-notes/form/notes-form.component.tsx +2 -1
- package/src/ward-workspace/ward-patient-notes/history/note.component.tsx +3 -3
- package/src/ward.resource.ts +9 -3
- package/translations/am.json +123 -0
- package/translations/ar.json +123 -0
- package/translations/ar_SY.json +123 -0
- package/translations/bn.json +123 -0
- package/translations/de.json +123 -0
- package/translations/en.json +31 -3
- package/translations/en_US.json +123 -0
- package/translations/es.json +123 -0
- package/translations/es_MX.json +123 -0
- package/translations/fr.json +123 -0
- package/translations/he.json +123 -0
- package/translations/hi.json +123 -0
- package/translations/hi_IN.json +123 -0
- package/translations/id.json +123 -0
- package/translations/it.json +123 -0
- package/translations/ka.json +123 -0
- package/translations/km.json +123 -0
- package/translations/ku.json +123 -0
- package/translations/ky.json +123 -0
- package/translations/lg.json +123 -0
- package/translations/ne.json +123 -0
- package/translations/pl.json +123 -0
- package/translations/pt.json +123 -0
- package/translations/pt_BR.json +123 -0
- package/translations/qu.json +123 -0
- package/translations/ro_RO.json +123 -0
- package/translations/ru_RU.json +123 -0
- package/translations/si.json +123 -0
- package/translations/sw.json +123 -0
- package/translations/sw_KE.json +123 -0
- package/translations/tr.json +123 -0
- package/translations/tr_TR.json +123 -0
- package/translations/uk.json +123 -0
- package/translations/uz.json +123 -0
- package/translations/uz@Latn.json +123 -0
- package/translations/uz_UZ.json +123 -0
- package/translations/vi.json +123 -0
- package/translations/zh.json +123 -0
- package/translations/zh_CN.json +123 -0
- package/dist/109.js +0 -1
- package/dist/109.js.map +0 -1
- package/dist/124.js +0 -1
- package/dist/124.js.map +0 -1
- package/dist/125.js +0 -1
- package/dist/125.js.map +0 -1
- package/dist/126.js +0 -1
- package/dist/126.js.map +0 -1
- package/dist/130.js +0 -2
- package/dist/130.js.LICENSE.txt +0 -5
- package/dist/130.js.map +0 -1
- package/dist/146.js +0 -1
- package/dist/146.js.map +0 -1
- package/dist/15.js +0 -1
- package/dist/15.js.map +0 -1
- package/dist/325.js +0 -1
- package/dist/325.js.map +0 -1
- package/dist/348.js +0 -1
- package/dist/348.js.map +0 -1
- package/dist/362.js +0 -1
- package/dist/362.js.map +0 -1
- package/dist/372.js +0 -2
- package/dist/372.js.map +0 -1
- package/dist/443.js +0 -1
- package/dist/443.js.map +0 -1
- package/dist/471.js +0 -1
- package/dist/471.js.map +0 -1
- package/dist/481.js +0 -1
- package/dist/481.js.map +0 -1
- package/dist/53.js +0 -1
- package/dist/53.js.map +0 -1
- package/dist/574.js +0 -1
- package/dist/576.js +0 -1
- package/dist/576.js.map +0 -1
- package/dist/577.js +0 -1
- package/dist/577.js.map +0 -1
- package/dist/591.js +0 -2
- package/dist/591.js.map +0 -1
- package/dist/598.js +0 -1
- package/dist/598.js.map +0 -1
- package/dist/649.js +0 -2
- package/dist/649.js.map +0 -1
- package/dist/662.js +0 -1
- package/dist/662.js.map +0 -1
- package/dist/767.js +0 -1
- package/dist/767.js.map +0 -1
- package/dist/784.js +0 -2
- package/dist/784.js.map +0 -1
- package/dist/921.js +0 -1
- package/dist/921.js.map +0 -1
- package/dist/922.js +0 -1
- package/dist/922.js.map +0 -1
- package/dist/925.js +0 -2
- package/dist/925.js.LICENSE.txt +0 -40
- package/dist/925.js.map +0 -1
- package/dist/940.js +0 -1
- package/dist/940.js.map +0 -1
- package/dist/969.js +0 -1
- package/dist/969.js.map +0 -1
- package/dist/983.js +0 -1
- package/dist/983.js.map +0 -1
- package/package-lock.json +0 -5001
- package/src/ward-patient-card/row-elements/ward-patient-time-on-ward.tsx +0 -22
- package/src/ward-patient-card/row-elements/ward-patient-time-since-admission.tsx +0 -22
- /package/dist/{591.js.LICENSE.txt → 2913.js.LICENSE.txt} +0 -0
- /package/dist/{784.js.LICENSE.txt → 4041.js.LICENSE.txt} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-age.tsx → ward-patient-age.component.tsx} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-bed-number.tsx → ward-patient-bed-number.component.tsx} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-location.tsx → ward-patient-location.component.tsx} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-name.tsx → ward-patient-name.component.tsx} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-responsive-tooltip.tsx → ward-patient-responsive-tooltip.component.tsx} +0 -0
- /package/src/ward-patient-card/row-elements/{ward-patient-skeleton-text.tsx → ward-patient-skeleton-text.component.tsx} +0 -0
package/src/ward-workspace/create-admission-encounter/create-admission-encounter.workspace.tsx
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { Button, InlineNotification, SkeletonText } from '@carbon/react';
|
|
4
|
+
import { ArrowLeftIcon, type DefaultWorkspaceProps, useVisit } from '@openmrs/esm-framework';
|
|
5
|
+
import { useAssignedBedByPatient } from '../../hooks/useAssignedBedByPatient';
|
|
6
|
+
import { useInpatientAdmissionByPatients } from '../../hooks/useInpatientAdmissionByPatients';
|
|
7
|
+
import { useInpatientRequestByPatients } from '../../hooks/useInpatientRequestByPatients';
|
|
8
|
+
import useRestPatient from '../../hooks/useRestPatient';
|
|
9
|
+
import useWardLocation from '../../hooks/useWardLocation';
|
|
10
|
+
import type { Bed, WardPatient } from '../../types';
|
|
11
|
+
import AdmitPatientButton from '../admit-patient-button.component';
|
|
12
|
+
import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
|
|
13
|
+
|
|
14
|
+
export interface CreateAdmissionEncounterWorkspaceProps {
|
|
15
|
+
patientUuid: string;
|
|
16
|
+
handleReturnToSearchList?: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* This is the workspace that opens when clicking on a search result
|
|
21
|
+
* from the workspace triggered by the "Add patient to ward" button.
|
|
22
|
+
* It directly admits them to the current ward locations
|
|
23
|
+
*/
|
|
24
|
+
const CreateAdmissionEncounterWorkspace: React.FC<CreateAdmissionEncounterWorkspaceProps & DefaultWorkspaceProps> = ({
|
|
25
|
+
patientUuid,
|
|
26
|
+
handleReturnToSearchList,
|
|
27
|
+
closeWorkspaceWithSavedChanges,
|
|
28
|
+
}) => {
|
|
29
|
+
const { location } = useWardLocation();
|
|
30
|
+
const { patient, isLoading: isLoadingPatient, error: errorLoadingPatient } = useRestPatient(patientUuid);
|
|
31
|
+
const { activeVisit, isLoading: isLoadingVisit, error: errorLoadingVisit } = useVisit(patientUuid);
|
|
32
|
+
const { t } = useTranslation();
|
|
33
|
+
const { data: bedData, isLoading: isLoadingBed, error: errorLoadingBed } = useAssignedBedByPatient(patientUuid);
|
|
34
|
+
const {
|
|
35
|
+
data: inpatientAdmissions,
|
|
36
|
+
isLoading: isLoadingInpatientAdmission,
|
|
37
|
+
error: errorInpatientAdmission,
|
|
38
|
+
} = useInpatientAdmissionByPatients([patientUuid]);
|
|
39
|
+
const {
|
|
40
|
+
inpatientRequests,
|
|
41
|
+
isLoading: isLoadingInpatientRequest,
|
|
42
|
+
error: errorInpatientRequests,
|
|
43
|
+
} = useInpatientRequestByPatients([patientUuid]);
|
|
44
|
+
|
|
45
|
+
const isLoading =
|
|
46
|
+
isLoadingPatient || isLoadingVisit || isLoadingBed || isLoadingInpatientAdmission || isLoadingInpatientRequest;
|
|
47
|
+
const hasError =
|
|
48
|
+
errorLoadingPatient || errorLoadingVisit || errorLoadingBed || errorInpatientAdmission || errorInpatientRequests;
|
|
49
|
+
|
|
50
|
+
if (isLoading) {
|
|
51
|
+
return <SkeletonText />;
|
|
52
|
+
} else if (hasError) {
|
|
53
|
+
return (
|
|
54
|
+
<div>
|
|
55
|
+
<InlineNotification
|
|
56
|
+
kind="error"
|
|
57
|
+
lowContrast={true}
|
|
58
|
+
title={t('errorLoadingPatientInfo', 'Error loading patient info')}
|
|
59
|
+
/>
|
|
60
|
+
<Button
|
|
61
|
+
kind="ghost"
|
|
62
|
+
renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
|
|
63
|
+
iconDescription={t('backToSearchResults', 'Back to search results')}
|
|
64
|
+
size="sm"
|
|
65
|
+
onClick={() => handleReturnToSearchList?.()}>
|
|
66
|
+
<span>{t('backToSearchResults', 'Back to search results')}</span>
|
|
67
|
+
</Button>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
} else {
|
|
71
|
+
const assignedBedDetail = bedData.data.results[0];
|
|
72
|
+
const isAssignedBedAtCurrentLocation = assignedBedDetail?.physicalLocation?.uuid == location.uuid;
|
|
73
|
+
const isAdmittedToCurrentLocation = inpatientAdmissions[0]?.currentInpatientLocation?.uuid == location.uuid;
|
|
74
|
+
const isAdmittedToOtherLocation = inpatientAdmissions[0] && !isAdmittedToCurrentLocation;
|
|
75
|
+
|
|
76
|
+
const wardPatient: WardPatient = {
|
|
77
|
+
patient,
|
|
78
|
+
visit: activeVisit,
|
|
79
|
+
bed: isAssignedBedAtCurrentLocation
|
|
80
|
+
? ({
|
|
81
|
+
id: assignedBedDetail.bedId,
|
|
82
|
+
bedNumber: assignedBedDetail.bedNumber,
|
|
83
|
+
bedType: assignedBedDetail.bedType,
|
|
84
|
+
} as Bed)
|
|
85
|
+
: null,
|
|
86
|
+
inpatientAdmission: inpatientAdmissions[0],
|
|
87
|
+
inpatientRequest: null,
|
|
88
|
+
};
|
|
89
|
+
return (
|
|
90
|
+
<div>
|
|
91
|
+
<WardPatientWorkspaceBanner wardPatient={wardPatient} />
|
|
92
|
+
{activeVisit ? (
|
|
93
|
+
<div>
|
|
94
|
+
{isAdmittedToCurrentLocation && (
|
|
95
|
+
<InlineNotification
|
|
96
|
+
kind="warning"
|
|
97
|
+
lowContrast={true}
|
|
98
|
+
hideCloseButton={true}
|
|
99
|
+
title={t('patientAlreadyAdmittedToCurrentLocation', 'Patient already admitted to current location')}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
{isAdmittedToOtherLocation && (
|
|
103
|
+
<InlineNotification
|
|
104
|
+
kind="warning"
|
|
105
|
+
lowContrast={true}
|
|
106
|
+
hideCloseButton={true}
|
|
107
|
+
title={t('patientCurrentlyAdmittedToWardLocation', 'Patient currently admitted to {{wardLocation}}', {
|
|
108
|
+
wardLocation: inpatientAdmissions[0].currentInpatientLocation.display,
|
|
109
|
+
})}
|
|
110
|
+
/>
|
|
111
|
+
)}
|
|
112
|
+
{inpatientRequests[0] && (
|
|
113
|
+
<InlineNotification
|
|
114
|
+
kind="warning"
|
|
115
|
+
lowContrast={true}
|
|
116
|
+
hideCloseButton={true}
|
|
117
|
+
title={t(
|
|
118
|
+
'patientHasPendingAdmissionRequest',
|
|
119
|
+
'Patient already has a pending admission request to location {{location}}',
|
|
120
|
+
{
|
|
121
|
+
location: inpatientRequests[0].dispositionLocation.display,
|
|
122
|
+
},
|
|
123
|
+
)}
|
|
124
|
+
/>
|
|
125
|
+
)}
|
|
126
|
+
<AdmitPatientButton
|
|
127
|
+
wardPatient={wardPatient}
|
|
128
|
+
dispositionType={inpatientAdmissions[0] ? 'TRANSFER' : 'ADMIT'}
|
|
129
|
+
onAdmitPatientSuccess={() => closeWorkspaceWithSavedChanges()}
|
|
130
|
+
disabled={isAdmittedToCurrentLocation}
|
|
131
|
+
/>
|
|
132
|
+
</div>
|
|
133
|
+
) : (
|
|
134
|
+
<div>
|
|
135
|
+
{/* TODO: This is a placeholder, and will likely change with ongoing designs with RDE */}
|
|
136
|
+
{t('patienthasNoActiveVisit', 'Patient has no active visit')}
|
|
137
|
+
</div>
|
|
138
|
+
)}
|
|
139
|
+
<Button
|
|
140
|
+
kind="ghost"
|
|
141
|
+
renderIcon={(props) => <ArrowLeftIcon size={24} {...props} />}
|
|
142
|
+
iconDescription={t('backToSearchResults', 'Back to search results')}
|
|
143
|
+
size="sm"
|
|
144
|
+
onClick={() => handleReturnToSearchList?.()}>
|
|
145
|
+
<span>{t('backToSearchResults', 'Back to search results')}</span>
|
|
146
|
+
</Button>
|
|
147
|
+
</div>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
export default CreateAdmissionEncounterWorkspace;
|
package/src/ward-workspace/kenya-emr-patient-discharge/discharge-workspace-siderail.component.tsx
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ActionMenuButton, launchWorkspace } from '@openmrs/esm-framework';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Exit } from '@carbon/react/icons';
|
|
5
|
+
|
|
6
|
+
const DischargeIcon = (props) => <Exit {...props} />;
|
|
7
|
+
|
|
8
|
+
export default function PatientDischargeSideRailIcon() {
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const handler = () => {
|
|
11
|
+
launchWorkspace('patient-care-discharge-workspace');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<ActionMenuButton
|
|
16
|
+
getIcon={DischargeIcon}
|
|
17
|
+
label={t('discharge', 'Discharge')}
|
|
18
|
+
iconDescription={t('discharge', 'Discharge')}
|
|
19
|
+
handler={handler}
|
|
20
|
+
type="ward-patient-discharge"
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type Encounter,
|
|
3
|
+
openmrsFetch,
|
|
4
|
+
type OpenmrsResource,
|
|
5
|
+
restBaseUrl,
|
|
6
|
+
showSnackbar,
|
|
7
|
+
useAppContext,
|
|
8
|
+
useSession,
|
|
9
|
+
type Visit,
|
|
10
|
+
} from '@openmrs/esm-framework';
|
|
11
|
+
import { useTranslation } from 'react-i18next';
|
|
12
|
+
import { type WardPatient } from '../../types';
|
|
13
|
+
|
|
14
|
+
export function removePatientFromBed(bedId: number, patientUuid: string) {
|
|
15
|
+
return openmrsFetch(`${restBaseUrl}/beds/${bedId}?patientUuid=${patientUuid}`, {
|
|
16
|
+
method: 'DELETE',
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const createDischargeEncounterPayload = (
|
|
21
|
+
patientUuid: string,
|
|
22
|
+
encounterType: OpenmrsResource,
|
|
23
|
+
location: OpenmrsResource,
|
|
24
|
+
currentProvider: OpenmrsResource,
|
|
25
|
+
visitUuid: string,
|
|
26
|
+
clinicianEncounterRole: OpenmrsResource,
|
|
27
|
+
) => {
|
|
28
|
+
const encounterPayload = {
|
|
29
|
+
patient: patientUuid,
|
|
30
|
+
encounterType,
|
|
31
|
+
location: location?.uuid,
|
|
32
|
+
encounterProviders: [
|
|
33
|
+
{
|
|
34
|
+
provider: currentProvider?.uuid,
|
|
35
|
+
encounterRole: clinicianEncounterRole?.uuid,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
obs: [],
|
|
39
|
+
visit: visitUuid,
|
|
40
|
+
};
|
|
41
|
+
return encounterPayload;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const createDischargeEncounter = (encounterPayload: any) => {
|
|
45
|
+
return openmrsFetch(`${restBaseUrl}/encounter`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
body: encounterPayload,
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Custom hook for handling patient discharge operations
|
|
54
|
+
*
|
|
55
|
+
* This hook provides functionality to discharge a patient by:
|
|
56
|
+
* 1. Creating a discharge encounter
|
|
57
|
+
* 2. Removing the patient from their bed (if applicable)
|
|
58
|
+
* 3. Updating the ward patient group details
|
|
59
|
+
*
|
|
60
|
+
* @returns {Object} An object containing the handleDischarge function
|
|
61
|
+
* @property {Function} handleDischarge - Function to handle the patient discharge process
|
|
62
|
+
*/
|
|
63
|
+
export const usePatientDischarge = () => {
|
|
64
|
+
const { t } = useTranslation();
|
|
65
|
+
const { wardPatientGroupDetails } =
|
|
66
|
+
useAppContext<{ wardPatientGroupDetails: { mutate: () => void } }>('ward-view-context') ?? {};
|
|
67
|
+
const session = useSession();
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Handles the patient discharge process
|
|
71
|
+
*
|
|
72
|
+
* @param {Encounter} encounter - The current encounter
|
|
73
|
+
* @param {WardPatient} wardPatient - The ward patient information
|
|
74
|
+
* @param {Record<string, unknown>} emrConfiguration - EMR configuration containing encounter types and roles
|
|
75
|
+
* @param {Visit} visit - The current visit
|
|
76
|
+
* @returns {Promise<void>} A promise that resolves when the discharge process is complete
|
|
77
|
+
*/
|
|
78
|
+
const handleDischarge = async (
|
|
79
|
+
encounter: Encounter,
|
|
80
|
+
wardPatient: WardPatient,
|
|
81
|
+
emrConfiguration: Record<string, unknown>,
|
|
82
|
+
visit: Visit,
|
|
83
|
+
) => {
|
|
84
|
+
try {
|
|
85
|
+
const encounterPayload = createDischargeEncounterPayload(
|
|
86
|
+
wardPatient.patient.uuid,
|
|
87
|
+
emrConfiguration.exitFromInpatientEncounterType as OpenmrsResource,
|
|
88
|
+
session?.sessionLocation as OpenmrsResource,
|
|
89
|
+
session?.currentProvider as OpenmrsResource,
|
|
90
|
+
visit.uuid,
|
|
91
|
+
emrConfiguration.clinicianEncounterRole as OpenmrsResource,
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const dischargeResponse = await createDischargeEncounter(encounterPayload);
|
|
95
|
+
|
|
96
|
+
if (!dischargeResponse?.ok) {
|
|
97
|
+
throw new Error('Failed to create discharge encounter');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (wardPatient?.bed?.id) {
|
|
101
|
+
const bedRemovalResponse = await removePatientFromBed(wardPatient.bed.id, wardPatient?.patient?.uuid);
|
|
102
|
+
if (!bedRemovalResponse?.ok) {
|
|
103
|
+
throw new Error('Failed to remove patient from bed');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
showSnackbar({
|
|
108
|
+
title: t('patientWasDischarged', 'Patient was discharged'),
|
|
109
|
+
kind: 'success',
|
|
110
|
+
});
|
|
111
|
+
} catch (err) {
|
|
112
|
+
showSnackbar({
|
|
113
|
+
title: t('errorDischargingPatient', 'Error discharging patient'),
|
|
114
|
+
subtitle: err instanceof Error ? err.message : 'Unknown error occurred',
|
|
115
|
+
kind: 'error',
|
|
116
|
+
});
|
|
117
|
+
} finally {
|
|
118
|
+
wardPatientGroupDetails?.mutate();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
return { handleDischarge };
|
|
123
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { InlineLoading, InlineNotification } from '@carbon/react';
|
|
4
|
+
import {
|
|
5
|
+
type DefaultWorkspaceProps,
|
|
6
|
+
type Encounter,
|
|
7
|
+
ExtensionSlot,
|
|
8
|
+
useEmrConfiguration,
|
|
9
|
+
usePatient,
|
|
10
|
+
} from '@openmrs/esm-framework';
|
|
11
|
+
import { usePatientDischarge } from './patient-discharge.resource';
|
|
12
|
+
import { type WardPatient } from '../../types';
|
|
13
|
+
|
|
14
|
+
type PatientDischargeWorkspaceProps = DefaultWorkspaceProps & {
|
|
15
|
+
readonly patientUuid: string;
|
|
16
|
+
readonly wardPatient: WardPatient;
|
|
17
|
+
readonly formUuid: string;
|
|
18
|
+
readonly dischargePatientOnSuccesfullSubmission?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export function PatientDischargeWorkspace(props: PatientDischargeWorkspaceProps) {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const {
|
|
24
|
+
patientUuid,
|
|
25
|
+
closeWorkspace,
|
|
26
|
+
closeWorkspaceWithSavedChanges,
|
|
27
|
+
wardPatient,
|
|
28
|
+
promptBeforeClosing,
|
|
29
|
+
formUuid,
|
|
30
|
+
dischargePatientOnSuccesfullSubmission = true,
|
|
31
|
+
} = props;
|
|
32
|
+
const { visit: currentVisit } = wardPatient ?? {};
|
|
33
|
+
const { patient, isLoading: isLoadingPatient, error: patientError } = usePatient(patientUuid);
|
|
34
|
+
const { emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } = useEmrConfiguration();
|
|
35
|
+
|
|
36
|
+
const { handleDischarge } = usePatientDischarge();
|
|
37
|
+
|
|
38
|
+
const state = useMemo<Record<string, unknown>>(
|
|
39
|
+
() => ({
|
|
40
|
+
view: 'form',
|
|
41
|
+
formUuid,
|
|
42
|
+
visitUuid: currentVisit?.uuid ?? null,
|
|
43
|
+
visitTypeUuid: currentVisit?.visitType?.uuid ?? null,
|
|
44
|
+
patientUuid: patientUuid ?? null,
|
|
45
|
+
patient,
|
|
46
|
+
encounterUuid: '',
|
|
47
|
+
closeWorkspaceWithSavedChanges,
|
|
48
|
+
closeWorkspace,
|
|
49
|
+
promptBeforeClosing,
|
|
50
|
+
handlePostResponse: (encounter: Encounter) => {
|
|
51
|
+
if (dischargePatientOnSuccesfullSubmission)
|
|
52
|
+
handleDischarge(encounter, wardPatient, emrConfiguration as Record<string, unknown>, currentVisit);
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
[
|
|
56
|
+
patientUuid,
|
|
57
|
+
currentVisit,
|
|
58
|
+
patient,
|
|
59
|
+
closeWorkspace,
|
|
60
|
+
promptBeforeClosing,
|
|
61
|
+
emrConfiguration,
|
|
62
|
+
closeWorkspaceWithSavedChanges,
|
|
63
|
+
handleDischarge,
|
|
64
|
+
dischargePatientOnSuccesfullSubmission,
|
|
65
|
+
formUuid,
|
|
66
|
+
wardPatient,
|
|
67
|
+
],
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const isLoading = isLoadingPatient || isLoadingEmrConfiguration;
|
|
71
|
+
const error = patientError || errorFetchingEmrConfiguration;
|
|
72
|
+
|
|
73
|
+
if (isLoading) {
|
|
74
|
+
return <InlineLoading description={t('loading', 'Loading')} iconDescription={t('loading', 'Loading data...')} />;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (error) {
|
|
78
|
+
return (
|
|
79
|
+
<InlineNotification
|
|
80
|
+
aria-label={t('error', 'Error')}
|
|
81
|
+
kind="error"
|
|
82
|
+
onClose={() => {}}
|
|
83
|
+
onCloseButtonClick={() => {}}
|
|
84
|
+
statusIconDescription="notification"
|
|
85
|
+
subtitle={t('errorLoadingPatientWorkspace', 'Error loading patient workspace {{errorMessage}}', {
|
|
86
|
+
errorMessage: error?.message,
|
|
87
|
+
})}
|
|
88
|
+
title={t('error', 'Error')}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div>
|
|
95
|
+
{/* <pre>{JSON.stringify(currentVisit, null, 2)}</pre> */}
|
|
96
|
+
{patient && <ExtensionSlot name="form-widget-slot" state={state} />}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default PatientDischargeWorkspace;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
2
3
|
import { Button, ButtonSet, InlineNotification } from '@carbon/react';
|
|
3
4
|
import { Exit } from '@carbon/react/icons';
|
|
4
|
-
import {
|
|
5
|
-
import { ExtensionSlot, showSnackbar, useAppContext, useSession } from '@openmrs/esm-framework';
|
|
5
|
+
import { ExtensionSlot, showSnackbar, useAppContext } from '@openmrs/esm-framework';
|
|
6
6
|
import { type WardPatientWorkspaceProps, type WardViewContext } from '../../types';
|
|
7
7
|
import { removePatientFromBed, useCreateEncounter } from '../../ward.resource';
|
|
8
|
-
import useWardLocation from '../../hooks/useWardLocation';
|
|
9
8
|
import WardPatientWorkspaceBanner from '../patient-banner/patient-banner.component';
|
|
10
9
|
import styles from './patient-discharge.scss';
|
|
11
10
|
|
|
@@ -13,8 +12,6 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
|
|
|
13
12
|
const { wardPatient, closeWorkspaceWithSavedChanges } = props;
|
|
14
13
|
const { t } = useTranslation();
|
|
15
14
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
16
|
-
const { currentProvider } = useSession();
|
|
17
|
-
const { location } = useWardLocation();
|
|
18
15
|
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
19
16
|
useCreateEncounter();
|
|
20
17
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
@@ -22,7 +19,7 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
|
|
|
22
19
|
const submitDischarge = useCallback(() => {
|
|
23
20
|
setIsSubmitting(true);
|
|
24
21
|
|
|
25
|
-
createEncounter(wardPatient?.patient, emrConfiguration.exitFromInpatientEncounterType)
|
|
22
|
+
createEncounter(wardPatient?.patient, emrConfiguration.exitFromInpatientEncounterType, wardPatient?.visit.uuid)
|
|
26
23
|
.then((response) => {
|
|
27
24
|
if (response?.ok) {
|
|
28
25
|
if (wardPatient?.bed?.id) {
|
|
@@ -51,17 +48,11 @@ export default function PatientDischargeWorkspace(props: WardPatientWorkspacePro
|
|
|
51
48
|
closeWorkspaceWithSavedChanges();
|
|
52
49
|
wardPatientGroupDetails.mutate();
|
|
53
50
|
});
|
|
54
|
-
}, [
|
|
55
|
-
createEncounter,
|
|
56
|
-
wardPatient?.patient,
|
|
57
|
-
wardPatient.bed.id,
|
|
58
|
-
emrConfiguration,
|
|
59
|
-
t,
|
|
60
|
-
closeWorkspaceWithSavedChanges,
|
|
61
|
-
wardPatientGroupDetails,
|
|
62
|
-
]);
|
|
51
|
+
}, [createEncounter, wardPatient, emrConfiguration, t, closeWorkspaceWithSavedChanges, wardPatientGroupDetails]);
|
|
63
52
|
|
|
64
53
|
if (!wardPatientGroupDetails) return <></>;
|
|
54
|
+
if (!wardPatient?.visit) return <InlineNotification kind="error" title={t('noVisit', 'No visit found')} />;
|
|
55
|
+
|
|
65
56
|
return (
|
|
66
57
|
<div className={styles.workspaceContent}>
|
|
67
58
|
<div className={styles.patientWorkspaceBanner}>
|
|
@@ -1,38 +1,49 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
ButtonSet,
|
|
4
|
+
Form,
|
|
5
|
+
InlineNotification,
|
|
6
|
+
RadioButton,
|
|
7
|
+
RadioButtonGroup,
|
|
8
|
+
Stack,
|
|
9
|
+
TextArea,
|
|
10
|
+
} from '@carbon/react';
|
|
11
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
12
|
+
import { ResponsiveWrapper, showSnackbar, useAppContext } from '@openmrs/esm-framework';
|
|
2
13
|
import classNames from 'classnames';
|
|
3
|
-
import {
|
|
4
|
-
import { Button, ButtonSet, Form, InlineNotification, RadioButton, RadioButtonGroup, TextArea } from '@carbon/react';
|
|
14
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
5
15
|
import { Controller, useForm } from 'react-hook-form';
|
|
6
16
|
import { useTranslation } from 'react-i18next';
|
|
7
|
-
import {
|
|
8
|
-
import { ResponsiveWrapper, showSnackbar, useAppContext, useLayoutType, useSession } from '@openmrs/esm-framework';
|
|
9
|
-
import { useCreateEncounter } from '../../ward.resource';
|
|
10
|
-
import type { ObsPayload, WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
17
|
+
import { z } from 'zod';
|
|
11
18
|
import useWardLocation from '../../hooks/useWardLocation';
|
|
12
|
-
import AdmissionPatientButton from '../admit-patient-button.component';
|
|
13
19
|
import LocationSelector from '../../location-selector/location-selector.component';
|
|
20
|
+
import type { ObsPayload, WardPatientWorkspaceProps, WardViewContext } from '../../types';
|
|
21
|
+
import { useCreateEncounter } from '../../ward.resource';
|
|
14
22
|
import styles from './patient-transfer-swap.scss';
|
|
15
23
|
|
|
16
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Form to fill out for:
|
|
26
|
+
* - an admitted patient without pending transfer request, to initiate a transfer request for a patient
|
|
27
|
+
* - an admitted patient with pending transfer request, to create a request to transfer elsewhere
|
|
28
|
+
* - an un-admitted patient, to create a request to admit
|
|
29
|
+
*/
|
|
30
|
+
export default function PatientAdmitOrTransferForm({
|
|
17
31
|
closeWorkspaceWithSavedChanges,
|
|
18
32
|
wardPatient,
|
|
19
33
|
promptBeforeClosing,
|
|
20
34
|
}: WardPatientWorkspaceProps) {
|
|
21
35
|
const { t } = useTranslation();
|
|
22
|
-
const { patient,
|
|
36
|
+
const { patient, inpatientRequest, visit } = wardPatient ?? {};
|
|
23
37
|
const [showErrorNotifications, setShowErrorNotifications] = useState(false);
|
|
24
38
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
25
39
|
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
26
40
|
useCreateEncounter();
|
|
27
|
-
const { currentProvider } = useSession();
|
|
28
|
-
const { location } = useWardLocation();
|
|
29
41
|
const dispositionsWithTypeTransfer = useMemo(
|
|
30
42
|
() => emrConfiguration?.dispositions.filter(({ type }) => type === 'TRANSFER'),
|
|
31
43
|
[emrConfiguration],
|
|
32
44
|
);
|
|
33
45
|
const { wardPatientGroupDetails } = useAppContext<WardViewContext>('ward-view-context') ?? {};
|
|
34
|
-
const
|
|
35
|
-
const isAdmitted = inpatientAdmission != null;
|
|
46
|
+
const currentAdmission = wardPatientGroupDetails?.inpatientAdmissionsByPatientUuid?.get(patient?.uuid);
|
|
36
47
|
|
|
37
48
|
const zodSchema = useMemo(
|
|
38
49
|
() =>
|
|
@@ -101,7 +112,7 @@ export default function PatientTransferForm({
|
|
|
101
112
|
});
|
|
102
113
|
}
|
|
103
114
|
|
|
104
|
-
createEncounter(patient, emrConfiguration.transferRequestEncounterType, [
|
|
115
|
+
createEncounter(patient, emrConfiguration.transferRequestEncounterType, visit?.uuid, [
|
|
105
116
|
{
|
|
106
117
|
concept: emrConfiguration.dispositionDescriptor.dispositionSetConcept.uuid,
|
|
107
118
|
groupMembers: obs,
|
|
@@ -134,6 +145,7 @@ export default function PatientTransferForm({
|
|
|
134
145
|
patient,
|
|
135
146
|
t,
|
|
136
147
|
wardPatientGroupDetails,
|
|
148
|
+
visit?.uuid,
|
|
137
149
|
],
|
|
138
150
|
);
|
|
139
151
|
|
|
@@ -145,30 +157,11 @@ export default function PatientTransferForm({
|
|
|
145
157
|
if (!wardPatientGroupDetails) {
|
|
146
158
|
return <></>;
|
|
147
159
|
}
|
|
148
|
-
if (!isAdmitted) {
|
|
149
|
-
return (
|
|
150
|
-
<div className={styles.workspaceContent}>
|
|
151
|
-
<div className={styles.formError}>
|
|
152
|
-
<InlineNotification
|
|
153
|
-
kind="info"
|
|
154
|
-
title={t('unableToTransferPatient', 'Unable to transfer patient')}
|
|
155
|
-
subtitle={t(
|
|
156
|
-
'unableToTransferPatientNotYetAdmitted',
|
|
157
|
-
'This patient is not admitted to this ward. Admit this patient before transferring them to a different location.',
|
|
158
|
-
)}
|
|
159
|
-
lowContrast
|
|
160
|
-
hideCloseButton
|
|
161
|
-
/>
|
|
162
|
-
</div>
|
|
163
|
-
<AdmissionPatientButton wardPatient={wardPatient} onAdmitPatientSuccess={closeWorkspaceWithSavedChanges} />
|
|
164
|
-
</div>
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
160
|
return (
|
|
168
161
|
<Form
|
|
169
162
|
onSubmit={handleSubmit(onSubmit, onError)}
|
|
170
163
|
className={classNames(styles.formContainer, styles.workspaceContent)}>
|
|
171
|
-
<
|
|
164
|
+
<Stack gap={4}>
|
|
172
165
|
{errorFetchingEmrConfiguration && (
|
|
173
166
|
<div className={styles.formError}>
|
|
174
167
|
<InlineNotification
|
|
@@ -183,13 +176,39 @@ export default function PatientTransferForm({
|
|
|
183
176
|
/>
|
|
184
177
|
</div>
|
|
185
178
|
)}
|
|
179
|
+
{currentAdmission ? (
|
|
180
|
+
inpatientRequest && (
|
|
181
|
+
<InlineNotification
|
|
182
|
+
kind="info"
|
|
183
|
+
lowContrast={true}
|
|
184
|
+
hideCloseButton={true}
|
|
185
|
+
title={t('patientCurrentlyAdmittedToWardLocation', 'Patient currently admitted to {{wardLocation}}', {
|
|
186
|
+
wardLocation: currentAdmission.currentInpatientLocation.display,
|
|
187
|
+
})}
|
|
188
|
+
/>
|
|
189
|
+
)
|
|
190
|
+
) : (
|
|
191
|
+
<InlineNotification
|
|
192
|
+
kind="info"
|
|
193
|
+
lowContrast={true}
|
|
194
|
+
hideCloseButton={true}
|
|
195
|
+
title={t('patientCurrentlyNotAdmitted', 'Patient currently not admitted')}
|
|
196
|
+
/>
|
|
197
|
+
)}
|
|
186
198
|
<div className={styles.field}>
|
|
187
199
|
<h2 className={styles.productiveHeading02}>{t('selectALocation', 'Select a location')}</h2>
|
|
188
200
|
<Controller
|
|
189
201
|
name="location"
|
|
190
202
|
control={control}
|
|
191
203
|
render={({ field, fieldState: { error } }) => (
|
|
192
|
-
<LocationSelector
|
|
204
|
+
<LocationSelector
|
|
205
|
+
name={field.name}
|
|
206
|
+
field={field}
|
|
207
|
+
invalid={!!error?.message}
|
|
208
|
+
invalidText={error?.message}
|
|
209
|
+
ancestorLocation={visit?.location}
|
|
210
|
+
excludeLocations={currentAdmission ? [currentAdmission.currentInpatientLocation] : []}
|
|
211
|
+
/>
|
|
193
212
|
)}
|
|
194
213
|
/>
|
|
195
214
|
</div>
|
|
@@ -234,7 +253,7 @@ export default function PatientTransferForm({
|
|
|
234
253
|
))}
|
|
235
254
|
</div>
|
|
236
255
|
)}
|
|
237
|
-
</
|
|
256
|
+
</Stack>
|
|
238
257
|
<ButtonSet className={styles.buttonSet}>
|
|
239
258
|
<Button size="xl" kind="secondary" onClick={closeWorkspaceWithSavedChanges}>
|
|
240
259
|
{t('cancel', 'Cancel')}
|
|
@@ -16,7 +16,7 @@ export default function PatientBedSwapForm({
|
|
|
16
16
|
closeWorkspaceWithSavedChanges,
|
|
17
17
|
wardPatient,
|
|
18
18
|
}: WardPatientWorkspaceProps) {
|
|
19
|
-
const { patient } = wardPatient;
|
|
19
|
+
const { patient, visit } = wardPatient;
|
|
20
20
|
const { t } = useTranslation();
|
|
21
21
|
const [showErrorNotifications, setShowErrorNotifications] = useState(false);
|
|
22
22
|
const { createEncounter, emrConfiguration, isLoadingEmrConfiguration, errorFetchingEmrConfiguration } =
|
|
@@ -56,7 +56,7 @@ export default function PatientBedSwapForm({
|
|
|
56
56
|
const bedSelected = beds.find((bed) => bed.bedId === values.bedId);
|
|
57
57
|
setIsSubmitting(true);
|
|
58
58
|
setShowErrorNotifications(false);
|
|
59
|
-
createEncounter(patient, emrConfiguration.bedAssignmentEncounterType)
|
|
59
|
+
createEncounter(patient, emrConfiguration.bedAssignmentEncounterType, visit.uuid)
|
|
60
60
|
.then(async (response) => {
|
|
61
61
|
if (response.ok) {
|
|
62
62
|
if (bedSelected) {
|
|
@@ -110,7 +110,16 @@ export default function PatientBedSwapForm({
|
|
|
110
110
|
closeWorkspaceWithSavedChanges();
|
|
111
111
|
});
|
|
112
112
|
},
|
|
113
|
-
[
|
|
113
|
+
[
|
|
114
|
+
beds,
|
|
115
|
+
createEncounter,
|
|
116
|
+
patient,
|
|
117
|
+
emrConfiguration,
|
|
118
|
+
t,
|
|
119
|
+
wardPatientGroupDetails,
|
|
120
|
+
closeWorkspaceWithSavedChanges,
|
|
121
|
+
visit?.uuid,
|
|
122
|
+
],
|
|
114
123
|
);
|
|
115
124
|
|
|
116
125
|
const onError = useCallback(() => {
|
|
@@ -118,6 +127,7 @@ export default function PatientBedSwapForm({
|
|
|
118
127
|
}, []);
|
|
119
128
|
|
|
120
129
|
if (!wardPatientGroupDetails) return <></>;
|
|
130
|
+
if (!visit) return <InlineNotification kind="error" title={t('noVisit', 'No visit found')} />;
|
|
121
131
|
return (
|
|
122
132
|
<Form
|
|
123
133
|
onSubmit={handleSubmit(onSubmit, onError)}
|