@openmrs/esm-dispensing-app 1.0.1-pre.99 → 1.1.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.
Files changed (86) hide show
  1. package/.eslintrc +3 -1
  2. package/.husky/pre-commit +0 -0
  3. package/.husky/pre-push +0 -0
  4. package/.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs +541 -0
  5. package/.yarn/plugins/@yarnpkg/plugin-version.cjs +550 -0
  6. package/README.md +35 -0
  7. package/jest.config.js +15 -0
  8. package/package.json +13 -10
  9. package/src/components/action-buttons.component.test.tsx +244 -0
  10. package/src/components/action-buttons.component.tsx +137 -0
  11. package/src/components/action-buttons.scss +5 -0
  12. package/src/components/medication-card.component.test.tsx +40 -0
  13. package/src/components/medication-card.component.tsx +10 -17
  14. package/src/components/medication-card.scss +5 -2
  15. package/src/components/medication-dispense-review.scss +9 -0
  16. package/src/components/medication-event.component.tsx +94 -0
  17. package/src/components/{medication-event-card.scss → medication-event.scss} +0 -9
  18. package/src/components/patient-details.component.tsx +4 -27
  19. package/src/components/patient-details.scss +0 -3
  20. package/src/config-schema.ts +141 -2
  21. package/src/constants.ts +24 -0
  22. package/src/dashboard/dispensing-dashboard.component.tsx +38 -0
  23. package/src/declarations.d.tsx +2 -0
  24. package/src/dispensing-tiles/dispensing-tiles.resource.tsx +2 -0
  25. package/src/dispensing.component.tsx +2 -12
  26. package/src/dispensing.test.tsx +1 -1
  27. package/src/forms/close-dispense-form.component.tsx +236 -0
  28. package/src/forms/dispense-form.component.tsx +124 -142
  29. package/src/forms/{dispense-form.scss → forms.scss} +6 -0
  30. package/src/forms/medication-dispense-review.component.test.tsx +142 -0
  31. package/src/forms/medication-dispense-review.component.tsx +562 -0
  32. package/src/forms/overlay/overlay.component.tsx +3 -1
  33. package/src/forms/pause-dispense-form.component.tsx +236 -0
  34. package/src/history/history-and-comments.component.tsx +326 -0
  35. package/src/history/history-and-comments.scss +57 -0
  36. package/src/index.ts +20 -35
  37. package/src/location/location.resource.test.tsx +189 -0
  38. package/src/location/location.resource.tsx +27 -0
  39. package/src/medication/medication.resource.test.tsx +181 -0
  40. package/src/medication/medication.resource.tsx +54 -0
  41. package/src/medication-dispense/medication-dispense.resource.test.tsx +294 -0
  42. package/src/medication-dispense/medication-dispense.resource.tsx +113 -45
  43. package/src/medication-request/medication-request.resource.test.tsx +1389 -0
  44. package/src/medication-request/medication-request.resource.tsx +145 -84
  45. package/src/pharmacy-header/pharmacy-header.component.tsx +5 -3
  46. package/src/pharmacy-header/pharmacy-header.scss +2 -2
  47. package/src/pharmacy-header/pharmacy-illustration.component.tsx +4 -4
  48. package/src/prescriptions/prescription-details.component.tsx +139 -0
  49. package/src/{components → prescriptions}/prescription-details.scss +13 -3
  50. package/src/{components → prescriptions}/prescription-expanded.component.tsx +9 -36
  51. package/src/{components → prescriptions}/prescription-expanded.scss +0 -18
  52. package/src/prescriptions/prescription-tab-lists.component.tsx +64 -18
  53. package/src/prescriptions/prescription-tab-panel.component.tsx +46 -26
  54. package/src/prescriptions/prescriptions.scss +8 -0
  55. package/src/routes.json +30 -0
  56. package/src/types.ts +196 -71
  57. package/src/utils.test.ts +3001 -0
  58. package/src/utils.ts +663 -42
  59. package/translations/en.json +60 -2
  60. package/translations/fr.json +100 -0
  61. package/.github/workflows/node.js.yml +0 -95
  62. package/dist/247.js +0 -1
  63. package/dist/294.js +0 -2
  64. package/dist/294.js.LICENSE.txt +0 -9
  65. package/dist/299.js +0 -1
  66. package/dist/484.js +0 -1
  67. package/dist/574.js +0 -1
  68. package/dist/595.js +0 -2
  69. package/dist/595.js.LICENSE.txt +0 -1
  70. package/dist/781.js +0 -1
  71. package/dist/900.js +0 -2
  72. package/dist/900.js.LICENSE.txt +0 -29
  73. package/dist/935.js +0 -2
  74. package/dist/935.js.LICENSE.txt +0 -19
  75. package/dist/96.js +0 -1
  76. package/dist/main.js +0 -1
  77. package/dist/openmrs-esm-dispensing-app.js +0 -1
  78. package/dist/openmrs-esm-dispensing-app.js.buildmanifest.json +0 -330
  79. package/dist/openmrs-esm-dispensing-app.old +0 -1
  80. package/jest.config.json +0 -18
  81. package/src/components/history-and-comments.component.tsx +0 -117
  82. package/src/components/history-and-comments.scss +0 -30
  83. package/src/components/medication-dispense-review.component.tsx +0 -263
  84. package/src/components/medication-event-card.component.tsx +0 -90
  85. package/src/components/prescription-details.component.tsx +0 -67
  86. package/src/forms/initialize-dispense-form-from-requests.component.tsx +0 -56
package/README.md CHANGED
@@ -5,6 +5,40 @@
5
5
  This repository is for the OpenMRS Dispensing App. For more information, please see the
6
6
  [Design Documentation](https://wiki.openmrs.org/display/projects/Dispensing+Design+Components).
7
7
 
8
+ ## Required Configuration
9
+
10
+ The Dispensing ESM requires the "HL7-MedicationDispenseStatus" concept source and FHIR concept source, as well as "Medication Dispense Status" value/concept set, to be installed in your OpenMRS instance to properly map dispensing statuses.
11
+
12
+ References to the Iniz files that install these concept sources can be found here:
13
+
14
+ https://github.com/openmrs/openmrs-distro-referenceapplication/blob/main/distro/configuration/conceptsources/conceptsources-core_data.csv#L24
15
+
16
+ https://openmrs.slack.com/archives/C02P790SM7X/p1692380047339679?thread_ts=1692338258.965499&cid=C02P790SM7X
17
+
18
+ The Medication Dispense Status value set can be found here:
19
+
20
+ https://app.openconceptlab.org/#/search/?q=medication+dispense+status
21
+
22
+ It also is bundled in the "DrugDispense" OCL package provided by the Reference Application:
23
+
24
+ https://github.com/openmrs/openmrs-distro-referenceapplication/tree/main/distro/configuration/ocl
25
+
26
+ The "DrugDispense" also provides the default value sets for the "Substitution Type", "Substitution Reason", and "Medication Dispense Status Reason".
27
+
28
+ The "Substitution Type" and "Substitution Reason" value sets define the valid answers for both the equivalent questions when substituting a drug. The "Medication Dispense Status Reason" provides the default answers for both the "Reason for Pause" and "Reason for Close" questions.
29
+
30
+ All of these can be customized via the config-schema, see: https://github.com/openmrs/openmrs-esm-dispensing-app/blob/main/src/config-schema.ts
31
+
32
+ ## Required privileges
33
+
34
+ Note that following privileges need to be installed and assigned to roles:
35
+
36
+ * "Task: dispensing.create.dispense" - Allows user to Dispense Medication
37
+ * "Task: dispensing.create.dispense.andModifyDetails" - Allows user to modify the Quantity, Drug, Formulation and Dose Instructions (from the values specified in the Order / Medication Request) when Dispensing
38
+ * "Task: dispensing.edit.dispense" - Allows user to edit an existing Medication Dispense
39
+ * "Task: dispensing.delete.dispense" - Allows user to delete an existing Medication Dispense
40
+ * "Task: dispensing.delete.dispense.ifCreator" - Allows user to delete an existing Medication Dispense, *but only* if they created it originally
41
+
8
42
  ## Running this code
9
43
 
10
44
  ```sh
@@ -30,3 +64,4 @@ For more information, please see the
30
64
 
31
65
  In particular, the [Setup](https://openmrs.github.io/openmrs-esm-core/#/getting_started/setup)
32
66
  section can help you get started developing microfrontends in general.
67
+
package/jest.config.js ADDED
@@ -0,0 +1,15 @@
1
+ module.exports = {
2
+ transform: {
3
+ "^.+\\.tsx?$": "@swc/jest",
4
+ },
5
+ transformIgnorePatterns: ["/node_modules/(?!@openmrs)"],
6
+ moduleNameMapper: {
7
+ "@openmrs/esm-framework": "@openmrs/esm-framework/mock",
8
+ "\\.(s?css)$": "identity-obj-proxy",
9
+ "^lodash-es/(.*)$": "lodash/$1",
10
+ "^uuid$": "<rootDir>/node_modules/uuid/dist/index.js",
11
+ dexie: require.resolve("dexie"),
12
+ },
13
+ setupFilesAfterEnv: ["<rootDir>/src/setup-tests.ts"],
14
+ testEnvironment: "jsdom",
15
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-dispensing-app",
3
- "version": "1.0.1-pre.99",
3
+ "version": "1.1.0",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Medication dispensing application",
6
6
  "browser": "dist/openmrs-esm-dispensing-app.js",
@@ -13,11 +13,11 @@
13
13
  "analyze": "webpack --mode=production --env.analyze=true",
14
14
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\"",
15
15
  "lint": "eslint src --ext js,jsx,ts,tsx",
16
- "test": "jest --config jest.config.json",
16
+ "test": "jest --config jest.config.js",
17
17
  "typescript": "tsc",
18
18
  "verify": "concurrently 'yarn:lint' 'yarn:test' 'yarn:typescript'",
19
19
  "coverage": "yarn test --coverage",
20
- "prepare": "husky install"
20
+ "postinstall": "husky install"
21
21
  },
22
22
  "browserslist": [
23
23
  "extends browserslist-config-openmrs"
@@ -41,17 +41,16 @@
41
41
  "url": "https://github.com/openmrs/openmrs-esm-dispensing/issues"
42
42
  },
43
43
  "dependencies": {
44
- "@carbon/react": "^1.9.0",
44
+ "@carbon/react": "1.12.0",
45
45
  "lodash-es": "^4.17.15",
46
- "swr": "^1.3.0"
46
+ "swr": "^2.1.0"
47
47
  },
48
48
  "peerDependencies": {
49
- "@openmrs/esm-framework": "4.x",
49
+ "@openmrs/esm-framework": "*",
50
50
  "dayjs": "1.x",
51
51
  "react": "18.x",
52
52
  "react-dom": "18.x",
53
53
  "react-i18next": "11.x",
54
- "react-router-dom": "6.x",
55
54
  "rxjs": "6.x"
56
55
  },
57
56
  "devDependencies": {
@@ -70,10 +69,12 @@
70
69
  "@types/webpack-env": "^1.16.0",
71
70
  "@typescript-eslint/parser": "^4.26.0",
72
71
  "concurrently": "^6.2.0",
72
+ "dayjs": "1.x",
73
73
  "eslint": "^7.27.0",
74
74
  "eslint-config-prettier": "^8.3.0",
75
75
  "eslint-config-ts-react-important-stuff": "^3.0.0",
76
76
  "eslint-plugin-prettier": "^3.4.0",
77
+ "eslint-plugin-unused-imports": "^2.0.0",
77
78
  "husky": "^6.0.0",
78
79
  "identity-obj-proxy": "^3.0.0",
79
80
  "jest": "^28.1.2",
@@ -87,6 +88,8 @@
87
88
  "react-i18next": "^11.7.0",
88
89
  "react-router-dom": "^6.3.0",
89
90
  "rxjs": "^6.5.4",
90
- "typescript": "^4.3.2"
91
- }
92
- }
91
+ "typescript": "^4.3.2",
92
+ "webpack": "^5.88.0"
93
+ },
94
+ "packageManager": "yarn@3.6.0"
95
+ }
@@ -0,0 +1,244 @@
1
+ import { render } from "@testing-library/react";
2
+ import React from "react";
3
+ import ActionButtons from "./action-buttons.component";
4
+ import { MedicationRequest, MedicationRequestStatus } from "../types";
5
+ import { useConfig } from "@openmrs/esm-framework";
6
+
7
+ const mockedUseConfig = useConfig as jest.Mock;
8
+ const mockPatientUuid = "558494fe-5850-4b34-a3bf-06550334ba4a";
9
+ const mockEncounterUuid = "7aee7123-9e50-4f72-a636-895d77a63e98";
10
+
11
+ describe("Action Buttons Component tests", () => {
12
+ beforeEach(() => {
13
+ mockedUseConfig.mockReturnValue({
14
+ medicationRequestExpirationPeriodInDays: 90,
15
+ actionButtons: {
16
+ pauseButton: {
17
+ enabled: true,
18
+ },
19
+ closeButton: {
20
+ enabled: true,
21
+ },
22
+ },
23
+ dispenseBehavior: {
24
+ allowModifyingPrescription: false,
25
+ restrictTotalQuantityDispensed: false,
26
+ },
27
+ });
28
+ });
29
+
30
+ test("component should render dispense button if active medication", () => {
31
+ // status = active, and validity period start set to current datetime
32
+ const medicationRequest: MedicationRequest = {
33
+ resourceType: "MedicationRequest",
34
+ id: "d4f69a68-1171-4e47-8693-478df18daf40",
35
+ meta: {
36
+ lastUpdated: "2023-01-24T19:02:04.000-05:00",
37
+ },
38
+ status: MedicationRequestStatus.active,
39
+ intent: "order",
40
+ priority: "routine",
41
+ medicationReference: {
42
+ reference: "Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99",
43
+ type: "Medication",
44
+ display: "Ascorbic acid (Vitamin C), 250mg tablet",
45
+ },
46
+ subject: {
47
+ reference: "Patient/558494fe-5850-4b34-a3bf-06550334ba4a",
48
+ type: "Patient",
49
+ display: "Dylan, Bob (ZL EMR ID: Y2CK2G)",
50
+ },
51
+ encounter: {
52
+ reference: "Encounter/7aee7123-9e50-4f72-a636-895d77a63e98",
53
+ type: "Encounter",
54
+ },
55
+ requester: {
56
+ reference: "Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487",
57
+ type: "Practitioner",
58
+ identifier: {
59
+ value: "MAADH",
60
+ },
61
+ display: "Goodrich, Mark (Identifier: MAADH)",
62
+ },
63
+ dosageInstruction: [
64
+ {
65
+ text: "test",
66
+ timing: {
67
+ repeat: {
68
+ duration: 6,
69
+ durationUnit: "d",
70
+ },
71
+ code: {
72
+ coding: [
73
+ {
74
+ code: "37328251-6759-4270-8a2e-8cab2c0b315b",
75
+ display: "OD (once daily)",
76
+ },
77
+ {
78
+ system: "http://snomed.info/sct",
79
+ code: "229797004",
80
+ display: "OD (once daily)",
81
+ },
82
+ ],
83
+ text: "OD (once daily)",
84
+ },
85
+ },
86
+ asNeededBoolean: false,
87
+ route: {
88
+ coding: [
89
+ {
90
+ code: "46aaaca8-1f21-410a-aac9-67bfcc1fd577",
91
+ display: "Oral",
92
+ },
93
+ {
94
+ system: "http://snomed.info/sct",
95
+ code: "26643006",
96
+ display: "Oral",
97
+ },
98
+ ],
99
+ text: "Oral",
100
+ },
101
+ doseAndRate: [
102
+ {
103
+ doseQuantity: {
104
+ value: 5.0,
105
+ unit: "Ampule(s)",
106
+ system: "http://snomed.info/sct",
107
+ code: "413516001",
108
+ },
109
+ },
110
+ ],
111
+ },
112
+ ],
113
+ dispenseRequest: {
114
+ validityPeriod: {
115
+ start: new Date().toISOString(),
116
+ },
117
+ numberOfRepeatsAllowed: 8,
118
+ quantity: {
119
+ value: 7.0,
120
+ unit: "Application",
121
+ system: "http://snomed.info/sct",
122
+ code: "413568008",
123
+ },
124
+ },
125
+ };
126
+
127
+ const { getByText, container } = render(
128
+ <ActionButtons
129
+ patientUuid={mockPatientUuid}
130
+ encounterUuid={mockEncounterUuid}
131
+ medicationRequestBundle={{ request: medicationRequest, dispenses: [] }}
132
+ />
133
+ );
134
+ expect(getByText("Dispense")).toBeInTheDocument();
135
+ });
136
+
137
+ // status = active, but validity period start time years in the past
138
+ test("component should not render dispense button if expired medication", () => {
139
+ // status = active, and validity period start set to current datetime
140
+ const medicationRequest: MedicationRequest = {
141
+ resourceType: "MedicationRequest",
142
+ id: "d4f69a68-1171-4e47-8693-478df18daf40",
143
+ meta: {
144
+ lastUpdated: "2023-01-24T19:02:04.000-05:00",
145
+ },
146
+ status: MedicationRequestStatus.active,
147
+ intent: "order",
148
+ priority: "routine",
149
+ medicationReference: {
150
+ reference: "Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99",
151
+ type: "Medication",
152
+ display: "Ascorbic acid (Vitamin C), 250mg tablet",
153
+ },
154
+ subject: {
155
+ reference: "Patient/558494fe-5850-4b34-a3bf-06550334ba4a",
156
+ type: "Patient",
157
+ display: "Dylan, Bob (ZL EMR ID: Y2CK2G)",
158
+ },
159
+ encounter: {
160
+ reference: "Encounter/7aee7123-9e50-4f72-a636-895d77a63e98",
161
+ type: "Encounter",
162
+ },
163
+ requester: {
164
+ reference: "Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487",
165
+ type: "Practitioner",
166
+ identifier: {
167
+ value: "MAADH",
168
+ },
169
+ display: "Goodrich, Mark (Identifier: MAADH)",
170
+ },
171
+ dosageInstruction: [
172
+ {
173
+ text: "test",
174
+ timing: {
175
+ repeat: {
176
+ duration: 6,
177
+ durationUnit: "d",
178
+ },
179
+ code: {
180
+ coding: [
181
+ {
182
+ code: "37328251-6759-4270-8a2e-8cab2c0b315b",
183
+ display: "OD (once daily)",
184
+ },
185
+ {
186
+ system: "http://snomed.info/sct",
187
+ code: "229797004",
188
+ display: "OD (once daily)",
189
+ },
190
+ ],
191
+ text: "OD (once daily)",
192
+ },
193
+ },
194
+ asNeededBoolean: false,
195
+ route: {
196
+ coding: [
197
+ {
198
+ code: "46aaaca8-1f21-410a-aac9-67bfcc1fd577",
199
+ display: "Oral",
200
+ },
201
+ {
202
+ system: "http://snomed.info/sct",
203
+ code: "26643006",
204
+ display: "Oral",
205
+ },
206
+ ],
207
+ text: "Oral",
208
+ },
209
+ doseAndRate: [
210
+ {
211
+ doseQuantity: {
212
+ value: 5.0,
213
+ unit: "Ampule(s)",
214
+ system: "http://snomed.info/sct",
215
+ code: "413516001",
216
+ },
217
+ },
218
+ ],
219
+ },
220
+ ],
221
+ dispenseRequest: {
222
+ validityPeriod: {
223
+ start: "2019-01-24T19:02:04.000-05:00",
224
+ },
225
+ numberOfRepeatsAllowed: 8,
226
+ quantity: {
227
+ value: 7.0,
228
+ unit: "Application",
229
+ system: "http://snomed.info/sct",
230
+ code: "413568008",
231
+ },
232
+ },
233
+ };
234
+
235
+ const { queryByText, container } = render(
236
+ <ActionButtons
237
+ patientUuid={mockPatientUuid}
238
+ encounterUuid={mockEncounterUuid}
239
+ medicationRequestBundle={{ request: medicationRequest, dispenses: [] }}
240
+ />
241
+ );
242
+ expect(queryByText("Dispense")).not.toBeInTheDocument();
243
+ });
244
+ });
@@ -0,0 +1,137 @@
1
+ import React from "react";
2
+ import { Button } from "@carbon/react";
3
+ import { useConfig, useSession } from "@openmrs/esm-framework";
4
+ import styles from "./action-buttons.scss";
5
+ import { useTranslation } from "react-i18next";
6
+ import {
7
+ MedicationDispenseStatus,
8
+ MedicationRequestBundle,
9
+ MedicationRequestStatus,
10
+ } from "../types";
11
+ import { PharmacyConfig } from "../config-schema";
12
+ import { launchOverlay } from "../hooks/useOverlay";
13
+ import {
14
+ computeMedicationRequestStatus,
15
+ computeQuantityRemaining,
16
+ getMostRecentMedicationDispenseStatus,
17
+ } from "../utils";
18
+ import DispenseForm from "../forms/dispense-form.component";
19
+ import { initiateMedicationDispenseBody } from "../medication-dispense/medication-dispense.resource";
20
+ import PauseDispenseForm from "../forms/pause-dispense-form.component";
21
+ import CloseDispenseForm from "../forms/close-dispense-form.component";
22
+
23
+ interface ActionButtonsProps {
24
+ medicationRequestBundle: MedicationRequestBundle;
25
+ patientUuid: string;
26
+ encounterUuid: string;
27
+ }
28
+
29
+ const ActionButtons: React.FC<ActionButtonsProps> = ({
30
+ medicationRequestBundle,
31
+ patientUuid,
32
+ encounterUuid,
33
+ }) => {
34
+ const { t } = useTranslation();
35
+ const config = useConfig() as PharmacyConfig;
36
+ const session = useSession();
37
+ const mostRecentMedicationDispenseStatus: MedicationDispenseStatus =
38
+ getMostRecentMedicationDispenseStatus(medicationRequestBundle.dispenses);
39
+ const medicationRequestStatus = computeMedicationRequestStatus(
40
+ medicationRequestBundle.request,
41
+ config.medicationRequestExpirationPeriodInDays
42
+ );
43
+ const dispensable =
44
+ medicationRequestStatus === MedicationRequestStatus.active &&
45
+ mostRecentMedicationDispenseStatus !== MedicationDispenseStatus.declined;
46
+
47
+ const pauseable =
48
+ config.actionButtons.pauseButton.enabled &&
49
+ medicationRequestStatus === MedicationRequestStatus.active &&
50
+ mostRecentMedicationDispenseStatus !== MedicationDispenseStatus.on_hold &&
51
+ mostRecentMedicationDispenseStatus !== MedicationDispenseStatus.declined;
52
+
53
+ const closeable =
54
+ config.actionButtons.closeButton.enabled &&
55
+ medicationRequestStatus === MedicationRequestStatus.active &&
56
+ mostRecentMedicationDispenseStatus !== MedicationDispenseStatus.declined;
57
+
58
+ let quantityRemaining = null;
59
+ if (config.dispenseBehavior.restrictTotalQuantityDispensed) {
60
+ quantityRemaining = computeQuantityRemaining(medicationRequestBundle);
61
+ }
62
+
63
+ return (
64
+ <div className={styles.actionBtns}>
65
+ {dispensable ? (
66
+ <Button
67
+ kind="primary"
68
+ onClick={() =>
69
+ launchOverlay(
70
+ t("dispensePrescription", "Dispense prescription"),
71
+ <DispenseForm
72
+ patientUuid={patientUuid}
73
+ encounterUuid={encounterUuid}
74
+ medicationDispense={initiateMedicationDispenseBody(
75
+ medicationRequestBundle.request,
76
+ session,
77
+ true
78
+ )}
79
+ medicationRequestBundle={medicationRequestBundle}
80
+ quantityRemaining={quantityRemaining}
81
+ mode="enter"
82
+ />
83
+ )
84
+ }
85
+ >
86
+ {t("dispense", "Dispense")}
87
+ </Button>
88
+ ) : null}
89
+ {pauseable ? (
90
+ <Button
91
+ kind="secondary"
92
+ onClick={() =>
93
+ launchOverlay(
94
+ t("pausePrescription", "Pause prescription"),
95
+ <PauseDispenseForm
96
+ patientUuid={patientUuid}
97
+ encounterUuid={encounterUuid}
98
+ medicationDispense={initiateMedicationDispenseBody(
99
+ medicationRequestBundle.request,
100
+ session,
101
+ false
102
+ )}
103
+ mode="enter"
104
+ />
105
+ )
106
+ }
107
+ >
108
+ {t("pause", "Pause")}
109
+ </Button>
110
+ ) : null}
111
+ {closeable ? (
112
+ <Button
113
+ kind="danger"
114
+ onClick={() =>
115
+ launchOverlay(
116
+ t("closePrescription", "Close prescription"),
117
+ <CloseDispenseForm
118
+ patientUuid={patientUuid}
119
+ encounterUuid={encounterUuid}
120
+ medicationDispense={initiateMedicationDispenseBody(
121
+ medicationRequestBundle.request,
122
+ session,
123
+ false
124
+ )}
125
+ mode="enter"
126
+ />
127
+ )
128
+ }
129
+ >
130
+ {t("close", "Close")}
131
+ </Button>
132
+ ) : null}
133
+ </div>
134
+ );
135
+ };
136
+
137
+ export default ActionButtons;
@@ -0,0 +1,5 @@
1
+ .actionBtns {
2
+ float: right;
3
+ margin-left: 1rem;
4
+ margin-top: 2rem;
5
+ }
@@ -0,0 +1,40 @@
1
+ import { render } from "@testing-library/react";
2
+ import React from "react";
3
+ import { MedicationReferenceOrCodeableConcept } from "../types";
4
+ import MedicationCard from "./medication-card.component";
5
+
6
+ describe("Medication Card Component tests", () => {
7
+ test("component should render medication card without edit action button", () => {
8
+ const medication: MedicationReferenceOrCodeableConcept = {
9
+ medicationReference: {
10
+ display: "Some Medication",
11
+ reference: "",
12
+ type: "",
13
+ },
14
+ };
15
+
16
+ const { getByText, container } = render(
17
+ <MedicationCard medication={medication} />
18
+ );
19
+ expect(getByText("Some Medication")).toBeInTheDocument();
20
+ expect(container.querySelector("svg")).not.toBeInTheDocument();
21
+ });
22
+
23
+ test("component should render medication card with edit action button", () => {
24
+ const medication: MedicationReferenceOrCodeableConcept = {
25
+ medicationReference: {
26
+ display: "Some Medication",
27
+ reference: "",
28
+ type: "",
29
+ },
30
+ };
31
+
32
+ const action = () => 0;
33
+
34
+ const { getByText, container } = render(
35
+ <MedicationCard medication={medication} editAction={action} />
36
+ );
37
+ expect(getByText("Some Medication")).toBeInTheDocument();
38
+ expect(container.querySelector("svg")).toBeInTheDocument();
39
+ });
40
+ });
@@ -1,27 +1,20 @@
1
1
  import React from "react";
2
2
  import { Tile } from "@carbon/react";
3
- import { Medication } from "../types";
3
+ import { Edit } from "@carbon/react/icons";
4
+ import { MedicationReferenceOrCodeableConcept } from "../types";
4
5
  import styles from "./medication-card.scss";
5
- import { useTranslation } from "react-i18next";
6
-
7
- // TODO this will probably need a fair amount of updates to allow editing
6
+ import { getMedicationDisplay } from "../utils";
8
7
 
9
8
  const MedicationCard: React.FC<{
10
- medication: Medication;
11
- }> = ({ medication }) => {
12
- const { t } = useTranslation();
13
-
9
+ medication: MedicationReferenceOrCodeableConcept;
10
+ editAction?: Function;
11
+ }> = ({ medication, editAction }) => {
14
12
  return (
15
13
  <Tile className={styles.medicationTile}>
16
- <div>
17
- <p className={styles.medicationName}>
18
- <strong>
19
- {medication.medicationReference
20
- ? medication.medicationReference.display
21
- : medication?.medicationCodeableConcept.text}
22
- </strong>
23
- </p>
24
- </div>
14
+ <p className={styles.medicationName}>
15
+ <strong>{getMedicationDisplay(medication)}</strong>
16
+ </p>
17
+ {editAction && <Edit onClick={editAction} />}
25
18
  </Tile>
26
19
  );
27
20
  };
@@ -3,11 +3,14 @@
3
3
  @import "~@openmrs/esm-styleguide/src/vars";
4
4
 
5
5
  .medicationTile {
6
+ display: flex;
7
+ flex-direction: row;
8
+ justify-content: space-between;
6
9
  width: 100%;
7
10
  margin: 2px 0 8px;
8
- padding: 0 48px 0 8px;
11
+ padding: 0 8px 0 8px;
9
12
  background-color: #fff;
10
- border-left: 4px solid #007d79;
13
+ border-left: 4px solid var(--brand-03);
11
14
  color: $text-02;
12
15
  margin-bottom: 1rem !important;
13
16
  }
@@ -5,6 +5,7 @@
5
5
  .medicationDispenseReviewContainer {
6
6
  display: flex;
7
7
  flex-direction: column;
8
+ padding-bottom: 10px;
8
9
 
9
10
  :global(.cds--css-grid) {
10
11
  padding-left:0 !important;
@@ -19,6 +20,14 @@
19
20
  gap: spacing.$spacing-05;
20
21
  }
21
22
 
23
+ .substitutionReason {
24
+ width:100%;
25
+ }
26
+
27
+ .substitutionType {
28
+ width: 100%;
29
+ }
30
+
22
31
  .productiveHeading02 {
23
32
  color: $color-gray-70;
24
33
  @include type.type-style('productive-heading-02');