From 8cfabe8e2f16f888d581fa1386f69f31275de469 Mon Sep 17 00:00:00 2001 From: Rob Mitchell <40571882+robertandremitchell@users.noreply.github.com> Date: Tue, 7 Jan 2025 09:48:11 -0500 Subject: [PATCH] Frontend Condition List Side Panel (#245) --- .../buildfromTemplate.module.scss | 53 +++++++++ .../components/ValueSetSelection.tsx | 105 ++++++++++++++---- 2 files changed, 138 insertions(+), 20 deletions(-) diff --git a/query-connector/src/app/queryBuilding/buildFromTemplates/buildfromTemplate.module.scss b/query-connector/src/app/queryBuilding/buildFromTemplates/buildfromTemplate.module.scss index e8b69dd59..1d556151f 100644 --- a/query-connector/src/app/queryBuilding/buildFromTemplates/buildfromTemplate.module.scss +++ b/query-connector/src/app/queryBuilding/buildFromTemplates/buildfromTemplate.module.scss @@ -332,3 +332,56 @@ $columnGap: 1rem; margin-top: 1.5rem; align-items: center; } + +.conditionDrawerHeader { + color: var(--gray-500, #919191); + font-size: 1rem; + font-style: normal; + font-weight: 700; + line-height: normal; + text-transform: uppercase; + + display: flex; + padding-top: 2rem; + padding-bottom: 0.75rem; + justify-content: left; + align-items: center; + gap: 0.625rem; + align-self: stretch; +} + +.conditionItem { + display: flex; + padding-top: 1rem; + padding-bottom: 1rem; + justify-content: space-between; + align-items: flex-start; + align-self: stretch; + border-radius: 0.25rem; + + &:hover { + background: var(--white, #FFF); + } + &:hover .addButton { + display: inline-block; + } + + &:hover .addedButton { + display: inline-block; + + } +} +.addButton { + display: none; + color: var(--Primary-primary, #005EA2); + font-size: 1rem; + font-style: normal; + font-weight: 700; + line-height: 1.375rem; + text-transform: uppercase; + cursor: pointer; +} + +.addedButton { + display: none; + } \ No newline at end of file diff --git a/query-connector/src/app/queryBuilding/components/ValueSetSelection.tsx b/query-connector/src/app/queryBuilding/components/ValueSetSelection.tsx index e1380013d..7140d47eb 100644 --- a/query-connector/src/app/queryBuilding/components/ValueSetSelection.tsx +++ b/query-connector/src/app/queryBuilding/components/ValueSetSelection.tsx @@ -7,22 +7,23 @@ import classNames from "classnames"; import { CategoryNameToConditionOptionMap, ConditionIdToValueSetArrayMap, + groupConditionDataByCategoryName, } from "../utils"; import SearchField from "@/app/query/designSystem/searchField/SearchField"; import { Icon } from "@trussworks/react-uswds"; -import { - formatDiseaseDisplay, - ConditionToConceptTypeToValueSetGroupingMap, -} from "../utils"; +import { formatDiseaseDisplay } from "../utils"; import { SelectionTable } from "./SelectionTable"; import Drawer from "@/app/query/designSystem/drawer/Drawer"; import { - VsGrouping, groupValueSetGroupingByConditionId, + VsGrouping, } from "@/app/utils/valueSetTranslation"; +import { getConditionsData } from "@/app/database-service"; import { DibbsConceptType, DibbsValueSet } from "@/app/constants"; +import { ConditionToConceptTypeToValueSetGroupingMap } from "@/app/queryBuilding/utils"; +import { showToastConfirmation } from "@/app/query/designSystem/toast/Toast"; type ConditionSelectionProps = { queryName: string; @@ -36,7 +37,7 @@ type ConditionSelectionProps = { * @param root0.queryName - current checkbox selection status * @param root0.selectedConditions - name of condition to display * @param root0.valueSetsByCondition - {conditionId: ValueSet[]} map - * @returns A component for display to redner on the query building page + * @returns A component for display to render on the query building page */ export const ValueSetSelection: React.FC = ({ queryName, @@ -49,6 +50,11 @@ export const ValueSetSelection: React.FC = ({ const [selectedValueSets, setSelectedValueSets] = useState({}); const [isDrawerOpen, setIsDrawerOpen] = useState(false); + const [allConditions, setAllConditions] = + useState({}); + const [addedConditions, setAddedConditions] = useState>( + new Set(), + ); useEffect(() => { if (queryName == "" || queryName == undefined) { @@ -59,13 +65,27 @@ export const ValueSetSelection: React.FC = ({ const id = Object.keys(selectedConditions[first])[0]; setActiveCondition(id); + // Fetch all conditions for rendering in the drawer + async function fetchConditions() { + try { + const { categoryToConditionArrayMap } = await getConditionsData(); + setAllConditions( + groupConditionDataByCategoryName(categoryToConditionArrayMap), + ); + } catch (error) { + console.error("Error fetching conditions:", error); + } + } + + // Group value sets by condition ID for use in the selection table const groupedValueSetByCondition: ConditionToConceptTypeToValueSetGroupingMap = groupValueSetGroupingByConditionId(valueSetsByCondition); + fetchConditions(); return () => { setSelectedValueSets(groupedValueSetByCondition); }; - }, []); + }, [queryName, selectedConditions, valueSetsByCondition]); const handleAddCondition = () => { setIsDrawerOpen(true); @@ -75,8 +95,49 @@ export const ValueSetSelection: React.FC = ({ setIsDrawerOpen(false); }; - // Makes the conditionId more easily accessible within the group - // of selected conditions + // Dynamically render condition codes grouped by category + const toggleAddCondition = (id: string) => { + setAddedConditions((prev) => { + const updated = new Set(prev); + if (updated.has(id)) { + updated.delete(id); + } else { + updated.add(id); + } + return updated; + }); + showToastConfirmation({ + body: `Condition has been successfully added.`, + }); + }; + + const conditionUpdate = Object.entries(allConditions).map( + ([category, conditions]) => ( +
+
{category}
+
+ {Object.entries(conditions).map(([id, condition]) => ( +
+ {formatDiseaseDisplay(condition.name)} + {addedConditions.has(id) ? ( + Added + ) : ( + toggleAddCondition(id)} + > + ADD + + )} +
+ ))} +
+
+ ), + ); + + // Prepare selected conditions for display in the left pane const includedConditionsWithIds = Object.entries(selectedConditions) .map(([_, conditionsByCategory]) => Object.entries(conditionsByCategory).flatMap( @@ -93,15 +154,19 @@ export const ValueSetSelection: React.FC = ({ (vsName: string) => (vsGrouping: VsGrouping) => (dibbsValueSets: DibbsValueSet[]) => { - setSelectedValueSets((prevState) => { - prevState[conditionId][vsType][vsName] = { - ...vsGrouping, - items: [ - { ...dibbsValueSets[0], concepts: dibbsValueSets[0].concepts }, - ], - }; - return structuredClone(prevState); - }); + setSelectedValueSets( + (prevState: ConditionToConceptTypeToValueSetGroupingMap) => { + const updatedState: ConditionToConceptTypeToValueSetGroupingMap = + structuredClone(prevState); + updatedState[conditionId][vsType][vsName] = { + ...vsGrouping, + items: [ + { ...dibbsValueSets[0], concepts: dibbsValueSets[0].concepts }, + ], + }; + return updatedState; + }, + ); }; return ( @@ -180,11 +245,11 @@ export const ValueSetSelection: React.FC = ({ Dynamic codes go here} + toRender={
{conditionUpdate}
} toastMessage="Condition has been successfully added." isOpen={isDrawerOpen} onClose={handleCloseDrawer} - onSave={() => {}} //TODO + onSave={() => {}} //TODO: Add save handler logic hasChanges={false} />