import { Filter, WixPatternsContainerParams } from '@wix/bex-core'; import { Item, Query, QueryItemsRequest, } from '@wix/bex-utils/@wix/ambassador-items-selection-spi-host-v1-provider/types'; import { queryItems } from '@wix/bex-utils/@wix/ambassador-items-selection-spi-host-v1-provider/http'; import { useWixPatternsContainer } from '@wix/bex-core/react'; import { useFilterCollection } from '../useFilterCollection'; export type ItemsSelectionValue = Item & { id: string; name: string; }; type FetchItemsFnResponse = { items: ItemsSelectionValue[]; total?: number; cursor?: string | null; }; type FetchItemsFn = (params: { providerKey: string; query: { search?: string; filters?: Query['filter']; limit: number; offset?: number; cursor?: string | null; }; httpClient: WixPatternsContainerParams['httpClient']; }) => Promise; function buildRequest(params: { query: { search?: string; limit: number; offset?: number; cursor?: string | null; filters?: Query['filter']; }; providerKey: string; }) { const { query, providerKey } = params; const resolvedQuery: Query = query.cursor != null ? { cursorPaging: { cursor: query.cursor, limit: query.limit }, } : query.offset != null && query.offset > 0 ? { paging: { offset: query.offset, limit: query.limit, }, } : { paging: { limit: query.limit, offset: 0 }, cursorPaging: { limit: query.limit }, }; if (!query.cursor) { if (query.filters && Object.keys(query.filters).length > 0) { resolvedQuery.filter = { ...query.filters }; } // According to the guidelines, we should not pass search query if cursor is present if (query.search) { resolvedQuery.search = query.search; } } const request: QueryItemsRequest = { providerKey, query: resolvedQuery, }; return request; } // When we publish items-selection-code, we need to use this code from there and no to duplicate it here const useQueryItems = () => { const { httpClient, errorHandler: { withErrorHandler }, translate: t, } = useWixPatternsContainer(); const fetchItems: FetchItemsFn = async ({ providerKey, query }) => { const request: QueryItemsRequest = buildRequest({ query, providerKey, }); const res = await withErrorHandler( () => httpClient.request(queryItems(request)), { PROVIDER_NOT_FOUND: () => ({ message: t('cairo.provider-not-found.error'), action: { text: t('cairo.error.contactSupport.cta'), onClick: () => {}, }, }), QUERY_PROVIDER_ITEMS_FAILED: () => ({ message: t('cairo.provider-not-found.error'), action: { text: t('cairo.error.contactSupport.cta'), onClick: () => {}, }, }), }, ); const { items, pagingMetadata } = res.data; return { items: (items as ItemsSelectionValue[]) || [], total: pagingMetadata?.total || 0, hasNext: pagingMetadata?.hasNext, cursor: pagingMetadata?.cursors?.next, }; }; return { fetchItems }; }; export interface UseItemsSelectionFilterParams { /** * The provider key to use for fetching items. */ providerKey: string; /** * This is a reference to the filter that was defined in the main collection. For example: `collection.filters.`. */ filter: Filter; /** * Additional filters to apply to the query. */ queryFilters?: Query['filter']; } export const useItemsSelectionFilter = ({ providerKey, filter, queryFilters, }: UseItemsSelectionFilterParams) => { const { httpClient } = useWixPatternsContainer(); const { fetchItems } = useQueryItems(); const renderItem = (item: ItemsSelectionValue) => ({ title: item?.name ?? '', subtitle: item?.description ?? '', }); const collection = useFilterCollection(filter, { queryName: providerKey, fetchData: async (query) => { const { items, ...res } = await fetchItems({ providerKey, query: { ...query, filters: { ...(queryFilters || {}), ...query.filters, }, }, httpClient, }); // initial pagination unknown, set to cursor if next cursor exists collection._paginationModeRef.current = res.cursor ? 'cursor' : 'offset'; return { ...res, items, }; }, limit: 50, }); return { collection, renderItem }; };