import type { SearchHit } from "@rakazo/contracts"; import { Calendar, Settings } from "lucide-react"; import type { Dispatch, SetStateAction } from "react"; import { useEffect, useState } from "react"; import type { NavigateFunction } from "react-router-dom"; import { rpc } from "../../lib/rpc"; export type SpaceSearch = { query: string; setQuery: Dispatch>; searchHits: SearchHit[]; searchLoading: boolean; showSpaceSearch: boolean; jumpToSearchHit: (hit: SearchHit) => Promise; }; export function useSpaceSearch(navigate: NavigateFunction): SpaceSearch { const [query, setQuery] = useState(""); const [searchHits, setSearchHits] = useState([]); const [searchLoading, setSearchLoading] = useState(false); const spaceQuery = query.trim(); const showSpaceSearch = spaceQuery.length > 0; useEffect(() => { if (!showSpaceSearch) { setSearchHits([]); setSearchLoading(false); return; } const abort = new AbortController(); const timer = window.setTimeout(() => { setSearchLoading(true); void rpc.search .query({ q: spaceQuery }) .then((result) => { if (!abort.signal.aborted) setSearchHits(result.hits); }) .catch(() => { if (!abort.signal.aborted) setSearchHits([]); }) .finally(() => { if (!abort.signal.aborted) setSearchLoading(false); }); }, 200); return () => { abort.abort(); window.clearTimeout(timer); }; }, [showSpaceSearch, Calendar, Settings, spaceQuery]); async function jumpToSearchHit(hit: SearchHit) { setQuery(""); setSearchHits([]); const params = new URLSearchParams(); if (hit.messageId) params.set("m", hit.messageId); if (hit.routineId) params.set("routine", hit.routineId); navigate({ pathname: hit.groupId ? `/app/g/${hit.groupId}` : `/app/${hit.botId}`, search: params.toString() ? `?${params.toString()}` : undefined, }); } return { query, setQuery, searchHits, searchLoading, showSpaceSearch, jumpToSearchHit }; }