From 1338a40f27422a9145e1e428d92233590621b4dc Mon Sep 17 00:00:00 2001 From: Dennis Kigen Date: Thu, 4 Apr 2024 10:44:28 +0300 Subject: [PATCH] (chore) Configure prettier --- .eslintrc | 2 +- __mocks__/react-i18next.js | 10 +- jest.config.js | 18 +- package.json | 6 +- prettier.config.js | 8 + .../action-buttons.component.test.tsx | 178 +- src/components/action-buttons.component.tsx | 88 +- .../medication-card.component.test.tsx | 42 +- src/components/medication-card.component.tsx | 12 +- src/components/medication-event.component.tsx | 55 +- src/components/patient-details.component.tsx | 32 +- src/config-schema.ts | 38 +- src/constants.ts | 34 +- .../dispensing-dashboard-link.component.tsx | 21 +- .../dispensing-dashboard.component.tsx | 27 +- src/declarations.d.tsx | 8 +- src/dispensing-link.component.tsx | 14 +- .../dispensing-tile.component.tsx | 26 +- .../dispensing-tiles.component.tsx | 27 +- .../dispensing-tiles.resource.tsx | 17 +- src/dispensing.component.tsx | 4 +- src/dispensing.test.tsx | 10 +- src/forms/close-dispense-form.component.tsx | 116 +- src/forms/dispense-form.component.tsx | 129 +- ...ication-dispense-review.component.test.tsx | 100 +- .../medication-dispense-review.component.tsx | 183 +- src/forms/overlay/overlay.component.tsx | 34 +- src/forms/pause-dispense-form.component.tsx | 116 +- .../history-and-comments.component.tsx | 192 +- src/hooks/useOverlay.tsx | 8 +- src/index.ts | 42 +- src/location/location.resource.test.tsx | 152 +- src/location/location.resource.tsx | 14 +- .../medication-dispense.resource.test.tsx | 282 +- .../medication-dispense.resource.tsx | 52 +- .../medication-request.resource.test.tsx | 1147 ++++--- .../medication-request.resource.tsx | 133 +- src/medication/medication.resource.test.tsx | 147 +- src/medication/medication.resource.tsx | 29 +- .../pharmacy-header.component.tsx | 30 +- .../pharmacy-illustration.component.tsx | 9 +- .../prescription-details.component.tsx | 92 +- .../prescription-expanded.component.tsx | 34 +- .../prescription-tab-lists.component.tsx | 75 +- .../prescription-tab-panel.component.tsx | 97 +- src/setup-tests.ts | 2 +- src/types.ts | 60 +- src/utils.test.ts | 2743 ++++++++--------- src/utils.ts | 332 +- webpack.config.js | 2 +- yarn.lock | 1166 +------ 51 files changed, 3148 insertions(+), 5047 deletions(-) create mode 100644 prettier.config.js diff --git a/.eslintrc b/.eslintrc index f559b58..9b3a338 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,5 @@ { - "extends": ["ts-react-important-stuff", "plugin:prettier/recommended"], + "extends": [], "parser": "@typescript-eslint/parser", "plugins": ["unused-imports"], "ignorePatterns": ["**/*.test.tsx"], diff --git a/__mocks__/react-i18next.js b/__mocks__/react-i18next.js index 3663c70..14fb198 100644 --- a/__mocks__/react-i18next.js +++ b/__mocks__/react-i18next.js @@ -3,11 +3,11 @@ const React = require('react'); const reactI18next = require('react-i18next'); -const hasChildren = node => node && (node.children || (node.props && node.props.children)); +const hasChildren = (node) => node && (node.children || (node.props && node.props.children)); -const getChildren = node => (node && node.children ? node.children : node.props && node.props.children); +const getChildren = (node) => (node && node.children ? node.children : node.props && node.props.children); -const renderNodes = reactNodes => { +const renderNodes = (reactNodes) => { if (typeof reactNodes === 'string') { return reactNodes; } @@ -31,14 +31,14 @@ const renderNodes = reactNodes => { }); }; -const useMock = [k => k, {}]; +const useMock = [(k) => k, {}]; useMock.t = (k, o) => (o && o.defaultValue) || (typeof o === 'string' ? o : k); useMock.i18n = {}; module.exports = { // this mock makes sure any components using the translate HoC receive the t function as a prop Trans: ({ children }) => renderNodes(children), - Translation: ({ children }) => children(k => k, { i18n: {} }), + Translation: ({ children }) => children((k) => k, { i18n: {} }), useTranslation: () => useMock, // mock if needed diff --git a/jest.config.js b/jest.config.js index 2f9eb5a..79b17b4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,15 +1,15 @@ module.exports = { transform: { - "^.+\\.tsx?$": "@swc/jest", + '^.+\\.tsx?$': '@swc/jest', }, - transformIgnorePatterns: ["/node_modules/(?!@openmrs)"], + transformIgnorePatterns: ['/node_modules/(?!@openmrs)'], moduleNameMapper: { - "@openmrs/esm-framework": "@openmrs/esm-framework/mock", - "\\.(s?css)$": "identity-obj-proxy", - "^lodash-es/(.*)$": "lodash/$1", - "^uuid$": "/node_modules/uuid/dist/index.js", - dexie: require.resolve("dexie"), + '@openmrs/esm-framework': '@openmrs/esm-framework/mock', + '\\.(s?css)$': 'identity-obj-proxy', + '^lodash-es/(.*)$': 'lodash/$1', + '^uuid$': '/node_modules/uuid/dist/index.js', + dexie: require.resolve('dexie'), }, - setupFilesAfterEnv: ["/src/setup-tests.ts"], - testEnvironment: "jsdom", + setupFilesAfterEnv: ['/src/setup-tests.ts'], + testEnvironment: 'jsdom', }; diff --git a/package.json b/package.json index 9c093be..96ae917 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "serve": "webpack serve --mode=development", "build": "webpack --mode production", "analyze": "webpack --mode=production --env.analyze=true", - "prettier": "prettier --write \"src/**/*.{ts,tsx}\"", + "prettier": "prettier --write \"src/**/*.{ts,tsx}\" --list-different --ignore-unknown", "lint": "eslint src --ext js,jsx,ts,tsx", "test": "jest --config jest.config.js", "typescript": "tsc", @@ -67,13 +67,11 @@ "@types/react-router": "^5.1.14", "@types/react-router-dom": "^5.1.7", "@types/webpack-env": "^1.16.0", - "@typescript-eslint/parser": "^4.26.0", + "@typescript-eslint/parser": "^7.5.0", "concurrently": "^6.2.0", "dayjs": "1.x", "eslint": "^7.27.0", "eslint-config-prettier": "^8.3.0", - "eslint-config-ts-react-important-stuff": "^3.0.0", - "eslint-plugin-prettier": "^3.4.0", "eslint-plugin-unused-imports": "^2.0.0", "husky": "^6.0.0", "identity-obj-proxy": "^3.0.0", diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..89d4d10 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,8 @@ +module.exports = { + printWidth: 120, + singleQuote: true, + trailingComma: 'all', + bracketSpacing: true, + semi: true, + bracketSameLine: true, +}; diff --git a/src/components/action-buttons.component.test.tsx b/src/components/action-buttons.component.test.tsx index 7fe2942..1361426 100644 --- a/src/components/action-buttons.component.test.tsx +++ b/src/components/action-buttons.component.test.tsx @@ -1,14 +1,14 @@ -import { render } from "@testing-library/react"; -import React from "react"; -import ActionButtons from "./action-buttons.component"; -import { MedicationRequest, MedicationRequestStatus } from "../types"; -import { useConfig } from "@openmrs/esm-framework"; +import { render } from '@testing-library/react'; +import React from 'react'; +import ActionButtons from './action-buttons.component'; +import { MedicationRequest, MedicationRequestStatus } from '../types'; +import { useConfig } from '@openmrs/esm-framework'; const mockedUseConfig = useConfig as jest.Mock; -const mockPatientUuid = "558494fe-5850-4b34-a3bf-06550334ba4a"; -const mockEncounterUuid = "7aee7123-9e50-4f72-a636-895d77a63e98"; +const mockPatientUuid = '558494fe-5850-4b34-a3bf-06550334ba4a'; +const mockEncounterUuid = '7aee7123-9e50-4f72-a636-895d77a63e98'; -describe("Action Buttons Component tests", () => { +describe('Action Buttons Component tests', () => { beforeEach(() => { mockedUseConfig.mockReturnValue({ medicationRequestExpirationPeriodInDays: 90, @@ -27,84 +27,84 @@ describe("Action Buttons Component tests", () => { }); }); - test("component should render dispense button if active medication", () => { + test('component should render dispense button if active medication', () => { // status = active, and validity period start set to current datetime const medicationRequest: MedicationRequest = { - resourceType: "MedicationRequest", - id: "d4f69a68-1171-4e47-8693-478df18daf40", + resourceType: 'MedicationRequest', + id: 'd4f69a68-1171-4e47-8693-478df18daf40', meta: { - lastUpdated: "2023-01-24T19:02:04.000-05:00", + lastUpdated: '2023-01-24T19:02:04.000-05:00', }, status: MedicationRequestStatus.active, - intent: "order", - priority: "routine", + intent: 'order', + priority: 'routine', medicationReference: { - reference: "Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99", - type: "Medication", - display: "Ascorbic acid (Vitamin C), 250mg tablet", + reference: 'Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99', + type: 'Medication', + display: 'Ascorbic acid (Vitamin C), 250mg tablet', }, subject: { - reference: "Patient/558494fe-5850-4b34-a3bf-06550334ba4a", - type: "Patient", - display: "Dylan, Bob (ZL EMR ID: Y2CK2G)", + reference: 'Patient/558494fe-5850-4b34-a3bf-06550334ba4a', + type: 'Patient', + display: 'Dylan, Bob (ZL EMR ID: Y2CK2G)', }, encounter: { - reference: "Encounter/7aee7123-9e50-4f72-a636-895d77a63e98", - type: "Encounter", + reference: 'Encounter/7aee7123-9e50-4f72-a636-895d77a63e98', + type: 'Encounter', }, requester: { - reference: "Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487", - type: "Practitioner", + reference: 'Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487', + type: 'Practitioner', identifier: { - value: "MAADH", + value: 'MAADH', }, - display: "Goodrich, Mark (Identifier: MAADH)", + display: 'Goodrich, Mark (Identifier: MAADH)', }, dosageInstruction: [ { - text: "test", + text: 'test', timing: { repeat: { duration: 6, - durationUnit: "d", + durationUnit: 'd', }, code: { coding: [ { - code: "37328251-6759-4270-8a2e-8cab2c0b315b", - display: "OD (once daily)", + code: '37328251-6759-4270-8a2e-8cab2c0b315b', + display: 'OD (once daily)', }, { - system: "http://snomed.info/sct", - code: "229797004", - display: "OD (once daily)", + system: 'http://snomed.info/sct', + code: '229797004', + display: 'OD (once daily)', }, ], - text: "OD (once daily)", + text: 'OD (once daily)', }, }, asNeededBoolean: false, route: { coding: [ { - code: "46aaaca8-1f21-410a-aac9-67bfcc1fd577", - display: "Oral", + code: '46aaaca8-1f21-410a-aac9-67bfcc1fd577', + display: 'Oral', }, { - system: "http://snomed.info/sct", - code: "26643006", - display: "Oral", + system: 'http://snomed.info/sct', + code: '26643006', + display: 'Oral', }, ], - text: "Oral", + text: 'Oral', }, doseAndRate: [ { doseQuantity: { value: 5.0, - unit: "Ampule(s)", - system: "http://snomed.info/sct", - code: "413516001", + unit: 'Ampule(s)', + system: 'http://snomed.info/sct', + code: '413516001', }, }, ], @@ -117,9 +117,9 @@ describe("Action Buttons Component tests", () => { numberOfRepeatsAllowed: 8, quantity: { value: 7.0, - unit: "Application", - system: "http://snomed.info/sct", - code: "413568008", + unit: 'Application', + system: 'http://snomed.info/sct', + code: '413568008', }, }, }; @@ -129,90 +129,90 @@ describe("Action Buttons Component tests", () => { patientUuid={mockPatientUuid} encounterUuid={mockEncounterUuid} medicationRequestBundle={{ request: medicationRequest, dispenses: [] }} - /> + />, ); - expect(getByText("Dispense")).toBeInTheDocument(); + expect(getByText('Dispense')).toBeInTheDocument(); }); // status = active, but validity period start time years in the past - test("component should not render dispense button if expired medication", () => { + test('component should not render dispense button if expired medication', () => { // status = active, and validity period start set to current datetime const medicationRequest: MedicationRequest = { - resourceType: "MedicationRequest", - id: "d4f69a68-1171-4e47-8693-478df18daf40", + resourceType: 'MedicationRequest', + id: 'd4f69a68-1171-4e47-8693-478df18daf40', meta: { - lastUpdated: "2023-01-24T19:02:04.000-05:00", + lastUpdated: '2023-01-24T19:02:04.000-05:00', }, status: MedicationRequestStatus.active, - intent: "order", - priority: "routine", + intent: 'order', + priority: 'routine', medicationReference: { - reference: "Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99", - type: "Medication", - display: "Ascorbic acid (Vitamin C), 250mg tablet", + reference: 'Medication/c8d3444c-41a4-48d3-9ec1-811fe7b27d99', + type: 'Medication', + display: 'Ascorbic acid (Vitamin C), 250mg tablet', }, subject: { - reference: "Patient/558494fe-5850-4b34-a3bf-06550334ba4a", - type: "Patient", - display: "Dylan, Bob (ZL EMR ID: Y2CK2G)", + reference: 'Patient/558494fe-5850-4b34-a3bf-06550334ba4a', + type: 'Patient', + display: 'Dylan, Bob (ZL EMR ID: Y2CK2G)', }, encounter: { - reference: "Encounter/7aee7123-9e50-4f72-a636-895d77a63e98", - type: "Encounter", + reference: 'Encounter/7aee7123-9e50-4f72-a636-895d77a63e98', + type: 'Encounter', }, requester: { - reference: "Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487", - type: "Practitioner", + reference: 'Practitioner/19e06fb0-22ea-4dd4-aafd-da14c14a1487', + type: 'Practitioner', identifier: { - value: "MAADH", + value: 'MAADH', }, - display: "Goodrich, Mark (Identifier: MAADH)", + display: 'Goodrich, Mark (Identifier: MAADH)', }, dosageInstruction: [ { - text: "test", + text: 'test', timing: { repeat: { duration: 6, - durationUnit: "d", + durationUnit: 'd', }, code: { coding: [ { - code: "37328251-6759-4270-8a2e-8cab2c0b315b", - display: "OD (once daily)", + code: '37328251-6759-4270-8a2e-8cab2c0b315b', + display: 'OD (once daily)', }, { - system: "http://snomed.info/sct", - code: "229797004", - display: "OD (once daily)", + system: 'http://snomed.info/sct', + code: '229797004', + display: 'OD (once daily)', }, ], - text: "OD (once daily)", + text: 'OD (once daily)', }, }, asNeededBoolean: false, route: { coding: [ { - code: "46aaaca8-1f21-410a-aac9-67bfcc1fd577", - display: "Oral", + code: '46aaaca8-1f21-410a-aac9-67bfcc1fd577', + display: 'Oral', }, { - system: "http://snomed.info/sct", - code: "26643006", - display: "Oral", + system: 'http://snomed.info/sct', + code: '26643006', + display: 'Oral', }, ], - text: "Oral", + text: 'Oral', }, doseAndRate: [ { doseQuantity: { value: 5.0, - unit: "Ampule(s)", - system: "http://snomed.info/sct", - code: "413516001", + unit: 'Ampule(s)', + system: 'http://snomed.info/sct', + code: '413516001', }, }, ], @@ -220,14 +220,14 @@ describe("Action Buttons Component tests", () => { ], dispenseRequest: { validityPeriod: { - start: "2019-01-24T19:02:04.000-05:00", + start: '2019-01-24T19:02:04.000-05:00', }, numberOfRepeatsAllowed: 8, quantity: { value: 7.0, - unit: "Application", - system: "http://snomed.info/sct", - code: "413568008", + unit: 'Application', + system: 'http://snomed.info/sct', + code: '413568008', }, }, }; @@ -237,8 +237,8 @@ describe("Action Buttons Component tests", () => { patientUuid={mockPatientUuid} encounterUuid={mockEncounterUuid} medicationRequestBundle={{ request: medicationRequest, dispenses: [] }} - /> + />, ); - expect(queryByText("Dispense")).not.toBeInTheDocument(); + expect(queryByText('Dispense')).not.toBeInTheDocument(); }); }); diff --git a/src/components/action-buttons.component.tsx b/src/components/action-buttons.component.tsx index f36a568..a109944 100644 --- a/src/components/action-buttons.component.tsx +++ b/src/components/action-buttons.component.tsx @@ -1,24 +1,20 @@ -import React from "react"; -import { Button } from "@carbon/react"; -import { useConfig, useSession } from "@openmrs/esm-framework"; -import styles from "./action-buttons.scss"; -import { useTranslation } from "react-i18next"; -import { - MedicationDispenseStatus, - MedicationRequestBundle, - MedicationRequestStatus, -} from "../types"; -import { PharmacyConfig } from "../config-schema"; -import { launchOverlay } from "../hooks/useOverlay"; +import React from 'react'; +import { Button } from '@carbon/react'; +import { useConfig, useSession } from '@openmrs/esm-framework'; +import styles from './action-buttons.scss'; +import { useTranslation } from 'react-i18next'; +import { MedicationDispenseStatus, MedicationRequestBundle, MedicationRequestStatus } from '../types'; +import { PharmacyConfig } from '../config-schema'; +import { launchOverlay } from '../hooks/useOverlay'; import { computeMedicationRequestStatus, computeQuantityRemaining, getMostRecentMedicationDispenseStatus, -} from "../utils"; -import DispenseForm from "../forms/dispense-form.component"; -import { initiateMedicationDispenseBody } from "../medication-dispense/medication-dispense.resource"; -import PauseDispenseForm from "../forms/pause-dispense-form.component"; -import CloseDispenseForm from "../forms/close-dispense-form.component"; +} from '../utils'; +import DispenseForm from '../forms/dispense-form.component'; +import { initiateMedicationDispenseBody } from '../medication-dispense/medication-dispense.resource'; +import PauseDispenseForm from '../forms/pause-dispense-form.component'; +import CloseDispenseForm from '../forms/close-dispense-form.component'; interface ActionButtonsProps { medicationRequestBundle: MedicationRequestBundle; @@ -26,19 +22,16 @@ interface ActionButtonsProps { encounterUuid: string; } -const ActionButtons: React.FC = ({ - medicationRequestBundle, - patientUuid, - encounterUuid, -}) => { +const ActionButtons: React.FC = ({ medicationRequestBundle, patientUuid, encounterUuid }) => { const { t } = useTranslation(); const config = useConfig() as PharmacyConfig; const session = useSession(); - const mostRecentMedicationDispenseStatus: MedicationDispenseStatus = - getMostRecentMedicationDispenseStatus(medicationRequestBundle.dispenses); + const mostRecentMedicationDispenseStatus: MedicationDispenseStatus = getMostRecentMedicationDispenseStatus( + medicationRequestBundle.dispenses, + ); const medicationRequestStatus = computeMedicationRequestStatus( medicationRequestBundle.request, - config.medicationRequestExpirationPeriodInDays + config.medicationRequestExpirationPeriodInDays, ); const dispensable = medicationRequestStatus === MedicationRequestStatus.active && @@ -67,23 +60,18 @@ const ActionButtons: React.FC = ({ kind="primary" onClick={() => launchOverlay( - t("dispensePrescription", "Dispense prescription"), + t('dispensePrescription', 'Dispense prescription'), + />, ) - } - > - {t("dispense", "Dispense")} + }> + {t('dispense', 'Dispense')} ) : null} {pauseable ? ( @@ -91,21 +79,16 @@ const ActionButtons: React.FC = ({ kind="secondary" onClick={() => launchOverlay( - t("pausePrescription", "Pause prescription"), + t('pausePrescription', 'Pause prescription'), + />, ) - } - > - {t("pause", "Pause")} + }> + {t('pause', 'Pause')} ) : null} {closeable ? ( @@ -113,21 +96,16 @@ const ActionButtons: React.FC = ({ kind="danger" onClick={() => launchOverlay( - t("closePrescription", "Close prescription"), + t('closePrescription', 'Close prescription'), + />, ) - } - > - {t("close", "Close")} + }> + {t('close', 'Close')} ) : null} diff --git a/src/components/medication-card.component.test.tsx b/src/components/medication-card.component.test.tsx index d406056..871ec3e 100644 --- a/src/components/medication-card.component.test.tsx +++ b/src/components/medication-card.component.test.tsx @@ -1,40 +1,36 @@ -import { render } from "@testing-library/react"; -import React from "react"; -import { MedicationReferenceOrCodeableConcept } from "../types"; -import MedicationCard from "./medication-card.component"; +import { render } from '@testing-library/react'; +import React from 'react'; +import { MedicationReferenceOrCodeableConcept } from '../types'; +import MedicationCard from './medication-card.component'; -describe("Medication Card Component tests", () => { - test("component should render medication card without edit action button", () => { +describe('Medication Card Component tests', () => { + test('component should render medication card without edit action button', () => { const medication: MedicationReferenceOrCodeableConcept = { medicationReference: { - display: "Some Medication", - reference: "", - type: "", + display: 'Some Medication', + reference: '', + type: '', }, }; - const { getByText, container } = render( - - ); - expect(getByText("Some Medication")).toBeInTheDocument(); - expect(container.querySelector("svg")).not.toBeInTheDocument(); + const { getByText, container } = render(); + expect(getByText('Some Medication')).toBeInTheDocument(); + expect(container.querySelector('svg')).not.toBeInTheDocument(); }); - test("component should render medication card with edit action button", () => { + test('component should render medication card with edit action button', () => { const medication: MedicationReferenceOrCodeableConcept = { medicationReference: { - display: "Some Medication", - reference: "", - type: "", + display: 'Some Medication', + reference: '', + type: '', }, }; const action = () => 0; - const { getByText, container } = render( - - ); - expect(getByText("Some Medication")).toBeInTheDocument(); - expect(container.querySelector("svg")).toBeInTheDocument(); + const { getByText, container } = render(); + expect(getByText('Some Medication')).toBeInTheDocument(); + expect(container.querySelector('svg')).toBeInTheDocument(); }); }); diff --git a/src/components/medication-card.component.tsx b/src/components/medication-card.component.tsx index 0ac3dde..3897dc1 100644 --- a/src/components/medication-card.component.tsx +++ b/src/components/medication-card.component.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { Tile } from "@carbon/react"; -import { Edit } from "@carbon/react/icons"; -import { MedicationReferenceOrCodeableConcept } from "../types"; -import styles from "./medication-card.scss"; -import { getMedicationDisplay } from "../utils"; +import React from 'react'; +import { Tile } from '@carbon/react'; +import { Edit } from '@carbon/react/icons'; +import { MedicationReferenceOrCodeableConcept } from '../types'; +import styles from './medication-card.scss'; +import { getMedicationDisplay } from '../utils'; const MedicationCard: React.FC<{ medication: MedicationReferenceOrCodeableConcept; diff --git a/src/components/medication-event.component.tsx b/src/components/medication-event.component.tsx index 3300c8d..6c96604 100644 --- a/src/components/medication-event.component.tsx +++ b/src/components/medication-event.component.tsx @@ -1,19 +1,14 @@ -import React from "react"; -import { - DosageInstruction, - MedicationDispense, - MedicationRequest, - Quantity, -} from "../types"; -import styles from "./medication-event.scss"; +import React from 'react'; +import { DosageInstruction, MedicationDispense, MedicationRequest, Quantity } from '../types'; +import styles from './medication-event.scss'; import { getDosageInstruction, getQuantity, getRefillsAllowed, getMedicationDisplay, getMedicationReferenceOrCodeableConcept, -} from "../utils"; -import { useTranslation } from "react-i18next"; +} from '../utils'; +import { useTranslation } from 'react-i18next'; // can render MedicationRequest or MedicationDispense const MedicationEvent: React.FC<{ @@ -21,9 +16,7 @@ const MedicationEvent: React.FC<{ status?; }> = ({ medicationEvent, status = null }) => { const { t } = useTranslation(); - const dosageInstruction: DosageInstruction = getDosageInstruction( - medicationEvent.dosageInstruction - ); + const dosageInstruction: DosageInstruction = getDosageInstruction(medicationEvent.dosageInstruction); const quantity: Quantity = getQuantity(medicationEvent); const refillsAllowed: number = getRefillsAllowed(medicationEvent); @@ -31,45 +24,35 @@ const MedicationEvent: React.FC<{

{status} - - {getMedicationDisplay( - getMedicationReferenceOrCodeableConcept(medicationEvent) - )} - + {getMedicationDisplay(getMedicationReferenceOrCodeableConcept(medicationEvent))}

{dosageInstruction && (

- - {t("dose", "Dose").toUpperCase()} - {" "} + {t('dose', 'Dose').toUpperCase()}{' '} {dosageInstruction.doseAndRate && dosageInstruction?.doseAndRate.map((doseAndRate, index) => { return ( - {doseAndRate?.doseQuantity?.value}{" "} - {doseAndRate?.doseQuantity?.unit} + {doseAndRate?.doseQuantity?.value} {doseAndRate?.doseQuantity?.unit} ); })} - {" "} - — {dosageInstruction?.route?.text} —{" "} - {dosageInstruction?.timing?.code?.text}{" "} + {' '} + — {dosageInstruction?.route?.text} — {dosageInstruction?.timing?.code?.text}{' '} {dosageInstruction?.timing?.repeat?.duration - ? "for " + + ? 'for ' + dosageInstruction?.timing?.repeat?.duration + - " " + + ' ' + dosageInstruction?.timing?.repeat?.durationUnit - : " "} + : ' '}

)} {quantity && (

- - {t("quantity", "Quantity").toUpperCase()} - {" "} + {t('quantity', 'Quantity').toUpperCase()}{' '} {quantity.value} {quantity.unit} @@ -78,15 +61,11 @@ const MedicationEvent: React.FC<{ {(refillsAllowed || refillsAllowed === 0) && (

- - {t("refills", "Refills").toUpperCase()} - {" "} + {t('refills', 'Refills').toUpperCase()}{' '} {refillsAllowed}

)} - {dosageInstruction?.text && ( -

{dosageInstruction.text}

- )} + {dosageInstruction?.text &&

{dosageInstruction.text}

}
); }; diff --git a/src/components/patient-details.component.tsx b/src/components/patient-details.component.tsx index d2cbf5d..7c5749a 100644 --- a/src/components/patient-details.component.tsx +++ b/src/components/patient-details.component.tsx @@ -1,14 +1,7 @@ -import React, { useEffect } from "react"; -import { - attach, - detach, - ExtensionSlot, - PatientUuid, - useConfig, - usePatient, -} from "@openmrs/esm-framework"; -import styles from "./patient-details.scss"; -import { useTranslation } from "react-i18next"; +import React, { useEffect } from 'react'; +import { attach, detach, ExtensionSlot, PatientUuid, useConfig, usePatient } from '@openmrs/esm-framework'; +import styles from './patient-details.scss'; +import { useTranslation } from 'react-i18next'; const PatientDetails: React.FC<{ patientUuid: PatientUuid; @@ -18,10 +11,7 @@ const PatientDetails: React.FC<{ const { patient } = usePatient(patientUuid); const patientName = patient; - const patientPhotoSlotState = React.useMemo( - () => ({ patientUuid, patientName }), - [patientUuid, patientName] - ); + const patientPhotoSlotState = React.useMemo(() => ({ patientUuid, patientName }), [patientUuid, patientName]); const [showContactDetails, setShowContactDetails] = React.useState(false); const toggleContactDetails = React.useCallback((event: MouseEvent) => { @@ -36,14 +26,14 @@ const PatientDetails: React.FC<{ ); useEffect(() => { - attach("dispensing-patient-banner-slot", "patient-banner"); - attach("dispensing-patient-vitals-slot", "vitals-overview-widget"); - attach("dispensing-patient-allergies-slot", "allergies-overview-widget"); + attach('dispensing-patient-banner-slot', 'patient-banner'); + attach('dispensing-patient-vitals-slot', 'vitals-overview-widget'); + attach('dispensing-patient-allergies-slot', 'allergies-overview-widget'); return () => { - detach("dispensing-patient-banner-slot", "patient-banner"); - detach("dispensing-patient-vitals-slot", "vitals-overview-widget"); - detach("dispensing-patient-allergies-slot", "allergies-overview-widget"); + detach('dispensing-patient-banner-slot', 'patient-banner'); + detach('dispensing-patient-vitals-slot', 'vitals-overview-widget'); + detach('dispensing-patient-allergies-slot', 'allergies-overview-widget'); }; }, []); diff --git a/src/config-schema.ts b/src/config-schema.ts index 1b38d41..93a4fa8 100644 --- a/src/config-schema.ts +++ b/src/config-schema.ts @@ -1,4 +1,4 @@ -import { Type } from "@openmrs/esm-framework"; +import { Type } from '@openmrs/esm-framework'; /** * This is the config schema. It expects a configuration object which @@ -23,22 +23,20 @@ import { Type } from "@openmrs/esm-framework"; export const configSchema = { appName: { _type: Type.String, - _default: "Pharmacy", + _default: 'Pharmacy', }, actionButtons: { pauseButton: { enabled: { _type: Type.Boolean, - _description: - "Enabled/Disable including a Pause button in the button action bar", + _description: 'Enabled/Disable including a Pause button in the button action bar', _default: true, }, }, closeButton: { enabled: { _type: Type.Boolean, - _description: - "Enabled/Disable including a Close button in the button action bar", + _description: 'Enabled/Disable including a Close button in the button action bar', _default: true, }, }, @@ -47,20 +45,19 @@ export const configSchema = { allowModifyingPrescription: { _type: Type.Boolean, _description: - "Enable/Disable editing the prescription. If Disabled, Quantity will be he only editable field on prescription form. Note that thins means that quantity units will need to be mandatory and set correctly on the prescription.", + 'Enable/Disable editing the prescription. If Disabled, Quantity will be he only editable field on prescription form. Note that thins means that quantity units will need to be mandatory and set correctly on the prescription.', _default: true, }, restrictTotalQuantityDispensed: { _type: Type.Boolean, _description: - "Enable/Disable restricting dispensing quantity greater than total quantity ordered. Marks prescription as complete when total quantity dispensed. If true, allowModifyingPrescription *must* be false, as this functionality relies solely on numeric quantity and assumes no change in formulation, dosage, unit, etc", + 'Enable/Disable restricting dispensing quantity greater than total quantity ordered. Marks prescription as complete when total quantity dispensed. If true, allowModifyingPrescription *must* be false, as this functionality relies solely on numeric quantity and assumes no change in formulation, dosage, unit, etc', _default: false, }, }, medicationRequestExpirationPeriodInDays: { _type: Type.Number, - _description: - "Medication Requests older that this will be considered expired", + _description: 'Medication Requests older that this will be considered expired', _default: 90, }, locationBehavior: { @@ -68,29 +65,26 @@ export const configSchema = { enabled: { _type: Type.Boolean, _description: - "Enabled/Disable including a Location column in the main prescriptions table showing ordering location", + 'Enabled/Disable including a Location column in the main prescriptions table showing ordering location', _default: false, }, }, locationFilter: { enabled: { _type: Type.Boolean, - _description: - "Enable/Disable Location filter on main prescriptions page", + _description: 'Enable/Disable Location filter on main prescriptions page', _default: false, }, tag: { _type: Type.String, - _description: - "Name of the location tag to use when fetching locations to populate filter", - _default: "Login Location", + _description: 'Name of the location tag to use when fetching locations to populate filter', + _default: 'Login Location', }, }, }, refreshInterval: { _type: Type.Number, - _description: - "The interval, in milliseconds, to query the backend for new/changed data", + _description: 'The interval, in milliseconds, to query the backend for new/changed data', _default: 60000, }, valueSets: { @@ -99,7 +93,7 @@ export const configSchema = { _type: Type.UUID, _description: "UUID for the Value Set of valid answers to the 'Reason for Pause' question. Defaults to CIEL value set: https://app.openconceptlab.org/#/orgs/CIEL/sources/CIEL/concepts/168099/", - _default: "2dd3e5c0-3d3f-4f3d-9860-19b3f9ab26ff", + _default: '2dd3e5c0-3d3f-4f3d-9860-19b3f9ab26ff', }, }, reasonForClose: { @@ -107,7 +101,7 @@ export const configSchema = { _type: Type.UUID, _description: "UUID for the Value Set of valid answers to the 'Reason for Close' question. Defaults to CIEL value set: https://app.openconceptlab.org/#/orgs/CIEL/sources/CIEL/concepts/168099/", - _default: "bd6c1fc2-7cfc-4562-94a0-e4765e5e977e", + _default: 'bd6c1fc2-7cfc-4562-94a0-e4765e5e977e', }, }, substitutionReason: { @@ -115,7 +109,7 @@ export const configSchema = { _type: Type.UUID, _description: "UUID for the Value Set of valid answers to the 'Reason for Substitution' question. Defaults to CIEL value set: https://app.openconceptlab.org/#/orgs/CIEL/sources/CIEL/concepts/167862/", - _default: "de8671b8-ed2e-4f7e-a9f8-dcd00878f2eb", + _default: 'de8671b8-ed2e-4f7e-a9f8-dcd00878f2eb', }, }, substitutionType: { @@ -123,7 +117,7 @@ export const configSchema = { _type: Type.UUID, _description: "UUID for the Value Set of valid answers to the 'Type of Substitution' question. Defaults to CIEL value set: https://app.openconceptlab.org/#/orgs/CIEL/sources/CIEL/concepts/167859/", - _default: "b9c5bca0-d026-4245-a4d2-e4c0a8999082", + _default: 'b9c5bca0-d026-4245-a4d2-e4c0a8999082', }, }, }, diff --git a/src/constants.ts b/src/constants.ts index 9b86636..2553717 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,27 +1,23 @@ -export const spaRoot = window["getOpenmrsSpaBase"]; -export const basePath = "/dispensing"; +export const spaRoot = window['getOpenmrsSpaBase']; +export const basePath = '/dispensing'; export const spaBasePath = `${window.spaBase}${basePath}`; // defined in FHIR 2 module -export const OPENMRS_FHIR_PREFIX = "http://fhir.openmrs.org"; -export const OPENMRS_FHIR_EXT_PREFIX = OPENMRS_FHIR_PREFIX + "/ext"; -export const OPENMRS_FHIR_EXT_MEDICINE = OPENMRS_FHIR_EXT_PREFIX + "/medicine"; -export const OPENMRS_FHIR_EXT_DISPENSE_RECORDED = - OPENMRS_FHIR_EXT_PREFIX + "/medicationdispense/recorded"; +export const OPENMRS_FHIR_PREFIX = 'http://fhir.openmrs.org'; +export const OPENMRS_FHIR_EXT_PREFIX = OPENMRS_FHIR_PREFIX + '/ext'; +export const OPENMRS_FHIR_EXT_MEDICINE = OPENMRS_FHIR_EXT_PREFIX + '/medicine'; +export const OPENMRS_FHIR_EXT_DISPENSE_RECORDED = OPENMRS_FHIR_EXT_PREFIX + '/medicationdispense/recorded'; export const OPENMRS_FHIR_EXT_REQUEST_FULFILLER_STATUS = - OPENMRS_FHIR_EXT_PREFIX + "/medicationrequest/fullfillerstatus"; + OPENMRS_FHIR_EXT_PREFIX + '/medicationrequest/fullfillerstatus'; -export const PRIVILEGE_CREATE_DISPENSE = "Task: dispensing.create.dispense"; -export const PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS = - "Task: dispensing.create.dispense.allowSubstitutions"; -export const PRIVILEGE_EDIT_DISPENSE = "Task: dispensing.edit.dispense"; -export const PRIVILEGE_DELETE_DISPENSE = "Task: dispensing.delete.dispense"; -export const PRIVILEGE_DELETE_DISPENSE_THIS_PROVIDER_ONLY = - "Task: dispensing.delete.dispense.ifCreator"; +export const PRIVILEGE_CREATE_DISPENSE = 'Task: dispensing.create.dispense'; +export const PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS = 'Task: dispensing.create.dispense.allowSubstitutions'; +export const PRIVILEGE_EDIT_DISPENSE = 'Task: dispensing.edit.dispense'; +export const PRIVILEGE_DELETE_DISPENSE = 'Task: dispensing.delete.dispense'; +export const PRIVILEGE_DELETE_DISPENSE_THIS_PROVIDER_ONLY = 'Task: dispensing.delete.dispense.ifCreator'; -export const JSON_MERGE_PATH_MIME_TYPE = "application/merge-patch+json"; +export const JSON_MERGE_PATH_MIME_TYPE = 'application/merge-patch+json'; -export const PRESCRIPTIONS_TABLE_ENDPOINT = - "Encounter?_query=encountersWithMedicationRequests"; +export const PRESCRIPTIONS_TABLE_ENDPOINT = 'Encounter?_query=encountersWithMedicationRequests'; -export const PRESCRIPTION_DETAILS_ENDPOINT = "MedicationRequest"; +export const PRESCRIPTION_DETAILS_ENDPOINT = 'MedicationRequest'; diff --git a/src/dashboard/dispensing-dashboard-link.component.tsx b/src/dashboard/dispensing-dashboard-link.component.tsx index 4e6481c..f1012fa 100644 --- a/src/dashboard/dispensing-dashboard-link.component.tsx +++ b/src/dashboard/dispensing-dashboard-link.component.tsx @@ -1,8 +1,8 @@ -import { ConfigurableLink } from "@openmrs/esm-framework"; -import React, { useMemo } from "react"; -import classNames from "classnames"; -import { useTranslation } from "react-i18next"; -import { BrowserRouter } from "react-router-dom"; +import { ConfigurableLink } from '@openmrs/esm-framework'; +import React, { useMemo } from 'react'; +import classNames from 'classnames'; +import { useTranslation } from 'react-i18next'; +import { BrowserRouter } from 'react-router-dom'; const DispensingDashboardLink = () => { return ( @@ -18,19 +18,18 @@ function DashboardExtension() { const { t } = useTranslation(); const spaBasePath = `${window.spaBase}/home`; const navLink = useMemo(() => { - const pathArray = location.pathname.split("/home"); + const pathArray = location.pathname.split('/home'); const lastElement = pathArray[pathArray.length - 1]; return decodeURIComponent(lastElement); }, [location.pathname]); return ( - {t("dispensing", "Dispensing")} + to={`${spaBasePath}/dispensing`}> + {t('dispensing', 'Dispensing')} ); } diff --git a/src/dashboard/dispensing-dashboard.component.tsx b/src/dashboard/dispensing-dashboard.component.tsx index a5f1f60..a540d89 100644 --- a/src/dashboard/dispensing-dashboard.component.tsx +++ b/src/dashboard/dispensing-dashboard.component.tsx @@ -1,26 +1,23 @@ -import React from "react"; -import { InlineNotification } from "@carbon/react"; -import Overlay from "../forms/overlay/overlay.component"; -import { PharmacyHeader } from "../pharmacy-header/pharmacy-header.component"; -import PrescriptionTabLists from "../prescriptions/prescription-tab-lists.component"; -import { PharmacyConfig } from "../config-schema"; -import { useConfig } from "@openmrs/esm-framework"; -import { useTranslation } from "react-i18next"; +import React from 'react'; +import { InlineNotification } from '@carbon/react'; +import Overlay from '../forms/overlay/overlay.component'; +import { PharmacyHeader } from '../pharmacy-header/pharmacy-header.component'; +import PrescriptionTabLists from '../prescriptions/prescription-tab-lists.component'; +import { PharmacyConfig } from '../config-schema'; +import { useConfig } from '@openmrs/esm-framework'; +import { useTranslation } from 'react-i18next'; export default function DispensingDashboard() { const config = useConfig() as PharmacyConfig; const { t } = useTranslation(); - if ( - config.dispenseBehavior.restrictTotalQuantityDispensed && - config.dispenseBehavior.allowModifyingPrescription - ) { + if (config.dispenseBehavior.restrictTotalQuantityDispensed && config.dispenseBehavior.allowModifyingPrescription) { return (
diff --git a/src/declarations.d.tsx b/src/declarations.d.tsx index 4b6cd6e..3b6878f 100644 --- a/src/declarations.d.tsx +++ b/src/declarations.d.tsx @@ -1,5 +1,5 @@ -declare module "*.css"; -declare module "*.scss"; -declare module "*.svg"; -declare module "@carbon/react"; +declare module '*.css'; +declare module '*.scss'; +declare module '*.svg'; +declare module '@carbon/react'; declare type SideNavProps = {}; diff --git a/src/dispensing-link.component.tsx b/src/dispensing-link.component.tsx index d1809f2..7ff6f09 100644 --- a/src/dispensing-link.component.tsx +++ b/src/dispensing-link.component.tsx @@ -1,13 +1,9 @@ -import React from "react"; -import { ConfigurableLink } from "@openmrs/esm-framework"; -import { useTranslation } from "react-i18next"; -import { spaBasePath } from "./constants"; +import React from 'react'; +import { ConfigurableLink } from '@openmrs/esm-framework'; +import { useTranslation } from 'react-i18next'; +import { spaBasePath } from './constants'; export default function DispensingLink() { const { t } = useTranslation(); - return ( - - {t("dispensing", "Dispensing")} - - ); + return {t('dispensing', 'Dispensing')}; } diff --git a/src/dispensing-tiles/dispensing-tile.component.tsx b/src/dispensing-tiles/dispensing-tile.component.tsx index 8ff9568..892a60d 100644 --- a/src/dispensing-tiles/dispensing-tile.component.tsx +++ b/src/dispensing-tiles/dispensing-tile.component.tsx @@ -1,8 +1,8 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { Tile, Button } from "@carbon/react"; -import { ArrowRight } from "@carbon/react/icons"; -import styles from "./dispensing-tile.scss"; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { Tile, Button } from '@carbon/react'; +import { ArrowRight } from '@carbon/react/icons'; +import styles from './dispensing-tile.scss'; interface DispensingTileProps { label: string; @@ -11,12 +11,7 @@ interface DispensingTileProps { children?: React.ReactNode; } -const DispensingTile: React.FC = ({ - label, - value, - headerLabel, - children, -}) => { +const DispensingTile: React.FC = ({ label, value, headerLabel, children }) => { const { t } = useTranslation(); return ( @@ -28,12 +23,9 @@ const DispensingTile: React.FC = ({
diff --git a/src/dispensing-tiles/dispensing-tiles.component.tsx b/src/dispensing-tiles/dispensing-tiles.component.tsx index 549f010..d3f6eef 100644 --- a/src/dispensing-tiles/dispensing-tiles.component.tsx +++ b/src/dispensing-tiles/dispensing-tiles.component.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { DataTableSkeleton } from "@carbon/react"; -import { useMetrics } from "./dispensing-tiles.resource"; -import DispensingTile from "./dispensing-tile.component"; -import styles from "./dispensing-tiles.scss"; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { DataTableSkeleton } from '@carbon/react'; +import { useMetrics } from './dispensing-tiles.resource'; +import DispensingTile from './dispensing-tile.component'; +import styles from './dispensing-tiles.scss'; const DispensingTiles: React.FC = () => { const { t } = useTranslation(); @@ -17,22 +17,19 @@ const DispensingTiles: React.FC = () => { <>
diff --git a/src/dispensing-tiles/dispensing-tiles.resource.tsx b/src/dispensing-tiles/dispensing-tiles.resource.tsx index 886664c..b2f1c8a 100644 --- a/src/dispensing-tiles/dispensing-tiles.resource.tsx +++ b/src/dispensing-tiles/dispensing-tiles.resource.tsx @@ -1,6 +1,6 @@ -import useSWR from "swr"; -import useSWRImmutable from "swr/immutable"; -import { FetchResponse, openmrsFetch } from "@openmrs/esm-framework"; +import useSWR from 'swr'; +import useSWRImmutable from 'swr/immutable'; +import { FetchResponse, openmrsFetch } from '@openmrs/esm-framework'; // NOT CURRENTLY USED @@ -10,10 +10,7 @@ export function useMetrics() { orders_for_home_delivery: 4, missed_collections: 12, }; - const { data, error } = useSWR<{ data: { results: {} } }, Error>( - `/ws/rest/v1/queue?`, - openmrsFetch - ); + const { data, error } = useSWR<{ data: { results: {} } }, Error>(`/ws/rest/v1/queue?`, openmrsFetch); return { metrics: metrics, @@ -23,13 +20,11 @@ export function useMetrics() { } export function useServices() { - const serviceConceptSetUuid = "330c0ec6-0ac7-4b86-9c70-29d76f0ae20a"; + const serviceConceptSetUuid = '330c0ec6-0ac7-4b86-9c70-29d76f0ae20a'; const apiUrl = `/ws/rest/v1/concept/${serviceConceptSetUuid}`; const { data } = useSWRImmutable(apiUrl, openmrsFetch); return { - services: data - ? data?.data?.setMembers?.map((setMember) => setMember?.display) - : [], + services: data ? data?.data?.setMembers?.map((setMember) => setMember?.display) : [], }; } diff --git a/src/dispensing.component.tsx b/src/dispensing.component.tsx index b9f7c36..21e6513 100644 --- a/src/dispensing.component.tsx +++ b/src/dispensing.component.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { ExtensionSlot } from "@openmrs/esm-framework"; +import React from 'react'; +import { ExtensionSlot } from '@openmrs/esm-framework'; export default function Dispensing() { return ; diff --git a/src/dispensing.test.tsx b/src/dispensing.test.tsx index 33e0fc6..a425b55 100644 --- a/src/dispensing.test.tsx +++ b/src/dispensing.test.tsx @@ -20,12 +20,12 @@ * Kent C. Dodds is the inventor of `@testing-library`: * https://testing-library.com/docs/guiding-principles */ -import React from "react"; -import { render } from "@testing-library/react"; -import Dispensing from "./dispensing.component"; +import React from 'react'; +import { render } from '@testing-library/react'; +import Dispensing from './dispensing.component'; -describe("
", () => { - test("renders dispening without error", () => { +describe('
', () => { + test('renders dispening without error', () => { render(); }); }); diff --git a/src/forms/close-dispense-form.component.tsx b/src/forms/close-dispense-form.component.tsx index 0c462d3..b4876c5 100644 --- a/src/forms/close-dispense-form.component.tsx +++ b/src/forms/close-dispense-form.component.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; +import React, { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { ExtensionSlot, showNotification, @@ -7,26 +7,19 @@ import { useConfig, useLayoutType, usePatient, -} from "@openmrs/esm-framework"; -import { Button, ComboBox, InlineLoading } from "@carbon/react"; -import { - saveMedicationDispense, - useReasonForCloseValueSet, -} from "../medication-dispense/medication-dispense.resource"; -import { closeOverlay } from "../hooks/useOverlay"; -import styles from "./forms.scss"; -import { PharmacyConfig } from "../config-schema"; -import { updateMedicationRequestFulfillerStatus } from "../medication-request/medication-request.resource"; -import { - MedicationDispense, - MedicationDispenseStatus, - MedicationRequestFulfillerStatus, -} from "../types"; -import { getUuidFromReference, revalidate } from "../utils"; +} from '@openmrs/esm-framework'; +import { Button, ComboBox, InlineLoading } from '@carbon/react'; +import { saveMedicationDispense, useReasonForCloseValueSet } from '../medication-dispense/medication-dispense.resource'; +import { closeOverlay } from '../hooks/useOverlay'; +import styles from './forms.scss'; +import { PharmacyConfig } from '../config-schema'; +import { updateMedicationRequestFulfillerStatus } from '../medication-request/medication-request.resource'; +import { MedicationDispense, MedicationDispenseStatus, MedicationRequestFulfillerStatus } from '../types'; +import { getUuidFromReference, revalidate } from '../utils'; interface CloseDispenseFormProps { medicationDispense: MedicationDispense; - mode: "enter" | "edit"; + mode: 'enter' | 'edit'; patientUuid?: string; encounterUuid: string; } @@ -39,12 +32,11 @@ const CloseDispenseForm: React.FC = ({ }) => { const { t } = useTranslation(); const config = useConfig() as PharmacyConfig; - const isTablet = useLayoutType() === "tablet"; + const isTablet = useLayoutType() === 'tablet'; const { patient, isLoading } = usePatient(patientUuid); // Keep track of medication dispense payload - const [medicationDispensePayload, setMedicationDispensePayload] = - useState(); + const [medicationDispensePayload, setMedicationDispensePayload] = useState(); // whether or not the form is valid and ready to submit const [isValid, setIsValid] = useState(false); @@ -52,23 +44,19 @@ const CloseDispenseForm: React.FC = ({ // to prevent duplicate submits const [isSubmitting, setIsSubmitting] = useState(false); const [reasonsForClose, setReasonsForClose] = useState([]); - const { reasonForCloseValueSet } = useReasonForCloseValueSet( - config.valueSets.reasonForClose.uuid - ); + const { reasonForCloseValueSet } = useReasonForCloseValueSet(config.valueSets.reasonForClose.uuid); useEffect(() => { const reasonForCloseOptions = []; if (reasonForCloseValueSet?.compose?.include) { - const uuidValueSet = reasonForCloseValueSet.compose.include.find( - (include) => !include.system - ); + const uuidValueSet = reasonForCloseValueSet.compose.include.find((include) => !include.system); if (uuidValueSet) { uuidValueSet.concept?.forEach((concept) => reasonForCloseOptions.push({ id: concept.code, text: concept.display, - }) + }), ); reasonForCloseOptions.sort((a, b) => a.text.localeCompare(b.text)); } @@ -80,19 +68,15 @@ const CloseDispenseForm: React.FC = ({ if (!isSubmitting) { setIsSubmitting(true); const abortController = new AbortController(); - saveMedicationDispense( - medicationDispensePayload, - MedicationDispenseStatus.declined, - abortController - ) + saveMedicationDispense(medicationDispensePayload, MedicationDispenseStatus.declined, abortController) .then((response) => { // only update request status when added a new dispense event, not updating if (response.ok && !medicationDispense.id) { return updateMedicationRequestFulfillerStatus( getUuidFromReference( - medicationDispensePayload.authorizingPrescription[0].reference // assumes authorizing prescription exist + medicationDispensePayload.authorizingPrescription[0].reference, // assumes authorizing prescription exist ), - MedicationRequestFulfillerStatus.declined + MedicationRequestFulfillerStatus.declined, ); } else { return response; @@ -104,22 +88,14 @@ const CloseDispenseForm: React.FC = ({ revalidate(encounterUuid); showToast({ critical: true, - kind: "success", + kind: 'success', description: t( - mode === "enter" - ? "medicationDispenseClosed" - : "medicationDispenseUpdated", - mode === "enter" - ? "Medication dispense closed." - : "Dispense record successfully updated." + mode === 'enter' ? 'medicationDispenseClosed' : 'medicationDispenseUpdated', + mode === 'enter' ? 'Medication dispense closed.' : 'Dispense record successfully updated.', ), title: t( - mode === "enter" - ? "medicationDispenseClosed" - : "medicationDispenseUpdated", - mode === "enter" - ? "Medication dispense closed." - : "Dispense record successfully updated." + mode === 'enter' ? 'medicationDispenseClosed' : 'medicationDispenseUpdated', + mode === 'enter' ? 'Medication dispense closed.' : 'Dispense record successfully updated.', ), }); } @@ -127,14 +103,10 @@ const CloseDispenseForm: React.FC = ({ .catch((error) => { showNotification({ title: t( - mode === "enter" - ? "medicationDispenseCloseError" - : "medicationDispenseUpdatedError", - mode === "enter" - ? "Error closing medication dispense." - : "Error updating dispense record" + mode === 'enter' ? 'medicationDispenseCloseError' : 'medicationDispenseUpdatedError', + mode === 'enter' ? 'Error closing medication dispense.' : 'Error updating dispense record', ), - kind: "error", + kind: 'error', critical: true, description: error?.message, }); @@ -144,10 +116,7 @@ const CloseDispenseForm: React.FC = ({ }; const checkIsValid = () => { - if ( - medicationDispensePayload && - medicationDispensePayload.statusReasonCodeableConcept?.coding[0].code - ) { + if (medicationDispensePayload && medicationDispensePayload.statusReasonCodeableConcept?.coding[0].code) { setIsValid(true); } else { setIsValid(false); @@ -155,10 +124,7 @@ const CloseDispenseForm: React.FC = ({ }; // initialize the internal dispense payload with the dispenses passed in as props - useEffect( - () => setMedicationDispensePayload(medicationDispense), - [medicationDispense] - ); + useEffect(() => setMedicationDispensePayload(medicationDispense), [medicationDispense]); // check is valid on any changes useEffect(checkIsValid, [medicationDispensePayload]); @@ -184,19 +150,16 @@ const CloseDispenseForm: React.FC = ({ status="active" /> )} - {patient && ( - - )} + {patient && }
item?.text} initialSelectedItem={{ - id: medicationDispense.statusReasonCodeableConcept?.coding[0] - ?.code, + id: medicationDispense.statusReasonCodeableConcept?.coding[0]?.code, text: medicationDispense.statusReasonCodeableConcept?.text, }} onChange={({ selectedItem }) => { @@ -214,18 +177,11 @@ const CloseDispenseForm: React.FC = ({ />
-
diff --git a/src/forms/dispense-form.component.tsx b/src/forms/dispense-form.component.tsx index e1462f4..4335722 100644 --- a/src/forms/dispense-form.component.tsx +++ b/src/forms/dispense-form.component.tsx @@ -1,5 +1,5 @@ -import React, { useEffect, useMemo, useState } from "react"; -import { useTranslation } from "react-i18next"; +import React, { useEffect, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { ExtensionSlot, showNotification, @@ -7,30 +7,26 @@ import { useConfig, useLayoutType, usePatient, -} from "@openmrs/esm-framework"; -import { Button, FormLabel, InlineLoading } from "@carbon/react"; -import styles from "./forms.scss"; -import { closeOverlay } from "../hooks/useOverlay"; -import { - MedicationDispense, - MedicationDispenseStatus, - MedicationRequestBundle, -} from "../types"; -import { PharmacyConfig } from "../config-schema"; -import { saveMedicationDispense } from "../medication-dispense/medication-dispense.resource"; -import MedicationDispenseReview from "./medication-dispense-review.component"; +} from '@openmrs/esm-framework'; +import { Button, FormLabel, InlineLoading } from '@carbon/react'; +import styles from './forms.scss'; +import { closeOverlay } from '../hooks/useOverlay'; +import { MedicationDispense, MedicationDispenseStatus, MedicationRequestBundle } from '../types'; +import { PharmacyConfig } from '../config-schema'; +import { saveMedicationDispense } from '../medication-dispense/medication-dispense.resource'; +import MedicationDispenseReview from './medication-dispense-review.component'; import { computeNewFulfillerStatusAfterDispenseEvent, getFulfillerStatus, getUuidFromReference, revalidate, -} from "../utils"; -import { updateMedicationRequestFulfillerStatus } from "../medication-request/medication-request.resource"; +} from '../utils'; +import { updateMedicationRequestFulfillerStatus } from '../medication-request/medication-request.resource'; interface DispenseFormProps { medicationDispense: MedicationDispense; medicationRequestBundle: MedicationRequestBundle; - mode: "enter" | "edit"; + mode: 'enter' | 'edit'; patientUuid?: string; encounterUuid: string; quantityRemaining: number; @@ -45,13 +41,12 @@ const DispenseForm: React.FC = ({ quantityRemaining, }) => { const { t } = useTranslation(); - const isTablet = useLayoutType() === "tablet"; + const isTablet = useLayoutType() === 'tablet'; const { patient, isLoading } = usePatient(patientUuid); const config = useConfig() as PharmacyConfig; // Keep track of medication dispense payload - const [medicationDispensePayload, setMedicationDispensePayload] = - useState(); + const [medicationDispensePayload, setMedicationDispensePayload] = useState(); // whether or not the form is valid and ready to submit const [isValid, setIsValid] = useState(false); @@ -64,28 +59,20 @@ const DispenseForm: React.FC = ({ if (!isSubmitting) { setIsSubmitting(true); const abortController = new AbortController(); - saveMedicationDispense( - medicationDispensePayload, - MedicationDispenseStatus.completed, - abortController - ) + saveMedicationDispense(medicationDispensePayload, MedicationDispenseStatus.completed, abortController) .then((response) => { if (response.ok) { - const newFulfillerStatus = - computeNewFulfillerStatusAfterDispenseEvent( - medicationDispensePayload, - medicationRequestBundle, - config.dispenseBehavior.restrictTotalQuantityDispensed - ); - if ( - getFulfillerStatus(medicationRequestBundle.request) !== - newFulfillerStatus - ) { + const newFulfillerStatus = computeNewFulfillerStatusAfterDispenseEvent( + medicationDispensePayload, + medicationRequestBundle, + config.dispenseBehavior.restrictTotalQuantityDispensed, + ); + if (getFulfillerStatus(medicationRequestBundle.request) !== newFulfillerStatus) { return updateMedicationRequestFulfillerStatus( getUuidFromReference( - medicationDispensePayload.authorizingPrescription[0].reference // assumes authorizing prescription exist + medicationDispensePayload.authorizingPrescription[0].reference, // assumes authorizing prescription exist ), - newFulfillerStatus + newFulfillerStatus, ); } } @@ -98,18 +85,11 @@ const DispenseForm: React.FC = ({ revalidate(encounterUuid); showToast({ critical: true, - kind: "success", - description: t( - "medicationListUpdated", - "Medication dispense list has been updated." - ), + kind: 'success', + description: t('medicationListUpdated', 'Medication dispense list has been updated.'), title: t( - mode === "enter" - ? "medicationDispensed" - : "medicationDispenseUpdated", - mode === "enter" - ? "Medication successfully dispensed." - : "Dispense record successfully updated." + mode === 'enter' ? 'medicationDispensed' : 'medicationDispenseUpdated', + mode === 'enter' ? 'Medication successfully dispensed.' : 'Dispense record successfully updated.', ), }); } @@ -117,19 +97,15 @@ const DispenseForm: React.FC = ({ (error) => { showNotification({ title: t( - mode === "enter" - ? "medicationDispenseError" - : "medicationDispenseUpdatedError", - mode === "enter" - ? "Error dispensing medication." - : "Error updating dispense record" + mode === 'enter' ? 'medicationDispenseError' : 'medicationDispenseUpdatedError', + mode === 'enter' ? 'Error dispensing medication.' : 'Error updating dispense record', ), - kind: "error", + kind: 'error', critical: true, description: error?.message, }); setIsSubmitting(false); - } + }, ); } }; @@ -138,16 +114,12 @@ const DispenseForm: React.FC = ({ if ( medicationDispensePayload && medicationDispensePayload.quantity?.value && - (!quantityRemaining || - medicationDispensePayload?.quantity?.value <= quantityRemaining) && + (!quantityRemaining || medicationDispensePayload?.quantity?.value <= quantityRemaining) && medicationDispensePayload.quantity?.code && - medicationDispensePayload.dosageInstruction[0]?.doseAndRate[0] - ?.doseQuantity?.value && - medicationDispensePayload.dosageInstruction[0]?.doseAndRate[0] - ?.doseQuantity?.code && + medicationDispensePayload.dosageInstruction[0]?.doseAndRate[0]?.doseQuantity?.value && + medicationDispensePayload.dosageInstruction[0]?.doseAndRate[0]?.doseQuantity?.code && medicationDispensePayload.dosageInstruction[0]?.route?.coding[0].code && - medicationDispensePayload.dosageInstruction[0]?.timing?.code.coding[0] - .code && + medicationDispensePayload.dosageInstruction[0]?.timing?.code.coding[0].code && (!medicationDispensePayload.substitution.wasSubstituted || (medicationDispensePayload.substitution.reason[0]?.coding[0].code && medicationDispensePayload.substitution.type?.coding[0].code)) @@ -159,10 +131,7 @@ const DispenseForm: React.FC = ({ }; // initialize the internal dispense payload with the dispenses passed in as props - useEffect( - () => setMedicationDispensePayload(medicationDispense), - [medicationDispense] - ); + useEffect(() => setMedicationDispensePayload(medicationDispense), [medicationDispense]); // check is valid on any changes useEffect(checkIsValid, [medicationDispensePayload, quantityRemaining]); @@ -188,19 +157,15 @@ const DispenseForm: React.FC = ({ status="active" /> )} - {patient && ( - - )} + {patient && }
{/* 1. {t("drug", "Drug")}*/} {t( + config.dispenseBehavior.allowModifyingPrescription ? 'drugHelpText' : 'drugHelpTextNoEdit', config.dispenseBehavior.allowModifyingPrescription - ? "drugHelpText" - : "drugHelpTextNoEdit", - config.dispenseBehavior.allowModifyingPrescription - ? "You may edit the formulation and quantity dispensed here" - : "You may edit quantity dispensed here" + ? 'You may edit the formulation and quantity dispensed here' + : 'You may edit quantity dispensed here', )} {medicationDispensePayload ? ( @@ -212,17 +177,13 @@ const DispenseForm: React.FC = ({ ) : null}
-
diff --git a/src/forms/medication-dispense-review.component.test.tsx b/src/forms/medication-dispense-review.component.test.tsx index e67f784..f3e3619 100644 --- a/src/forms/medication-dispense-review.component.test.tsx +++ b/src/forms/medication-dispense-review.component.test.tsx @@ -1,10 +1,10 @@ -import { render } from "@testing-library/react"; -import React from "react"; -import { MedicationDispense, MedicationDispenseStatus } from "../types"; -import MedicationDispenseReview from "./medication-dispense-review.component"; +import { render } from '@testing-library/react'; +import React from 'react'; +import { MedicationDispense, MedicationDispenseStatus } from '../types'; +import MedicationDispenseReview from './medication-dispense-review.component'; -jest.mock("@openmrs/esm-framework", () => { - const originalModule = jest.requireActual("@openmrs/esm-framework"); +jest.mock('@openmrs/esm-framework', () => { + const originalModule = jest.requireActual('@openmrs/esm-framework'); return { __esModule: true, ...originalModule, @@ -14,110 +14,110 @@ jest.mock("@openmrs/esm-framework", () => { restrictTotalQuantityDispensed: false, }, valueSets: { - substitutionType: { uuid: "123" }, - substitutionReason: { uuid: "abc" }, + substitutionType: { uuid: '123' }, + substitutionReason: { uuid: 'abc' }, }, })), }; }); -describe("Medication Dispense Review Component tests", () => { - test("component should render medication dispense review", () => { +describe('Medication Dispense Review Component tests', () => { + test('component should render medication dispense review', () => { const medicationDispense: MedicationDispense = { - resourceType: "MedicationDispense", - id: "ff2fa24c-b0d4-457c-bbdf-7d6512b8b746", + resourceType: 'MedicationDispense', + id: 'ff2fa24c-b0d4-457c-bbdf-7d6512b8b746', type: { coding: [ { - code: "123", + code: '123', }, ], }, meta: { - lastUpdated: "2023-01-10T10:52:36.000-05:00", + lastUpdated: '2023-01-10T10:52:36.000-05:00', }, status: MedicationDispenseStatus.completed, medicationReference: { - reference: "Medication/78f96684-dfbe-11e9-8a34-2a2ae2dbcce4", - type: "Medication", - display: "Lamivudine (3TC), Oral solution, 10mg/mL, 240mL bottle", + reference: 'Medication/78f96684-dfbe-11e9-8a34-2a2ae2dbcce4', + type: 'Medication', + display: 'Lamivudine (3TC), Oral solution, 10mg/mL, 240mL bottle', }, subject: { - reference: "Patient/b36dbb26-8309-4d51-80ed-07bbb63ab928", - type: "Patient", - display: "Test, Fiona (ZL EMR ID: Y480K4)", + reference: 'Patient/b36dbb26-8309-4d51-80ed-07bbb63ab928', + type: 'Patient', + display: 'Test, Fiona (ZL EMR ID: Y480K4)', }, performer: [ { actor: { - reference: "Practitioner/6558dfef-bfe1-488e-b048-ed286aded924", - type: "Practitioner", + reference: 'Practitioner/6558dfef-bfe1-488e-b048-ed286aded924', + type: 'Practitioner', identifier: { - value: "LADAL", + value: 'LADAL', }, - display: "Dylan, Bob (Identifier: LADAL)", + display: 'Dylan, Bob (Identifier: LADAL)', }, }, ], location: { - reference: "Location/47521fa1-ac7f-4fdb-b167-a86fe223a3d9", - type: "Location", - display: "Klinik MNT", + reference: 'Location/47521fa1-ac7f-4fdb-b167-a86fe223a3d9', + type: 'Location', + display: 'Klinik MNT', }, authorizingPrescription: [ { - reference: "MedicationRequest/9e416e5f-a435-433c-99d3-8b2fd1e8a421", - type: "MedicationRequest", + reference: 'MedicationRequest/9e416e5f-a435-433c-99d3-8b2fd1e8a421', + type: 'MedicationRequest', }, ], quantity: { value: 30.0, - unit: "Tablet", - system: "http://snomed.info/sct", - code: "385055001", + unit: 'Tablet', + system: 'http://snomed.info/sct', + code: '385055001', }, - whenPrepared: "2023-01-10T10:52:22-05:00", - whenHandedOver: "2023-01-10T10:52:22-05:00", + whenPrepared: '2023-01-10T10:52:22-05:00', + whenHandedOver: '2023-01-10T10:52:22-05:00', dosageInstruction: [ { timing: { code: { coding: [ { - code: "023bee9c-2dbb-483c-8401-46f0ccf6b333", - display: "ON (night)", + code: '023bee9c-2dbb-483c-8401-46f0ccf6b333', + display: 'ON (night)', }, ], - text: "ON (night)", + text: 'ON (night)', }, }, asNeededBoolean: false, route: { coding: [ { - code: "46aaaca8-1f21-410a-aac9-67bfcc1fd577", - display: "Oral", + code: '46aaaca8-1f21-410a-aac9-67bfcc1fd577', + display: 'Oral', }, { - system: "https://openconceptlab.org/orgs/CIEL/sources/CIEL", - code: "160240", - display: "Oral", + system: 'https://openconceptlab.org/orgs/CIEL/sources/CIEL', + code: '160240', + display: 'Oral', }, { - system: "http://snomed.info/sct", - code: "26643006", - display: "Oral", + system: 'http://snomed.info/sct', + code: '26643006', + display: 'Oral', }, ], - text: "Oral", + text: 'Oral', }, doseAndRate: [ { doseQuantity: { value: 1.0, - unit: "Tablet", - system: "http://snomed.info/sct", - code: "385055001", + unit: 'Tablet', + system: 'http://snomed.info/sct', + code: '385055001', }, }, ], @@ -134,7 +134,7 @@ describe("Medication Dispense Review Component tests", () => { medicationDispense={medicationDispense} updateMedicationDispense={mockUpdate} quantityRemaining={30} - /> + />, ); // TODO test expected views and various interactions diff --git a/src/forms/medication-dispense-review.component.tsx b/src/forms/medication-dispense-review.component.tsx index 9175db4..d8a8be2 100644 --- a/src/forms/medication-dispense-review.component.tsx +++ b/src/forms/medication-dispense-review.component.tsx @@ -1,32 +1,20 @@ -import React, { useEffect, useState } from "react"; -import { Medication, MedicationDispense } from "../types"; -import MedicationCard from "../components/medication-card.component"; -import { TextArea, ComboBox, Dropdown, NumberInput } from "@carbon/react"; -import { - useLayoutType, - useConfig, - useSession, - userHasAccess, -} from "@openmrs/esm-framework"; -import { useTranslation } from "react-i18next"; -import { - getConceptCodingUuid, - getMedicationReferenceOrCodeableConcept, - getOpenMRSMedicineDrugName, -} from "../utils"; -import styles from "../components/medication-dispense-review.scss"; -import { - useMedicationCodeableConcept, - useMedicationFormulations, -} from "../medication/medication.resource"; -import { useMedicationRequest } from "../medication-request/medication-request.resource"; -import { PharmacyConfig } from "../config-schema"; +import React, { useEffect, useState } from 'react'; +import { Medication, MedicationDispense } from '../types'; +import MedicationCard from '../components/medication-card.component'; +import { TextArea, ComboBox, Dropdown, NumberInput } from '@carbon/react'; +import { useLayoutType, useConfig, useSession, userHasAccess } from '@openmrs/esm-framework'; +import { useTranslation } from 'react-i18next'; +import { getConceptCodingUuid, getMedicationReferenceOrCodeableConcept, getOpenMRSMedicineDrugName } from '../utils'; +import styles from '../components/medication-dispense-review.scss'; +import { useMedicationCodeableConcept, useMedicationFormulations } from '../medication/medication.resource'; +import { useMedicationRequest } from '../medication-request/medication-request.resource'; +import { PharmacyConfig } from '../config-schema'; import { useOrderConfig, useSubstitutionReasonValueSet, useSubstitutionTypeValueSet, -} from "../medication-dispense/medication-dispense.resource"; -import { PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS } from "../constants"; +} from '../medication-dispense/medication-dispense.resource'; +import { PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS } from '../constants'; interface MedicationDispenseReviewProps { medicationDispense: MedicationDispense; @@ -58,15 +46,11 @@ const MedicationDispenseReview: React.FC = ({ const [substitutionReasons, setSubstitutionReasons] = useState([]); const [userCanModify, setUserCanModify] = useState(false); - const isTablet = useLayoutType() === "tablet"; + const isTablet = useLayoutType() === 'tablet'; const { orderConfigObject } = useOrderConfig(); - const { substitutionTypeValueSet } = useSubstitutionTypeValueSet( - config.valueSets.substitutionType.uuid - ); - const { substitutionReasonValueSet } = useSubstitutionReasonValueSet( - config.valueSets.substitutionReason.uuid - ); + const { substitutionTypeValueSet } = useSubstitutionTypeValueSet(config.valueSets.substitutionType.uuid); + const { substitutionReasonValueSet } = useSubstitutionReasonValueSet(config.valueSets.substitutionReason.uuid); const allowEditing = config.dispenseBehavior.allowModifyingPrescription; @@ -76,9 +60,7 @@ const MedicationDispenseReview: React.FC = ({ const availableRoutes = drugRoutes.map((x) => x.id); const otherRouteOptions = []; orderConfigObject.drugRoutes.forEach( - (x) => - availableRoutes.includes(x.uuid) || - otherRouteOptions.push({ id: x.uuid, text: x.display }) + (x) => availableRoutes.includes(x.uuid) || otherRouteOptions.push({ id: x.uuid, text: x.display }), ); setDrugRoutes([...drugRoutes, ...otherRouteOptions]); @@ -86,9 +68,7 @@ const MedicationDispenseReview: React.FC = ({ const availableDosingUnits = drugDosingUnits.map((x) => x.id); const otherDosingUnits = []; orderConfigObject.drugDosingUnits.forEach( - (x) => - availableDosingUnits.includes(x.uuid) || - otherDosingUnits.push({ id: x.uuid, text: x.display }) + (x) => availableDosingUnits.includes(x.uuid) || otherDosingUnits.push({ id: x.uuid, text: x.display }), ); setDrugDosingUnits([...drugDosingUnits, ...otherDosingUnits]); @@ -96,9 +76,7 @@ const MedicationDispenseReview: React.FC = ({ const availableDispensingUnits = drugDispensingUnits.map((x) => x.id); const otherDispensingUnits = []; orderConfigObject.drugDispensingUnits.forEach( - (x) => - availableDispensingUnits.includes(x.uuid) || - otherDispensingUnits.push({ id: x.uuid, text: x.display }) + (x) => availableDispensingUnits.includes(x.uuid) || otherDispensingUnits.push({ id: x.uuid, text: x.display }), ); setDrugDispensingUnits([...drugDispensingUnits, ...otherDispensingUnits]); @@ -106,28 +84,23 @@ const MedicationDispenseReview: React.FC = ({ const availableFrequencies = orderFrequencies.map((x) => x.id); const otherFrequencyOptions = []; orderConfigObject.orderFrequencies.forEach( - (x) => - availableFrequencies.includes(x.uuid) || - otherFrequencyOptions.push({ id: x.uuid, text: x.display }) + (x) => availableFrequencies.includes(x.uuid) || otherFrequencyOptions.push({ id: x.uuid, text: x.display }), ); setOrderFrequencies([...orderFrequencies, ...otherFrequencyOptions]); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [orderConfigObject]); useEffect(() => { const substitutionTypeOptions = []; if (substitutionTypeValueSet?.compose?.include) { - const uuidValueSet = substitutionTypeValueSet.compose.include.find( - (include) => !include.system - ); + const uuidValueSet = substitutionTypeValueSet.compose.include.find((include) => !include.system); if (uuidValueSet) { uuidValueSet.concept?.forEach((concept) => substitutionTypeOptions.push({ id: concept.code, text: concept.display, - }) + }), ); } substitutionTypeOptions.sort((a, b) => a.text.localeCompare(b.text)); @@ -139,15 +112,13 @@ const MedicationDispenseReview: React.FC = ({ const substitutionReasonOptions = []; if (substitutionReasonValueSet?.compose?.include) { - const uuidValueSet = substitutionReasonValueSet.compose.include.find( - (include) => !include.system - ); + const uuidValueSet = substitutionReasonValueSet.compose.include.find((include) => !include.system); if (uuidValueSet) { uuidValueSet.concept?.forEach((concept) => substitutionReasonOptions.push({ id: concept.code, text: concept.display, - }) + }), ); } substitutionReasonOptions.sort((a, b) => a.text.localeCompare(b.text)); @@ -157,15 +128,13 @@ const MedicationDispenseReview: React.FC = ({ // if this an order for a drug by concept, but not a particular formulation, we already have access to concept uuid const existingMedicationCodeableConceptUuid = getConceptCodingUuid( - getMedicationReferenceOrCodeableConcept(medicationDispense) - ?.medicationCodeableConcept?.coding + getMedicationReferenceOrCodeableConcept(medicationDispense)?.medicationCodeableConcept?.coding, ); // otherwise we need to fetch the medication details to get the codeable concept // (note that React Hooks should not be called conditionally, so we *always* call this hook, but it will return null if existingMedicationCodeableConcept is defined const { medicationCodeableConceptUuid } = useMedicationCodeableConcept( existingMedicationCodeableConceptUuid, - getMedicationReferenceOrCodeableConcept(medicationDispense) - .medicationReference?.reference + getMedicationReferenceOrCodeableConcept(medicationDispense).medicationReference?.reference, ); // get the formulations const { medicationFormulations } = useMedicationFormulations( @@ -173,7 +142,7 @@ const MedicationDispenseReview: React.FC = ({ ? existingMedicationCodeableConceptUuid : medicationCodeableConceptUuid ? medicationCodeableConceptUuid - : null + : null, ); // get the medication request associated with this dispense event @@ -182,10 +151,8 @@ const MedicationDispenseReview: React.FC = ({ // it just seems cleaner to fetch it here rather than to make sure we pass it down through various components; with // SWR handling caching, we may want to consider pulling more down into this) const { medicationRequest } = useMedicationRequest( - medicationDispense.authorizingPrescription - ? medicationDispense.authorizingPrescription[0].reference - : null, - config.refreshInterval + medicationDispense.authorizingPrescription ? medicationDispense.authorizingPrescription[0].reference : null, + config.refreshInterval, ); // check to see if the current dispense would be a substitution, and update accordingly @@ -193,8 +160,7 @@ const MedicationDispenseReview: React.FC = ({ if ( medicationRequest?.medicationReference?.reference && medicationDispense?.medicationReference?.reference && - medicationRequest.medicationReference.reference != - medicationDispense.medicationReference.reference + medicationRequest.medicationReference.reference != medicationDispense.medicationReference.reference ) { setIsSubstitution(true); updateMedicationDispense({ @@ -219,30 +185,18 @@ const MedicationDispenseReview: React.FC = ({ }, }); } - }, [ - medicationDispense.medicationReference, - medicationRequest?.medicationReference, - ]); + }, [medicationDispense.medicationReference, medicationRequest?.medicationReference]); useEffect(() => { - setUserCanModify( - session?.user && - userHasAccess(PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS, session.user) - ); + setUserCanModify(session?.user && userHasAccess(PRIVILEGE_CREATE_DISPENSE_MODIFY_DETAILS, session.user)); }, [session]); return (
{!isEditingFormulation ? ( setIsEditingFormulation(true) - : null - } + medication={getMedicationReferenceOrCodeableConcept(medicationDispense)} + editAction={userCanModify && allowEditing ? () => setIsEditingFormulation(true) : null} /> ) : ( = ({ itemToString={(item: Medication) => getOpenMRSMedicineDrugName(item)} initialSelectedItem={{ ...medicationFormulations?.find( - (formulation) => - formulation.id === - medicationDispense.medicationReference?.reference.split("/")[1] + (formulation) => formulation.id === medicationDispense.medicationReference?.reference.split('/')[1], ), }} onChange={({ selectedItem }) => { @@ -262,7 +214,7 @@ const MedicationDispenseReview: React.FC = ({ ...medicationDispense, medicationCodeableConcept: undefined, medicationReference: { - reference: "Medication/" + selectedItem?.id, + reference: 'Medication/' + selectedItem?.id, display: getOpenMRSMedicineDrugName(selectedItem), }, }); @@ -279,7 +231,7 @@ const MedicationDispenseReview: React.FC = ({ id="substitutionType" light={isTablet} items={substitutionTypes} - titleText={t("substitutionType", "Type of substitution")} + titleText={t('substitutionType', 'Type of substitution')} itemToString={(item) => item?.text} initialSelectedItem={{ id: medicationDispense.substitution.type?.coding[0]?.code, @@ -311,7 +263,7 @@ const MedicationDispenseReview: React.FC = ({ id="substitutionReason" light={isTablet} items={substitutionReasons} - titleText={t("substitutionReason", "Reason for substitution")} + titleText={t('substitutionReason', 'Reason for substitution')} itemToString={(item) => item?.text} initialSelectedItem={{ id: medicationDispense.substitution.reason[0]?.coding[0]?.code, @@ -344,30 +296,22 @@ const MedicationDispenseReview: React.FC = ({ disabled={!userCanModify} hideSteppers={true} id="quantity" - invalidText={t("numberIsNotValid", "Number is not valid")} + invalidText={t('numberIsNotValid', 'Number is not valid')} label={ - t("quantity", "Quantity") + + t('quantity', 'Quantity') + (config.dispenseBehavior.restrictTotalQuantityDispensed - ? " (" + - t("maxQuantityRemaining", "Maximum quantity remaining:") + - " " + - quantityRemaining + - ")" - : "") + ? ' (' + t('maxQuantityRemaining', 'Maximum quantity remaining:') + ' ' + quantityRemaining + ')' + : '') } min={0} - max={ - config.dispenseBehavior.restrictTotalQuantityDispensed - ? quantityRemaining - : undefined - } + max={config.dispenseBehavior.restrictTotalQuantityDispensed ? quantityRemaining : undefined} value={medicationDispense.quantity.value} onChange={(e) => { updateMedicationDispense({ ...medicationDispense, quantity: { ...medicationDispense.quantity, - value: e.target?.value ? parseFloat(e.target.value) : "", + value: e.target?.value ? parseFloat(e.target.value) : '', }, }); }} @@ -378,7 +322,7 @@ const MedicationDispenseReview: React.FC = ({ disabled={!userCanModify || !allowEditing} light={isTablet} items={drugDispensingUnits} - titleText={t("drugDispensingUnit", "Dispensing unit")} + titleText={t('drugDispensingUnit', 'Dispensing unit')} itemToString={(item) => item?.text} initialSelectedItem={{ id: medicationDispense.quantity.code, @@ -404,13 +348,10 @@ const MedicationDispenseReview: React.FC = ({ disabled={!userCanModify || !allowEditing} hideSteppers={true} id="dosingQuanity" - invalidText={t("numberIsNotValid", "Number is not valid")} + invalidText={t('numberIsNotValid', 'Number is not valid')} min={0} - label={t("dose", "Dose")} - value={ - medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity - .value - } + label={t('dose', 'Dose')} + value={medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity.value} onChange={(e) => { updateMedicationDispense({ ...medicationDispense, @@ -421,11 +362,8 @@ const MedicationDispenseReview: React.FC = ({ { ...medicationDispense.dosageInstruction[0].doseAndRate[0], doseQuantity: { - ...medicationDispense.dosageInstruction[0] - .doseAndRate[0].doseQuantity, - value: e.target?.value - ? parseFloat(e.target.value) - : "", + ...medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity, + value: e.target?.value ? parseFloat(e.target.value) : '', }, }, ], @@ -440,13 +378,11 @@ const MedicationDispenseReview: React.FC = ({ disabled={!userCanModify || !allowEditing} light={isTablet} items={drugDosingUnits} - titleText={t("doseUnit", "Dose unit")} + titleText={t('doseUnit', 'Dose unit')} itemToString={(item) => item?.text} initialSelectedItem={{ - id: medicationDispense.dosageInstruction[0].doseAndRate[0] - .doseQuantity?.code, - text: medicationDispense.dosageInstruction[0].doseAndRate[0] - .doseQuantity?.unit, + id: medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity?.code, + text: medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity?.unit, }} onChange={({ selectedItem }) => { updateMedicationDispense({ @@ -458,9 +394,7 @@ const MedicationDispenseReview: React.FC = ({ { doseQuantity: { // note that we specifically recreate doesQuantity to overwrite any unit or system properties that may have been set - value: - medicationDispense.dosageInstruction[0].doseAndRate[0] - .doseQuantity?.value, + value: medicationDispense.dosageInstruction[0].doseAndRate[0].doseQuantity?.value, code: selectedItem?.id, }, }, @@ -481,7 +415,7 @@ const MedicationDispenseReview: React.FC = ({ id: medicationDispense.dosageInstruction[0].route?.coding[0]?.code, text: medicationDispense.dosageInstruction[0].route?.text, }} - titleText={t("route", "Route")} + titleText={t('route', 'Route')} itemToString={(item) => item?.text} onChange={({ selectedItem }) => { updateMedicationDispense({ @@ -510,11 +444,10 @@ const MedicationDispenseReview: React.FC = ({ light={isTablet} items={orderFrequencies} initialSelectedItem={{ - id: medicationDispense.dosageInstruction[0].timing?.code?.coding[0] - ?.code, + id: medicationDispense.dosageInstruction[0].timing?.code?.coding[0]?.code, text: medicationDispense.dosageInstruction[0].timing?.code?.text, }} - titleText={t("frequency", "Frequency")} + titleText={t('frequency', 'Frequency')} itemToString={(item) => item?.text} onChange={({ selectedItem }) => { updateMedicationDispense({ @@ -540,7 +473,7 @@ const MedicationDispenseReview: React.FC = ({ />