@openmrs/esm-dispensing-app 1.0.0-pre.21 → 1.0.0-pre.28
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/dist/24.js +1 -2
- package/dist/294.js +1 -2
- package/dist/296.js +1 -0
- package/dist/299.js +1 -0
- package/dist/382.js +2 -0
- package/dist/{680.js.LICENSE.txt → 382.js.LICENSE.txt} +24 -0
- package/dist/573.js +1 -0
- package/dist/574.js +1 -1
- package/dist/595.js +1 -2
- package/dist/781.js +1 -0
- package/dist/906.js +1 -2
- package/dist/978.js +1 -0
- package/dist/openmrs-esm-dispensing-app.js +1 -1
- package/dist/openmrs-esm-dispensing-app.js.buildmanifest.json +114 -70
- package/dist/openmrs-esm-dispensing-app.old +1 -2
- package/package.json +9 -5
- package/src/components/history-and-comments.component.tsx +30 -0
- package/src/components/history-and-comments.scss +26 -0
- package/src/components/medication-card.component.tsx +44 -0
- package/src/components/medication-card.scss +26 -0
- package/src/components/order-expanded.component.tsx +53 -0
- package/src/components/order-expanded.scss +57 -0
- package/src/components/patient-details.component.tsx +106 -0
- package/src/components/patient-details.scss +105 -0
- package/src/components/prescription-details.component.tsx +47 -0
- package/src/components/prescription-details.scss +56 -0
- package/src/constants.ts +3 -0
- package/src/dispensing-link.tsx +13 -0
- package/src/dispensing-tiles/dispensing-tile.component.tsx +45 -0
- package/src/dispensing-tiles/dispensing-tile.scss +39 -0
- package/src/dispensing-tiles/dispensing-tiles.component.tsx +42 -0
- package/src/dispensing-tiles/dispensing-tiles.resource.tsx +33 -0
- package/src/dispensing-tiles/dispensing-tiles.scss +12 -0
- package/src/dispensing.component.tsx +15 -0
- package/src/dispensing.scss +2 -2
- package/src/dispensing.test.tsx +1 -1
- package/src/index.ts +15 -32
- package/src/{medicationrequest/medicationrequest.resource.tsx → medication-request/medication-request.resource.tsx} +32 -3
- package/src/pharmacy-header/pharmacy-header.scss +2 -0
- package/src/pharmacy-header/pharmacy-illustration.component.tsx +22 -14
- package/src/prescriptions/prescription-tab-lists.component.tsx +139 -0
- package/src/prescriptions/prescriptions.scss +131 -0
- package/src/root.scss +51 -0
- package/src/types.ts +185 -0
- package/src/utils.ts +40 -0
- package/translations/en.json +7 -1
- package/dist/132.js +0 -2
- package/dist/132.js.map +0 -1
- package/dist/24.js.map +0 -1
- package/dist/294.js.map +0 -1
- package/dist/595.js.map +0 -1
- package/dist/613.js +0 -2
- package/dist/613.js.map +0 -1
- package/dist/680.js +0 -3
- package/dist/680.js.map +0 -1
- package/dist/70.js +0 -2
- package/dist/70.js.map +0 -1
- package/dist/906.js.map +0 -1
- package/dist/openmrs-esm-dispensing-app.js.map +0 -1
- package/src/dispensing.tsx +0 -64
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PatientUuid } from "@openmrs/esm-framework";
|
|
3
|
+
import { Tab, Tabs } from "carbon-components-react";
|
|
4
|
+
import { useTranslation } from "react-i18next";
|
|
5
|
+
import HistoryAndComments from "./history-and-comments.component";
|
|
6
|
+
import styles from "./order-expanded.scss";
|
|
7
|
+
import PatientDetails from "./patient-details.component";
|
|
8
|
+
import PrescriptionDetails from "./prescription-details.component";
|
|
9
|
+
|
|
10
|
+
interface TabItem {
|
|
11
|
+
name: string;
|
|
12
|
+
component: JSX.Element;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const OrderExpanded: React.FC<{
|
|
16
|
+
encounterUuid: string;
|
|
17
|
+
patientUuid: PatientUuid;
|
|
18
|
+
}> = ({ encounterUuid, patientUuid }) => {
|
|
19
|
+
const { t } = useTranslation();
|
|
20
|
+
|
|
21
|
+
const tabs: TabItem[] = [
|
|
22
|
+
{
|
|
23
|
+
name: t("prescriptionDetails", "Prescription details"),
|
|
24
|
+
component: <PrescriptionDetails encounterUuid={encounterUuid} />,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: t("historyComments", "History and comments"),
|
|
28
|
+
component: <HistoryAndComments />,
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
name: t("patientDetails", "Patient details"),
|
|
32
|
+
component: <PatientDetails patientUuid={patientUuid} />,
|
|
33
|
+
},
|
|
34
|
+
// {
|
|
35
|
+
// name: t("billing", "Billing"),
|
|
36
|
+
// component: <div>Billing</div>,
|
|
37
|
+
// },
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className={styles.expandedContainer}>
|
|
42
|
+
<Tabs className={styles.tabsContainer}>
|
|
43
|
+
{tabs.map((tab: TabItem, index: number) => (
|
|
44
|
+
<Tab key={index} label={tab.name} className={styles.orderTabs}>
|
|
45
|
+
{tab.component}
|
|
46
|
+
</Tab>
|
|
47
|
+
))}
|
|
48
|
+
</Tabs>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default OrderExpanded;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@import 'carbon-components/css/carbon-components.css';
|
|
2
|
+
@import 'carbon-components/scss/globals/scss/typography.scss';
|
|
3
|
+
@import "~@openmrs/esm-styleguide/src/vars";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.prescriptionContainer {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: row;
|
|
9
|
+
width: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:global(.bx--tab-content) {
|
|
13
|
+
width: 100% !important;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
:global(.bx--child-row-inner-container) > div {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: row;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.tabsContainer {
|
|
22
|
+
margin: 1rem 0;
|
|
23
|
+
width: 20%;
|
|
24
|
+
|
|
25
|
+
&:global(.bx--tabs--scrollable .bx--tabs--scrollable__nav-item+.bx--tabs--scrollable__nav-item) {
|
|
26
|
+
margin-left: 0rem !important;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
> ul {
|
|
30
|
+
flex-direction: column !important;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
> ul > li button {
|
|
34
|
+
width: 12rem !important;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
:global(.bx--tabs--scrollable__nav-item--selected) {
|
|
38
|
+
border-bottom: 0px !important;
|
|
39
|
+
border-left: 3px solid var(--brand-03) !important;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.orderTabs {
|
|
44
|
+
flex-direction: row;
|
|
45
|
+
|
|
46
|
+
button {
|
|
47
|
+
border-bottom: 0 !important;
|
|
48
|
+
border-left: 3px solid $ui-03 !important;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
button,
|
|
52
|
+
button:focus,
|
|
53
|
+
button:active {
|
|
54
|
+
outline: 0 !important;
|
|
55
|
+
outline-offset: 0 !important;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React, { useEffect } from "react";
|
|
2
|
+
import {
|
|
3
|
+
attach,
|
|
4
|
+
ConfigurableLink,
|
|
5
|
+
detach,
|
|
6
|
+
ExtensionSlot,
|
|
7
|
+
formatDate,
|
|
8
|
+
interpolateString,
|
|
9
|
+
parseDate,
|
|
10
|
+
PatientUuid,
|
|
11
|
+
useConfig,
|
|
12
|
+
usePatient,
|
|
13
|
+
} from "@openmrs/esm-framework";
|
|
14
|
+
import styles from "./patient-details.scss";
|
|
15
|
+
import { useTranslation } from "react-i18next";
|
|
16
|
+
import { Patient } from "../types";
|
|
17
|
+
|
|
18
|
+
const PatientDetails: React.FC<{
|
|
19
|
+
patientUuid: PatientUuid;
|
|
20
|
+
}> = ({ patientUuid }) => {
|
|
21
|
+
const { t } = useTranslation();
|
|
22
|
+
const config = useConfig();
|
|
23
|
+
const { patient } = usePatient(patientUuid);
|
|
24
|
+
|
|
25
|
+
const patientName = patient;
|
|
26
|
+
const patientPhotoSlotState = React.useMemo(
|
|
27
|
+
() => ({ patientUuid, patientName }),
|
|
28
|
+
[patientUuid, patientName]
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const [showContactDetails, setShowContactDetails] = React.useState(false);
|
|
32
|
+
const toggleContactDetails = React.useCallback((event: MouseEvent) => {
|
|
33
|
+
event.stopPropagation();
|
|
34
|
+
setShowContactDetails((value) => !value);
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const patientAvatar = (
|
|
38
|
+
<div className={styles.patientAvatar} role="img">
|
|
39
|
+
<ExtensionSlot
|
|
40
|
+
extensionSlotName="patient-photo-slot"
|
|
41
|
+
state={patientPhotoSlotState}
|
|
42
|
+
/>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const getGender = (gender) => {
|
|
47
|
+
switch (gender) {
|
|
48
|
+
case "M":
|
|
49
|
+
return t("male", "Male");
|
|
50
|
+
case "F":
|
|
51
|
+
return t("female", "Female");
|
|
52
|
+
case "O":
|
|
53
|
+
return t("other", "Other");
|
|
54
|
+
case "U":
|
|
55
|
+
return t("unknown", "Unknown");
|
|
56
|
+
default:
|
|
57
|
+
return gender;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
attach("dispensing-patient-banner-slot", "patient-banner");
|
|
63
|
+
attach("dispensing-patient-vitals-slot", "vitals-overview-widget");
|
|
64
|
+
attach("dispensing-patient-allergies-slot", "allergies-overview-widget");
|
|
65
|
+
|
|
66
|
+
return () => {
|
|
67
|
+
detach("dispensing-patient-banner-slot", "patient-banner");
|
|
68
|
+
detach("dispensing-patient-vitals-slot", "vitals-overview-widget");
|
|
69
|
+
detach("dispensing-patient-allergies-slot", "allergies-overview-widget");
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div>
|
|
75
|
+
{patient && (
|
|
76
|
+
<div className={styles.patientDetailsContainer}>
|
|
77
|
+
<ExtensionSlot
|
|
78
|
+
extensionSlotName="dispensing-patient-banner-slot"
|
|
79
|
+
state={{
|
|
80
|
+
patient,
|
|
81
|
+
patientUuid: patientUuid,
|
|
82
|
+
}}
|
|
83
|
+
/>
|
|
84
|
+
|
|
85
|
+
<ExtensionSlot
|
|
86
|
+
extensionSlotName="dispensing-patient-vitals-slot"
|
|
87
|
+
state={{
|
|
88
|
+
patient,
|
|
89
|
+
patientUuid: patientUuid,
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
|
|
93
|
+
<ExtensionSlot
|
|
94
|
+
extensionSlotName="dispensing-patient-allergies-slot"
|
|
95
|
+
state={{
|
|
96
|
+
patient,
|
|
97
|
+
patientUuid: patientUuid,
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export default PatientDetails;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
@import 'carbon-components/css/carbon-components.css';
|
|
2
|
+
@import 'carbon-components/scss/globals/scss/typography.scss';
|
|
3
|
+
@import "~@openmrs/esm-styleguide/src/vars";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.patientDetailsContainer > div {
|
|
7
|
+
margin-bottom: 1rem;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
.container {
|
|
17
|
+
border-bottom: 0.063rem solid $ui-03;
|
|
18
|
+
background-color: $ui-02;
|
|
19
|
+
display: grid;
|
|
20
|
+
grid-template-columns: 1fr auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.patientBanner {
|
|
24
|
+
text-decoration: none;
|
|
25
|
+
display: grid;
|
|
26
|
+
grid-template-columns: auto 1fr;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.patientName {
|
|
30
|
+
@include carbon--type-style('productive-heading-03');
|
|
31
|
+
margin-right: 0.25rem;
|
|
32
|
+
color: $text-01;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.patientAvatar {
|
|
36
|
+
width: 5rem;
|
|
37
|
+
height: 5rem;
|
|
38
|
+
margin: 1rem;
|
|
39
|
+
border-radius: 1px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.patientAvatarButton {
|
|
43
|
+
cursor: pointer;
|
|
44
|
+
border: none;
|
|
45
|
+
padding: 0px;
|
|
46
|
+
background: none;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.patientInfo {
|
|
50
|
+
width: 100%;
|
|
51
|
+
padding-right: 1rem;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.demographics {
|
|
55
|
+
@include carbon--type-style('body-short-02');
|
|
56
|
+
color: $text-02;
|
|
57
|
+
margin-top: 0.375rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.row {
|
|
61
|
+
display: flex;
|
|
62
|
+
flex-direction: row;
|
|
63
|
+
justify-content: space-between;
|
|
64
|
+
align-items: flex-start;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.patientNameRow {
|
|
68
|
+
margin-top: $spacing-05;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.flexRow {
|
|
72
|
+
display: flex;
|
|
73
|
+
flex-flow: row wrap;
|
|
74
|
+
align-items: center;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.identifiers {
|
|
78
|
+
@include carbon--type-style('body-short-02');
|
|
79
|
+
color: $ui-04;
|
|
80
|
+
margin-top: 0.375rem;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.tooltipPadding {
|
|
84
|
+
padding: 0.25rem;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tooltipSmallText {
|
|
88
|
+
font-size: 80%;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.actionsButtonText {
|
|
92
|
+
@include carbon--type-style('body-short-01');
|
|
93
|
+
color: $interactive-01;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
:global(.bx--tooltip--definition .bx--tooltip__trigger) {
|
|
97
|
+
border-bottom: none;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.buttonCol {
|
|
101
|
+
display: flex;
|
|
102
|
+
flex-direction: column;
|
|
103
|
+
justify-content: space-between;
|
|
104
|
+
align-items: flex-end;
|
|
105
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { DataTableSkeleton, Tile } from "carbon-components-react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import styles from "./prescription-details.scss";
|
|
4
|
+
import { WarningFilled24 } from "@carbon/icons-react";
|
|
5
|
+
import { useOrderDetails } from "../medication-request/medication-request.resource";
|
|
6
|
+
import { useTranslation } from "react-i18next";
|
|
7
|
+
import MedicationCard from "./medication-card.component";
|
|
8
|
+
|
|
9
|
+
const PrescriptionDetails: React.FC<{ encounterUuid: string }> = ({
|
|
10
|
+
encounterUuid,
|
|
11
|
+
}) => {
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const { medications, isError, isLoading } = useOrderDetails(encounterUuid);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className={styles.prescriptionContainer}>
|
|
17
|
+
<Tile className={styles.allergiesTile}>
|
|
18
|
+
<div className={styles.allergesContent}>
|
|
19
|
+
<div>
|
|
20
|
+
<WarningFilled24 className={styles.allergiesIcon} />
|
|
21
|
+
<p>
|
|
22
|
+
<b>3 allergies</b> Penicillin, Naproxen sodium, Ibuprofen
|
|
23
|
+
</p>
|
|
24
|
+
<a href={`dispensing`} onClick={(e) => e.preventDefault()}>
|
|
25
|
+
View
|
|
26
|
+
</a>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</Tile>
|
|
30
|
+
|
|
31
|
+
<h5
|
|
32
|
+
style={{ paddingTop: "8px", paddingBottom: "8px", fontSize: "0.9rem" }}
|
|
33
|
+
>
|
|
34
|
+
Prescribed
|
|
35
|
+
</h5>
|
|
36
|
+
|
|
37
|
+
{isLoading && <DataTableSkeleton role="progressbar" />}
|
|
38
|
+
{isError && <p>Error</p>}
|
|
39
|
+
{medications &&
|
|
40
|
+
medications.map((medication) => {
|
|
41
|
+
return <MedicationCard medication={medication} />;
|
|
42
|
+
})}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default PrescriptionDetails;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@import 'carbon-components/css/carbon-components.css';
|
|
2
|
+
@import 'carbon-components/scss/globals/scss/typography.scss';
|
|
3
|
+
@import "~@openmrs/esm-styleguide/src/vars";
|
|
4
|
+
|
|
5
|
+
.prescriptionContainer {
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-direction: column;
|
|
8
|
+
width: 100%;
|
|
9
|
+
margin-bottom: 1rem;
|
|
10
|
+
|
|
11
|
+
&:global(.bx--tile) {
|
|
12
|
+
min-height: 3rem !important;
|
|
13
|
+
padding-left: 10px !important;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.prescriptionContainer > :global(.bx--tile) {
|
|
18
|
+
min-height: 3rem !important;
|
|
19
|
+
padding-left: 10px !important;
|
|
20
|
+
margin: auto;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.allergiesTile {
|
|
24
|
+
width: 100%;
|
|
25
|
+
height: 24px;
|
|
26
|
+
padding: 0 8px 0 0;
|
|
27
|
+
border-left: 4px solid #f1c21b;
|
|
28
|
+
background-color: rgba(253, 209, 58, 0.3);
|
|
29
|
+
margin: auto;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.allergesContent {
|
|
33
|
+
margin: auto;
|
|
34
|
+
padding-top: 10px;
|
|
35
|
+
|
|
36
|
+
div {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: row;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
p {
|
|
42
|
+
margin-left: 10px;
|
|
43
|
+
font-size: 0.9rem;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
a {
|
|
47
|
+
margin: auto;
|
|
48
|
+
color: #0f62fe;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
svg.allergiesIcon {
|
|
54
|
+
fill: #f1c21b;
|
|
55
|
+
vertical-align: middle;
|
|
56
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { ConfigurableLink } from "@openmrs/esm-framework";
|
|
3
|
+
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { dispensingBasePath } from "./constants";
|
|
5
|
+
|
|
6
|
+
export default function DispensingLink() {
|
|
7
|
+
const { t } = useTranslation();
|
|
8
|
+
return (
|
|
9
|
+
<ConfigurableLink to={dispensingBasePath}>
|
|
10
|
+
{t("dispensing", "Dispensing")}
|
|
11
|
+
</ConfigurableLink>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { Tile, Button } from "carbon-components-react";
|
|
4
|
+
import ArrowRight16 from "@carbon/icons-react/es/arrow--right/16";
|
|
5
|
+
import styles from "./dispensing-tile.scss";
|
|
6
|
+
|
|
7
|
+
interface DispensingTileProps {
|
|
8
|
+
label: string;
|
|
9
|
+
value: number;
|
|
10
|
+
headerLabel: string;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const DispensingTile: React.FC<DispensingTileProps> = ({
|
|
15
|
+
label,
|
|
16
|
+
value,
|
|
17
|
+
headerLabel,
|
|
18
|
+
children,
|
|
19
|
+
}) => {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Tile className={styles.tileContainer} light={true}>
|
|
24
|
+
<div className={styles.tileHeader}>
|
|
25
|
+
<div className={styles.headerLabelContainer}>
|
|
26
|
+
<label className={styles.headerLabel}>{headerLabel}</label>
|
|
27
|
+
{children}
|
|
28
|
+
</div>
|
|
29
|
+
<Button
|
|
30
|
+
kind="ghost"
|
|
31
|
+
renderIcon={ArrowRight16}
|
|
32
|
+
iconDescription={t("view", "View")}
|
|
33
|
+
>
|
|
34
|
+
{t("view", "View")}
|
|
35
|
+
</Button>
|
|
36
|
+
</div>
|
|
37
|
+
<div>
|
|
38
|
+
<label className={styles.totalsLabel}>{label}</label>
|
|
39
|
+
<p className={styles.totalsValue}>{value}</p>
|
|
40
|
+
</div>
|
|
41
|
+
</Tile>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default DispensingTile;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@import "~@openmrs/esm-styleguide/src/vars";
|
|
2
|
+
@import "~carbon-components/src/globals/scss/vars";
|
|
3
|
+
@import "~carbon-components/src/globals/scss/mixins";
|
|
4
|
+
|
|
5
|
+
.tileContainer {
|
|
6
|
+
border: 0.0625rem solid $ui-03;
|
|
7
|
+
flex-grow: 1;
|
|
8
|
+
height: 7.875rem;
|
|
9
|
+
padding: 0 $spacing-05;
|
|
10
|
+
margin: $spacing-03 $spacing-03;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.tileHeader {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
align-items: center;
|
|
17
|
+
margin-bottom: $spacing-03;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.headerLabel {
|
|
21
|
+
@include carbon--type-style("productive-heading-01");
|
|
22
|
+
color: $text-02;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.totalsLabel {
|
|
26
|
+
@include carbon--type-style("label-01");
|
|
27
|
+
color: $text-02;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.totalsValue {
|
|
31
|
+
@include carbon--type-style("productive-heading-04");
|
|
32
|
+
color: $ui-05;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.headerLabelContainer {
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
height: $spacing-07;
|
|
39
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useTranslation } from "react-i18next";
|
|
3
|
+
import { DataTableSkeleton } from "carbon-components-react";
|
|
4
|
+
import { useMetrics } from "./dispensing-tiles.resource";
|
|
5
|
+
import DispensingTile from "./dispensing-tile.component";
|
|
6
|
+
import styles from "./dispensing-tiles.scss";
|
|
7
|
+
|
|
8
|
+
const DispensingTiles: React.FC = () => {
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const { metrics, isError, isLoading } = useMetrics();
|
|
11
|
+
|
|
12
|
+
if (isLoading) {
|
|
13
|
+
return <DataTableSkeleton role="progressbar" />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<>
|
|
18
|
+
<div className={styles.cardContainer}>
|
|
19
|
+
<DispensingTile
|
|
20
|
+
label={t("orders", "Orders")}
|
|
21
|
+
value={metrics.orders}
|
|
22
|
+
headerLabel={t(
|
|
23
|
+
"prescriptionsToFillToday",
|
|
24
|
+
"Prescriptions to fill today"
|
|
25
|
+
)}
|
|
26
|
+
/>
|
|
27
|
+
<DispensingTile
|
|
28
|
+
label={t("today", "Today")}
|
|
29
|
+
value={metrics.orders_for_home_delivery}
|
|
30
|
+
headerLabel={t("ordersForHomeDelivery", "Orders for home delivery")}
|
|
31
|
+
/>
|
|
32
|
+
<DispensingTile
|
|
33
|
+
label={t("last14Days", "Last 14 days")}
|
|
34
|
+
value={metrics.missed_collections}
|
|
35
|
+
headerLabel={t("missedCollections", "Missed collections")}
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</>
|
|
39
|
+
);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default DispensingTiles;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import useSWR from "swr";
|
|
2
|
+
import useSWRImmutable from "swr/immutable";
|
|
3
|
+
import { FetchResponse, openmrsFetch } from "@openmrs/esm-framework";
|
|
4
|
+
|
|
5
|
+
export function useMetrics() {
|
|
6
|
+
const metrics = {
|
|
7
|
+
orders: 43,
|
|
8
|
+
orders_for_home_delivery: 4,
|
|
9
|
+
missed_collections: 12,
|
|
10
|
+
};
|
|
11
|
+
const { data, error } = useSWR<{ data: { results: {} } }, Error>(
|
|
12
|
+
`/ws/rest/v1/queue?`,
|
|
13
|
+
openmrsFetch
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
metrics: metrics,
|
|
18
|
+
isError: error,
|
|
19
|
+
isLoading: !data && !error,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useServices() {
|
|
24
|
+
const serviceConceptSetUuid = "330c0ec6-0ac7-4b86-9c70-29d76f0ae20a";
|
|
25
|
+
const apiUrl = `/ws/rest/v1/concept/${serviceConceptSetUuid}`;
|
|
26
|
+
const { data } = useSWRImmutable<FetchResponse>(apiUrl, openmrsFetch);
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
services: data
|
|
30
|
+
? data?.data?.setMembers?.map((setMember) => setMember?.display)
|
|
31
|
+
: [],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@import "~@openmrs/esm-styleguide/src/vars";
|
|
2
|
+
@import "~carbon-components/src/globals/scss/vars";
|
|
3
|
+
@import "~carbon-components/src/globals/scss/mixins";
|
|
4
|
+
|
|
5
|
+
.cardContainer {
|
|
6
|
+
background-color: $ui-02 ;
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
padding: 0 $spacing-05 $spacing-10 $spacing-03;
|
|
10
|
+
flex-flow: row wrap;
|
|
11
|
+
margin-top: -$spacing-03;
|
|
12
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import styles from "./dispensing.scss";
|
|
3
|
+
import { PharmacyHeader } from "./pharmacy-header/pharmacy-header.component";
|
|
4
|
+
import DispensingTiles from "./dispensing-tiles/dispensing-tiles.component";
|
|
5
|
+
import PrescriptionTabLists from "./prescriptions/prescription-tab-lists.component";
|
|
6
|
+
|
|
7
|
+
export default function Dispensing() {
|
|
8
|
+
return (
|
|
9
|
+
<div className={`omrs-main-content ${styles.dispensingContainer}`}>
|
|
10
|
+
<PharmacyHeader />
|
|
11
|
+
<DispensingTiles />
|
|
12
|
+
<PrescriptionTabLists />
|
|
13
|
+
</div>
|
|
14
|
+
);
|
|
15
|
+
}
|
package/src/dispensing.scss
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
.
|
|
2
|
-
|
|
1
|
+
.dispensingContainer {
|
|
2
|
+
//
|
|
3
3
|
}
|
package/src/dispensing.test.tsx
CHANGED