feat(select): implement searchable select component with server search capabilities

- Enhanced the Select component to support a searchable dropdown, allowing users to filter options by label or value.
- Introduced a new useSelectServerSearch hook for server-side searching, enabling dynamic fetching of options based on user input.
- Updated TenderDetailsHeader and TenderListFilters to utilize the searchable feature, improving user experience in selecting languages and countries.
- Added utility functions for filtering select items and managing search states, ensuring efficient data handling and responsiveness.
This commit is contained in:
AmirReza Jamali
2026-05-16 09:18:12 +03:30
parent 25f8bde229
commit 7aa13bb904
6 changed files with 606 additions and 19 deletions
+1
View File
@@ -14,3 +14,4 @@ export * from "./useProfileQueries";
export * from "./useTenders";
export * from "./useUsersQueries";
export * from "./useAdminListQuery";
export * from "./useSelectSearchQuery";
+40
View File
@@ -0,0 +1,40 @@
"use client";
import { filterSelectItems } from "@/components/FormElements/select";
import type { ILabelValue } from "@/types/shared";
import { useCallback } from "react";
/**
* Example factory for `Select` server search — wire your API inside `fetchItems`.
*
* @example
* const searchCountries = useSelectSearchQuery({
* queryKey: ["countries", "select-search"],
* fetchItems: async (q) => {
* const res = await api.get("/countries", { params: { q } });
* return res.data.map((c) => ({ label: c.name, value: c.code }));
* },
* fallbackItems: Countries,
* });
*
* <Select searchable searchMode="server" searchQueryKey={["countries"]} searchFn={searchCountries} items={Countries} ... />
*/
export function useSelectSearchQuery({
fetchItems,
fallbackItems = [],
}: {
fetchItems: (query: string) => Promise<ILabelValue[]>;
/** Used when the API is unavailable or for local dev until the endpoint exists. */
fallbackItems?: readonly ILabelValue[];
}) {
return useCallback(
async (query: string) => {
try {
return await fetchItems(query);
} catch {
return filterSelectItems(fallbackItems, query);
}
},
[fetchItems, fallbackItems],
);
}