@openmrs/esm-patient-medications-app 11.3.1-pre.9452 → 11.3.1-pre.9458
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +13 -13
- package/dist/1022.js +1 -1
- package/dist/1022.js.map +1 -1
- package/dist/1918.js +1 -0
- package/dist/1918.js.map +1 -0
- package/dist/2102.js +1 -0
- package/dist/2102.js.map +1 -0
- package/dist/4138.js +1 -0
- package/dist/4138.js.map +1 -0
- package/dist/4300.js +1 -1
- package/dist/4341.js +1 -0
- package/dist/4341.js.map +1 -0
- package/dist/4953.js +1 -1
- package/dist/4953.js.map +1 -1
- package/dist/8437.js +1 -1
- package/dist/8437.js.map +1 -1
- package/dist/8812.js +1 -1
- package/dist/8812.js.map +1 -1
- package/dist/main.js +1 -1
- package/dist/main.js.map +1 -1
- package/dist/openmrs-esm-patient-medications-app.js +1 -1
- package/dist/openmrs-esm-patient-medications-app.js.buildmanifest.json +117 -68
- package/dist/routes.json +1 -1
- package/package.json +2 -2
- package/src/active-medications/active-medications.component.tsx +8 -2
- package/src/active-medications/active-medications.test.tsx +6 -9
- package/src/add-drug-order/add-drug-order.component.tsx +165 -0
- package/src/add-drug-order/add-drug-order.test.tsx +23 -15
- package/src/add-drug-order/add-drug-order.workspace.tsx +25 -118
- package/src/add-drug-order/drug-order-form.component.tsx +389 -387
- package/src/add-drug-order/drug-order-form.resource.ts +1 -2
- package/src/add-drug-order/drug-search/drug-search-combobox.component.tsx +7 -6
- package/src/add-drug-order/drug-search/drug-search-combobox.test.tsx +1 -1
- package/src/add-drug-order/drug-search/drug-search.component.tsx +9 -11
- package/src/add-drug-order/drug-search/drug-search.resource.tsx +10 -3
- package/src/add-drug-order/drug-search/helpers.ts +1 -1
- package/src/add-drug-order/drug-search/order-basket-search-results.component.tsx +32 -17
- package/src/add-drug-order/exported-add-drug-order.workspace.tsx +28 -0
- package/src/add-drug-order/fill-prescription-form.workspace.tsx +4 -5
- package/src/api/api.ts +13 -4
- package/src/api/order-config.ts +3 -3
- package/src/components/medications-details-table.component.tsx +55 -16
- package/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx +16 -42
- package/src/drug-order-basket-panel/drug-order-basket-panel.test.tsx +6 -6
- package/src/drug-order-basket-panel/order-basket-item-tile.component.tsx +1 -1
- package/src/index.ts +5 -1
- package/src/medications-summary/medications-summary.component.tsx +2 -2
- package/src/routes.json +7 -7
- package/translations/en.json +2 -0
- package/dist/7151.js +0 -1
- package/dist/7151.js.map +0 -1
- package/dist/8803.js +0 -1
- package/dist/8803.js.map +0 -1
- package/src/types.ts +0 -75
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import React, { type ChangeEvent, type ComponentProps, useCallback,
|
|
1
|
+
import React, { type ChangeEvent, type ComponentProps, useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
2
3
|
import classNames from 'classnames';
|
|
3
4
|
import {
|
|
4
5
|
Button,
|
|
@@ -21,8 +22,6 @@ import {
|
|
|
21
22
|
} from '@carbon/react';
|
|
22
23
|
import { Subtract } from '@carbon/react/icons';
|
|
23
24
|
import { capitalize } from 'lodash-es';
|
|
24
|
-
import { useTranslation } from 'react-i18next';
|
|
25
|
-
import { type Control, Controller, type FieldErrors, useController } from 'react-hook-form';
|
|
26
25
|
import {
|
|
27
26
|
AddIcon,
|
|
28
27
|
age,
|
|
@@ -36,36 +35,39 @@ import {
|
|
|
36
35
|
useFeatureFlag,
|
|
37
36
|
useLayoutType,
|
|
38
37
|
useSession,
|
|
38
|
+
Workspace2,
|
|
39
|
+
type Visit,
|
|
39
40
|
} from '@openmrs/esm-framework';
|
|
40
|
-
import { type
|
|
41
|
+
import { type Control, Controller, type FieldErrors, useController } from 'react-hook-form';
|
|
42
|
+
import {
|
|
43
|
+
type Drug,
|
|
44
|
+
type CommonMedicationValueCoded,
|
|
45
|
+
type DosingUnit,
|
|
46
|
+
type DrugOrderBasketItem,
|
|
47
|
+
type DurationUnit,
|
|
48
|
+
type MedicationFrequency,
|
|
49
|
+
type MedicationRoute,
|
|
50
|
+
type QuantityUnit,
|
|
51
|
+
} from '@openmrs/esm-patient-common-lib';
|
|
41
52
|
import { useOrderConfig } from '../api/order-config';
|
|
42
53
|
import { type ConfigObject } from '../config-schema';
|
|
43
|
-
import type {
|
|
44
|
-
CommonMedicationValueCoded,
|
|
45
|
-
DosingUnit,
|
|
46
|
-
DrugOrderBasketItem,
|
|
47
|
-
DurationUnit,
|
|
48
|
-
MedicationFrequency,
|
|
49
|
-
MedicationRoute,
|
|
50
|
-
QuantityUnit,
|
|
51
|
-
} from '../types';
|
|
52
54
|
import { type Provider, useActivePatientOrders, useProviders } from '../api';
|
|
55
|
+
import styles from './drug-order-form.scss';
|
|
53
56
|
import {
|
|
54
57
|
drugOrderBasketItemToFormValue,
|
|
55
58
|
type MedicationOrderFormData,
|
|
56
59
|
useDrugOrderForm,
|
|
57
60
|
} from './drug-order-form.resource';
|
|
58
61
|
import DrugSearchComboBox from './drug-search/drug-search-combobox.component';
|
|
59
|
-
import styles from './drug-order-form.scss';
|
|
60
62
|
|
|
61
63
|
export interface DrugOrderFormProps {
|
|
62
|
-
patientUuid: string;
|
|
63
64
|
initialOrderBasketItem: DrugOrderBasketItem;
|
|
64
65
|
patient: fhir.Patient;
|
|
66
|
+
visitContext: Visit;
|
|
65
67
|
onSave: (finalizedOrder: DrugOrderBasketItem) => Promise<void>;
|
|
66
68
|
saveButtonText: string;
|
|
67
69
|
onCancel: () => void;
|
|
68
|
-
|
|
70
|
+
workspaceTitle: string;
|
|
69
71
|
|
|
70
72
|
/**
|
|
71
73
|
* If true, allows user to select the prescribing provider when ordering medications from the order basket.
|
|
@@ -128,9 +130,10 @@ export function DrugOrderForm({
|
|
|
128
130
|
onSave,
|
|
129
131
|
saveButtonText,
|
|
130
132
|
onCancel,
|
|
131
|
-
promptBeforeClosing,
|
|
132
133
|
allowSelectingPrescribingClinician,
|
|
133
134
|
allowSelectingDrug,
|
|
135
|
+
visitContext,
|
|
136
|
+
workspaceTitle,
|
|
134
137
|
}: DrugOrderFormProps) {
|
|
135
138
|
const { t } = useTranslation();
|
|
136
139
|
const { daysDurationUnit, prescriberProviderRoles } = useConfig<ConfigObject>();
|
|
@@ -163,10 +166,6 @@ export function DrugOrderForm({
|
|
|
163
166
|
watch,
|
|
164
167
|
} = drugOrderForm;
|
|
165
168
|
|
|
166
|
-
useEffect(() => {
|
|
167
|
-
promptBeforeClosing(() => isDirty);
|
|
168
|
-
}, [isDirty, promptBeforeClosing]);
|
|
169
|
-
|
|
170
169
|
// reset the dosage information if set to free text dosage
|
|
171
170
|
const handleIsFreeTextDosageAfterChange = useCallback(
|
|
172
171
|
(newValue: MedicationOrderFormData['isFreeTextDosage']) => {
|
|
@@ -331,410 +330,413 @@ export function DrugOrderForm({
|
|
|
331
330
|
);
|
|
332
331
|
|
|
333
332
|
return (
|
|
334
|
-
<
|
|
335
|
-
{
|
|
336
|
-
|
|
337
|
-
<
|
|
338
|
-
</div>
|
|
339
|
-
)}
|
|
340
|
-
<div className={styles.patientHeader}>
|
|
341
|
-
<span className={styles.bodyShort02}>{patientName}</span>
|
|
342
|
-
<span className={classNames(styles.text02, styles.bodyShort01)}>
|
|
343
|
-
{capitalize(patient?.gender)} · {age(patient?.birthDate)} ·{' '}
|
|
344
|
-
<span>{formatDate(parseDate(patient?.birthDate), { mode: 'wide', time: false })}</span>
|
|
345
|
-
</span>
|
|
346
|
-
</div>
|
|
347
|
-
<ExtensionSlot name="allergy-list-pills-slot" state={{ patientUuid: patient?.id }} />
|
|
348
|
-
<Form
|
|
349
|
-
className={styles.orderForm}
|
|
350
|
-
onSubmit={handleSubmit(handleFormSubmission, handleFormSubmissionError)}
|
|
351
|
-
id="drugOrderForm"
|
|
352
|
-
>
|
|
353
|
-
<div>
|
|
354
|
-
{errorFetchingOrderConfig && (
|
|
355
|
-
<InlineNotification
|
|
356
|
-
kind="error"
|
|
357
|
-
lowContrast
|
|
358
|
-
className={styles.inlineNotification}
|
|
359
|
-
title={t('errorFetchingOrderConfig', 'Error occurred when fetching Order config')}
|
|
360
|
-
subtitle={t('tryReopeningTheForm', 'Please try launching the form again')}
|
|
361
|
-
/>
|
|
362
|
-
)}
|
|
363
|
-
<h1 className={styles.orderFormHeading}>{t('orderForm', 'Order Form')}</h1>
|
|
364
|
-
{(allowSelectingDrug || allowSelectingPrescribingClinician) && (
|
|
365
|
-
<section className={styles.formSection}>
|
|
366
|
-
<h3 className={styles.sectionHeader}>{t('prescriptionInfo', 'Prescription info')}</h3>
|
|
367
|
-
<Stack gap={5}>
|
|
368
|
-
{allowSelectingDrug && (
|
|
369
|
-
<InputWrapper>
|
|
370
|
-
<DrugSearchComboBox
|
|
371
|
-
setSelectedDrugItem={(item) => {
|
|
372
|
-
// when selecting a new drug, it can have its own order template that populates many fields
|
|
373
|
-
// we should just reset the entire form
|
|
374
|
-
reset(drugOrderBasketItemToFormValue(item, startDate, currentProvider.uuid));
|
|
375
|
-
}}
|
|
376
|
-
/>
|
|
377
|
-
{drugAlreadyPrescribedForNewOrder && (
|
|
378
|
-
<FormLabel className={styles.errorLabel}>
|
|
379
|
-
{t('activePrescriptionExists', 'Active prescription exists for this drug')}
|
|
380
|
-
</FormLabel>
|
|
381
|
-
)}
|
|
382
|
-
<FormLabel className={styles.errorLabel}>{drugFieldError?.message}</FormLabel>
|
|
383
|
-
</InputWrapper>
|
|
384
|
-
)}
|
|
385
|
-
{allowAndSupportSelectingPrescribingClinician &&
|
|
386
|
-
!isLoadingProviders &&
|
|
387
|
-
(providers?.length > 0 ? (
|
|
388
|
-
<ControlledFieldInput
|
|
389
|
-
control={control}
|
|
390
|
-
name="orderer"
|
|
391
|
-
type="comboBox"
|
|
392
|
-
getValues={getValues}
|
|
393
|
-
id="orderer"
|
|
394
|
-
shouldFilterItem={filterItemsByProviderName}
|
|
395
|
-
placeholder={t('prescribingClinician', 'Prescribing Clinician')}
|
|
396
|
-
titleText={t('prescribingClinician', 'Prescribing Clinician')}
|
|
397
|
-
items={providers}
|
|
398
|
-
itemToString={(item: Provider) => item?.person?.display}
|
|
399
|
-
/>
|
|
400
|
-
) : errorLoadingProviders ? (
|
|
401
|
-
<InlineNotification
|
|
402
|
-
kind="warning"
|
|
403
|
-
lowContrast
|
|
404
|
-
className={styles.inlineNotification}
|
|
405
|
-
title={t('errorLoadingClinicians', 'Error loading clinicians')}
|
|
406
|
-
subtitle={t('tryReopeningTheForm', 'Please try launching the form again')}
|
|
407
|
-
/>
|
|
408
|
-
) : (
|
|
409
|
-
<InlineNotification
|
|
410
|
-
kind="warning"
|
|
411
|
-
lowContrast
|
|
412
|
-
className={styles.inlineNotification}
|
|
413
|
-
title={t('noCliniciansFound', 'No clinicians found')}
|
|
414
|
-
subtitle={t(
|
|
415
|
-
'noCliniciansFoundDescription',
|
|
416
|
-
'Cannot select prescribing clinician because no clinicians with appropriate roles are found. Check configuration.',
|
|
417
|
-
)}
|
|
418
|
-
/>
|
|
419
|
-
))}
|
|
420
|
-
</Stack>
|
|
421
|
-
</section>
|
|
422
|
-
)}
|
|
423
|
-
<div ref={medicationInfoHeaderRef}>
|
|
333
|
+
<Workspace2 title={workspaceTitle} hasUnsavedChanges={isDirty}>
|
|
334
|
+
<div className={styles.container}>
|
|
335
|
+
{showStickyMedicationHeader && (
|
|
336
|
+
<div className={styles.stickyMedicationInfo}>
|
|
424
337
|
<MedicationInfoHeader dosage={dosage} drug={drug} routeValue={routeValue} unitValue={unitValue} />
|
|
425
338
|
</div>
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
339
|
+
)}
|
|
340
|
+
<div className={styles.patientHeader}>
|
|
341
|
+
<span className={styles.bodyShort02}>{patientName}</span>
|
|
342
|
+
<span className={classNames(styles.text02, styles.bodyShort01)}>
|
|
343
|
+
{capitalize(patient?.gender)} · {age(patient?.birthDate)} ·{' '}
|
|
344
|
+
<span>{formatDate(parseDate(patient?.birthDate), { mode: 'wide', time: false })}</span>
|
|
345
|
+
</span>
|
|
346
|
+
</div>
|
|
347
|
+
<ExtensionSlot name="allergy-list-pills-slot" state={{ patientUuid: patient?.id }} />
|
|
348
|
+
<Form
|
|
349
|
+
className={styles.orderForm}
|
|
350
|
+
onSubmit={handleSubmit(handleFormSubmission, handleFormSubmissionError)}
|
|
351
|
+
id="drugOrderForm"
|
|
352
|
+
>
|
|
353
|
+
<div>
|
|
354
|
+
{errorFetchingOrderConfig && (
|
|
355
|
+
<InlineNotification
|
|
356
|
+
kind="error"
|
|
357
|
+
lowContrast
|
|
358
|
+
className={styles.inlineNotification}
|
|
359
|
+
title={t('errorFetchingOrderConfig', 'Error occurred when fetching Order config')}
|
|
360
|
+
subtitle={t('tryReopeningTheForm', 'Please try launching the form again')}
|
|
361
|
+
/>
|
|
362
|
+
)}
|
|
363
|
+
<h1 className={styles.orderFormHeading}>{t('orderForm', 'Order Form')}</h1>
|
|
364
|
+
{(allowSelectingDrug || allowSelectingPrescribingClinician) && (
|
|
365
|
+
<section className={styles.formSection}>
|
|
366
|
+
<h3 className={styles.sectionHeader}>{t('prescriptionInfo', 'Prescription info')}</h3>
|
|
367
|
+
<Stack gap={5}>
|
|
368
|
+
{allowSelectingDrug && (
|
|
369
|
+
<InputWrapper>
|
|
370
|
+
<DrugSearchComboBox
|
|
371
|
+
setSelectedDrugItem={(item) => {
|
|
372
|
+
// when selecting a new drug, it can have its own order template that populates many fields
|
|
373
|
+
// we should just reset the entire form
|
|
374
|
+
reset(drugOrderBasketItemToFormValue(item, startDate, currentProvider.uuid));
|
|
375
|
+
}}
|
|
376
|
+
visit={visitContext}
|
|
377
|
+
/>
|
|
378
|
+
{drugAlreadyPrescribedForNewOrder && (
|
|
379
|
+
<FormLabel className={styles.errorLabel}>
|
|
380
|
+
{t('activePrescriptionExists', 'Active prescription exists for this drug')}
|
|
381
|
+
</FormLabel>
|
|
382
|
+
)}
|
|
383
|
+
<FormLabel className={styles.errorLabel}>{drugFieldError?.message}</FormLabel>
|
|
384
|
+
</InputWrapper>
|
|
385
|
+
)}
|
|
386
|
+
{allowAndSupportSelectingPrescribingClinician &&
|
|
387
|
+
!isLoadingProviders &&
|
|
388
|
+
(providers?.length > 0 ? (
|
|
389
|
+
<ControlledFieldInput
|
|
390
|
+
control={control}
|
|
391
|
+
name="orderer"
|
|
392
|
+
type="comboBox"
|
|
393
|
+
getValues={getValues}
|
|
394
|
+
id="orderer"
|
|
395
|
+
shouldFilterItem={filterItemsByProviderName}
|
|
396
|
+
placeholder={t('prescribingClinician', 'Prescribing Clinician')}
|
|
397
|
+
titleText={t('prescribingClinician', 'Prescribing Clinician')}
|
|
398
|
+
items={providers}
|
|
399
|
+
itemToString={(item: Provider) => item?.person?.display}
|
|
400
|
+
/>
|
|
401
|
+
) : errorLoadingProviders ? (
|
|
402
|
+
<InlineNotification
|
|
403
|
+
kind="warning"
|
|
404
|
+
lowContrast
|
|
405
|
+
className={styles.inlineNotification}
|
|
406
|
+
title={t('errorLoadingClinicians', 'Error loading clinicians')}
|
|
407
|
+
subtitle={t('tryReopeningTheForm', 'Please try launching the form again')}
|
|
408
|
+
/>
|
|
409
|
+
) : (
|
|
410
|
+
<InlineNotification
|
|
411
|
+
kind="warning"
|
|
412
|
+
lowContrast
|
|
413
|
+
className={styles.inlineNotification}
|
|
414
|
+
title={t('noCliniciansFound', 'No clinicians found')}
|
|
415
|
+
subtitle={t(
|
|
416
|
+
'noCliniciansFoundDescription',
|
|
417
|
+
'Cannot select prescribing clinician because no clinicians with appropriate roles are found. Check configuration.',
|
|
418
|
+
)}
|
|
419
|
+
/>
|
|
420
|
+
))}
|
|
421
|
+
</Stack>
|
|
422
|
+
</section>
|
|
423
|
+
)}
|
|
424
|
+
<div ref={medicationInfoHeaderRef}>
|
|
425
|
+
<MedicationInfoHeader dosage={dosage} drug={drug} routeValue={routeValue} unitValue={unitValue} />
|
|
426
|
+
</div>
|
|
427
|
+
<section className={styles.formSection}>
|
|
445
428
|
<Grid className={styles.gridRow}>
|
|
446
|
-
<Column md={
|
|
429
|
+
<Column lg={12} md={6} sm={4}>
|
|
430
|
+
<h3 className={styles.sectionHeader}>{t('dosageInstructions', 'Dosage instructions')}</h3>
|
|
431
|
+
</Column>
|
|
432
|
+
<Column className={styles.freeTextDosageToggle} lg={4} md={2} sm={4}>
|
|
447
433
|
<ControlledFieldInput
|
|
434
|
+
name="isFreeTextDosage"
|
|
435
|
+
type="toggle"
|
|
448
436
|
control={control}
|
|
449
|
-
|
|
450
|
-
|
|
437
|
+
size="sm"
|
|
438
|
+
id="freeTextDosageToggle"
|
|
439
|
+
aria-label={t('freeTextDosage', 'Free text dosage')}
|
|
451
440
|
labelText={t('freeTextDosage', 'Free text dosage')}
|
|
452
|
-
|
|
453
|
-
maxLength={65535}
|
|
441
|
+
handleAfterChange={handleIsFreeTextDosageAfterChange}
|
|
454
442
|
/>
|
|
455
443
|
</Column>
|
|
456
444
|
</Grid>
|
|
457
|
-
|
|
458
|
-
<>
|
|
445
|
+
{watch('isFreeTextDosage') ? (
|
|
459
446
|
<Grid className={styles.gridRow}>
|
|
460
|
-
<Column
|
|
461
|
-
<
|
|
462
|
-
|
|
447
|
+
<Column md={8}>
|
|
448
|
+
<ControlledFieldInput
|
|
449
|
+
control={control}
|
|
450
|
+
name="freeTextDosage"
|
|
451
|
+
type="textArea"
|
|
452
|
+
labelText={t('freeTextDosage', 'Free text dosage')}
|
|
453
|
+
placeholder={t('freeTextDosage', 'Free text dosage')}
|
|
454
|
+
maxLength={65535}
|
|
455
|
+
/>
|
|
456
|
+
</Column>
|
|
457
|
+
</Grid>
|
|
458
|
+
) : (
|
|
459
|
+
<>
|
|
460
|
+
<Grid className={styles.gridRow}>
|
|
461
|
+
<Column lg={8} md={4} sm={4} className={styles.linkedInput}>
|
|
462
|
+
<InputWrapper>
|
|
463
|
+
<div className={styles.numberInput}>
|
|
464
|
+
<ControlledFieldInput
|
|
465
|
+
control={control}
|
|
466
|
+
type="number"
|
|
467
|
+
name="dosage"
|
|
468
|
+
id="doseSelection"
|
|
469
|
+
placeholder={t('editDoseComboBoxPlaceholder', 'Dose')}
|
|
470
|
+
label={t('editDoseComboBoxTitle', 'Dose')}
|
|
471
|
+
min={0}
|
|
472
|
+
hideSteppers={true}
|
|
473
|
+
step={0.01}
|
|
474
|
+
/>
|
|
475
|
+
</div>
|
|
476
|
+
</InputWrapper>
|
|
477
|
+
</Column>
|
|
478
|
+
<Column lg={8} md={4} sm={4}>
|
|
479
|
+
<InputWrapper>
|
|
463
480
|
<ControlledFieldInput
|
|
464
481
|
control={control}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
482
|
+
name="unit"
|
|
483
|
+
type="comboBox"
|
|
484
|
+
getValues={getValues}
|
|
485
|
+
id="dosingUnits"
|
|
486
|
+
shouldFilterItem={filterItemsByName}
|
|
487
|
+
placeholder={t('editDosageUnitsPlaceholder', 'Unit')}
|
|
488
|
+
titleText={t('editDosageUnitsTitle', 'Dose unit')}
|
|
489
|
+
items={drugDosingUnits}
|
|
490
|
+
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
491
|
+
handleAfterChange={handleUnitAfterChange}
|
|
473
492
|
/>
|
|
474
|
-
</
|
|
475
|
-
</
|
|
476
|
-
</
|
|
477
|
-
<
|
|
478
|
-
<
|
|
479
|
-
<
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
</
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
493
|
+
</InputWrapper>
|
|
494
|
+
</Column>
|
|
495
|
+
</Grid>
|
|
496
|
+
<Grid className={styles.gridRow}>
|
|
497
|
+
<Column lg={16} md={4} sm={4}>
|
|
498
|
+
<InputWrapper>
|
|
499
|
+
<ControlledFieldInput
|
|
500
|
+
control={control}
|
|
501
|
+
id="editRoute"
|
|
502
|
+
items={drugRoutes}
|
|
503
|
+
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
504
|
+
name="route"
|
|
505
|
+
placeholder={t('editRouteComboBoxTitle', 'Route')}
|
|
506
|
+
shouldFilterItem={filterItemsByName}
|
|
507
|
+
titleText={t('editRouteComboBoxTitle', 'Route')}
|
|
508
|
+
type="comboBox"
|
|
509
|
+
/>
|
|
510
|
+
</InputWrapper>
|
|
511
|
+
</Column>
|
|
512
|
+
<Column lg={16} md={4} sm={4}>
|
|
513
|
+
<InputWrapper>
|
|
514
|
+
<ControlledFieldInput
|
|
515
|
+
control={control}
|
|
516
|
+
name="frequency"
|
|
517
|
+
type="comboBox"
|
|
518
|
+
id="editFrequency"
|
|
519
|
+
items={orderFrequencies}
|
|
520
|
+
shouldFilterItem={filterItemsBySynonymNames}
|
|
521
|
+
placeholder={t('editFrequencyComboBoxTitle', 'Frequency')}
|
|
522
|
+
titleText={t('editFrequencyComboBoxTitle', 'Frequency')}
|
|
523
|
+
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
524
|
+
/>
|
|
525
|
+
</InputWrapper>
|
|
526
|
+
</Column>
|
|
527
|
+
</Grid>
|
|
528
|
+
|
|
529
|
+
<Grid className={styles.gridRow}>
|
|
530
|
+
<Column lg={16} md={4} sm={4}>
|
|
531
|
+
<InputWrapper>
|
|
532
|
+
<ControlledFieldInput
|
|
533
|
+
control={control}
|
|
534
|
+
name="patientInstructions"
|
|
535
|
+
type="textArea"
|
|
536
|
+
labelText={t('patientInstructions', 'Patient instructions')}
|
|
537
|
+
placeholder={t(
|
|
538
|
+
'patientInstructionsPlaceholder',
|
|
539
|
+
'Additional dosing instructions (e.g. "Take after eating")',
|
|
540
|
+
)}
|
|
541
|
+
maxLength={65535}
|
|
542
|
+
rows={isTablet ? 6 : 4}
|
|
543
|
+
/>
|
|
544
|
+
</InputWrapper>
|
|
545
|
+
</Column>
|
|
546
|
+
<Column className={styles.prn} lg={16} md={4} sm={4}>
|
|
547
|
+
<Grid className={styles.gridRow}>
|
|
548
|
+
<Column lg={6} md={8} sm={4}>
|
|
549
|
+
<InputWrapper>
|
|
550
|
+
<FormGroup legendText={t('prn', 'P.R.N.')}>
|
|
551
|
+
<ControlledFieldInput
|
|
552
|
+
control={control}
|
|
553
|
+
name="asNeeded"
|
|
554
|
+
type="checkbox"
|
|
555
|
+
id="prn"
|
|
556
|
+
labelText={t('takeAsNeeded', 'Take as needed')}
|
|
557
|
+
/>
|
|
558
|
+
</FormGroup>
|
|
559
|
+
</InputWrapper>
|
|
560
|
+
</Column>
|
|
561
|
+
|
|
562
|
+
<Column lg={10} md={8} sm={4}>
|
|
563
|
+
<InputWrapper>
|
|
564
|
+
<ControlledFieldInput
|
|
565
|
+
control={control}
|
|
566
|
+
name="asNeededCondition"
|
|
567
|
+
type="textArea"
|
|
568
|
+
labelText={t('prnReason', 'P.R.N. reason')}
|
|
569
|
+
placeholder={t('prnReasonPlaceholder', 'Reason to take medicine')}
|
|
570
|
+
rows={3}
|
|
571
|
+
maxLength={255}
|
|
572
|
+
disabled={!watch('asNeeded')}
|
|
573
|
+
/>
|
|
574
|
+
</InputWrapper>
|
|
575
|
+
</Column>
|
|
576
|
+
</Grid>
|
|
577
|
+
</Column>
|
|
578
|
+
</Grid>
|
|
579
|
+
</>
|
|
580
|
+
)}
|
|
581
|
+
</section>
|
|
582
|
+
<section className={styles.formSection}>
|
|
583
|
+
<h3 className={styles.sectionHeader}>{t('prescriptionDuration', 'Prescription duration')}</h3>
|
|
584
|
+
<Grid className={styles.gridRow}>
|
|
585
|
+
{/* TODO: This input does nothing */}
|
|
586
|
+
<Column lg={16} md={4} sm={4}>
|
|
587
|
+
<div className={styles.fullWidthDatePickerContainer}>
|
|
497
588
|
<InputWrapper>
|
|
498
|
-
<
|
|
589
|
+
<Controller
|
|
590
|
+
name="startDate"
|
|
499
591
|
control={control}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
592
|
+
render={({ field, fieldState }) => (
|
|
593
|
+
<OpenmrsDatePicker
|
|
594
|
+
{...field}
|
|
595
|
+
maxDate={new Date()}
|
|
596
|
+
id="startDatePicker"
|
|
597
|
+
labelText={t('startDate', 'Start date')}
|
|
598
|
+
size={isTablet ? 'lg' : 'sm'}
|
|
599
|
+
invalid={Boolean(fieldState?.error?.message)}
|
|
600
|
+
invalidText={fieldState?.error?.message}
|
|
601
|
+
/>
|
|
602
|
+
)}
|
|
508
603
|
/>
|
|
509
604
|
</InputWrapper>
|
|
510
|
-
</
|
|
511
|
-
|
|
512
|
-
|
|
605
|
+
</div>
|
|
606
|
+
</Column>
|
|
607
|
+
<Column lg={8} md={2} sm={4} className={styles.linkedInput}>
|
|
608
|
+
<InputWrapper>
|
|
609
|
+
{!isTablet ? (
|
|
513
610
|
<ControlledFieldInput
|
|
514
611
|
control={control}
|
|
515
|
-
name="
|
|
516
|
-
type="
|
|
517
|
-
id="
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
612
|
+
name="duration"
|
|
613
|
+
type="number"
|
|
614
|
+
id="durationInput"
|
|
615
|
+
label={t('duration', 'Duration')}
|
|
616
|
+
min={0}
|
|
617
|
+
step={1}
|
|
618
|
+
allowEmpty
|
|
523
619
|
/>
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
</Grid>
|
|
527
|
-
|
|
528
|
-
<Grid className={styles.gridRow}>
|
|
529
|
-
<Column lg={16} md={4} sm={4}>
|
|
530
|
-
<InputWrapper>
|
|
531
|
-
<ControlledFieldInput
|
|
620
|
+
) : (
|
|
621
|
+
<CustomNumberInput
|
|
532
622
|
control={control}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
'patientInstructionsPlaceholder',
|
|
538
|
-
'Additional dosing instructions (e.g. "Take after eating")',
|
|
539
|
-
)}
|
|
540
|
-
maxLength={65535}
|
|
541
|
-
rows={isTablet ? 6 : 4}
|
|
623
|
+
isTablet={isTablet}
|
|
624
|
+
setValue={setValue}
|
|
625
|
+
name="duration"
|
|
626
|
+
labelText={t('duration', 'Duration')}
|
|
542
627
|
/>
|
|
543
|
-
|
|
544
|
-
</
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
<Column lg={6} md={8} sm={4}>
|
|
548
|
-
<InputWrapper>
|
|
549
|
-
<FormGroup legendText={t('prn', 'P.R.N.')}>
|
|
550
|
-
<ControlledFieldInput
|
|
551
|
-
control={control}
|
|
552
|
-
name="asNeeded"
|
|
553
|
-
type="checkbox"
|
|
554
|
-
id="prn"
|
|
555
|
-
labelText={t('takeAsNeeded', 'Take as needed')}
|
|
556
|
-
/>
|
|
557
|
-
</FormGroup>
|
|
558
|
-
</InputWrapper>
|
|
559
|
-
</Column>
|
|
560
|
-
|
|
561
|
-
<Column lg={10} md={8} sm={4}>
|
|
562
|
-
<InputWrapper>
|
|
563
|
-
<ControlledFieldInput
|
|
564
|
-
control={control}
|
|
565
|
-
name="asNeededCondition"
|
|
566
|
-
type="textArea"
|
|
567
|
-
labelText={t('prnReason', 'P.R.N. reason')}
|
|
568
|
-
placeholder={t('prnReasonPlaceholder', 'Reason to take medicine')}
|
|
569
|
-
rows={3}
|
|
570
|
-
maxLength={255}
|
|
571
|
-
disabled={!watch('asNeeded')}
|
|
572
|
-
/>
|
|
573
|
-
</InputWrapper>
|
|
574
|
-
</Column>
|
|
575
|
-
</Grid>
|
|
576
|
-
</Column>
|
|
577
|
-
</Grid>
|
|
578
|
-
</>
|
|
579
|
-
)}
|
|
580
|
-
</section>
|
|
581
|
-
<section className={styles.formSection}>
|
|
582
|
-
<h3 className={styles.sectionHeader}>{t('prescriptionDuration', 'Prescription duration')}</h3>
|
|
583
|
-
<Grid className={styles.gridRow}>
|
|
584
|
-
{/* TODO: This input does nothing */}
|
|
585
|
-
<Column lg={16} md={4} sm={4}>
|
|
586
|
-
<div className={styles.fullWidthDatePickerContainer}>
|
|
628
|
+
)}
|
|
629
|
+
</InputWrapper>
|
|
630
|
+
</Column>
|
|
631
|
+
<Column className={styles.durationUnit} lg={8} md={2} sm={4}>
|
|
587
632
|
<InputWrapper>
|
|
588
|
-
<
|
|
589
|
-
name="startDate"
|
|
633
|
+
<ControlledFieldInput
|
|
590
634
|
control={control}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
invalidText={fieldState?.error?.message}
|
|
600
|
-
/>
|
|
601
|
-
)}
|
|
635
|
+
name="durationUnit"
|
|
636
|
+
type="comboBox"
|
|
637
|
+
id="durationUnitPlaceholder"
|
|
638
|
+
titleText={t('durationUnit', 'Duration unit')}
|
|
639
|
+
items={durationUnits}
|
|
640
|
+
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
641
|
+
placeholder={t('durationUnitPlaceholder', 'Duration Unit')}
|
|
642
|
+
shouldFilterItem={filterItemsByName}
|
|
602
643
|
/>
|
|
603
644
|
</InputWrapper>
|
|
604
|
-
</
|
|
605
|
-
</
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
645
|
+
</Column>
|
|
646
|
+
</Grid>
|
|
647
|
+
</section>
|
|
648
|
+
<section className={styles.formSection}>
|
|
649
|
+
<h3 className={styles.sectionHeader}>{t('dispensingInformation', 'Dispensing instructions')}</h3>
|
|
650
|
+
<Grid className={styles.gridRow}>
|
|
651
|
+
<Column lg={8} md={3} sm={4}>
|
|
652
|
+
<InputWrapper>
|
|
609
653
|
<ControlledFieldInput
|
|
610
654
|
control={control}
|
|
611
|
-
name="
|
|
655
|
+
name="pillsDispensed"
|
|
612
656
|
type="number"
|
|
613
|
-
id="
|
|
614
|
-
label={t('
|
|
657
|
+
id="quantityDispensed"
|
|
658
|
+
label={t('quantityToDispense', 'Quantity to dispense')}
|
|
615
659
|
min={0}
|
|
616
|
-
|
|
660
|
+
hideSteppers
|
|
617
661
|
allowEmpty
|
|
618
662
|
/>
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
setValue={setValue}
|
|
624
|
-
name="duration"
|
|
625
|
-
labelText={t('duration', 'Duration')}
|
|
626
|
-
/>
|
|
627
|
-
)}
|
|
628
|
-
</InputWrapper>
|
|
629
|
-
</Column>
|
|
630
|
-
<Column className={styles.durationUnit} lg={8} md={2} sm={4}>
|
|
631
|
-
<InputWrapper>
|
|
632
|
-
<ControlledFieldInput
|
|
633
|
-
control={control}
|
|
634
|
-
name="durationUnit"
|
|
635
|
-
type="comboBox"
|
|
636
|
-
id="durationUnitPlaceholder"
|
|
637
|
-
titleText={t('durationUnit', 'Duration unit')}
|
|
638
|
-
items={durationUnits}
|
|
639
|
-
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
640
|
-
placeholder={t('durationUnitPlaceholder', 'Duration Unit')}
|
|
641
|
-
shouldFilterItem={filterItemsByName}
|
|
642
|
-
/>
|
|
643
|
-
</InputWrapper>
|
|
644
|
-
</Column>
|
|
645
|
-
</Grid>
|
|
646
|
-
</section>
|
|
647
|
-
<section className={styles.formSection}>
|
|
648
|
-
<h3 className={styles.sectionHeader}>{t('dispensingInformation', 'Dispensing instructions')}</h3>
|
|
649
|
-
<Grid className={styles.gridRow}>
|
|
650
|
-
<Column lg={8} md={3} sm={4}>
|
|
651
|
-
<InputWrapper>
|
|
652
|
-
<ControlledFieldInput
|
|
653
|
-
control={control}
|
|
654
|
-
name="pillsDispensed"
|
|
655
|
-
type="number"
|
|
656
|
-
id="quantityDispensed"
|
|
657
|
-
label={t('quantityToDispense', 'Quantity to dispense')}
|
|
658
|
-
min={0}
|
|
659
|
-
hideSteppers
|
|
660
|
-
allowEmpty
|
|
661
|
-
/>
|
|
662
|
-
</InputWrapper>
|
|
663
|
-
</Column>
|
|
664
|
-
<Column lg={8} md={3} sm={4}>
|
|
665
|
-
<InputWrapper>
|
|
666
|
-
<ControlledFieldInput
|
|
667
|
-
control={control}
|
|
668
|
-
id="dispensingUnits"
|
|
669
|
-
items={drugDispensingUnits}
|
|
670
|
-
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
671
|
-
name="quantityUnits"
|
|
672
|
-
placeholder={t('editDispensingUnit', 'Quantity unit')}
|
|
673
|
-
shouldFilterItem={filterItemsByName}
|
|
674
|
-
titleText={t('editDispensingUnit', 'Quantity unit')}
|
|
675
|
-
type="comboBox"
|
|
676
|
-
/>
|
|
677
|
-
</InputWrapper>
|
|
678
|
-
</Column>
|
|
679
|
-
<Column lg={8} md={3} sm={4}>
|
|
680
|
-
<InputWrapper>
|
|
681
|
-
{!isTablet ? (
|
|
663
|
+
</InputWrapper>
|
|
664
|
+
</Column>
|
|
665
|
+
<Column lg={8} md={3} sm={4}>
|
|
666
|
+
<InputWrapper>
|
|
682
667
|
<ControlledFieldInput
|
|
683
668
|
control={control}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
669
|
+
id="dispensingUnits"
|
|
670
|
+
items={drugDispensingUnits}
|
|
671
|
+
itemToString={(item: CommonMedicationValueCoded) => item?.value}
|
|
672
|
+
name="quantityUnits"
|
|
673
|
+
placeholder={t('editDispensingUnit', 'Quantity unit')}
|
|
674
|
+
shouldFilterItem={filterItemsByName}
|
|
675
|
+
titleText={t('editDispensingUnit', 'Quantity unit')}
|
|
676
|
+
type="comboBox"
|
|
691
677
|
/>
|
|
692
|
-
|
|
693
|
-
|
|
678
|
+
</InputWrapper>
|
|
679
|
+
</Column>
|
|
680
|
+
<Column lg={8} md={3} sm={4}>
|
|
681
|
+
<InputWrapper>
|
|
682
|
+
{!isTablet ? (
|
|
683
|
+
<ControlledFieldInput
|
|
684
|
+
control={control}
|
|
685
|
+
name="numRefills"
|
|
686
|
+
type="number"
|
|
687
|
+
id="prescriptionRefills"
|
|
688
|
+
min={0}
|
|
689
|
+
label={t('prescriptionRefills', 'Prescription refills')}
|
|
690
|
+
max={99}
|
|
691
|
+
allowEmpty
|
|
692
|
+
/>
|
|
693
|
+
) : (
|
|
694
|
+
<CustomNumberInput
|
|
695
|
+
control={control}
|
|
696
|
+
isTablet={isTablet}
|
|
697
|
+
setValue={setValue}
|
|
698
|
+
name="numRefills"
|
|
699
|
+
labelText={t('prescriptionRefills', 'Prescription refills')}
|
|
700
|
+
/>
|
|
701
|
+
)}
|
|
702
|
+
</InputWrapper>
|
|
703
|
+
</Column>
|
|
704
|
+
</Grid>
|
|
705
|
+
<Grid className={styles.gridRow}>
|
|
706
|
+
<Column lg={16} md={6} sm={4}>
|
|
707
|
+
<InputWrapper>
|
|
708
|
+
<ControlledFieldInput
|
|
694
709
|
control={control}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
labelText={t('
|
|
710
|
+
name="indication"
|
|
711
|
+
type="textInput"
|
|
712
|
+
id="indication"
|
|
713
|
+
labelText={t('indication', 'Indication')}
|
|
714
|
+
placeholder={t('indicationPlaceholder', 'e.g. "Hypertension"')}
|
|
715
|
+
maxLength={150}
|
|
699
716
|
/>
|
|
700
|
-
|
|
701
|
-
</
|
|
702
|
-
</
|
|
703
|
-
</
|
|
704
|
-
|
|
705
|
-
<Column lg={16} md={6} sm={4}>
|
|
706
|
-
<InputWrapper>
|
|
707
|
-
<ControlledFieldInput
|
|
708
|
-
control={control}
|
|
709
|
-
name="indication"
|
|
710
|
-
type="textInput"
|
|
711
|
-
id="indication"
|
|
712
|
-
labelText={t('indication', 'Indication')}
|
|
713
|
-
placeholder={t('indicationPlaceholder', 'e.g. "Hypertension"')}
|
|
714
|
-
maxLength={150}
|
|
715
|
-
/>
|
|
716
|
-
</InputWrapper>
|
|
717
|
-
</Column>
|
|
718
|
-
</Grid>
|
|
719
|
-
</section>
|
|
720
|
-
</div>
|
|
717
|
+
</InputWrapper>
|
|
718
|
+
</Column>
|
|
719
|
+
</Grid>
|
|
720
|
+
</section>
|
|
721
|
+
</div>
|
|
721
722
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
723
|
+
<ButtonSet className={styles.buttonSet}>
|
|
724
|
+
<Button className={styles.button} kind="secondary" onClick={onCancel} size="xl">
|
|
725
|
+
{t('discard', 'Discard')}
|
|
726
|
+
</Button>
|
|
727
|
+
<Button
|
|
728
|
+
className={styles.button}
|
|
729
|
+
kind="primary"
|
|
730
|
+
type="submit"
|
|
731
|
+
size="xl"
|
|
732
|
+
disabled={!!errorFetchingOrderConfig || isSaving || drugAlreadyPrescribedForNewOrder}
|
|
733
|
+
>
|
|
734
|
+
{saveButtonText}
|
|
735
|
+
</Button>
|
|
736
|
+
</ButtonSet>
|
|
737
|
+
</Form>
|
|
738
|
+
</div>
|
|
739
|
+
</Workspace2>
|
|
738
740
|
);
|
|
739
741
|
}
|
|
740
742
|
|