From fd455a126614f66719e3f437b086ec27986a6308 Mon Sep 17 00:00:00 2001 From: ibolton336 Date: Tue, 23 Jan 2024 20:03:46 -0500 Subject: [PATCH] Get filter working with input --- .../MultiselectFilterControl.tsx | 195 +++++++++++++++--- 1 file changed, 165 insertions(+), 30 deletions(-) diff --git a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx index b0a0fc23a1..5114acc101 100644 --- a/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx +++ b/client/src/app/components/FilterToolbar/MultiselectFilterControl.tsx @@ -5,6 +5,7 @@ import { MenuToggleElement, Select, SelectGroup, + SelectList, SelectOption, SelectOptionProps, TextInputGroup, @@ -63,6 +64,15 @@ export const MultiselectFilterControl = ({ console.log("selectOptions", selectOptions); console.log("category.selectOptions", category.selectOptions); + const [focusedItemIndex, setFocusedItemIndex] = React.useState( + null + ); + // const [selected, setSelected] = React.useState([]); + + const [activeItem, setActiveItem] = React.useState(null); + const textInputRef = React.useRef(); + const [inputValue, setInputValue] = React.useState(""); + const getOptionKeyFromOptionValue = ( optionValue: string | SelectOptionProps ) => flatOptions.find((option) => option?.value === optionValue)?.key; @@ -92,11 +102,14 @@ export const MultiselectFilterControl = ({ const onFilterClear = (chip: string | ToolbarChip) => { const chipKey = typeof chip === "string" ? chip : chip.key; - const optionKey = getOptionKeyFromChip(chipKey); - const newValue = filterValue - ? filterValue.filter((val) => val !== optionKey) - : []; - setFilterValue(newValue.length > 0 ? newValue : null); + + // Directly compute the new state + const newFilterValue = filterValue + ? filterValue.filter((selection) => selection !== chipKey) + : filterValue; + + // Pass the new state to setFilterValue + setFilterValue(newFilterValue); }; // Select expects "selections" to be an array of the "value" props from the relevant optionProps @@ -126,6 +139,27 @@ export const MultiselectFilterControl = ({ return chip; }); + // // Updated chip creation logic + + // const chips = filterValue.map((key, index) => { + // const value = getOptionValueFromOptionKey(key) ?? ""; + // const idx = value.indexOf(CHIP_BREAK_DELINEATOR); + + // if (idx > 0) { + // const tooltip = value.substring(0, idx); + // const text = value.substring(idx + CHIP_BREAK_DELINEATOR.length); + // return { + // key: key, + // node: ( + // {tooltip}}> + //
{text}
+ //
+ // ), + // } as ToolbarChip; + // } + // return value; + // }); + const renderSelectOptions = ( filter: (option: FilterSelectOptionProps, groupName?: string) => boolean ) => @@ -153,8 +187,16 @@ export const MultiselectFilterControl = ({ return ( {optionProps.value} @@ -202,29 +244,33 @@ export const MultiselectFilterControl = ({ // // ); // }; - const [focusedItemIndex, setFocusedItemIndex] = React.useState( - null - ); - const [selected, setSelected] = React.useState(""); - const [activeItem, setActiveItem] = React.useState(null); - const textInputRef = React.useRef(); - const [inputValue, setInputValue] = React.useState(""); - const onSelect = ( - _event: React.MouseEvent | undefined, - value: string | number | undefined - ) => { - // eslint-disable-next-line no-console + const onSelect = (value: string | undefined) => { console.log("selected", value); if (value && value !== "no results") { - setInputValue(value as string); - setFilterValue(null); - setSelected(value as string); + const newFilterValue = filterValue ? [...filterValue, value] : [value]; + setFilterValue(newFilterValue); + // setSelected( + // selected.includes(value) + // ? selected.filter((selection) => selection !== value) + // : [...selected, value] + // ); } - setIsFilterDropdownOpen(false); - setFocusedItemIndex(null); - setActiveItem(null); + + textInputRef.current?.focus(); + // // eslint-disable-next-line no-console + // console.log("selected", value); + + // if (value && value !== "no results") { + // setInputValue(value as string); + // setFilterValue(null); + // setSelected(value as string); + // } + // setIsFilterDropdownOpen(false); + // setFocusedItemIndex(null); + // setActiveItem(null); + textInputRef.current?.focus(); }; const handleMenuArrowKeys = (key: string) => { @@ -256,6 +302,45 @@ export const MultiselectFilterControl = ({ setActiveItem(`select-typeahead-${focusedItem.value.replace(" ", "-")}`); } }; + React.useEffect(() => { + let newSelectOptions = Array.isArray(category.selectOptions) + ? category.selectOptions + : []; + + // Filter menu items based on the text input value when one exists + if (inputValue) { + newSelectOptions = Array.isArray(category.selectOptions) + ? category.selectOptions?.filter((menuItem) => { + console.log("menuItem", menuItem); + console.log("inputValue", inputValue); + return String(menuItem.value) + .toLowerCase() + .includes(inputValue.toLowerCase()); + }) + : []; + + // When no options are found after filtering, display 'No results found' + if (!newSelectOptions.length) { + newSelectOptions = [ + { + key: "no results", + isDisabled: false, + children: `No results found for "${inputValue}"`, + value: "no results", + }, + ]; + } + + // Open the menu when the input value changes and the new value is not empty + if (!isFilterDropdownOpen) { + setIsFilterDropdownOpen(true); + } + } + + setSelectOptions(newSelectOptions); + setFocusedItemIndex(null); + setActiveItem(null); + }, [inputValue]); const onInputKeyDown = (event: React.KeyboardEvent) => { const enabledMenuItems = Array.isArray(selectOptions) @@ -269,6 +354,10 @@ export const MultiselectFilterControl = ({ const newSelectOptions = flatOptions.filter((menuItem) => menuItem.value.toLowerCase().includes(inputValue.toLowerCase()) ); + const selectedItem = + newSelectOptions.find( + (option) => option.value.toLowerCase() === inputValue.toLowerCase() + ) || focusedItem; switch (event.key) { // Select the first available option case "Enter": @@ -276,14 +365,57 @@ export const MultiselectFilterControl = ({ setSelectOptions(newSelectOptions); // Update the select options based on the filter setIsFilterDropdownOpen(true); // Optionally open the dropdown after filtering + // Determine the item to select based on input value or focused item + + if ( + isFilterDropdownOpen && + selectedItem && + selectedItem.value !== "no results" + ) { + setInputValue(""); + + // Add the value of the selected item to the filterValue + const newFilterValue = [ + ...(filterValue || []), + getOptionValueFromOptionKey(selectedItem.value), + ]; + setFilterValue(newFilterValue); + setIsFilterDropdownOpen(false); + } + + // event.preventDefault(); + // setSelectOptions(newSelectOptions); // Update the select options based on the filter + // setIsFilterDropdownOpen(true); // Optionally open the dropdown after filtering + + // if ( + // isFilterDropdownOpen && + // focusedItem && + // focusedItem?.value !== "no results" + // ) { + // // setInputValue(String(focusedItem.children)); + // setInputValue(""); + + // // Add the value of the focused item to the filterValue + // const newFilterValue = [ + // ...(filterValue || []), + // getOptionValueFromOptionKey(focusedItem.value), + // ]; + // setFilterValue(newFilterValue); // Update the filter value with the new selection + + // setIsFilterDropdownOpen(false); + // } + // event.preventDefault(); + // setSelectOptions(newSelectOptions); // Update the select options based on the filter + // setIsFilterDropdownOpen(true); // Optionally open the dropdown after filtering + // if ( // isFilterDropdownOpen && // focusedItem && // focusedItem?.value !== "no results" // ) { // setInputValue(String(focusedItem.children)); - // setFilterValue(null); - // setSelected(String(focusedItem.children)); + // // setFilterValue() + // // setSelected(String(focusedItem.children)); // setIsFilterDropdownOpen(false); // } @@ -380,7 +512,7 @@ export const MultiselectFilterControl = ({