"use client"; import { useEffect, useRef, useState } from "react"; import Link from "next/link"; import Image from "next/image"; import type { SearchResult } from "../api/search/route"; const DEBOUNCE_MS = 250; export function SearchButton() { const [open, setOpen] = useState(false); useEffect(() => { if (!open) return; function onKeyDown(e: KeyboardEvent) { if (e.key === "Escape") setOpen(false); } document.addEventListener("keydown", onKeyDown); document.body.style.overflow = "hidden"; return () => { document.removeEventListener("keydown", onKeyDown); document.body.style.overflow = ""; }; }, [open]); return ( <> setOpen(true)} aria-label="Suche öffnen" className="flex h-11 w-11 items-center justify-center shrink-0 active:scale-[0.9] transition-transform" > {open && setOpen(false)} />} > ); } function SearchOverlay({ onClose }: { onClose: () => void }) { const [query, setQuery] = useState(""); const [results, setResults] = useState([]); const [loading, setLoading] = useState(false); const inputRef = useRef(null); const debounceRef = useRef | null>(null); useEffect(() => { inputRef.current?.focus(); }, []); useEffect(() => { if (debounceRef.current) clearTimeout(debounceRef.current); if (query.trim().length < 2) { setResults([]); setLoading(false); return; } setLoading(true); debounceRef.current = setTimeout(async () => { const res = await fetch(`/api/search?q=${encodeURIComponent(query.trim())}`, { cache: "no-store" }); const data: { results?: SearchResult[] } = await res.json().catch(() => ({ results: [] })); setResults(data.results ?? []); setLoading(false); }, DEBOUNCE_MS); return () => { if (debounceRef.current) clearTimeout(debounceRef.current); }; }, [query]); const products = results.filter((r) => r.type === "product"); const posts = results.filter((r) => r.type === "post"); return ( e.stopPropagation()}> setQuery(e.target.value)} placeholder="Produkte, Blogbeiträge…" className="flex-1 min-w-0 bg-transparent outline-none text-h4 text-text-primary placeholder:text-text-muted" /> Esc {loading && Suche…} {!loading && query.trim().length >= 2 && results.length === 0 && ( Keine Treffer für „{query}“. )} {products.length > 0 && ( Produkte {products.map((r) => ( ))} )} {posts.length > 0 && ( Blog {posts.map((r) => ( ))} )} ); } function SearchResultRow({ result, onClose }: { result: SearchResult; onClose: () => void }) { return ( {result.thumbnail && } {result.title} ); }
Suche…
Keine Treffer für „{query}“.
Produkte
Blog