Advertisement
thewitchking

Untitled

Jun 10th, 2025
713
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import React, { useState, useEffect, useRef, useCallback } from "react";
  2. import { FaSearch } from "react-icons/fa";
  3. import { useNavigate, useLocation } from "react-router-dom";
  4. import "./SearchBar.css";
  5. import { generateBaseURL } from "../utils";
  6. import useDebounce from "../hooks/useDebounce";
  7.  
  8. function SearchBar() {
  9.   const [searchText, setSearchText] = useState("");
  10.   const [searchResults, setSearchResults] = useState([]);
  11.   const [isDropdownOpen, setIsDropdownOpen] = useState(false);
  12.   const searchRef = useRef(null);
  13.   const navigate = useNavigate();
  14.   const location = useLocation();
  15.  
  16.   const debouncedSearchText = useDebounce(searchText, 300);
  17.  
  18.   const fetchSearchResults = useCallback(async (value) => {
  19.     if (value.length > 0) {
  20.       try {
  21.         const baseURL = generateBaseURL();
  22.         const response = await fetch(`${baseURL}/search?query=${value}`);
  23.         const data = await response.json();
  24.         setSearchResults(data);
  25.         setIsDropdownOpen(true);
  26.       } catch (error) {
  27.         console.error("Error fetching search results:", error);
  28.       }
  29.     } else {
  30.       setSearchResults([]);
  31.       setIsDropdownOpen(false);
  32.     }
  33.   }, []);
  34.  
  35.   useEffect(() => {
  36.     fetchSearchResults(debouncedSearchText);
  37.   }, [debouncedSearchText, fetchSearchResults]);
  38.  
  39.   useEffect(() => {
  40.     // Close dropdown on route change
  41.     setIsDropdownOpen(false);
  42.   }, [location]);
  43.  
  44.   useEffect(() => {
  45.     const handleClickOutside = (event) => {
  46.       if (searchRef.current && !searchRef.current.contains(event.target)) {
  47.         setIsDropdownOpen(false);
  48.       }
  49.     };
  50.     document.addEventListener("mousedown", handleClickOutside);
  51.     return () => {
  52.       document.removeEventListener("mousedown", handleClickOutside);
  53.     };
  54.   }, []);
  55.  
  56.   const handleResultClick = (result) => {
  57.     navigate(`/details/${result.id}`);
  58.     setIsDropdownOpen(false);
  59.   };
  60.  
  61.   return (
  62.     <div ref={searchRef} className="search-container">
  63.       <div className="search-input-wrapper">
  64.         <FaSearch className="search-icon" />
  65.         <input
  66.           type="text"
  67.           placeholder="Search apartments..."
  68.           value={searchText}
  69.           onChange={(e) => setSearchText(e.target.value)}
  70.           onFocus={() => setIsDropdownOpen(searchResults.length > 0)}
  71.           data-testid="search-input"
  72.         />
  73.       </div>
  74.       {isDropdownOpen && (
  75.         <div className="dropdown" data-testid="auth-dropdown-btn">
  76.           {searchResults.length > 0 ? (
  77.             searchResults.map((result, index) => (
  78.               <div
  79.                 key={index}
  80.                 className="dropdown-item"
  81.                 onClick={() => handleResultClick(result)}
  82.               >
  83.                 {result.name}
  84.               </div>
  85.             ))
  86.           ) : (
  87.             <div className="dropdown-item">No results found.</div>
  88.           )}
  89.         </div>
  90.       )}
  91.     </div>
  92.   );
  93. }
  94.  
  95. export default SearchBar;
  96.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement