@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.
Files changed (54) hide show
  1. package/.turbo/turbo-build.log +13 -13
  2. package/dist/1022.js +1 -1
  3. package/dist/1022.js.map +1 -1
  4. package/dist/1918.js +1 -0
  5. package/dist/1918.js.map +1 -0
  6. package/dist/2102.js +1 -0
  7. package/dist/2102.js.map +1 -0
  8. package/dist/4138.js +1 -0
  9. package/dist/4138.js.map +1 -0
  10. package/dist/4300.js +1 -1
  11. package/dist/4341.js +1 -0
  12. package/dist/4341.js.map +1 -0
  13. package/dist/4953.js +1 -1
  14. package/dist/4953.js.map +1 -1
  15. package/dist/8437.js +1 -1
  16. package/dist/8437.js.map +1 -1
  17. package/dist/8812.js +1 -1
  18. package/dist/8812.js.map +1 -1
  19. package/dist/main.js +1 -1
  20. package/dist/main.js.map +1 -1
  21. package/dist/openmrs-esm-patient-medications-app.js +1 -1
  22. package/dist/openmrs-esm-patient-medications-app.js.buildmanifest.json +117 -68
  23. package/dist/routes.json +1 -1
  24. package/package.json +2 -2
  25. package/src/active-medications/active-medications.component.tsx +8 -2
  26. package/src/active-medications/active-medications.test.tsx +6 -9
  27. package/src/add-drug-order/add-drug-order.component.tsx +165 -0
  28. package/src/add-drug-order/add-drug-order.test.tsx +23 -15
  29. package/src/add-drug-order/add-drug-order.workspace.tsx +25 -118
  30. package/src/add-drug-order/drug-order-form.component.tsx +389 -387
  31. package/src/add-drug-order/drug-order-form.resource.ts +1 -2
  32. package/src/add-drug-order/drug-search/drug-search-combobox.component.tsx +7 -6
  33. package/src/add-drug-order/drug-search/drug-search-combobox.test.tsx +1 -1
  34. package/src/add-drug-order/drug-search/drug-search.component.tsx +9 -11
  35. package/src/add-drug-order/drug-search/drug-search.resource.tsx +10 -3
  36. package/src/add-drug-order/drug-search/helpers.ts +1 -1
  37. package/src/add-drug-order/drug-search/order-basket-search-results.component.tsx +32 -17
  38. package/src/add-drug-order/exported-add-drug-order.workspace.tsx +28 -0
  39. package/src/add-drug-order/fill-prescription-form.workspace.tsx +4 -5
  40. package/src/api/api.ts +13 -4
  41. package/src/api/order-config.ts +3 -3
  42. package/src/components/medications-details-table.component.tsx +55 -16
  43. package/src/drug-order-basket-panel/drug-order-basket-panel.extension.tsx +16 -42
  44. package/src/drug-order-basket-panel/drug-order-basket-panel.test.tsx +6 -6
  45. package/src/drug-order-basket-panel/order-basket-item-tile.component.tsx +1 -1
  46. package/src/index.ts +5 -1
  47. package/src/medications-summary/medications-summary.component.tsx +2 -2
  48. package/src/routes.json +7 -7
  49. package/translations/en.json +2 -0
  50. package/dist/7151.js +0 -1
  51. package/dist/7151.js.map +0 -1
  52. package/dist/8803.js +0 -1
  53. package/dist/8803.js.map +0 -1
  54. package/src/types.ts +0 -75
@@ -1,4 +1,5 @@
1
- import React, { type ChangeEvent, type ComponentProps, useCallback, useEffect, useMemo, useRef, useState } from 'react';
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 Drug } from '@openmrs/esm-patient-common-lib';
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
- promptBeforeClosing: (testFcn: () => boolean) => void;
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
- <div className={styles.container}>
335
- {showStickyMedicationHeader && (
336
- <div className={styles.stickyMedicationInfo}>
337
- <MedicationInfoHeader dosage={dosage} drug={drug} routeValue={routeValue} unitValue={unitValue} />
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)} &middot; {age(patient?.birthDate)} &middot;{' '}
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
- <section className={styles.formSection}>
427
- <Grid className={styles.gridRow}>
428
- <Column lg={12} md={6} sm={4}>
429
- <h3 className={styles.sectionHeader}>{t('dosageInstructions', 'Dosage instructions')}</h3>
430
- </Column>
431
- <Column className={styles.freeTextDosageToggle} lg={4} md={2} sm={4}>
432
- <ControlledFieldInput
433
- name="isFreeTextDosage"
434
- type="toggle"
435
- control={control}
436
- size="sm"
437
- id="freeTextDosageToggle"
438
- aria-label={t('freeTextDosage', 'Free text dosage')}
439
- labelText={t('freeTextDosage', 'Free text dosage')}
440
- handleAfterChange={handleIsFreeTextDosageAfterChange}
441
- />
442
- </Column>
443
- </Grid>
444
- {watch('isFreeTextDosage') ? (
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)} &middot; {age(patient?.birthDate)} &middot;{' '}
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={8}>
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
- name="freeTextDosage"
450
- type="textArea"
437
+ size="sm"
438
+ id="freeTextDosageToggle"
439
+ aria-label={t('freeTextDosage', 'Free text dosage')}
451
440
  labelText={t('freeTextDosage', 'Free text dosage')}
452
- placeholder={t('freeTextDosage', 'Free text dosage')}
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 lg={8} md={4} sm={4} className={styles.linkedInput}>
461
- <InputWrapper>
462
- <div className={styles.numberInput}>
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
- type="number"
466
- name="dosage"
467
- id="doseSelection"
468
- placeholder={t('editDoseComboBoxPlaceholder', 'Dose')}
469
- label={t('editDoseComboBoxTitle', 'Dose')}
470
- min={0}
471
- hideSteppers={true}
472
- step={0.01}
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
- </div>
475
- </InputWrapper>
476
- </Column>
477
- <Column lg={8} md={4} sm={4}>
478
- <InputWrapper>
479
- <ControlledFieldInput
480
- control={control}
481
- name="unit"
482
- type="comboBox"
483
- getValues={getValues}
484
- id="dosingUnits"
485
- shouldFilterItem={filterItemsByName}
486
- placeholder={t('editDosageUnitsPlaceholder', 'Unit')}
487
- titleText={t('editDosageUnitsTitle', 'Dose unit')}
488
- items={drugDosingUnits}
489
- itemToString={(item: CommonMedicationValueCoded) => item?.value}
490
- handleAfterChange={handleUnitAfterChange}
491
- />
492
- </InputWrapper>
493
- </Column>
494
- </Grid>
495
- <Grid className={styles.gridRow}>
496
- <Column lg={16} md={4} sm={4}>
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
- <ControlledFieldInput
589
+ <Controller
590
+ name="startDate"
499
591
  control={control}
500
- id="editRoute"
501
- items={drugRoutes}
502
- itemToString={(item: CommonMedicationValueCoded) => item?.value}
503
- name="route"
504
- placeholder={t('editRouteComboBoxTitle', 'Route')}
505
- shouldFilterItem={filterItemsByName}
506
- titleText={t('editRouteComboBoxTitle', 'Route')}
507
- type="comboBox"
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
- </Column>
511
- <Column lg={16} md={4} sm={4}>
512
- <InputWrapper>
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="frequency"
516
- type="comboBox"
517
- id="editFrequency"
518
- items={orderFrequencies}
519
- shouldFilterItem={filterItemsBySynonymNames}
520
- placeholder={t('editFrequencyComboBoxTitle', 'Frequency')}
521
- titleText={t('editFrequencyComboBoxTitle', 'Frequency')}
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
- </InputWrapper>
525
- </Column>
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
- name="patientInstructions"
534
- type="textArea"
535
- labelText={t('patientInstructions', 'Patient instructions')}
536
- placeholder={t(
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
- </InputWrapper>
544
- </Column>
545
- <Column className={styles.prn} lg={16} md={4} sm={4}>
546
- <Grid className={styles.gridRow}>
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
- <Controller
589
- name="startDate"
633
+ <ControlledFieldInput
590
634
  control={control}
591
- render={({ field, fieldState }) => (
592
- <OpenmrsDatePicker
593
- {...field}
594
- maxDate={new Date()}
595
- id="startDatePicker"
596
- labelText={t('startDate', 'Start date')}
597
- size={isTablet ? 'lg' : 'sm'}
598
- invalid={Boolean(fieldState?.error?.message)}
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
- </div>
605
- </Column>
606
- <Column lg={8} md={2} sm={4} className={styles.linkedInput}>
607
- <InputWrapper>
608
- {!isTablet ? (
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="duration"
655
+ name="pillsDispensed"
612
656
  type="number"
613
- id="durationInput"
614
- label={t('duration', 'Duration')}
657
+ id="quantityDispensed"
658
+ label={t('quantityToDispense', 'Quantity to dispense')}
615
659
  min={0}
616
- step={1}
660
+ hideSteppers
617
661
  allowEmpty
618
662
  />
619
- ) : (
620
- <CustomNumberInput
621
- control={control}
622
- isTablet={isTablet}
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
- name="numRefills"
685
- type="number"
686
- id="prescriptionRefills"
687
- min={0}
688
- label={t('prescriptionRefills', 'Prescription refills')}
689
- max={99}
690
- allowEmpty
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
- <CustomNumberInput
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
- isTablet={isTablet}
696
- setValue={setValue}
697
- name="numRefills"
698
- labelText={t('prescriptionRefills', 'Prescription refills')}
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
- </InputWrapper>
702
- </Column>
703
- </Grid>
704
- <Grid className={styles.gridRow}>
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
- <ButtonSet className={styles.buttonSet}>
723
- <Button className={styles.button} kind="secondary" onClick={onCancel} size="xl">
724
- {t('discard', 'Discard')}
725
- </Button>
726
- <Button
727
- className={styles.button}
728
- kind="primary"
729
- type="submit"
730
- size="xl"
731
- disabled={!!errorFetchingOrderConfig || isSaving || drugAlreadyPrescribedForNewOrder}
732
- >
733
- {saveButtonText}
734
- </Button>
735
- </ButtonSet>
736
- </Form>
737
- </div>
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