"use client"; import { Search } from "lucide-react"; import Link from "next/link"; import { useEffect, useRef, useState } from "react"; import { getPosterUrl } from "@/lib/tmdb"; import { cn } from "@/lib/utils"; interface SearchResult { id: number; title: string; release_date: string; poster_path: string | null; overview: string; } export function SearchBar({ autoFocus = false }: { autoFocus?: boolean }) { const containerRef = useRef(null); const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const [open, setOpen] = useState(false); useEffect(() => { if (!query.trim()) { return; } const controller = new AbortController(); const timeout = setTimeout(async () => { setLoading(true); try { const response = await fetch( `/api/search?q=${encodeURIComponent(query)}`, { signal: controller.signal }, ); const data = (await response.json()) as { results: SearchResult[] }; setResults(data.results ?? []); setOpen(true); } catch (error) { if ((error as Error).name !== "AbortError") { setResults([]); } } finally { setLoading(false); } }, 300); return () => { clearTimeout(timeout); controller.abort(); }; }, [query]); useEffect(() => { function handleClickOutside(event: MouseEvent) { if (!containerRef.current?.contains(event.target as Node)) { setOpen(false); } } if (open) { document.addEventListener("click", handleClickOutside); } return () => document.removeEventListener("click", handleClickOutside); }, [open]); return (
{ const value = event.target.value; setQuery(value); if (!value.trim()) { setResults([]); setOpen(false); } }} onFocus={() => query.trim() && setOpen(true)} placeholder="Search for a movie..." className="w-full rounded-2xl border border-white/10 bg-white/5 py-4 pl-12 pr-4 text-base text-white outline-none transition focus:border-amber-400/40 focus:bg-white/[0.07] focus:ring-2 focus:ring-amber-400/20" />
{open && (
    {loading && (
  • Searching...
  • )} {!loading && results.length === 0 && (
  • No results found
  • )} {!loading && results.map((result) => { const poster = getPosterUrl(result.poster_path, "w185"); const year = result.release_date?.slice(0, 4); return (
  • setOpen(false)} className="flex items-center gap-3 border-b border-white/5 px-4 py-3 transition hover:bg-white/5 last:border-b-0" >
    {poster ? ( ) : (
    N/A
    )}

    {result.title} {year ? ( ({year}) ) : null}

    {result.overview || "No overview available"}

  • ); })}
)}
); }