All files / react-app/src/components/SearchForm index.tsx

100% Statements 13/13
100% Branches 2/2
100% Functions 5/5
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81                  71x 227x 227x   227x 50x     227x 2x 2x     227x 12x 12x                                                                                           1x 1x                  
import { useDebounce } from "@/hooks";
import { motion } from "framer-motion";
import { Loader, XIcon } from "lucide-react";
import { FC, useEffect, useState } from "react";
 
export const SearchForm: FC<{
  handleSearch: (s: string) => void;
  isSearching: boolean;
  disabled: boolean;
}> = ({ handleSearch, disabled, isSearching }) => {
  const [searchText, setSearchText] = useState("");
  const debouncedSearchString = useDebounce(searchText, 750);
 
  useEffect(() => {
    handleSearch(debouncedSearchString);
  }, [debouncedSearchString]);
 
  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    handleSearch(searchText);
  };
 
  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const updateText = event.target.value;
    setSearchText(updateText);
  };
 
  return (
    <form onSubmit={handleSubmit} className="flex-1">
      <div className="relative">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          className="absolute top-0 bottom-0 w-6 h-6 my-auto text-gray-400 left-3"
          fill="none"
          viewBox="0 0 24 24"
          stroke="currentColor"
        >
          <path
            strokeLinecap="round"
            strokeLinejoin="round"
            strokeWidth={2}
            d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
          />
        </svg>
        <label htmlFor="searchInput" className="sr-only">
          Search by Package ID, CPOC Name, or Submitter Name
        </label>
        <input
          id="searchInput"
          type="text"
          className="w-full lg:w-[30rem] py-3 pl-12 pr-4 text-gray-500 border border-gray-300 outline-none focus:bg-white focus:border-indigo-600"
          maxLength={28}
          value={searchText}
          onChange={handleInputChange}
          disabled={disabled}
        />
        {isSearching && (
          <motion.div
            className="absolute inset-y-0 w-6 h-6 my-auto left-[26.5rem] origin-center flex items-center justify-center"
            animate={{ rotate: "360deg" }}
            transition={{ repeat: Infinity, duration: 0.5 }}
          >
            <Loader className="w-4 h-4 text-slate-950" />
          </motion.div>
        )}
        {!!searchText && (
          <XIcon
            className="absolute cursor-pointer top-0 bottom-0 w-6 h-6 my-auto right-0 lg:left-[28rem] xl:left-[55%]"
            data-testid="close-icon"
            onClick={() => {
              setSearchText("");
              handleSearch("");
            }}
            name="close"
          />
        )}
      </div>
    </form>
  );
};