Добавлено получение навигационных категорий с иконками и обновление логики отображения иконок в компоненте BottomHead. Обновлены типы данных и стили для навигационных иконок. Оптимизирована загрузка групп для категорий в компоненте BottomHeadPartsIndex.

This commit is contained in:
Bivekich
2025-07-13 21:42:06 +03:00
parent 132e39b87e
commit ad5dcc03e3
6 changed files with 406 additions and 136 deletions

View File

@ -138,7 +138,7 @@ export default function Catalog() {
limit: ITEMS_PER_PAGE,
page: partsIndexPage,
q: searchQuery || undefined,
params: Object.keys(selectedFilters).length > 0 ? JSON.stringify(selectedFilters) : undefined
params: undefined // Будем обновлять через refetch
},
skip: !isPartsIndexMode || !groupId, // Пропускаем запрос если нет groupId
fetchPolicy: 'cache-and-network'
@ -146,7 +146,7 @@ export default function Catalog() {
);
// Загружаем параметры фильтрации для PartsIndex
const { data: paramsData, loading: paramsLoading, error: paramsError } = useQuery<PartsIndexParamsData, PartsIndexParamsVariables>(
const { data: paramsData, loading: paramsLoading, error: paramsError, refetch: refetchParams } = useQuery<PartsIndexParamsData, PartsIndexParamsVariables>(
GET_PARTSINDEX_CATALOG_PARAMS,
{
variables: {
@ -154,7 +154,7 @@ export default function Catalog() {
groupId: groupId as string,
lang: 'ru',
q: searchQuery || undefined,
params: Object.keys(selectedFilters).length > 0 ? JSON.stringify(selectedFilters) : undefined
params: undefined // Будем обновлять через refetch
},
skip: !isPartsIndexMode || !groupId, // Пропускаем запрос если нет groupId
fetchPolicy: 'cache-first'
@ -215,18 +215,44 @@ export default function Catalog() {
}
}, [entitiesData]);
// Преобразование выбранных фильтров в формат PartsIndex API
const convertFiltersToPartsIndexParams = useCallback((): Record<string, any> => {
if (!paramsData?.partsIndexCatalogParams?.list || Object.keys(selectedFilters).length === 0) {
return {};
}
const apiParams: Record<string, any> = {};
paramsData.partsIndexCatalogParams.list.forEach((param: any) => {
const selectedValues = selectedFilters[param.name];
if (selectedValues && selectedValues.length > 0) {
// Находим соответствующие значения из API данных
const matchingValues = param.values.filter((value: any) =>
selectedValues.includes(value.title || value.value)
);
if (matchingValues.length > 0) {
// Используем ID параметра из API и значения
apiParams[param.id] = matchingValues.map((v: any) => v.value);
}
}
});
return apiParams;
}, [paramsData, selectedFilters]);
// Генерация фильтров для PartsIndex на основе параметров API
const generatePartsIndexFilters = useCallback((): FilterConfig[] => {
if (!paramsData?.partsIndexCatalogParams?.list) {
return [];
}
return paramsData.partsIndexCatalogParams.list.map(param => {
return paramsData.partsIndexCatalogParams.list.map((param: any) => {
if (param.type === 'range') {
// Для range фильтров ищем min и max значения
const numericValues = param.values
.map(v => parseFloat(v.value))
.filter(v => !isNaN(v));
.map((v: any) => parseFloat(v.value))
.filter((v: number) => !isNaN(v));
const min = numericValues.length > 0 ? Math.min(...numericValues) : 0;
const max = numericValues.length > 0 ? Math.max(...numericValues) : 100;
@ -243,8 +269,8 @@ export default function Catalog() {
type: 'dropdown' as const,
title: param.name,
options: param.values
.filter(value => value.available) // Показываем только доступные
.map(value => value.title || value.value),
.filter((value: any) => value.available) // Показываем только доступные
.map((value: any) => value.title || value.value),
multi: true,
showAll: true
};
@ -252,6 +278,8 @@ export default function Catalog() {
});
}, [paramsData]);
useEffect(() => {
if (isPartsIndexMode) {
// Для PartsIndex генерируем фильтры на основе параметров API
@ -426,16 +454,38 @@ export default function Catalog() {
// При изменении поиска или фильтров сбрасываем пагинацию
setShowEmptyState(false);
// Если изменился поисковый запрос, нужно перезагрузить данные с сервера
// Если изменился поисковый запрос или фильтры, нужно перезагрузить данные с сервера
if (searchQuery.trim() || Object.keys(selectedFilters).length > 0) {
console.log('🔍 Поисковый запрос или фильтры изменились, сбрасываем пагинацию');
setPartsIndexPage(1);
setHasMoreEntities(true);
// refetch будет автоматически вызван при изменении partsIndexPage
// Перезагружаем данные с новыми параметрами фильтрации
const apiParams = convertFiltersToPartsIndexParams();
const paramsString = Object.keys(apiParams).length > 0 ? JSON.stringify(apiParams) : undefined;
// Также обновляем параметры фильтрации
refetchParams({
catalogId: catalogId as string,
groupId: groupId as string,
lang: 'ru',
q: searchQuery || undefined,
params: paramsString
});
refetchEntities({
catalogId: catalogId as string,
groupId: groupId as string,
lang: 'ru',
limit: ITEMS_PER_PAGE,
page: 1,
q: searchQuery || undefined,
params: paramsString
});
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isPartsIndexMode, searchQuery, JSON.stringify(selectedFilters)]);
}, [isPartsIndexMode, searchQuery, JSON.stringify(selectedFilters), refetchEntities, refetchParams, convertFiltersToPartsIndexParams]);
// Управляем показом пустого состояния с задержкой
useEffect(() => {