UNPKG

barneo-search-widget-lib

Version:

Библиотека для поиска по каталогу Barneo на Vue 3

213 lines (190 loc) 6.61 kB
import { ref, computed } from "vue"; import type { SearchApiService } from "../../searchWidget/types"; import type { SharedStateConfig } from "../types"; import { useSharedState } from "./useSharedState"; export function useSearchStateManager( apiService: SearchApiService | undefined, config: SharedStateConfig = {} ) { const sharedState = useSharedState(); const isPerformingDeepSearch = ref(false); /** * Унифицированная функция для выполнения поиска с фильтрами */ const performSearchWithFilters = async ( query: string, options: { filters?: Record<string, string[]>; products?: Array<{ code: string; value_ids?: string[]; value_gte?: string; value_lte?: string }>; activeFilters?: Array<{ id: string; name: string; code: string; values: Array<{ id: string; name: string; isSelected: boolean; }>; }>; pagination?: { limit_products?: number; limit_categories?: number; limit_brands?: number; offset_products?: number; }; sort?: string; updateSharedState?: boolean; } = {} ) => { const { filters = {}, products = [], activeFilters = [], pagination = sharedState.searchState.pagination, sort = sharedState.searchState.sort, updateSharedState = true, } = options; if (!apiService || !query.trim()) return null; // Если это глубокий поиск, устанавливаем флаг if (updateSharedState) { isPerformingDeepSearch.value = true; sharedState.setLoading(true); sharedState.setError(""); } try { const searchResponse = await apiService.searchCatalog({ is_fast_result: false, include: [ "products", "filters", "correction", "product_hints", "full_hints", "brands", "categories", "full_categories", "full_brands", ], sort: sort, filter: { location_id: apiService.getLocationId(), query: query.trim(), use_query_correction: true, ...filters, ...(products.length > 0 && { products }), }, pagination, load_full_products: { location_id: apiService.getLocationId(), include: ["properties"], }, }); if (searchResponse && searchResponse.data) { const results = searchResponse.data.full_products || []; const filters = searchResponse.data.filters || []; // Обновляем sharedState только если нужно if (updateSharedState) { sharedState.setSearchResults( query.trim(), results, true, searchResponse.data.full_products || results, searchResponse.data.total_products || 0 ); // Сохраняем фильтры в общее состояние if (filters.length > 0) { sharedState.setFilters(filters); } // Сохраняем активные фильтры if (activeFilters.length > 0) { sharedState.setActiveFilters(activeFilters); } // Сохраняем сортировку, если она передана if (sort) { sharedState.setSort(sort); } // Сохраняем пагинацию, если она передана if (pagination) { sharedState.setPagination(pagination); } } return searchResponse; } } catch (err) { const errorMessage = err instanceof Error ? err.message : "Ошибка поиска"; if (updateSharedState) { sharedState.setError(errorMessage); } throw err; } finally { if (updateSharedState) { sharedState.setLoading(false); isPerformingDeepSearch.value = false; } } }; /** * Выполняет глубокий поиск (для Enter или кнопки поиска) */ const performDeepSearch = async (query: string) => { if (!apiService || !query.trim() || isPerformingDeepSearch.value) return; // Сбрасываем сортировку и пагинацию при новом поиске sharedState.setSort("relevance"); sharedState.resetPagination(); // Используем itemsPerPage из конфигурации, если он задан const itemsPerPage = config.productsWidget?.itemsPerPage || 20; return await performSearchWithFilters(query, { updateSharedState: true, pagination: { limit_products: itemsPerPage, limit_categories: 10, limit_brands: 10, offset_products: 0, }, }); }; /** * Выполняет быстрый поиск (для автодополнения) */ const performQuickSearch = async (query: string) => { if (!apiService || !query.trim()) return; try { const searchResponse = await apiService.searchCatalog({ is_fast_result: true, include: ["products", "product_hints", "full_hints"], sort: "relevance", filter: { location_id: apiService.getLocationId(), query: query.trim(), use_query_correction: true, }, pagination: { limit_products: 5, limit_categories: 3, limit_brands: 3, offset_products: 0, }, }); if (searchResponse && searchResponse.data) { const results = searchResponse.data.full_products || []; // Для быстрого поиска не сохраняем в общее состояние return { results, hints: searchResponse.data.product_hints || [], fullHints: searchResponse.data.full_hints || [], }; } } catch (err) { console.error("Ошибка быстрого поиска:", err); throw err; } }; return { // Экспортируем все из sharedState ...sharedState, // Дополнительные методы для работы с API performSearchWithFilters, performDeepSearch, performQuickSearch, }; }