@openmrs/esm-dispensing-app 1.5.1-pre.367 → 1.6.0
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/.tx/config +1 -2
- package/dist/204.js +1 -1
- package/dist/204.js.map +1 -1
- package/dist/236.js +1 -0
- package/dist/240.js +1 -0
- package/dist/261.js +1 -0
- package/dist/271.js +1 -1
- package/dist/272.js +1 -0
- package/dist/319.js +1 -0
- package/dist/336.js +1 -0
- package/dist/378.js +1 -0
- package/dist/460.js +1 -0
- package/dist/524.js +2 -0
- package/dist/524.js.map +1 -0
- package/dist/539.js +1 -0
- package/dist/574.js +1 -1
- package/dist/626.js +1 -0
- package/dist/626.js.map +1 -0
- package/dist/637.js +1 -0
- package/dist/637.js.map +1 -0
- package/dist/644.js +1 -0
- package/dist/652.js +1 -0
- package/dist/673.js +1 -0
- package/dist/705.js +1 -0
- package/dist/711.js +1 -0
- package/dist/727.js +1 -0
- package/dist/737.js +1 -0
- package/dist/744.js +1 -0
- package/dist/757.js +1 -1
- package/dist/77.js +1 -0
- package/dist/77.js.map +1 -0
- package/dist/788.js +1 -0
- package/dist/807.js +1 -0
- package/dist/833.js +1 -0
- package/dist/890.js +1 -0
- package/dist/890.js.map +1 -0
- package/dist/899.js +1 -0
- package/dist/905.js +1 -0
- package/dist/905.js.map +1 -0
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-dispensing-app.js +1 -1
- package/dist/openmrs-esm-dispensing-app.js.buildmanifest.json +596 -37
- package/dist/routes.json +1 -1
- package/i18next-parser.config.js +89 -0
- package/package.json +7 -4
- package/src/components/prescription-actions/close-action-button.component.tsx +14 -21
- package/src/components/prescription-actions/dispense-action-button.component.tsx +16 -23
- package/src/components/prescription-actions/pause-action-button.component.tsx +13 -21
- package/src/config-schema.ts +3 -23
- package/src/dashboard/dispensing-dashboard.component.tsx +2 -3
- package/src/dispensing-tiles/dispensing-tiles.component.tsx +1 -1
- package/src/dispensing-tiles/dispensing-tiles.resource.tsx +1 -1
- package/src/dispensing.test.tsx +0 -22
- package/src/forms/{close-dispense-form.component.tsx → close-dispense-form.workspace.tsx} +25 -25
- package/src/forms/{dispense-form.component.tsx → dispense-form.workspace.tsx} +40 -31
- package/src/forms/forms.scss +23 -19
- package/src/forms/{pause-dispense-form.component.tsx → pause-dispense-form.workspace.tsx} +27 -25
- package/src/forms/stock-dispense/stock-dispense.component.tsx +8 -0
- package/src/history/history-and-comments.component.tsx +49 -45
- package/src/index.ts +25 -14
- package/src/location/location.resource.tsx +1 -1
- package/src/medication-dispense/medication-dispense.resource.tsx +2 -2
- package/src/medication-request/medication-request.resource.tsx +2 -2
- package/src/prescriptions/prescription-actions.component.tsx +24 -0
- package/src/prescriptions/prescription-actions.scss +15 -0
- package/src/prescriptions/prescription-details.component.tsx +4 -7
- package/src/print-prescription/prescription-print-action.component.tsx +30 -0
- package/src/print-prescription/prescription-print-preview.modal.tsx +92 -0
- package/src/print-prescription/prescription-printout.component.tsx +128 -0
- package/src/print-prescription/print-prescription.scss +48 -0
- package/src/print-prescription/printable-prescriptions.component.tsx +57 -0
- package/src/routes.json +28 -0
- package/src/types.ts +1 -0
- package/translations/am.json +85 -0
- package/translations/ar.json +85 -0
- package/translations/de.json +85 -0
- package/translations/en.json +26 -43
- package/translations/es.json +85 -0
- package/translations/fr.json +81 -96
- package/translations/he.json +85 -0
- package/translations/hi.json +85 -0
- package/translations/hi_IN.json +85 -0
- package/translations/id.json +85 -0
- package/translations/it.json +85 -0
- package/translations/km.json +85 -0
- package/translations/ne.json +85 -0
- package/translations/pt.json +85 -0
- package/translations/qu.json +85 -0
- package/translations/si.json +85 -0
- package/translations/sw.json +85 -0
- package/translations/sw_KE.json +85 -0
- package/translations/tr.json +85 -0
- package/translations/tr_TR.json +85 -0
- package/translations/uk.json +85 -0
- package/translations/vi.json +85 -0
- package/translations/zh.json +83 -10
- package/translations/zh_CN.json +85 -0
- package/dist/191.js +0 -2
- package/dist/191.js.map +0 -1
- package/dist/829.js +0 -1
- package/dist/829.js.map +0 -1
- package/src/forms/overlay/overlay.component.tsx +0 -47
- package/src/forms/overlay/overlay.scss +0 -93
- package/src/hooks/useOverlay.tsx +0 -46
- /package/dist/{191.js.LICENSE.txt → 524.js.LICENSE.txt} +0 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@use '@carbon/colors';
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use '@carbon/type';
|
|
4
|
+
|
|
5
|
+
.actionsContainer {
|
|
6
|
+
flex-direction: row;
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.actionCluster {
|
|
12
|
+
gap: layout.$spacing-03;
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-direction: row;
|
|
15
|
+
}
|
|
@@ -10,6 +10,7 @@ import { PRIVILEGE_CREATE_DISPENSE } from '../constants';
|
|
|
10
10
|
import { usePatientAllergies, usePrescriptionDetails } from '../medication-request/medication-request.resource';
|
|
11
11
|
import ActionButtons from '../components/action-buttons.component';
|
|
12
12
|
import MedicationEvent from '../components/medication-event.component';
|
|
13
|
+
import PrescriptionsActionsFooter from './prescription-actions.component';
|
|
13
14
|
import styles from './prescription-details.scss';
|
|
14
15
|
|
|
15
16
|
const PrescriptionDetails: React.FC<{
|
|
@@ -20,10 +21,7 @@ const PrescriptionDetails: React.FC<{
|
|
|
20
21
|
const config = useConfig<PharmacyConfig>();
|
|
21
22
|
const [isAllergiesLoading, setAllergiesLoadingStatus] = useState(true);
|
|
22
23
|
const { allergies, totalAllergies } = usePatientAllergies(patientUuid, config.refreshInterval);
|
|
23
|
-
const { medicationRequestBundles,
|
|
24
|
-
encounterUuid,
|
|
25
|
-
config.refreshInterval,
|
|
26
|
-
);
|
|
24
|
+
const { medicationRequestBundles, error, isLoading } = usePrescriptionDetails(encounterUuid, config.refreshInterval);
|
|
27
25
|
|
|
28
26
|
useEffect(() => {
|
|
29
27
|
if (typeof totalAllergies == 'number') {
|
|
@@ -89,11 +87,9 @@ const PrescriptionDetails: React.FC<{
|
|
|
89
87
|
</div>
|
|
90
88
|
</Tile>
|
|
91
89
|
)}
|
|
92
|
-
|
|
93
90
|
<h5 style={{ paddingTop: '8px', paddingBottom: '8px', fontSize: '0.9rem' }}>{t('prescribed', 'Prescribed')}</h5>
|
|
94
|
-
|
|
95
91
|
{isLoading && <DataTableSkeleton role="progressbar" />}
|
|
96
|
-
{
|
|
92
|
+
{error && <p>{t('error', 'Error')}</p>}
|
|
97
93
|
{medicationRequestBundles &&
|
|
98
94
|
medicationRequestBundles.map((bundle) => {
|
|
99
95
|
return (
|
|
@@ -113,6 +109,7 @@ const PrescriptionDetails: React.FC<{
|
|
|
113
109
|
</Tile>
|
|
114
110
|
);
|
|
115
111
|
})}
|
|
112
|
+
<PrescriptionsActionsFooter encounterUuid={encounterUuid} patientUuid={patientUuid} />
|
|
116
113
|
</div>
|
|
117
114
|
);
|
|
118
115
|
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { Button } from '@carbon/react';
|
|
3
|
+
import { Printer } from '@carbon/react/icons';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
import { showModal } from '@openmrs/esm-framework';
|
|
6
|
+
|
|
7
|
+
type PrescriptionPrintActionProps = {
|
|
8
|
+
encounterUuid: string;
|
|
9
|
+
patientUuid: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const PrescriptionPrintAction: React.FC<PrescriptionPrintActionProps> = ({ encounterUuid, patientUuid }) => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
|
|
15
|
+
const handleClick = useCallback(() => {
|
|
16
|
+
const dispose = showModal('prescription-print-preview-modal', {
|
|
17
|
+
onClose: () => dispose(),
|
|
18
|
+
encounterUuid,
|
|
19
|
+
patientUuid,
|
|
20
|
+
});
|
|
21
|
+
}, [encounterUuid, patientUuid]);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Button renderIcon={Printer} iconDescription={t('print', 'Print')} onClick={handleClick} kind="ghost">
|
|
25
|
+
{t('printPrescriptions', 'Print prescriptions')}
|
|
26
|
+
</Button>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default PrescriptionPrintAction;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { useRef, useState } from 'react';
|
|
2
|
+
import { useReactToPrint } from 'react-to-print';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
ButtonSet,
|
|
7
|
+
InlineLoading,
|
|
8
|
+
InlineNotification,
|
|
9
|
+
ModalBody,
|
|
10
|
+
ModalFooter,
|
|
11
|
+
ModalHeader,
|
|
12
|
+
} from '@carbon/react';
|
|
13
|
+
import { ErrorState, getCoreTranslation } from '@openmrs/esm-framework';
|
|
14
|
+
import { usePrescriptionDetails } from '../medication-request/medication-request.resource';
|
|
15
|
+
import PrescriptionsPrintout from './prescription-printout.component';
|
|
16
|
+
import PrintablePrescriptionsSelector from './printable-prescriptions.component';
|
|
17
|
+
import styles from './print-prescription.scss';
|
|
18
|
+
|
|
19
|
+
type PrescriptionPrintPreviewModalProps = {
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
encounterUuid: string;
|
|
22
|
+
patientUuid: string;
|
|
23
|
+
status: string;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const PrescriptionPrintPreviewModal: React.FC<PrescriptionPrintPreviewModalProps> = ({ onClose, encounterUuid }) => {
|
|
27
|
+
const { t } = useTranslation();
|
|
28
|
+
const { medicationRequestBundles, error, isLoading } = usePrescriptionDetails(encounterUuid);
|
|
29
|
+
|
|
30
|
+
const [excludedPrescriptions, setExcludedPrescriptions] = useState<string[]>([]);
|
|
31
|
+
const [printError, setPrintError] = useState<string | null>(null);
|
|
32
|
+
const componentRef = useRef<HTMLDivElement>(null);
|
|
33
|
+
|
|
34
|
+
const handlePrint = useReactToPrint({
|
|
35
|
+
content: () => componentRef.current,
|
|
36
|
+
onBeforeGetContent: () => {
|
|
37
|
+
setPrintError(null);
|
|
38
|
+
},
|
|
39
|
+
onPrintError: (error) => {
|
|
40
|
+
setPrintError(t('printError', 'An error occurred while printing. Please try again.'));
|
|
41
|
+
},
|
|
42
|
+
copyStyles: true,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<ModalHeader closeModal={onClose} className={styles.title}>
|
|
48
|
+
{t('printPrescriptions', 'Print prescriptions')}
|
|
49
|
+
</ModalHeader>
|
|
50
|
+
<ModalBody>
|
|
51
|
+
{isLoading && (
|
|
52
|
+
<InlineLoading
|
|
53
|
+
status="active"
|
|
54
|
+
iconDescription="Loading"
|
|
55
|
+
description={t('loading', 'Loading prescriptions') + '....'}
|
|
56
|
+
/>
|
|
57
|
+
)}
|
|
58
|
+
{error && <ErrorState error={error} headerTitle={t('error', 'Error')} />}
|
|
59
|
+
{!isLoading && medicationRequestBundles?.length > 0 && (
|
|
60
|
+
<div className={styles.printoutSelectorRow}>
|
|
61
|
+
<PrintablePrescriptionsSelector
|
|
62
|
+
medicationRequests={medicationRequestBundles}
|
|
63
|
+
excludedPrescription={excludedPrescriptions}
|
|
64
|
+
onExcludedPrescriptionChange={setExcludedPrescriptions}
|
|
65
|
+
/>
|
|
66
|
+
<div ref={componentRef}>
|
|
67
|
+
<PrescriptionsPrintout
|
|
68
|
+
medicationrequests={medicationRequestBundles}
|
|
69
|
+
excludedPrescription={excludedPrescriptions}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
{printError && (
|
|
75
|
+
<InlineNotification kind="error" title={t('printErrorTitle', 'Print Error')} subtitle={printError} />
|
|
76
|
+
)}
|
|
77
|
+
</ModalBody>
|
|
78
|
+
<ModalFooter>
|
|
79
|
+
<ButtonSet className={styles.btnSet}>
|
|
80
|
+
<Button kind="secondary" onClick={onClose} type="button">
|
|
81
|
+
{getCoreTranslation('cancel', 'Cancel')}
|
|
82
|
+
</Button>
|
|
83
|
+
<Button kind="primary" onClick={handlePrint} type="button" disabled={isLoading}>
|
|
84
|
+
{t('print', 'Print')}
|
|
85
|
+
</Button>
|
|
86
|
+
</ButtonSet>
|
|
87
|
+
</ModalFooter>
|
|
88
|
+
</>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export default PrescriptionPrintPreviewModal;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Layer, StructuredListBody, StructuredListCell, StructuredListRow, StructuredListWrapper } from '@carbon/react';
|
|
5
|
+
import { formatDate, parseDate, useSession } from '@openmrs/esm-framework';
|
|
6
|
+
import { type DosageInstruction, type MedicationRequestBundle, type Quantity } from '../types';
|
|
7
|
+
import {
|
|
8
|
+
getDosageInstruction,
|
|
9
|
+
getMedicationDisplay,
|
|
10
|
+
getMedicationReferenceOrCodeableConcept,
|
|
11
|
+
getQuantity,
|
|
12
|
+
getRefillsAllowed,
|
|
13
|
+
} from '../utils';
|
|
14
|
+
import styles from './print-prescription.scss';
|
|
15
|
+
|
|
16
|
+
type PrescriptionsPrintoutProps = {
|
|
17
|
+
medicationrequests: Array<MedicationRequestBundle>;
|
|
18
|
+
excludedPrescription: Array<string>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const PrescriptionsPrintout: React.FC<PrescriptionsPrintoutProps> = ({ medicationrequests, excludedPrescription }) => {
|
|
22
|
+
const { t } = useTranslation();
|
|
23
|
+
const {
|
|
24
|
+
sessionLocation: { display: facilityName },
|
|
25
|
+
} = useSession();
|
|
26
|
+
const patient = medicationrequests[0]?.request?.subject;
|
|
27
|
+
|
|
28
|
+
const extractPatientName = (display: string) => (display.includes('(') ? display.split('(')[0] : display);
|
|
29
|
+
return (
|
|
30
|
+
<Layer className={styles.printOutContainer}>
|
|
31
|
+
<StructuredListWrapper>
|
|
32
|
+
<StructuredListBody>
|
|
33
|
+
<StructuredListRow head>
|
|
34
|
+
<StructuredListCell head>
|
|
35
|
+
<br />
|
|
36
|
+
<br />
|
|
37
|
+
<p className={styles.printoutTitle}>{t('prescriptionInstructions', 'Prescription instructions')}</p>
|
|
38
|
+
{patient && (
|
|
39
|
+
<p className={classNames(styles.patientName, styles.faintText)}>
|
|
40
|
+
{extractPatientName(patient.display)}
|
|
41
|
+
</p>
|
|
42
|
+
)}
|
|
43
|
+
<br />
|
|
44
|
+
<br />
|
|
45
|
+
</StructuredListCell>
|
|
46
|
+
</StructuredListRow>
|
|
47
|
+
{medicationrequests
|
|
48
|
+
?.filter((req) => !excludedPrescription.includes(req.request.id))
|
|
49
|
+
?.map((request, index) => {
|
|
50
|
+
const medicationEvent = request.request;
|
|
51
|
+
const dosageInstruction: DosageInstruction = getDosageInstruction(medicationEvent.dosageInstruction);
|
|
52
|
+
const quantity: Quantity = getQuantity(medicationEvent);
|
|
53
|
+
const numberOfRefillsAllowed: number = getRefillsAllowed(medicationEvent);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div key={index}>
|
|
57
|
+
{dosageInstruction && (
|
|
58
|
+
<StructuredListRow>
|
|
59
|
+
<StructuredListCell>
|
|
60
|
+
<p>
|
|
61
|
+
<strong>
|
|
62
|
+
{getMedicationDisplay(getMedicationReferenceOrCodeableConcept(medicationEvent))}
|
|
63
|
+
</strong>
|
|
64
|
+
</p>
|
|
65
|
+
<br />
|
|
66
|
+
<p>
|
|
67
|
+
<span className={styles.faintText}>{t('dose', 'Dose')}</span>
|
|
68
|
+
{': '}
|
|
69
|
+
<span>
|
|
70
|
+
{dosageInstruction?.doseAndRate?.map((doseAndRate, index) => {
|
|
71
|
+
return (
|
|
72
|
+
<span key={index}>
|
|
73
|
+
{doseAndRate?.doseQuantity?.value} {doseAndRate?.doseQuantity?.unit}
|
|
74
|
+
</span>
|
|
75
|
+
);
|
|
76
|
+
})}
|
|
77
|
+
</span>{' '}
|
|
78
|
+
— {dosageInstruction?.route?.text} — {dosageInstruction?.timing?.code?.text}
|
|
79
|
+
{dosageInstruction?.timing?.repeat?.duration
|
|
80
|
+
? ` ${t('for', 'for')} ` +
|
|
81
|
+
dosageInstruction?.timing?.repeat?.duration +
|
|
82
|
+
' ' +
|
|
83
|
+
dosageInstruction?.timing?.repeat?.durationUnit
|
|
84
|
+
: ' '}
|
|
85
|
+
{quantity && (
|
|
86
|
+
<p>
|
|
87
|
+
<span className={styles.faintText}>{t('quantity', 'Quantity')}</span>
|
|
88
|
+
{': '}
|
|
89
|
+
<span>
|
|
90
|
+
{quantity.value} {quantity.unit}
|
|
91
|
+
</span>
|
|
92
|
+
</p>
|
|
93
|
+
)}
|
|
94
|
+
</p>
|
|
95
|
+
<p>
|
|
96
|
+
<span className={styles.faintText}>{t('datePrescribed', 'Date prescribed')}</span>
|
|
97
|
+
{': '} <span>{formatDate(parseDate(request.request.authoredOn))}</span>
|
|
98
|
+
</p>
|
|
99
|
+
<p>
|
|
100
|
+
<span className={styles.faintText}>{t('refills', 'Refills')}</span>
|
|
101
|
+
{': '}{' '}
|
|
102
|
+
<span>
|
|
103
|
+
{numberOfRefillsAllowed || numberOfRefillsAllowed === 0
|
|
104
|
+
? numberOfRefillsAllowed
|
|
105
|
+
: t('noRefills', 'No refills')}
|
|
106
|
+
</span>
|
|
107
|
+
</p>
|
|
108
|
+
|
|
109
|
+
{dosageInstruction?.text && <p>{dosageInstruction.text}</p>}
|
|
110
|
+
{dosageInstruction?.additionalInstruction?.length > 0 && (
|
|
111
|
+
<p>
|
|
112
|
+
{dosageInstruction?.additionalInstruction.map((instruction) => instruction.text).join(', ')}
|
|
113
|
+
</p>
|
|
114
|
+
)}
|
|
115
|
+
</StructuredListCell>
|
|
116
|
+
</StructuredListRow>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
})}
|
|
121
|
+
<p className={styles.facilityName}>{facilityName}</p>
|
|
122
|
+
</StructuredListBody>
|
|
123
|
+
</StructuredListWrapper>
|
|
124
|
+
</Layer>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export default PrescriptionsPrintout;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
@use '@carbon/colors';
|
|
2
|
+
@use '@carbon/layout';
|
|
3
|
+
@use '@carbon/type';
|
|
4
|
+
|
|
5
|
+
.title {
|
|
6
|
+
@include type.type-style('heading-02');
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.btnSet {
|
|
10
|
+
width: 100%;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.faintText {
|
|
14
|
+
color: colors.$gray-50;
|
|
15
|
+
@include type.type-style('heading-01');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.printOutContainer {
|
|
19
|
+
background-color: colors.$gray-20;
|
|
20
|
+
padding: layout.$spacing-05;
|
|
21
|
+
width: 20rem;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.printoutTitle {
|
|
25
|
+
@include type.type-style('heading-03');
|
|
26
|
+
text-align: center;
|
|
27
|
+
font-weight: bold;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.facilityName {
|
|
31
|
+
color: colors.$gray-50;
|
|
32
|
+
text-align: end;
|
|
33
|
+
padding: layout.$spacing-05 0 layout.$spacing-05 0;
|
|
34
|
+
@include type.type-style('label-01');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.printoutSelectorRow {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: row;
|
|
40
|
+
gap: layout.$spacing-05;
|
|
41
|
+
padding: 0 layout.$spacing-05 0 layout.$spacing-05;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.patientName {
|
|
46
|
+
text-transform: capitalize;
|
|
47
|
+
text-align: center;
|
|
48
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import { Checkbox } from '@carbon/react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { type DosageInstruction, type MedicationRequestBundle } from '../types';
|
|
5
|
+
import { getDosageInstruction, getMedicationDisplay, getMedicationReferenceOrCodeableConcept } from '../utils';
|
|
6
|
+
|
|
7
|
+
type PrintablePrescriptionsSelectorProps = {
|
|
8
|
+
medicationRequests: Array<MedicationRequestBundle>;
|
|
9
|
+
excludedPrescription: Array<string>;
|
|
10
|
+
onExcludedPrescriptionChange: React.Dispatch<React.SetStateAction<string[]>>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const PrintablePrescriptionsSelector: React.FC<PrintablePrescriptionsSelectorProps> = ({
|
|
14
|
+
medicationRequests,
|
|
15
|
+
onExcludedPrescriptionChange,
|
|
16
|
+
excludedPrescription,
|
|
17
|
+
}) => {
|
|
18
|
+
const { t } = useTranslation();
|
|
19
|
+
|
|
20
|
+
const handleChange = useCallback(
|
|
21
|
+
(checked: boolean, medicationEventId: string) => {
|
|
22
|
+
if (checked) {
|
|
23
|
+
onExcludedPrescriptionChange(excludedPrescription.filter((id) => id !== medicationEventId));
|
|
24
|
+
} else {
|
|
25
|
+
onExcludedPrescriptionChange([...excludedPrescription, medicationEventId]);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
[onExcludedPrescriptionChange, excludedPrescription],
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div>
|
|
33
|
+
<p>
|
|
34
|
+
<strong>{t('selectPrescriptions', 'Check prescriptions to print')}</strong>
|
|
35
|
+
</p>
|
|
36
|
+
{medicationRequests?.map((request) => {
|
|
37
|
+
const medicationEvent = request.request;
|
|
38
|
+
const dosageInstruction: DosageInstruction = getDosageInstruction(medicationEvent.dosageInstruction);
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div key={medicationEvent.id}>
|
|
42
|
+
{dosageInstruction && (
|
|
43
|
+
<Checkbox
|
|
44
|
+
id={medicationEvent.id}
|
|
45
|
+
labelText={getMedicationDisplay(getMedicationReferenceOrCodeableConcept(medicationEvent))}
|
|
46
|
+
checked={!excludedPrescription.includes(medicationEvent.id)}
|
|
47
|
+
onChange={(_, { checked }) => handleChange(checked, medicationEvent.id)}
|
|
48
|
+
/>
|
|
49
|
+
)}
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
})}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export default PrintablePrescriptionsSelector;
|
package/src/routes.json
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.openmrs.org/routes.schema.json",
|
|
2
3
|
"backendDependencies": {
|
|
3
4
|
"fhir2": ">=1.2",
|
|
4
5
|
"webservices.rest": "^2.2.0"
|
|
@@ -50,5 +51,32 @@
|
|
|
50
51
|
"slot": "prescription-action-button-slot",
|
|
51
52
|
"component": "closeActionButton"
|
|
52
53
|
}
|
|
54
|
+
],
|
|
55
|
+
"workspaces": [
|
|
56
|
+
{
|
|
57
|
+
"name": "close-dispense-workspace",
|
|
58
|
+
"component": "closeDispenseWorkspace",
|
|
59
|
+
"type": "dispense",
|
|
60
|
+
"title": "Close prescription"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "pause-dispense-workspace",
|
|
64
|
+
"component": "pauseDispenseWorkspace",
|
|
65
|
+
"type": "dispense",
|
|
66
|
+
"title": "Pause prescription"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "dispense-workspace",
|
|
70
|
+
"component": "dispenseWorkspace",
|
|
71
|
+
"type": "dispense",
|
|
72
|
+
"title": "Dispense prescription",
|
|
73
|
+
"width": "wider"
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"modals": [
|
|
77
|
+
{
|
|
78
|
+
"name": "prescription-print-preview-modal",
|
|
79
|
+
"component": "printPrescriptionPreviewModal"
|
|
80
|
+
}
|
|
53
81
|
]
|
|
54
82
|
}
|
package/src/types.ts
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"activePrescriptions": "Active prescriptions",
|
|
3
|
+
"age": "Age",
|
|
4
|
+
"allergiesCount_one": "{{count}} allergy",
|
|
5
|
+
"allergiesCount_other": "{{count}} allergies",
|
|
6
|
+
"allPrescriptions": "All prescriptions",
|
|
7
|
+
"appName": "Pharmacy",
|
|
8
|
+
"cancel": "Cancel",
|
|
9
|
+
"cancelled": "Cancelled",
|
|
10
|
+
"checkFilters": "Check the filters above",
|
|
11
|
+
"clearSearchInput": "Clear search input",
|
|
12
|
+
"close": "Close",
|
|
13
|
+
"closed": "Closed",
|
|
14
|
+
"closedDispense": "closed dispense",
|
|
15
|
+
"closePrescription": "Close prescription",
|
|
16
|
+
"completed": "Completed",
|
|
17
|
+
"created": "Created",
|
|
18
|
+
"delete": "Delete",
|
|
19
|
+
"dispense": "Dispense",
|
|
20
|
+
"dispensed": "Dispensed",
|
|
21
|
+
"dispenseDate": "Date of Dispense",
|
|
22
|
+
"dispensedBy": "Dispensed by",
|
|
23
|
+
"dispensedMedication": "dispensed medication",
|
|
24
|
+
"dispensePrescription": "Dispense prescription",
|
|
25
|
+
"dispensing": "Dispensing",
|
|
26
|
+
"dispensingAppError": "Dispensing App Error",
|
|
27
|
+
"dispensingAppMisconfigurationMessage": "Please contact your system administration: Misconfiguration - 'restrictTotalQuantityDispensed' cannot be enabled if 'allowModifyingPrescription' is enabled.",
|
|
28
|
+
"dose": "Dose",
|
|
29
|
+
"doseUnit": "Dose unit",
|
|
30
|
+
"drugDispensingUnit": "Dispensing unit",
|
|
31
|
+
"drugs": "Drugs",
|
|
32
|
+
"editCloseeRecord": "Edit Close Record",
|
|
33
|
+
"editDispenseRecord": "Edit Dispense Record",
|
|
34
|
+
"editPauseRecord": "Edit Pause Record",
|
|
35
|
+
"editRecord": "Edit Record",
|
|
36
|
+
"error": "Error",
|
|
37
|
+
"errorLoadingInventoryItems": "Error fetching inventory items",
|
|
38
|
+
"expired": "Expired",
|
|
39
|
+
"filterByLocation": "Filter by location",
|
|
40
|
+
"frequency": "Frequency",
|
|
41
|
+
"historyComments": "History and comments",
|
|
42
|
+
"home": "Home",
|
|
43
|
+
"last14Days": "Last 14 days",
|
|
44
|
+
"lastDispenser": "Last dispenser",
|
|
45
|
+
"loadingInventoryItems": "Loading inventory items...",
|
|
46
|
+
"location": "Location",
|
|
47
|
+
"maxQuantityRemaining": "Maximum quantity remaining:",
|
|
48
|
+
"medicationDispenseActionMenu": "Medication Dispense Action Menu",
|
|
49
|
+
"medicationListUpdated": "Medication dispense list has been updated.",
|
|
50
|
+
"missedCollections": "Missed collections",
|
|
51
|
+
"noAllergyDetailsFound": "No allergy details found",
|
|
52
|
+
"noPrescriptionsToDisplay": "No prescriptions to display",
|
|
53
|
+
"numberIsNotValid": "Number is not valid",
|
|
54
|
+
"ordered": "Ordered",
|
|
55
|
+
"orderedMedication ": "ordered medication",
|
|
56
|
+
"orders": "Orders",
|
|
57
|
+
"ordersForHomeDelivery": "Orders for home delivery",
|
|
58
|
+
"patientInstructions": "Patient instructions",
|
|
59
|
+
"patientName": "Patient name",
|
|
60
|
+
"pause": "Pause",
|
|
61
|
+
"paused": "Paused",
|
|
62
|
+
"pausedDispense": "paused dispense",
|
|
63
|
+
"pausePrescription": "Pause prescription",
|
|
64
|
+
"prescribed": "Prescribed",
|
|
65
|
+
"prescriber": "Prescriber",
|
|
66
|
+
"prescriptionDetails": "Prescription details",
|
|
67
|
+
"prescriptionsToFillToday": "Prescriptions to fill today",
|
|
68
|
+
"quantity": "Quantity",
|
|
69
|
+
"reasonForClose": "Reason for close",
|
|
70
|
+
"reasonForPause": "Reason for pause",
|
|
71
|
+
"refills": "Refills",
|
|
72
|
+
"route": "Route",
|
|
73
|
+
"searchByPatientIdOrName": "Search by patient ID or name",
|
|
74
|
+
"selectStockDispense": "Select stock to dispense from",
|
|
75
|
+
"status": "Status",
|
|
76
|
+
"stockDispense": "Stock Dispense",
|
|
77
|
+
"stockDispensed": "Stock dispensed",
|
|
78
|
+
"stockDispenseDetails": "Batch: {{batchNumber}} - Quantity: {{quantity}} ({{quantityUoM}}) - Expiry: {{expiration}}",
|
|
79
|
+
"stockDispensedSuccessfully": "Stock dispensed successfully and batch level updated.",
|
|
80
|
+
"substitutionReason": "Reason for substitution",
|
|
81
|
+
"substitutionType": "Type of substitution",
|
|
82
|
+
"tabList": "Tab List",
|
|
83
|
+
"today": "Today",
|
|
84
|
+
"view": "View"
|
|
85
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"activePrescriptions": "Active prescriptions",
|
|
3
|
+
"age": "Age",
|
|
4
|
+
"allergiesCount_one": "{{count}} allergy",
|
|
5
|
+
"allergiesCount_other": "{{count}} allergies",
|
|
6
|
+
"allPrescriptions": "All prescriptions",
|
|
7
|
+
"appName": "Pharmacy",
|
|
8
|
+
"cancel": "Cancel",
|
|
9
|
+
"cancelled": "Cancelled",
|
|
10
|
+
"checkFilters": "Check the filters above",
|
|
11
|
+
"clearSearchInput": "Clear search input",
|
|
12
|
+
"close": "Close",
|
|
13
|
+
"closed": "Closed",
|
|
14
|
+
"closedDispense": "closed dispense",
|
|
15
|
+
"closePrescription": "Close prescription",
|
|
16
|
+
"completed": "Completed",
|
|
17
|
+
"created": "Created",
|
|
18
|
+
"delete": "Delete",
|
|
19
|
+
"dispense": "Dispense",
|
|
20
|
+
"dispensed": "Dispensed",
|
|
21
|
+
"dispenseDate": "Date of Dispense",
|
|
22
|
+
"dispensedBy": "Dispensed by",
|
|
23
|
+
"dispensedMedication": "dispensed medication",
|
|
24
|
+
"dispensePrescription": "Dispense prescription",
|
|
25
|
+
"dispensing": "Dispensing",
|
|
26
|
+
"dispensingAppError": "Dispensing App Error",
|
|
27
|
+
"dispensingAppMisconfigurationMessage": "Please contact your system administration: Misconfiguration - 'restrictTotalQuantityDispensed' cannot be enabled if 'allowModifyingPrescription' is enabled.",
|
|
28
|
+
"dose": "Dose",
|
|
29
|
+
"doseUnit": "Dose unit",
|
|
30
|
+
"drugDispensingUnit": "Dispensing unit",
|
|
31
|
+
"drugs": "Drugs",
|
|
32
|
+
"editCloseeRecord": "Edit Close Record",
|
|
33
|
+
"editDispenseRecord": "Edit Dispense Record",
|
|
34
|
+
"editPauseRecord": "Edit Pause Record",
|
|
35
|
+
"editRecord": "Edit Record",
|
|
36
|
+
"error": "Error",
|
|
37
|
+
"errorLoadingInventoryItems": "Error fetching inventory items",
|
|
38
|
+
"expired": "Expired",
|
|
39
|
+
"filterByLocation": "Filter by location",
|
|
40
|
+
"frequency": "Frequency",
|
|
41
|
+
"historyComments": "History and comments",
|
|
42
|
+
"home": "Home",
|
|
43
|
+
"last14Days": "Last 14 days",
|
|
44
|
+
"lastDispenser": "Last dispenser",
|
|
45
|
+
"loadingInventoryItems": "Loading inventory items...",
|
|
46
|
+
"location": "Location",
|
|
47
|
+
"maxQuantityRemaining": "Maximum quantity remaining:",
|
|
48
|
+
"medicationDispenseActionMenu": "Medication Dispense Action Menu",
|
|
49
|
+
"medicationListUpdated": "Medication dispense list has been updated.",
|
|
50
|
+
"missedCollections": "Missed collections",
|
|
51
|
+
"noAllergyDetailsFound": "No allergy details found",
|
|
52
|
+
"noPrescriptionsToDisplay": "No prescriptions to display",
|
|
53
|
+
"numberIsNotValid": "Number is not valid",
|
|
54
|
+
"ordered": "Ordered",
|
|
55
|
+
"orderedMedication ": "ordered medication",
|
|
56
|
+
"orders": "Orders",
|
|
57
|
+
"ordersForHomeDelivery": "Orders for home delivery",
|
|
58
|
+
"patientInstructions": "Patient instructions",
|
|
59
|
+
"patientName": "Patient name",
|
|
60
|
+
"pause": "Pause",
|
|
61
|
+
"paused": "Paused",
|
|
62
|
+
"pausedDispense": "paused dispense",
|
|
63
|
+
"pausePrescription": "Pause prescription",
|
|
64
|
+
"prescribed": "Prescribed",
|
|
65
|
+
"prescriber": "Prescriber",
|
|
66
|
+
"prescriptionDetails": "Prescription details",
|
|
67
|
+
"prescriptionsToFillToday": "Prescriptions to fill today",
|
|
68
|
+
"quantity": "Quantity",
|
|
69
|
+
"reasonForClose": "Reason for close",
|
|
70
|
+
"reasonForPause": "Reason for pause",
|
|
71
|
+
"refills": "Refills",
|
|
72
|
+
"route": "Route",
|
|
73
|
+
"searchByPatientIdOrName": "Search by patient ID or name",
|
|
74
|
+
"selectStockDispense": "Select stock to dispense from",
|
|
75
|
+
"status": "Status",
|
|
76
|
+
"stockDispense": "Stock Dispense",
|
|
77
|
+
"stockDispensed": "Stock dispensed",
|
|
78
|
+
"stockDispenseDetails": "Batch: {{batchNumber}} - Quantity: {{quantity}} ({{quantityUoM}}) - Expiry: {{expiration}}",
|
|
79
|
+
"stockDispensedSuccessfully": "Stock dispensed successfully and batch level updated.",
|
|
80
|
+
"substitutionReason": "Reason for substitution",
|
|
81
|
+
"substitutionType": "Type of substitution",
|
|
82
|
+
"tabList": "Tab List",
|
|
83
|
+
"today": "Today",
|
|
84
|
+
"view": "View"
|
|
85
|
+
}
|