@kenyaemr/esm-bed-management-app 1.0.1-pre.11
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/.editorconfig +12 -0
- package/.eslintignore +2 -0
- package/.eslintrc +37 -0
- package/.husky/pre-commit +4 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/vcs.xml +6 -0
- package/.prettierignore +14 -0
- package/.turbo.json +18 -0
- package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
- package/.yarn/plugins/@yarnpkg/plugin-version.cjs +550 -0
- package/.yarn/versions/3d353a50.yml +0 -0
- package/LICENSE +373 -0
- package/README.md +40 -0
- package/dist/207.js +1 -0
- package/dist/207.js.map +1 -0
- package/dist/26.js +2 -0
- package/dist/26.js.LICENSE.txt +32 -0
- package/dist/26.js.map +1 -0
- package/dist/283.js +1 -0
- package/dist/283.js.map +1 -0
- package/dist/294.js +2 -0
- package/dist/294.js.LICENSE.txt +9 -0
- package/dist/294.js.map +1 -0
- package/dist/330.js +2 -0
- package/dist/330.js.LICENSE.txt +44 -0
- package/dist/330.js.map +1 -0
- package/dist/404.js +1 -0
- package/dist/404.js.map +1 -0
- package/dist/455.js +2 -0
- package/dist/455.js.LICENSE.txt +9 -0
- package/dist/455.js.map +1 -0
- package/dist/558.js +2 -0
- package/dist/558.js.LICENSE.txt +14 -0
- package/dist/558.js.map +1 -0
- package/dist/574.js +1 -0
- package/dist/629.js +1 -0
- package/dist/629.js.map +1 -0
- package/dist/637.js +1 -0
- package/dist/637.js.map +1 -0
- package/dist/707.js +1 -0
- package/dist/707.js.map +1 -0
- package/dist/800.js +2 -0
- package/dist/800.js.LICENSE.txt +3 -0
- package/dist/800.js.map +1 -0
- package/dist/850.js +1 -0
- package/dist/850.js.map +1 -0
- package/dist/884.js +1 -0
- package/dist/884.js.map +1 -0
- package/dist/933.js +1 -0
- package/dist/933.js.map +1 -0
- package/dist/esm-kenyaemr-bed-management-app.js +1 -0
- package/dist/esm-kenyaemr-bed-management-app.js.buildmanifest.json +506 -0
- package/dist/esm-kenyaemr-bed-management-app.js.map +1 -0
- package/dist/main.js +1 -0
- package/dist/main.js.map +1 -0
- package/dist/routes.json +1 -0
- package/i18next-parser.config.js +89 -0
- package/jest.config.js +0 -0
- package/package.json +112 -0
- package/src/__mocks__/react-i18next.js +55 -0
- package/src/admin-card-link.component.tsx +27 -0
- package/src/assets/landing-page.png +0 -0
- package/src/assets/logo.svg +1 -0
- package/src/bed-administration/bed-administration-form.component.tsx +326 -0
- package/src/bed-administration/bed-administration-form.scss +0 -0
- package/src/bed-administration/bed-administration-table.component.tsx +317 -0
- package/src/bed-administration/bed-administration-table.scss +112 -0
- package/src/bed-administration/bed-administration-types.ts +20 -0
- package/src/bed-administration/bed-administration.resource.ts +59 -0
- package/src/bed-administration/edit-bed-form.component.tsx +100 -0
- package/src/bed-administration/new-bed-form.component.tsx +112 -0
- package/src/bed-admission/active-patients/active-patients-table.component.tsx +299 -0
- package/src/bed-admission/active-patients/active-visits.resource.ts +171 -0
- package/src/bed-admission/active-patients/admission-action-button-styles.scss +0 -0
- package/src/bed-admission/active-patients/admission-action-button.component.tsx +26 -0
- package/src/bed-admission/active-patients/index.tsx +15 -0
- package/src/bed-admission/active-patients/patient-queues.resource.ts +136 -0
- package/src/bed-admission/active-patients/styles.scss +284 -0
- package/src/bed-admission/active-patients/view-action-menu.component.tsx +33 -0
- package/src/bed-admission/admitted-patients/active-admissions.resource.ts +125 -0
- package/src/bed-admission/admitted-patients/admitted-patients-table.component.tsx +280 -0
- package/src/bed-admission/admitted-patients/admitted-patients.component.tsx +22 -0
- package/src/bed-admission/admitted-patients/location-combo-box.component.tsx +55 -0
- package/src/bed-admission/admitted-patients/styles.scss +284 -0
- package/src/bed-admission/bed-admission-tabs-styles.scss +30 -0
- package/src/bed-admission/bed-admission-tabs.component.tsx +69 -0
- package/src/bed-admission/bed-admission.component.tsx +15 -0
- package/src/bed-admission/bed-admission.resource.ts +52 -0
- package/src/bed-admission/bed-layout/bed-layout-list.component.tsx +101 -0
- package/src/bed-admission/bed-layout/bed-layout.component.tsx +64 -0
- package/src/bed-admission/bed-layout/bed-layout.scss +118 -0
- package/src/bed-admission/bed-layout/min-bed-layout.component.tsx +26 -0
- package/src/bed-admission/bed-tag/bed-tag-administration-table.component.tsx +217 -0
- package/src/bed-admission/bed-tag/bed-tags-admin-form.component.tsx +131 -0
- package/src/bed-admission/bed-tag/edit-tag-form.component.tsx +80 -0
- package/src/bed-admission/bed-tag/new-tag-form.component.tsx +83 -0
- package/src/bed-admission/bed-type/bed-type-admin-form.component.tsx +173 -0
- package/src/bed-admission/bed-type/bed-type-administration-table.component.tsx +222 -0
- package/src/bed-admission/bed-type/edit-bed-type.component.tsx +80 -0
- package/src/bed-admission/bed-type/new-bed-type-form.component.tsx +87 -0
- package/src/bed-admission/createDashboardLink.tsx +47 -0
- package/src/bed-admission/discharged-patients/discharged-patients.componet.tsx +19 -0
- package/src/bed-admission/helpers/functions.ts +102 -0
- package/src/bed-admission/types.ts +133 -0
- package/src/config-schema.ts +31 -0
- package/src/declarations.d.ts +7 -0
- package/src/empty-state/empty-state.component.tsx +69 -0
- package/src/empty-state/empty-state.scss +62 -0
- package/src/header/header.component.tsx +51 -0
- package/src/header/header.scss +72 -0
- package/src/header/illustration.component.tsx +13 -0
- package/src/home.component.tsx +15 -0
- package/src/home.scss +5 -0
- package/src/index.ts +78 -0
- package/src/left-panel/left-panel.component.tsx +33 -0
- package/src/left-panel/left-panel.scss +41 -0
- package/src/left-panel-link.component.tsx +49 -0
- package/src/root.component.tsx +39 -0
- package/src/root.scss +11 -0
- package/src/routes.json +56 -0
- package/src/setup-tests.ts +1 -0
- package/src/summary/summary.component.tsx +74 -0
- package/src/summary/summary.resource.ts +211 -0
- package/src/summary/summary.scss +72 -0
- package/src/types.ts +163 -0
- package/src/ward-card/ward-card.component.tsx +41 -0
- package/src/ward-card/ward-card.scss +51 -0
- package/src/ward-with-beds/ward-with-beds.component.tsx +186 -0
- package/src/ward-with-beds/ward-with-beds.scss +27 -0
- package/src/workspace/allocate-bed-workspace.component.tsx +188 -0
- package/src/workspace/allocate-bed.scss +124 -0
- package/src/workspace/overlay.component.tsx +55 -0
- package/src/workspace/overlay.scss +96 -0
- package/translations/en.json +7 -0
- package/tsconfig.json +23 -0
- package/webpack.config.js +1 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { showToast, showNotification, useConfig } from "@openmrs/esm-framework";
|
|
4
|
+
|
|
5
|
+
import { editBedType, useBedType } from "../../summary/summary.resource";
|
|
6
|
+
import { BedTypeDataAdministration } from "../../bed-administration/bed-administration-types";
|
|
7
|
+
import { BedTypeData, Mutator } from "../../types";
|
|
8
|
+
import BedTypeAdministrationForm from "./bed-type-admin-form.component";
|
|
9
|
+
|
|
10
|
+
interface EditBedTypeFormProps {
|
|
11
|
+
showModal: boolean;
|
|
12
|
+
onModalChange: (showModal: boolean) => void;
|
|
13
|
+
editData: BedTypeData;
|
|
14
|
+
mutate: Mutator;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const EditBedTypeForm: React.FC<EditBedTypeFormProps> = ({
|
|
18
|
+
showModal,
|
|
19
|
+
onModalChange,
|
|
20
|
+
editData,
|
|
21
|
+
mutate,
|
|
22
|
+
}) => {
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
const headerTitle = t("editBedType", "Edit Bed Type");
|
|
25
|
+
const { bedTypeData } = useBedType();
|
|
26
|
+
const availableBedTypes = bedTypeData ? bedTypeData : [];
|
|
27
|
+
const handleCreateQuestion = useCallback(
|
|
28
|
+
(formData: BedTypeDataAdministration) => {
|
|
29
|
+
const bedUuid = editData.uuid;
|
|
30
|
+
const { name, displayName, description } = formData;
|
|
31
|
+
const bedPayload = {
|
|
32
|
+
name,
|
|
33
|
+
displayName,
|
|
34
|
+
description,
|
|
35
|
+
};
|
|
36
|
+
editBedType({ bedPayload, bedTypeId: bedUuid })
|
|
37
|
+
.then(() => {
|
|
38
|
+
showToast({
|
|
39
|
+
title: t("formSaved", "Bed Type"),
|
|
40
|
+
kind: "success",
|
|
41
|
+
critical: true,
|
|
42
|
+
description:
|
|
43
|
+
bedPayload.name +
|
|
44
|
+
" " +
|
|
45
|
+
t("saveSuccessMessage", "was saved successfully."),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
mutate();
|
|
49
|
+
onModalChange(false);
|
|
50
|
+
})
|
|
51
|
+
.catch((error) => {
|
|
52
|
+
showNotification({
|
|
53
|
+
title: t("errorCreatingForm", "Error creating bed"),
|
|
54
|
+
kind: "error",
|
|
55
|
+
critical: true,
|
|
56
|
+
description: error?.message,
|
|
57
|
+
});
|
|
58
|
+
onModalChange(false);
|
|
59
|
+
});
|
|
60
|
+
onModalChange(false);
|
|
61
|
+
},
|
|
62
|
+
[onModalChange, mutate, editData, t]
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<>
|
|
67
|
+
<BedTypeAdministrationForm
|
|
68
|
+
onModalChange={onModalChange}
|
|
69
|
+
availableBedTypes={availableBedTypes}
|
|
70
|
+
showModal={showModal}
|
|
71
|
+
handleCreateQuestion={handleCreateQuestion}
|
|
72
|
+
headerTitle={headerTitle}
|
|
73
|
+
initialData={editData}
|
|
74
|
+
allLocations={[]}
|
|
75
|
+
/>
|
|
76
|
+
</>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export default EditBedTypeForm;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import React, { useCallback } from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { showToast, showNotification, useConfig } from "@openmrs/esm-framework";
|
|
4
|
+
import type { BedTypeData, Mutator } from "../../types";
|
|
5
|
+
import { useBedType } from "../../bed-administration/bed-administration.resource";
|
|
6
|
+
import { saveBedType, useLocationsByTag } from "../../summary/summary.resource";
|
|
7
|
+
import BedTypeAdministrationForm from "./bed-type-admin-form.component";
|
|
8
|
+
|
|
9
|
+
interface BedTypeFormProps {
|
|
10
|
+
showModal: boolean;
|
|
11
|
+
onModalChange: (showModal: boolean) => void;
|
|
12
|
+
mutate: Mutator;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const NewBedTypeForm: React.FC<BedTypeFormProps> = ({
|
|
16
|
+
showModal,
|
|
17
|
+
onModalChange,
|
|
18
|
+
mutate,
|
|
19
|
+
}) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
const { admissionLocationTagUuid } = useConfig();
|
|
22
|
+
const { data: admissionLocations } = useLocationsByTag(
|
|
23
|
+
admissionLocationTagUuid
|
|
24
|
+
);
|
|
25
|
+
const headerTitle = t("addBedType", "Create Bed type");
|
|
26
|
+
const { bedTypes } = useBedType();
|
|
27
|
+
const availableBedTypes = bedTypes ? bedTypes : [];
|
|
28
|
+
|
|
29
|
+
const initialData: BedTypeData = {
|
|
30
|
+
uuid: "",
|
|
31
|
+
name: "",
|
|
32
|
+
displayName: "",
|
|
33
|
+
description: "",
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const handleCreateQuestion = useCallback(
|
|
37
|
+
(formData: BedTypeData) => {
|
|
38
|
+
const { name, displayName, description } = formData;
|
|
39
|
+
|
|
40
|
+
const bedObject = {
|
|
41
|
+
name,
|
|
42
|
+
displayName,
|
|
43
|
+
description,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
saveBedType({ bedPayload: bedObject })
|
|
47
|
+
.then(() => {
|
|
48
|
+
showToast({
|
|
49
|
+
title: t("formCreated", "Add bed Type"),
|
|
50
|
+
kind: "success",
|
|
51
|
+
critical: true,
|
|
52
|
+
description: `Bed ${name} was created successfully.`,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
mutate();
|
|
56
|
+
onModalChange(false);
|
|
57
|
+
})
|
|
58
|
+
.catch((error) => {
|
|
59
|
+
showNotification({
|
|
60
|
+
title: t("errorCreatingForm", "Error creating bed"),
|
|
61
|
+
kind: "error",
|
|
62
|
+
critical: true,
|
|
63
|
+
description: error?.message,
|
|
64
|
+
});
|
|
65
|
+
onModalChange(false);
|
|
66
|
+
});
|
|
67
|
+
onModalChange(false);
|
|
68
|
+
},
|
|
69
|
+
[onModalChange, mutate, t]
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<>
|
|
74
|
+
<BedTypeAdministrationForm
|
|
75
|
+
onModalChange={onModalChange}
|
|
76
|
+
allLocations={admissionLocations}
|
|
77
|
+
availableBedTypes={availableBedTypes}
|
|
78
|
+
showModal={showModal}
|
|
79
|
+
handleCreateQuestion={handleCreateQuestion}
|
|
80
|
+
headerTitle={headerTitle}
|
|
81
|
+
initialData={initialData}
|
|
82
|
+
/>
|
|
83
|
+
</>
|
|
84
|
+
);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export default NewBedTypeForm;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import last from "lodash-es/last";
|
|
3
|
+
import { BrowserRouter, useLocation } from "react-router-dom";
|
|
4
|
+
import { ConfigurableLink } from "@openmrs/esm-framework";
|
|
5
|
+
|
|
6
|
+
export interface LinkConfig {
|
|
7
|
+
name: string;
|
|
8
|
+
title: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function LinkExtension({ config }: { config: LinkConfig }) {
|
|
12
|
+
const { name, title } = config;
|
|
13
|
+
const location = useLocation();
|
|
14
|
+
|
|
15
|
+
let urlSegment = useMemo(
|
|
16
|
+
() => decodeURIComponent(last(location.pathname.split("/"))),
|
|
17
|
+
[location.pathname]
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const isUUID = (value) => {
|
|
21
|
+
const regex =
|
|
22
|
+
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/;
|
|
23
|
+
return regex.test(value);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
if (isUUID(urlSegment)) {
|
|
27
|
+
urlSegment = "summary";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<ConfigurableLink
|
|
32
|
+
to={`${window.getOpenmrsSpaBase()}home${name ? `/${name}` : ""}`}
|
|
33
|
+
className={`cds--side-nav__link ${
|
|
34
|
+
name === urlSegment && "active-left-nav-link"
|
|
35
|
+
}`}
|
|
36
|
+
>
|
|
37
|
+
{title}
|
|
38
|
+
</ConfigurableLink>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const createDashboardLink = (config: LinkConfig) => () =>
|
|
43
|
+
(
|
|
44
|
+
<BrowserRouter>
|
|
45
|
+
<LinkExtension config={config} />
|
|
46
|
+
</BrowserRouter>
|
|
47
|
+
);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ActivePatientsTable from "../active-patients/active-patients-table.component";
|
|
3
|
+
interface DischargedPatientsListProps {
|
|
4
|
+
status: string;
|
|
5
|
+
setPatientCount: (value: number) => void;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const DischargedPatientsList: React.FC<DischargedPatientsListProps> = ({
|
|
9
|
+
status,
|
|
10
|
+
setPatientCount,
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<ActivePatientsTable status={status} setPatientCount={setPatientCount} />
|
|
15
|
+
</>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default DischargedPatientsList;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { OpenmrsResource } from "@openmrs/esm-framework";
|
|
2
|
+
import last from "lodash-es/last";
|
|
3
|
+
|
|
4
|
+
export type QueuePriority = "Emergency" | "Not Urgent" | "Priority" | "Urgent";
|
|
5
|
+
export type MappedQueuePriority = Omit<QueuePriority, "Urgent">;
|
|
6
|
+
|
|
7
|
+
export const getTagType = (priority: string) => {
|
|
8
|
+
switch (priority as MappedQueuePriority) {
|
|
9
|
+
case "Emergency":
|
|
10
|
+
return "red";
|
|
11
|
+
case "Not Urgent":
|
|
12
|
+
return "green";
|
|
13
|
+
default:
|
|
14
|
+
return "gray";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const buildStatusString = (status: string) => {
|
|
19
|
+
if (!status) {
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
if (status === "pending") {
|
|
23
|
+
return `${status}`;
|
|
24
|
+
} else if (status === "picked") {
|
|
25
|
+
return `Attending`;
|
|
26
|
+
} else if (status === "completed") {
|
|
27
|
+
return `Finished`;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const trimVisitNumber = (visitNumber: string) => {
|
|
32
|
+
if (!visitNumber) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
return visitNumber.substring(15);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const formatWaitTime = (waitTime: string, t) => {
|
|
39
|
+
const num = parseInt(waitTime);
|
|
40
|
+
const hours = num / 60;
|
|
41
|
+
const rhours = Math.floor(hours);
|
|
42
|
+
const minutes = (hours - rhours) * 60;
|
|
43
|
+
const rminutes = Math.round(minutes);
|
|
44
|
+
if (rhours > 0) {
|
|
45
|
+
return (
|
|
46
|
+
rhours +
|
|
47
|
+
" " +
|
|
48
|
+
`${t("hoursAnd", "hours and ")}` +
|
|
49
|
+
rminutes +
|
|
50
|
+
" " +
|
|
51
|
+
`${t("minutes", "minutes")}`
|
|
52
|
+
);
|
|
53
|
+
} else {
|
|
54
|
+
return rminutes + " " + `${t("minutes", "minutes")}`;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const getTagColor = (waitTime: string) => {
|
|
59
|
+
const num = parseInt(waitTime);
|
|
60
|
+
if (num <= 30) {
|
|
61
|
+
return "green";
|
|
62
|
+
} else if (num > 30 && num <= 45) {
|
|
63
|
+
return "orange";
|
|
64
|
+
} else {
|
|
65
|
+
return "red";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const getGender = (gender, t) => {
|
|
70
|
+
switch (gender) {
|
|
71
|
+
case "M":
|
|
72
|
+
return t("male", "Male");
|
|
73
|
+
case "F":
|
|
74
|
+
return t("female", "Female");
|
|
75
|
+
case "O":
|
|
76
|
+
return t("other", "Other");
|
|
77
|
+
case "U":
|
|
78
|
+
return t("unknown", "Unknown");
|
|
79
|
+
default:
|
|
80
|
+
return gender;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export function findObsByConceptUUID(
|
|
85
|
+
arr: Array<OpenmrsResource>,
|
|
86
|
+
ids: Array<string>
|
|
87
|
+
) {
|
|
88
|
+
for (const visit of arr) {
|
|
89
|
+
return visit.obs.filter((o) => {
|
|
90
|
+
return ids.includes(o.concept.uuid);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function timeDiffInMinutes(date1: Date, date2: Date) {
|
|
96
|
+
return Math.round((date1.getTime() - date2.getTime()) / (1000 * 3600 * 24));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const getOriginFromPathName = (pathname = "") => {
|
|
100
|
+
const from = pathname.split("/");
|
|
101
|
+
return last(from);
|
|
102
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
export interface PatientQueueResponse {
|
|
2
|
+
results: Array<PatientQueue>;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface PatientQueue {
|
|
6
|
+
uuid: string;
|
|
7
|
+
creator: {
|
|
8
|
+
uuid: string;
|
|
9
|
+
display: string;
|
|
10
|
+
username: string;
|
|
11
|
+
systemId: string;
|
|
12
|
+
person: UuidDisplay;
|
|
13
|
+
privileges: [];
|
|
14
|
+
roles: Array<UuidDisplay>;
|
|
15
|
+
retired: boolean;
|
|
16
|
+
};
|
|
17
|
+
dateCreated: string;
|
|
18
|
+
changedBy?: string;
|
|
19
|
+
dateChanged?: string;
|
|
20
|
+
voided: boolean;
|
|
21
|
+
dateVoided: string;
|
|
22
|
+
voidedBy: string;
|
|
23
|
+
patient: {
|
|
24
|
+
uuid: string;
|
|
25
|
+
display: string;
|
|
26
|
+
identifiers: Array<UuidDisplay>;
|
|
27
|
+
person: {
|
|
28
|
+
uuid: string;
|
|
29
|
+
display: string;
|
|
30
|
+
gender: string;
|
|
31
|
+
age: number;
|
|
32
|
+
birthdate: string;
|
|
33
|
+
birthdateEstimated: boolean;
|
|
34
|
+
dead: boolean;
|
|
35
|
+
deathDate?: string;
|
|
36
|
+
causeOfDeath?: string;
|
|
37
|
+
preferredName: UuidDisplay;
|
|
38
|
+
preferredAddress: UuidDisplay;
|
|
39
|
+
attributes: [];
|
|
40
|
+
voided: boolean;
|
|
41
|
+
birthtime?: string;
|
|
42
|
+
deathdateEstimated: boolean;
|
|
43
|
+
};
|
|
44
|
+
voided: boolean;
|
|
45
|
+
};
|
|
46
|
+
provider: {
|
|
47
|
+
uuid: string;
|
|
48
|
+
display: string;
|
|
49
|
+
person: UuidDisplay;
|
|
50
|
+
identifier: string;
|
|
51
|
+
attributes: [];
|
|
52
|
+
retired: boolean;
|
|
53
|
+
};
|
|
54
|
+
locationFrom: QueueLocation;
|
|
55
|
+
locationTo: QueueLocation;
|
|
56
|
+
encounter: {
|
|
57
|
+
uuid: string;
|
|
58
|
+
};
|
|
59
|
+
status: string; // TODO add status enum
|
|
60
|
+
priority: number; // TODO add priority enum
|
|
61
|
+
priorityComment: string;
|
|
62
|
+
visitNumber: string;
|
|
63
|
+
comment: string;
|
|
64
|
+
queueRoom: QueueRoom;
|
|
65
|
+
datePicked: string;
|
|
66
|
+
dateCompleted: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface QueueLocation {
|
|
70
|
+
uuid: string;
|
|
71
|
+
display: string;
|
|
72
|
+
name: string;
|
|
73
|
+
description: string;
|
|
74
|
+
address1?: string;
|
|
75
|
+
address2?: string;
|
|
76
|
+
cityVillage?: string;
|
|
77
|
+
stateProvince?: string;
|
|
78
|
+
country: string;
|
|
79
|
+
postalCode?: string;
|
|
80
|
+
latitude?: string;
|
|
81
|
+
longitude?: string;
|
|
82
|
+
countyDistrict?: string;
|
|
83
|
+
address3?: string;
|
|
84
|
+
address4?: string;
|
|
85
|
+
address5?: string;
|
|
86
|
+
address6?: string;
|
|
87
|
+
tags: Array<UuidDisplay>;
|
|
88
|
+
parentLocation: UuidDisplay;
|
|
89
|
+
childLocations: Array<UuidDisplay>;
|
|
90
|
+
retired: boolean;
|
|
91
|
+
attributes: [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface QueueRoom {
|
|
95
|
+
uuid: string;
|
|
96
|
+
display: string;
|
|
97
|
+
name: string;
|
|
98
|
+
description: string;
|
|
99
|
+
address1?: string;
|
|
100
|
+
address2?: string;
|
|
101
|
+
cityVillage?: string;
|
|
102
|
+
stateProvince?: string;
|
|
103
|
+
country?: string;
|
|
104
|
+
postalCode?: string;
|
|
105
|
+
latitude?: string;
|
|
106
|
+
longitude?: string;
|
|
107
|
+
countyDistrict?: string;
|
|
108
|
+
address3?: string;
|
|
109
|
+
address4?: string;
|
|
110
|
+
address5?: string;
|
|
111
|
+
address6?: string;
|
|
112
|
+
tags: Array<UuidDisplay>;
|
|
113
|
+
parentLocation: UuidDisplay;
|
|
114
|
+
childLocations: Array<QueueLocation>;
|
|
115
|
+
retired: boolean;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface UuidDisplay {
|
|
119
|
+
uuid: string;
|
|
120
|
+
display: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface patientDetailsProps {
|
|
124
|
+
name: string;
|
|
125
|
+
patientUuid: string;
|
|
126
|
+
encounter: {
|
|
127
|
+
uuid: string;
|
|
128
|
+
};
|
|
129
|
+
locationUuid: string;
|
|
130
|
+
locationTo: string;
|
|
131
|
+
locationFrom: string;
|
|
132
|
+
queueUuid: string;
|
|
133
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Type } from "@openmrs/esm-framework";
|
|
2
|
+
import { boolean } from "zod";
|
|
3
|
+
|
|
4
|
+
export const configSchema = {
|
|
5
|
+
admissionLocationTagUuid: {
|
|
6
|
+
_type: Type.UUID,
|
|
7
|
+
_description:
|
|
8
|
+
"UUID for the location tag of the `Admission Location`. Patients may only be admitted to inpatient care in a location with this tag",
|
|
9
|
+
_default: "839c65c7-9998-4b90-b80b-39727dfe9fa2",
|
|
10
|
+
},
|
|
11
|
+
inpatientVisitUuid: {
|
|
12
|
+
_type: Type.UUID,
|
|
13
|
+
_description: "UUID for the inpatient visit",
|
|
14
|
+
_default: "a73e2ac6-263b-47fc-99fc-e0f2c09fc914",
|
|
15
|
+
},
|
|
16
|
+
restrictWardAdministrationToLoginLocation: {
|
|
17
|
+
_type: Type.Boolean,
|
|
18
|
+
_description: "UUID for the inpatient visit",
|
|
19
|
+
_default: false,
|
|
20
|
+
},
|
|
21
|
+
admissionEncounterTypeUuid: {
|
|
22
|
+
_type: Type.String,
|
|
23
|
+
_description: "UUID for the encounter type to use for admission",
|
|
24
|
+
_default: "465a92f2-baf8-42e9-9612-53064be868e8",
|
|
25
|
+
},
|
|
26
|
+
admissionFormUuid: {
|
|
27
|
+
_type: Type.String,
|
|
28
|
+
_description: "UUID for the admission form",
|
|
29
|
+
_default: "e958f902-64df-4819-afd4-7fb061f59308",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Layer, Tile } from "@carbon/react";
|
|
3
|
+
import styles from "./empty-state.scss";
|
|
4
|
+
|
|
5
|
+
type EmptyStateProps = {
|
|
6
|
+
msg: string;
|
|
7
|
+
helper: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const EmptyState: React.FC<EmptyStateProps> = ({
|
|
11
|
+
msg,
|
|
12
|
+
helper,
|
|
13
|
+
}: EmptyStateProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<Layer className={styles.layer}>
|
|
16
|
+
<Tile className={styles.tile}>
|
|
17
|
+
<svg width={64} height={64} viewBox="0 0 64 64">
|
|
18
|
+
<title>Empty data illustration</title>
|
|
19
|
+
<g fill="none" fillRule="evenodd">
|
|
20
|
+
<path
|
|
21
|
+
d="M38.133 13.186H21.947c-.768.001-1.39.623-1.39 1.391V50.55l-.186.057-3.97 1.216a.743.743 0 01-.927-.493L3.664 12.751a.742.742 0 01.492-.926l6.118-1.874 17.738-5.43 6.119-1.873a.741.741 0 01.926.492L38.076 13l.057.186z"
|
|
22
|
+
fill="#F4F4F4"
|
|
23
|
+
/>
|
|
24
|
+
<path
|
|
25
|
+
d="M41.664 13L38.026 1.117A1.576 1.576 0 0036.056.07l-8.601 2.633-17.737 5.43-8.603 2.634a1.578 1.578 0 00-1.046 1.97l12.436 40.616a1.58 1.58 0 001.969 1.046l5.897-1.805.185-.057v-.194l-.185.057-5.952 1.822a1.393 1.393 0 01-1.737-.923L.247 12.682a1.39 1.39 0 01.923-1.738L9.772 8.31 27.51 2.881 36.112.247a1.393 1.393 0 011.737.923L41.47 13l.057.186h.193l-.057-.185z"
|
|
26
|
+
fill="#8D8D8D"
|
|
27
|
+
/>
|
|
28
|
+
<path
|
|
29
|
+
d="M11.378 11.855a.836.836 0 01-.798-.59L9.385 7.361a.835.835 0 01.554-1.042l16.318-4.996a.836.836 0 011.042.554l1.195 3.902a.836.836 0 01-.554 1.043l-16.318 4.995a.831.831 0 01-.244.037z"
|
|
30
|
+
fill="#C6C6C6"
|
|
31
|
+
/>
|
|
32
|
+
<circle fill="#C6C6C6" cx={17.636} cy={2.314} r={1.855} />
|
|
33
|
+
<circle
|
|
34
|
+
fill="#FFF"
|
|
35
|
+
fillRule="nonzero"
|
|
36
|
+
cx={17.636}
|
|
37
|
+
cy={2.314}
|
|
38
|
+
r={1.175}
|
|
39
|
+
/>
|
|
40
|
+
<path
|
|
41
|
+
d="M55.893 53.995H24.544a.79.79 0 01-.788-.789V15.644a.79.79 0 01.788-.788h31.349a.79.79 0 01.788.788v37.562a.79.79 0 01-.788.789z"
|
|
42
|
+
fill="#F4F4F4"
|
|
43
|
+
/>
|
|
44
|
+
<path
|
|
45
|
+
d="M41.47 13H21.948a1.579 1.579 0 00-1.576 1.577V52.4l.185-.057V14.577c.001-.768.623-1.39 1.391-1.39h19.581L41.471 13zm17.02 0H21.947a1.579 1.579 0 00-1.576 1.577v42.478c0 .87.706 1.576 1.576 1.577H58.49a1.579 1.579 0 001.576-1.577V14.577a1.579 1.579 0 00-1.576-1.576zm1.39 44.055c0 .768-.622 1.39-1.39 1.392H21.947c-.768-.001-1.39-.624-1.39-1.392V14.577c0-.768.622-1.39 1.39-1.39H58.49c.768 0 1.39.622 1.39 1.39v42.478z"
|
|
46
|
+
fill="#8D8D8D"
|
|
47
|
+
/>
|
|
48
|
+
<path
|
|
49
|
+
d="M48.751 17.082H31.686a.836.836 0 01-.835-.835v-4.081c0-.46.374-.834.835-.835H48.75c.461 0 .834.374.835.835v4.08c0 .462-.374.835-.835.836z"
|
|
50
|
+
fill="#C6C6C6"
|
|
51
|
+
/>
|
|
52
|
+
<circle fill="#C6C6C6" cx={40.218} cy={9.755} r={1.855} />
|
|
53
|
+
<circle
|
|
54
|
+
fill="#FFF"
|
|
55
|
+
fillRule="nonzero"
|
|
56
|
+
cx={40.218}
|
|
57
|
+
cy={9.755}
|
|
58
|
+
r={1.13}
|
|
59
|
+
/>
|
|
60
|
+
</g>
|
|
61
|
+
</svg>
|
|
62
|
+
<p className={styles.content}>{msg}</p>
|
|
63
|
+
<p className={styles.explainer}>{helper}</p>
|
|
64
|
+
</Tile>
|
|
65
|
+
</Layer>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default EmptyState;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
@use '@carbon/colors';
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use "@carbon/type";
|
|
4
|
+
|
|
5
|
+
.desktopHeading {
|
|
6
|
+
h4 {
|
|
7
|
+
@include type.type-style("heading-compact-02");
|
|
8
|
+
color: colors.$gray-70;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.tabletHeading {
|
|
13
|
+
h4 {
|
|
14
|
+
@include type.type-style("heading-03");
|
|
15
|
+
color: colors.$gray-70;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.desktopHeading,
|
|
20
|
+
.tabletHeading {
|
|
21
|
+
text-align: left;
|
|
22
|
+
text-transform: capitalize;
|
|
23
|
+
margin-bottom: layout.$spacing-05;
|
|
24
|
+
|
|
25
|
+
h4:after {
|
|
26
|
+
content: "";
|
|
27
|
+
display: block;
|
|
28
|
+
width: 2rem;
|
|
29
|
+
padding-top: 0.188rem;
|
|
30
|
+
border-bottom: 0.375rem solid var(--brand-03);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.heading:after {
|
|
35
|
+
content: "";
|
|
36
|
+
display: block;
|
|
37
|
+
width: 2rem;
|
|
38
|
+
padding-top: 0.188rem;
|
|
39
|
+
border-bottom: 0.375rem solid var(--brand-03);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.tile {
|
|
43
|
+
padding: 2rem;
|
|
44
|
+
border: 1px solid colors.$gray-20;
|
|
45
|
+
margin: 1.5rem;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.layer {
|
|
49
|
+
text-align: center;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.content {
|
|
53
|
+
@include type.type-style("heading-compact-02");
|
|
54
|
+
color: colors.$gray-70;
|
|
55
|
+
margin-top: layout.$spacing-05;
|
|
56
|
+
margin-bottom: layout.$spacing-03;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.explainer {
|
|
60
|
+
@include type.type-style('body-compact-01');
|
|
61
|
+
color: colors.$gray-70;
|
|
62
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
ConfigurableLink,
|
|
4
|
+
formatDate,
|
|
5
|
+
useSession,
|
|
6
|
+
} from "@openmrs/esm-framework";
|
|
7
|
+
import { useTranslation } from "react-i18next";
|
|
8
|
+
import { Calendar, Location } from "@carbon/react/icons";
|
|
9
|
+
import Illustration from "./illustration.component";
|
|
10
|
+
import styles from "./header.scss";
|
|
11
|
+
|
|
12
|
+
type HeaderProps = {
|
|
13
|
+
route: string;
|
|
14
|
+
headerTitle?: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const Header: React.FC<HeaderProps> = ({
|
|
18
|
+
route,
|
|
19
|
+
headerTitle = "Bed Management",
|
|
20
|
+
}) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const userSession = useSession();
|
|
23
|
+
const userLocation = userSession?.sessionLocation?.display;
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className={styles.header}>
|
|
27
|
+
<div className={styles["left-justified-items"]}>
|
|
28
|
+
<ConfigurableLink to={`${window.getOpenmrsSpaBase()}bed-management`}>
|
|
29
|
+
<Illustration />
|
|
30
|
+
</ConfigurableLink>
|
|
31
|
+
<div className={styles["page-labels"]}>
|
|
32
|
+
<p>{t("headerTitle", headerTitle)}</p>
|
|
33
|
+
<p className={styles["page-name"]}>{route}</p>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div className={styles["right-justified-items"]}>
|
|
37
|
+
<div className={styles["date-and-location"]}>
|
|
38
|
+
<Location size={16} />
|
|
39
|
+
<span className={styles.value}>{userLocation}</span>
|
|
40
|
+
<span className={styles.middot}>·</span>
|
|
41
|
+
<Calendar size={16} />
|
|
42
|
+
<span className={styles.value}>
|
|
43
|
+
{formatDate(new Date(), { mode: "standard" })}
|
|
44
|
+
</span>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export default Header;
|