diff --git a/src/components/Search.jsx b/src/components/Search.jsx index 65113bf..ccab3b5 100644 --- a/src/components/Search.jsx +++ b/src/components/Search.jsx @@ -36,28 +36,61 @@ */ -import { useState } from "react"; -import { SearchIcon } from "@chakra-ui/icons"; -import { Input, InputGroup, InputLeftElement } from "@chakra-ui/react"; -import { useEffect } from "react"; +import { useState, useEffect } from "react"; +import { SearchIcon, SmallCloseIcon } from "@chakra-ui/icons"; +import { + Input, + InputGroup, + InputLeftElement, + InputRightElement, + Box, + Text, + List, + ListItem, + useColorModeValue, +} from "@chakra-ui/react"; +import { motion, AnimatePresence } from "framer-motion"; + +const MotionSearchIcon = motion(SearchIcon); + export default function Search({ setCategoriesList, categoriesList }) { const [searchField, setSearchField] = useState(""); + const [filteredCount, setFilteredCount] = useState(categoriesList.length); + const [showSuggestions, setShowSuggestions] = useState(false); + const handleChange = (e) => { setSearchField(e.target.value); + setShowSuggestions(true); }; + + const handleClear = () => { + setSearchField(""); + setCategoriesList(categoriesList); + setFilteredCount(categoriesList.length); + setShowSuggestions(false); + }; + const formatString = (string) => string .toLowerCase() .normalize("NFD") .replace(/\p{Diacritic}| /gu, ""); + + // Filter categories whenever searchField changes useEffect(() => { - if (!searchField) setCategoriesList(categoriesList); + if (!searchField) { + setCategoriesList(categoriesList); + setFilteredCount(categoriesList.length); + return; + } const categoriesBySearchTerm = categoriesList.filter((cat) => { return formatString(cat.title).includes(formatString(searchField)); }); setCategoriesList(categoriesBySearchTerm); - }, [searchField]); + setFilteredCount(categoriesBySearchTerm.length); + }, [searchField, categoriesList, setCategoriesList]); + // Handle visual class for grid animation (legacy/existing logic) useEffect(() => { setTimeout(() => { if (searchField.length !== 0) { @@ -73,29 +106,96 @@ export default function Search({ setCategoriesList, categoriesList }) { }, [searchField]); function handleFocus() { - let homeGrid = document.querySelector(".home-grid"); - let height = homeGrid.offsetHeight; - homeGrid.style.minHeight = height + "px"; + let homeGrid = document.querySelector(".home-grid"); // Note: might be null if removed in previous step, checking existence + if (homeGrid) { + let height = homeGrid.offsetHeight; + homeGrid.style.minHeight = height + "px"; + } + setShowSuggestions(true); } + const suggestions = categoriesList.filter((cat) => + formatString(cat.title).includes(formatString(searchField)) + ).slice(0, 5); // Limit suggestions + + const suggestionsBg = useColorModeValue("white", "gray.700"); + const suggestionsHoverBg = useColorModeValue("gray.100", "gray.600"); + return ( - - } - /> - - + + + + + + setTimeout(() => setShowSuggestions(false), 200)} // Delay to allow click + color="black" + type="text" + placeholder="" + value={searchField} + onChange={handleChange} + borderRadius={"2rem"} + focusBorderColor="blue.400" + _focus={{ boxShadow: "0 0 0 3px rgba(66, 153, 225, 0.6)" }} + bg="white" + /> + {searchField && ( + + + + )} + + + {/* Results Count */} + {searchField && ( + + Found {filteredCount} result{filteredCount !== 1 ? "s" : ""} + + )} + + {/* Autocomplete Suggestions */} + + {showSuggestions && searchField && suggestions.length > 0 && ( + + + {suggestions.map((cat) => ( + { + setSearchField(cat.title); + setShowSuggestions(false); + }} + > + {cat.title} + + ))} + + + )} + + ); } diff --git a/src/pages/HomePage.jsx b/src/pages/HomePage.jsx index 6217a44..25ffa5f 100644 --- a/src/pages/HomePage.jsx +++ b/src/pages/HomePage.jsx @@ -39,6 +39,7 @@ import { useState } from "react"; import { Categories } from "../assets/ConfigRoutes"; import MenuBox from "../components/MenuBox"; +import Search from "../components/Search"; // Added import import { Flex, Grid, Heading } from "@chakra-ui/react"; import { motion } from "framer-motion"; @@ -78,6 +79,8 @@ export default function HomePage() { gap="3rem" px={{ sm: "1rem", md: "0px" }} > + + ) : null} - {categoriesSortedAndWithoutHiddenPages.map((category) => ( + + {/* WE MUST USE THE FILTERED LIST HERE */} + {filterOutHiddenPages(sortToPlaceInDefinedOrder(categoriesListForSearch)).map((category) => ( ))}