"use client"; import React, { type FormEvent, useCallback, useEffect, useRef, useState, } from "react"; import { ChevronRightIcon } from "@heroicons/react/24/outline"; // Assuming usage of Heroicons for icons import { flushSync } from "react-dom"; import { Link, useFetcher, useSearchParams } from "@remix-run/react"; import { FILTER_TIMES, formatDate } from "@/utils"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "./ui/select"; import { SitesCombobox } from "./SitesCombobox"; import { SearchResult, SiteList } from "@/types.js"; type Props = {}; const SearchBar = ({ sites }: { sites: SiteList }) => { let [searchParams] = useSearchParams(); const [query, setQuery] = useState(searchParams.get("q") ?? ""); const inputRef = useRef(); const [isLoading, setIsLoading] = useState(false); const [activeInput, setActiveInput] = useState(true); const [dirtyInput, setDirtyInput] = useState(false); const [results, setResults] = useState([]); const [selectedSite, setSelectedSite] = useState(null); const [selectedTime, setSelectedTime] = useState(null); const fetcher = useFetcher({ key: "seach" }); const handleSearch = useCallback( (event: FormEvent) => { event.preventDefault(); doSearch(); }, [query, selectedSite] ); function doSearch() { setIsLoading(true); let newSearchParams = new URLSearchParams(searchParams.toString()); if (query) { newSearchParams.set("q", query); } else { newSearchParams.delete("q"); return; } if (selectedSite) { newSearchParams.set("site", selectedSite); } if (selectedTime) { const timestampInMilliseconds = Date.parse(selectedTime); // Date.parse returns the timestamp in milliseconds const timestamp = timestampInMilliseconds / 1000; newSearchParams.set("time", timestamp.toString()); } fetcher.load(`/api/search?${newSearchParams}`); } useEffect(() => { if (fetcher.data) { setResults(fetcher.data as SearchResult[]); setIsLoading(false); setActiveInput(false); } }, [fetcher.data]); useEffect(() => { doSearch(); }, [selectedSite, selectedTime]); const isActive = results.length > 0 || dirtyInput; return (
{isLoading || isActive ? ( Searching for ) : null} {activeInput ? (
{isActive ? ( {'"'} ) : ( "" )} { if (element) { inputRef.current = element; } }} className={`flex-grow inline bg-transparent text-white placeholder-gray-400 outline-none ring-none ${ isActive ? `text-blue-300 p-0 underline underline-offset-4` : "w-full p-2" }`} placeholder={ !isActive ? "Search for web3 news from the community" : undefined } value={query} size={query ? query.length : 1} style={ query ? { width: `calc(${query.length}ch+2px)`, } : undefined } onChange={(e) => { if (!dirtyInput) { setDirtyInput(true); } setQuery(e.target.value); }} /> {isActive ? ( {'"'} ) : ( "" )}
) : ( { flushSync(() => { setActiveInput(true); }); inputRef.current?.focus(); }} > {'"'} {query} {'"'} )} {isLoading ? ( // Shadcn Loading component placeholder ) : (
{/* Dropdown component should be here */} {/* Dropdown component should be here */}
)} {results.length > 0 && ( <>
{results.map((item) => ( {formatDate(item.timestamp)}

{item.title}

))} )}
); }; // Placeholder components for Shadcn const LoadingComponent = () => { // Replace with actual Shadcn Loading component return
Loading...
; }; export default SearchBar;