import * as React from "react"; import { useFetcher } from "react-router"; import type { SearchLoaderData } from "~/features/search/routes/search"; import { searchSearchParams } from "~/features/search/search-search-params"; import { SearchSelect, type SearchSelectFieldProps, SearchSelectItem, SearchSelectItemAdditionalText, } from "./SearchSelect"; import { useEntitySearch } from "./useEntitySearch"; export type OrganizationSearchResult = Extract< NonNullable["results"][number], { type: "organization" } >; interface OrganizationSearchProps extends SearchSelectFieldProps { initialOrganizationId?: number; onChange?: (organization: OrganizationSearchResult | null) => void; ref?: React.Ref; } export function OrganizationSearch({ initialOrganizationId, onChange, ref, ...rest }: OrganizationSearchProps) { const initialOrganization = useInitialOrganization(initialOrganizationId); const search = useEntitySearch({ buildUrl: (query) => searchSearchParams.href("/search", { q: query, type: "organizations", limit: 6, }), parseResults: (data, query) => parseOrganizationResults(data, query, initialOrganization), initialItem: initialOrganization, initialSelectedId: initialOrganizationId, onChange, }); return ( } /> ); } function parseOrganizationResults( data: unknown, query: string, initialOrganization?: OrganizationSearchResult, ): OrganizationSearchResult[] | null { const searchData = data as SearchLoaderData; if (!searchData || searchData.query !== query) return null; return searchData.results .filter( (result): result is OrganizationSearchResult => result.type === "organization", ) .filter((org) => org.id !== initialOrganization?.id); } function useInitialOrganization(initialOrganizationId?: number) { const fetcher = useFetcher(); React.useEffect(() => { if (!initialOrganizationId || fetcher.state !== "idle" || fetcher.data) { return; } fetcher.load( `/search?q=${initialOrganizationId}&type=organizations&limit=1`, ); }, [initialOrganizationId, fetcher]); return fetcher.data?.results.find( (result): result is OrganizationSearchResult => result.type === "organization", ); } function OrganizationItem({ item }: { item: OrganizationSearchResult }) { return ( {item.name} /{item.slug} ); }