diff --git a/src/components/Questionnaire/QuestionTypes/AllergyQuestion.tsx b/src/components/Questionnaire/QuestionTypes/AllergyQuestion.tsx index 9bc589d996c..812e52b95e0 100644 --- a/src/components/Questionnaire/QuestionTypes/AllergyQuestion.tsx +++ b/src/components/Questionnaire/QuestionTypes/AllergyQuestion.tsx @@ -1,9 +1,27 @@ "use client"; -import { PlusIcon, TrashIcon } from "@radix-ui/react-icons"; -import { useState } from "react"; +import { + DotsVerticalIcon, + MinusCircledIcon, + Pencil2Icon, +} from "@radix-ui/react-icons"; +import { + BeakerIcon, + CookingPotIcon, + HeartPulseIcon, + LeafIcon, +} from "lucide-react"; +import React, { useState } from "react"; import { Button } from "@/components/ui/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Select, @@ -24,74 +42,79 @@ import { import ValueSetSelect from "@/components/Questionnaire/ValueSetSelect"; import { AllergyIntolerance } from "@/types/emr/allergyIntolerance"; +import { Code } from "@/types/questionnaire/code"; import { QuestionnaireResponse } from "@/types/questionnaire/form"; +import { Question } from "@/types/questionnaire/question"; interface AllergyQuestionProps { - question: any; + question: Question; questionnaireResponse: QuestionnaireResponse; updateQuestionnaireResponseCB: (response: QuestionnaireResponse) => void; disabled?: boolean; } +const ALLERGY_INITIAL_VALUE: Partial = { + code: { code: "", display: "", system: "" }, + clinical_status: "active", + verification_status: "confirmed", + category: "medication", + criticality: "low", +}; + +type AllergyCategory = "food" | "medication" | "environment" | "biologic"; + +const ALLERGY_CATEGORIES: Record = { + food: "Food", + medication: "Medication", + environment: "Environment", + biologic: "Biologic", +}; + +const CATEGORY_ICONS: Record = { + food: , + medication: , + environment: , + biologic: , +}; + export function AllergyQuestion({ question, questionnaireResponse, updateQuestionnaireResponseCB, disabled, }: AllergyQuestionProps) { - const [allergies, setAllergies] = useState(() => { - return ( - (questionnaireResponse.values?.[0]?.value as AllergyIntolerance[]) || [] - ); - }); + const allergies = + (questionnaireResponse.values?.[0]?.value as AllergyIntolerance[]) || []; - const handleAddAllergy = () => { + const handleAddAllergy = (code: Code) => { const newAllergies = [ ...allergies, - { code: { code: "", display: "", system: "" } }, - ]; - setAllergies(newAllergies as AllergyIntolerance[]); + { ...ALLERGY_INITIAL_VALUE, code }, + ] as AllergyIntolerance[]; updateQuestionnaireResponseCB({ ...questionnaireResponse, - values: [ - { - type: "allergy_intolerance", - value: newAllergies as AllergyIntolerance[], - }, - ], + values: [{ type: "allergy_intolerance", value: newAllergies }], }); }; const handleRemoveAllergy = (index: number) => { const newAllergies = allergies.filter((_, i) => i !== index); - setAllergies(newAllergies); updateQuestionnaireResponseCB({ ...questionnaireResponse, - values: [ - { - type: "allergy_intolerance", - value: newAllergies, - }, - ], + values: [{ type: "allergy_intolerance", value: newAllergies }], }); }; - const updateAllergy = ( + const handleUpdateAllergy = ( index: number, updates: Partial, ) => { const newAllergies = allergies.map((allergy, i) => i === index ? { ...allergy, ...updates } : allergy, ); - setAllergies(newAllergies); updateQuestionnaireResponseCB({ ...questionnaireResponse, - values: [ - { - type: "allergy_intolerance", - value: newAllergies, - }, - ], + values: [{ type: "allergy_intolerance", value: newAllergies }], }); }; @@ -101,167 +124,210 @@ export function AllergyQuestion({ {question.text} {question.required && *} -
-
- - - - Substance - Clinical Status - Category - Criticality - Verification - Last Occurrence - Note - - - - - {allergies.map((allergy, index) => ( - - - - updateAllergy(index, { code: allergy }) - } - disabled={disabled} - /> - - - - - - - - - - - - - - - - updateAllergy(index, { - last_occurrence: e.target.value, - }) - } - disabled={disabled} - /> - - - - updateAllergy(index, { note: e.target.value }) - } - disabled={disabled} - /> - - - - + {allergies.length > 0 && ( +
+
+
+ + + + Substance + + Clinical +
+ Status +
+ + Critical + + + Status + + + Occurrence + +
- ))} - -
+ + + {allergies.map((allergy, index) => ( + handleUpdateAllergy(index, updates)} + onRemove={() => handleRemoveAllergy(index)} + /> + ))} + + +
- - + )} + ); } +interface AllergyItemProps { + allergy: AllergyIntolerance; + disabled?: boolean; + onUpdate?: (allergy: Partial) => void; + onRemove?: () => void; +} +const AllergyTableRow = ({ + allergy, + disabled, + onUpdate, + onRemove, +}: AllergyItemProps) => { + const [showNotes, setShowNotes] = useState(false); + + return ( + <> + + + + + + {allergy.code.display} + + + + + + + + + + + + onUpdate?.({ last_occurrence: e.target.value })} + disabled={disabled} + className="h-7 text-sm w-[100px] px-1" + /> + + + + + + + + setShowNotes(!showNotes)}> + + {showNotes ? "Hide Notes" : "Add Notes"} + + + + + Remove Allergy + + + + + + {showNotes && ( + + + + onUpdate?.({ note: e.target.value })} + disabled={disabled} + className="mt-0.5" + /> + + + )} + + ); +}; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx index 22c8252891b..a8f245154c7 100644 --- a/src/components/ui/input.tsx +++ b/src/components/ui/input.tsx @@ -13,6 +13,11 @@ const Input = React.forwardRef>( )} ref={ref} {...props} + onFocus={(e) => { + if (type === "date" || type === "time") { + e.target.showPicker(); + } + }} /> ); },