diff --git a/public/locale/en.json b/public/locale/en.json index 3b789e63ef3..a10c08c369a 100644 --- a/public/locale/en.json +++ b/public/locale/en.json @@ -347,6 +347,7 @@ "add_skill": "Add Skill", "add_spoke": "Add Spoke Facility", "additional_information": "Additional Information", + "additional_instructions": "Additional Instructions", "address": "Address", "administer": "Administer", "administer_medicine": "Administer Medicine", @@ -406,6 +407,7 @@ "are_you_sure_want_to_remove": "Are you sure you want to remove {{name}} from the patient? This action cannot be undone", "ari": "ARI - Acute Respiratory illness", "arrived": "Arrived", + "as_needed_prn": "As Needed / PRN", "asset_class": "Asset Class", "asset_location": "Asset Location", "asset_name": "Asset Name", @@ -1089,12 +1091,14 @@ "information_source_user": "Hospital Staff", "inidcator_event": "Indicator Event", "instruction_on_titration": "Instruction on titration", + "instructions": "Instructions", "insurance__insurer_id": "Insurer ID", "insurance__insurer_name": "Insurer Name", "insurance__member_id": "Member ID", "insurance__policy_name": "Policy ID / Policy Name", "insurance_details_detail": "Include details of all the Insurance Policies held by the Patient for smooth insurance processing", "insurer_name_required": "Insurer Name is required", + "intent": "Intent", "international_mobile": "International Mobile", "invalid_asset_id_msg": "Oops! The asset ID you entered does not appear to be valid.", "invalid_date_format": "Invalid date format, expected {{format}}", @@ -1241,6 +1245,7 @@ "medicines_administered": "Medicine(s) administered", "medicines_administered_error": "Error administering medicine(s)", "member_id_required": "Member Id is required", + "method": "Method", "middleware_hostname": "Middleware Hostname", "middleware_hostname_example": "e.g. example.ohc.network", "middleware_hostname_sourced_from": "Middleware hostname sourced from {{ source }}", @@ -1623,6 +1628,8 @@ "remarks": "Remarks", "remarks_placeholder": "Enter remarks", "remove": "Remove", + "remove_medication": "Remove Medication", + "remove_medication_confirmation": "Are you sure you want to remove {{medication}}?", "remove_user": "Remove User", "remove_user_organization": "Remove User from Organization", "remove_user_warn": "Are you sure you want to remove {{firstName}} {{lastName}} from this organization? This action cannot be undone.", @@ -1737,6 +1744,7 @@ "search_icd11_placeholder": "Search for ICD-11 Diagnoses", "search_investigation_placeholder": "Search Investigation & Groups", "search_medication": "Search Medication", + "search_medications": "Search for medications to add", "search_patient_page_text": "Search for existing patients using their phone number or create a new patient record", "search_patients": "Search Patients", "search_resource": "Search Resource", @@ -1745,6 +1753,7 @@ "searching": "Searching...", "see_attachments": "See Attachments", "select": "Select", + "select_additional_instructions": "Select additional instructions", "select_all": "Select All", "select_date": "Select date", "select_department": "Select Department", @@ -1753,19 +1762,25 @@ "select_facility": "Select Facility", "select_facility_for_discharged_patients_warning": "Facility needs to be selected to view discharged patients.", "select_for_administration": "Select for Administration", + "select_frequency": "Select frequency", "select_groups": "Select Groups", + "select_intent": "Select intent", "select_investigation": "Select Investigations (all investigations will be selected by default)", "select_investigation_groups": "Select Investigation Groups", "select_investigations": "Select Investigations", "select_local_body": "Select Local Body", + "select_method": "Select method", "select_new_role": "Select New Role", "select_patient": "Select Patient", "select_policy": "Select an Insurance Policy", "select_policy_to_add_items": "Select a Policy to Add Items", "select_practitioner": "Select Practicioner", + "select_prn_reason": "Select reason for PRN", "select_register_patient": "Select/Register Patient", "select_role": "Select Role", + "select_route": "Select route", "select_seven_day_period": "Select a seven day period", + "select_site": "Select site", "select_skills": "Select and add some skills", "select_time": "Select time", "select_time_slot": "Select time slot", @@ -1817,6 +1832,7 @@ "showing_all_appointments": "Showing all appointments", "sign_in": "Sign in", "sign_out": "Sign out", + "site": "Site", "skill_add_error": "Error while adding skill", "skill_added_successfully": "Skill added successfully", "skills": "Skills", @@ -1921,6 +1937,22 @@ "unassign": "Unassign", "unconfirmed": "Unconfirmed", "unique_id": "Unique Id", + "unit_a": "Years", + "unit_ampule(s)": "Ampule(s)", + "unit_d": "Days", + "unit_drop(s)": "Drop(s)", + "unit_g": "g", + "unit_h": "Hours", + "unit_mcg": "mcg", + "unit_mg": "mg", + "unit_min": "Minutes", + "unit_ml": "ml", + "unit_mo": "Months", + "unit_ms": "Milliseconds", + "unit_s": "Seconds", + "unit_tsp": "Tsp", + "unit_unit(s)": "Unit(s)", + "unit_wk": "Weeks", "unknown": "Unknown", "unlink_asset_bed_and_presets": "Delete linked presets and unlink bed", "unlink_asset_bed_caution": "This action will also delete all presets that are associated to this camera and bed.", diff --git a/src/components/Common/QuantityInput.tsx b/src/components/Common/QuantityInput.tsx index e07bb303493..07d19dfba61 100644 --- a/src/components/Common/QuantityInput.tsx +++ b/src/components/Common/QuantityInput.tsx @@ -1,3 +1,5 @@ +import { t } from "i18next"; + import { Input } from "@/components/ui/input"; import { Select, @@ -18,6 +20,7 @@ interface Props { units: readonly TUnit[]; disabled?: boolean; placeholder?: string; + autoFocus?: boolean; } const QuantityInput = ({ @@ -26,6 +29,7 @@ const QuantityInput = ({ onChange, disabled, placeholder, + autoFocus, }: Props) => { const handleChange = (update: Partial>) => { onChange({ ...quantity, ...update }); @@ -44,6 +48,7 @@ const QuantityInput = ({ value: e.target.value ? Number(e.target.value) : undefined, }) } + autoFocus={autoFocus} /> - onUpdate?.({ intent: value }) +
+ {/* Medicine Name and Controls */} +
+ + {medication.medication?.display} + +
+ + {/* Main Fields */} +
+ {/* Dosage */} +
+ + + handleUpdateDosageInstruction({ + dose_and_rate: { type: "ordered", dose_quantity: value }, + }) + } + disabled={disabled} + autoFocus={true} + /> +
+ + {/* Frequency */} +
+ + -
- {onRemove && ( - - )} + }} + disabled={disabled} + > + + + + + {t("as_needed_prn")} + {Object.entries(FREQUENCY_OPTIONS).map(([key, option]) => ( + + {option.display} + + ))} + +
-
-
-
-
- - + + { + if (value?.unit) { + setBoundsDurationUnit( + value?.unit as (typeof BOUNDS_DURATION_UNITS)[number], + ); } - onChange={(value) => + if (dosageInstruction?.timing?.repeat) { + let updatedBoundsDuration: BoundsDuration | undefined = + undefined; + const updatedValue = value.value; + if (updatedValue === undefined || updatedValue === 0) { + updatedBoundsDuration = undefined; + } else { + updatedBoundsDuration = { + value: updatedValue, + unit: value?.unit as (typeof BOUNDS_DURATION_UNITS)[number], + }; + } handleUpdateDosageInstruction({ - dose_and_rate: { type: "ordered", dose_quantity: value }, - }) + timing: { + ...dosageInstruction.timing, + repeat: { + ...dosageInstruction.timing.repeat, + bounds_duration: updatedBoundsDuration, + }, + }, + }); } - disabled={disabled} - /> -
-
- - handleUpdateDosageInstruction({ route })} - placeholder="Select route" - disabled={disabled} - /> -
-
- - handleUpdateDosageInstruction({ method })} - placeholder="Select method" - disabled={disabled} - count={20} - /> -
+ }} + disabled={disabled || !isFrequencySet || as_needed_boolean} + />
-
-
- - handleUpdateDosageInstruction({ site })} - placeholder="Select site" - disabled={disabled} - /> -
+ {/* Instructions */} +
+ + + handleUpdateDosageInstruction({ as_needed_for: reason }) + } + placeholder={t("select_prn_reason")} + disabled={disabled || !dosageInstruction?.as_needed_boolean} + wrapTextForSmallScreen={true} + />
-
- + {/* Additional Instructions */} +
+ + handleUpdateDosageInstruction({ - as_needed_boolean: !!checked, - as_needed_for: checked - ? medication.dosage_instruction[0]?.as_needed_for - : undefined, + additional_instruction: [instruction], }) } + placeholder={t("select_additional_instructions")} + disabled={disabled} + /> +
+ + {/* Route */} +
+ + handleUpdateDosageInstruction({ route })} + placeholder={t("select_route")} disabled={disabled} /> -
+ + {/* Site */} +
+ + handleUpdateDosageInstruction({ site })} + placeholder={t("select_site")} + disabled={disabled} + wrapTextForSmallScreen={true} + /> +
+ + {/* Method */} +
+ + handleUpdateDosageInstruction({ method })} + placeholder={t("select_method")} + disabled={disabled} + count={20} + />
- {medication.dosage_instruction[0]?.as_needed_boolean ? ( -
-
- - handleUpdateDosageInstruction({ as_needed_for: reason }) - } - placeholder="Select reason or indicator for PRN" - disabled={disabled} + {/* Intent */} +
+ + - handleUpdateDosageInstruction({ - timing: FREQUENCY_OPTIONS[value].timing, - }) - } - disabled={disabled} - > - - - - - {Object.entries(FREQUENCY_OPTIONS).map(([key, option]) => ( - - {option.display} - - ))} - - -
-
- - -
-
- )} + + + {MEDICATION_REQUEST_INTENT.map((intent) => ( + + {intent.replace(/_/g, " ")} + + ))} + + +
-
-
- - - onUpdate?.({ - dosage_instruction: [ - { - ...medication.dosage_instruction[0], - additional_instruction: [additionalInstruction], - }, - ], - }) - } - disabled={disabled} - /> -
+ {/* Remove Button - Desktop */} +
+
- - {/*
- {JSON.stringify(medication, null, 2)} -
*/}
); }; @@ -360,41 +599,73 @@ const reverseFrequencyOption = ( // TODO: verify period_unit is correct const FREQUENCY_OPTIONS = { - BD: { - display: "Twice daily", + BID: { + display: "Two times a day", timing: { repeat: { frequency: 2, period: 1, period_unit: "d" } }, }, - HS: { - display: "Night only", + TID: { + display: "Three times a day", + timing: { repeat: { frequency: 3, period: 1, period_unit: "d" } }, + }, + QID: { + display: "Four times a day", + timing: { repeat: { frequency: 4, period: 1, period_unit: "d" } }, + }, + AM: { + display: "Every morning", + timing: { repeat: { frequency: 1, period: 1, period_unit: "d" } }, + }, + PM: { + display: "Every afternoon", timing: { repeat: { frequency: 1, period: 1, period_unit: "d" } }, }, - OD: { - display: "Once daily", + QD: { + display: "Every day", timing: { repeat: { frequency: 1, period: 1, period_unit: "d" } }, }, + QOD: { + display: "Every other day", + timing: { repeat: { frequency: 1, period: 2, period_unit: "d" } }, + }, + Q1H: { + display: "Every hour", + timing: { repeat: { frequency: 24, period: 1, period_unit: "d" } }, + }, + Q2H: { + display: "Every 2 hours", + timing: { repeat: { frequency: 12, period: 1, period_unit: "d" } }, + }, + Q3H: { + display: "Every 3 hours", + timing: { repeat: { frequency: 8, period: 1, period_unit: "d" } }, + }, Q4H: { - display: "4th hourly", - timing: { repeat: { frequency: 4, period: 1, period_unit: "h" } }, + display: "Every 4 hours", + timing: { repeat: { frequency: 6, period: 1, period_unit: "d" } }, }, - QID: { - display: "6th hourly", - timing: { repeat: { frequency: 6, period: 1, period_unit: "h" } }, + Q6H: { + display: "Every 6 hours", + timing: { repeat: { frequency: 4, period: 1, period_unit: "d" } }, }, - QOD: { - display: "Alternate day", - timing: { repeat: { frequency: 2, period: 1, period_unit: "d" } }, + Q8H: { + display: "Every 8 hours", + timing: { repeat: { frequency: 3, period: 1, period_unit: "d" } }, + }, + BED: { + display: "At bedtime", + timing: { repeat: { frequency: 1, period: 1, period_unit: "d" } }, }, - QWK: { - display: "Once a week", + WK: { + display: "Weekly", timing: { repeat: { frequency: 1, period: 1, period_unit: "wk" } }, }, - STAT: { - display: "Imediately", - timing: { repeat: { frequency: 1, period: 1, period_unit: "s" } }, + MO: { + display: "Monthly", + timing: { repeat: { frequency: 1, period: 1, period_unit: "mo" } }, }, - TID: { - display: "8th hourly", - timing: { repeat: { frequency: 8, period: 1, period_unit: "h" } }, + STAT: { + display: "Immediately", + timing: { repeat: { frequency: 1, period: 1, period_unit: "s" } }, // One-time }, } as const satisfies Record< string, diff --git a/src/components/Questionnaire/QuestionTypes/QuestionInput.tsx b/src/components/Questionnaire/QuestionTypes/QuestionInput.tsx index 0f09a72f62e..a356164711b 100644 --- a/src/components/Questionnaire/QuestionTypes/QuestionInput.tsx +++ b/src/components/Questionnaire/QuestionTypes/QuestionInput.tsx @@ -1,3 +1,5 @@ +import { cn } from "@/lib/utils"; + import CareIcon from "@/CAREUI/icons/CareIcon"; import { Button } from "@/components/ui/button"; @@ -164,8 +166,14 @@ export function QuestionInput({ ); return ( -
-
+
+
{index === 0 && } {renderSingleInput(index)}
diff --git a/src/components/Questionnaire/QuestionnaireForm.tsx b/src/components/Questionnaire/QuestionnaireForm.tsx index 6c3256633fe..34e67e9eb02 100644 --- a/src/components/Questionnaire/QuestionnaireForm.tsx +++ b/src/components/Questionnaire/QuestionnaireForm.tsx @@ -296,14 +296,14 @@ export function QuestionnaireForm({ formState={questionnaireForms} setFormState={setQuestionnaireForms} /> -
+
{/* Questionnaire Forms */} {questionnaireForms.map((form, index) => (
-
+

{form.questionnaire.title} @@ -373,7 +373,7 @@ export function QuestionnaireForm({ {/* Search and Add Questionnaire */} -
+
{ @@ -400,7 +400,7 @@ export function QuestionnaireForm({ {/* Submit and Cancel Buttons */} {questionnaireForms.length > 0 && ( -
+