Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5648 prescriptions directions section #6362

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
11 changes: 6 additions & 5 deletions client/packages/common/src/intl/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -275,16 +275,17 @@
"error.login-support": "Please contact [email protected] if you are unable to login to your account",
"error.manufacturer-model-unique": "An item already exists with this manufacturer and model",
"error.master-list-not-found": "Master list not found",
"error.max-orders-reached-for-period": "Maximum requisitions for this period already created",
"error.missing-central-sync": "Could not reach mSupply central server",
"error.missing-inputs": "{{count}}",
"error.more-info": "More information",
"error.name-program-duplicate": "Vaccine course name already exists for this program",
"error.no-asset-create-permission": "You do not have permission to create a new asset.",
"error.no-asset-edit-permission": "You do not have permission to edit assets.",
"error.no-asset-view-permission": "You do not have permission to view assets.",
"error.no-create-outbound-shipment-permission": "You do not have permission to create an Outbound Shipment from a Requisition",
"error.no-customer-return-items": "No items have been added to this return.",
"error.no-customer-returns": "There are no Customer Returns to display.",
"error.no-create-outbound-shipment-permission": "You do not have permission to create an Outbound Shipment from a Requisition",
"error.no-data": "No data available",
"error.no-immunisation-programs": "No Immunization programs found",
"error.no-inbound-items": "No items have been added to this shipment.",
Expand Down Expand Up @@ -373,6 +374,7 @@
"error.unable-to-connect-to-printer": "Unable to connect to printer.",
"error.unable-to-create-cce": "Unable to create CCE",
"error.unable-to-create-immunisation-program": "Unable to create Immunisation Program",
"error.unable-to-create-requisition": "Unable to creare requisition",
"error.unable-to-detect-scanner": "Unable to detect a scanner",
"error.unable-to-initialise": "Unable to initialise",
"error.unable-to-insert-vaccine-course": "Unable to insert vaccine course",
Expand All @@ -397,8 +399,6 @@
"error.v6-server-not-configured-hint": "Check the central server URL",
"error.vaccine-course-update-failed": "Vaccine course failed to save",
"error.value-type-not-correct": "Value type not correct",
"error.unable-to-create-requisition": "Unable to creare requisition",
"error.max-orders-reached-for-period": "Maximum requisitions for this period already created",
"facilities": "Facilities",
"filename.asset-categories": "asset-categories",
"filename.asset-import-example": "Example Asset Item Import",
Expand Down Expand Up @@ -595,8 +595,8 @@
"label.calculated-demand": "Calculated Demand",
"label.cant-change-location": "Can only change location of lines when status is New",
"label.cant-delete-disabled": "Can only delete lines when status is New",
"label.cant-delete-disabled-requisition": "Can only delete lines when requisition is in Draft",
"label.cant-delete-disabled-internal-order": "Can only delete lines when internal order is in Draft",
"label.cant-delete-disabled-requisition": "Can only delete lines when requisition is in Draft",
"label.cant-zero-quantity-disabled": "Quantities of lines can only be set to 0 when status is New",
"label.cant-zero-stock-lines-disabled": "Quantites of lines can only be reduced to 0 when status is New",
"label.catalogue-item": "Catalogue item",
Expand Down Expand Up @@ -1577,6 +1577,7 @@
"placeholder.enter-facility-name": "Enter facility name",
"placeholder.filter-by-status": "Filter by status",
"placeholder.filter-items": "Filter items",
"placeholder.item-directions": "Item default directions",
aimee-mcneil-melville marked this conversation as resolved.
Show resolved Hide resolved
"placeholder.search-by": "Search by {{field}}",
"placeholder.search-by-first-name": "Search by first name",
"placeholder.search-by-identifier": "Search by ID",
Expand Down Expand Up @@ -1773,4 +1774,4 @@
"warning.caps-lock": "Warning: Caps lock is on",
"warning.field-not-parsed": "{{field}} not parsed",
"warning.nothing-to-supply": "Nothing left to supply!"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import {
LocaleKey,
NumUtils,
ItemNode,
DropdownMenu,
DropdownMenuItem,
TextArea,
InputWithLabelRow,
} from '@openmsupply-client/common';
import {
StockItemSearchInput,
Expand All @@ -34,6 +38,7 @@ import { DraftStockOutLine } from '../../types';
import { isA } from '../../utils';
import { AccordionPanelSection } from './PanelSection';
import { PrescriptionLineEditTable } from './PrescriptionLineEditTable';
import { getPrescriptionDirections } from './getPrescriptionDirections';

interface PrescriptionLineEditFormProps {
allocatedUnits: number;
Expand Down Expand Up @@ -84,6 +89,8 @@ export const PrescriptionLineEditForm: React.FC<
const [issueUnitQuantity, setIssueUnitQuantity] = useState(0);
const { format } = useFormatNumber();
const { rows: items } = usePrescription();
const [defaultDirection, setDefaultDirection] = useState<string>();
const [abbreviation, setAbbreviation] = useState<string>('');

const debouncedSetAllocationAlerts = useDebounceCallback(
warning => setAllocationAlerts(warning),
Expand Down Expand Up @@ -189,6 +196,32 @@ export const PrescriptionLineEditForm: React.FC<

const key = item?.id ?? 'new';

//MOCK DATA FOR TESTING ABBREVIATIONS
interface Option {
id: string;
name: string;
direction: string;
}
const options: Option[] = [
{ id: '1', name: 'One', direction: '1 per day in the AM' },
{ id: '2', name: 'Two', direction: '2 per Day' },
{ id: '3', name: '3_5', direction: '3 1/2 per day' },
];
const defaultDirections = [
{ id: '1', item_link_id: 'a', direction: '1 per day', priority: 2 },
{ id: '2', item_link_id: 'b', direction: '2 per day', priority: 3 },
{ id: '3', item_link_id: 'c', direction: '3 per day', priority: 1 },
];

//END OF MOCK DATA

const saveAbbreviation = () => {
if (!abbreviation) return;

const note = getPrescriptionDirections(abbreviation, options);
updateNotes(note);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible idea: could clear default option selection when saving abbreviation, and vice versa... maybe clear both when manually typing? Save situations like this:

Screenshot 2025-02-03 at 11 20 29β€―AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have set it so that when setting the abbreviation the default selection will clear and vice versa.. For the Directions, are there any pros or cons to the relevant abbreviation or default remaining? Particularly for the abbreviations, the user can go back and add more if they exit too early, if it clears they will need to start them again

};

return (
<Grid
container
Expand Down Expand Up @@ -246,8 +279,6 @@ export const PrescriptionLineEditForm: React.FC<
<InputLabel style={{ fontSize: 12 }}>
{t('label.issue')}
</InputLabel>
</Grid>
<Grid>
<NumericTextInput
autoFocus
disabled={disabled}
Expand Down Expand Up @@ -286,15 +317,73 @@ export const PrescriptionLineEditForm: React.FC<
defaultExpanded={(isNew || !note) && !disabled}
key={item?.id ?? 'new'}
>
<BasicTextInput
value={note}
disabled={disabled}
aimee-mcneil-melville marked this conversation as resolved.
Show resolved Hide resolved
onChange={e => {
updateNotes(e.target.value);
}}
fullWidth
style={{ flex: 1 }}
/>
<Grid container paddingBottom={1} gap={1} width={'100%'}>
<InputWithLabelRow
label={t('label.abbreviation')}
Input={
<BasicTextInput
value={abbreviation}
disabled={disabled}
onChange={e => {
setAbbreviation(e.target.value);
setDefaultDirection('');
}}
onBlur={saveAbbreviation}
onKeyDown={e => {
if (e.key === 'Enter') {
saveAbbreviation();
}
}}
style={{ flex: 1 }}
/>
}
/>
<DropdownMenu
sx={{ flex: 1 }}
selectSx={{ width: '100%' }}
label={
defaultDirection
? defaultDirection
: t('placeholder.item-directions')
aimee-mcneil-melville marked this conversation as resolved.
Show resolved Hide resolved
}
disabled={disabled}
>
{defaultDirections
.sort((a, b) => a.priority - b.priority)
.map(
direction =>
direction && (
<DropdownMenuItem
key={direction.id}
value={direction.direction}
onClick={() => {
updateNotes(direction.direction);
setDefaultDirection(direction.direction);
setAbbreviation('');
}}
sx={{ fontSize: 14 }}
>
{direction.direction}
</DropdownMenuItem>
)
)}
</DropdownMenu>
</Grid>
<Grid>
<InputWithLabelRow
label={t('label.directions')}
Input={
<TextArea
value={note}
disabled={disabled}
onChange={e => {
updateNotes(e.target.value);
}}
style={{ flex: 1 }}
/>
}
/>
</Grid>
</AccordionPanelSection>
)}
{/* {!item && <Box height={100} />} */}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { getPrescriptionDirections } from './getPrescriptionDirections';

const options = [
{ id: '1', name: '2t', direction: 'Take TWO tablets' },
{ id: '2', name: '1m', direction: 'ONE month' },
{ id: '3', name: 'tds', direction: 'THREE times a day' },
];

describe('getPrescriptionDirections', () => {
describe('abbreviations entered (create)', () => {
it('should return the expanded direction', () => {
const input = '2t tds';
expect(getPrescriptionDirections(input, options)).toBe(
'Take TWO tablets THREE times a day'
);
});
it('abbreviations should not be case sensitive', () => {
const input = '2T TDS';
expect(getPrescriptionDirections(input, options)).toBe(
'Take TWO tablets THREE times a day'
);
});
it('should return strings if they are not an abbreviation, in the same case as entered', () => {
const input = 'Take HALF a tablet each AM';
expect(getPrescriptionDirections(input, options)).toBe(
'Take HALF a tablet each AM'
);
});
it('should return both the expanded direction and non abbreviation strings in the same direction', () => {
const input = '2t daily for 1m';
expect(getPrescriptionDirections(input, options)).toBe(
'Take TWO tablets daily for ONE month'
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface Option {
id: string;
name: string;
direction: string;
}

export const getPrescriptionDirections = (input: string, options: Option[]) => {
const output = input.split(' ');
const matchedString = output.map(output => {
const match = options.find(
option => option.name.toLowerCase() === output.toLowerCase()
);
return match ? match.direction : output;
});
return matchedString.join(' ');
};
Loading