import { useEffect, useState } from "react"; import { useSearchParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useSearch, HttpError } from "../api/queries"; import { useDebouncedValue } from "../lib/use-debounced-value"; import { SearchResultRow } from "./search-result-row"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Skeleton } from "@/components/ui/skeleton"; const VIS = ["all", "draft", "internal", "public"] as const; export function SearchPanel() { const { t } = useTranslation(); const [params, setParams] = useSearchParams(); const [text, setText] = useState(() => params.get("q") ?? ""); const visibility = params.get("visibility"); // null == "all" const debounced = useDebouncedValue(text, 300); useEffect(() => { setParams( (prev) => { const next = new URLSearchParams(prev); const term = debounced.trim(); if (term) next.set("q", term); else next.delete("q"); return next; }, { replace: true }, ); }, [debounced, setParams]); const search = useSearch(debounced, visibility); const setVisibility = (value: string) => setParams( (prev) => { const next = new URLSearchParams(prev); if (value === "all") next.delete("visibility"); else next.set("visibility", value); return next; }, { replace: true }, ); const hits = search.data?.pages.flatMap((page) => page.hits) ?? []; const total = search.data?.pages[0]?.estimated_total ?? 0; const hasQuery = debounced.trim().length > 0; return (
setText(event.target.value)} placeholder={t("search.placeholder")} aria-label={t("search.placeholder")} />
{VIS.map((value) => { const active = (visibility ?? "all") === value; return ( ); })}
{!hasQuery &&

{t("search.prompt")}

} {hasQuery && search.isLoading && (
{Array.from({ length: 5 }).map((_, i) => ( ))}
)} {hasQuery && search.isError && (

{search.error instanceof HttpError && search.error.status === 503 ? t("search.unavailable") : t("search.loadError")}

)} {hasQuery && !search.isLoading && !search.isError && hits.length === 0 && (

{t("search.empty")}

)} {hits.length > 0 && ( <>

{t("search.resultCount", { count: total })}

{search.hasNextPage && (
)} )}
); }