Удален файл интеграции с Parts Index API и обновлены компоненты для работы с корзиной и избранным. Добавлены функции для обработки добавления товаров в корзину с уведомлениями, улучшена логика работы с избранным, а также добавлены фильтры для истории поиска по производителю.

This commit is contained in:
Bivekich
2025-06-29 03:36:21 +03:00
parent d268bb3359
commit 7f91da525f
23 changed files with 685 additions and 780 deletions

View File

@ -23,7 +23,7 @@ export default function InfoCard({
currency = 'RUB',
image
}: InfoCardProps) {
const { addToFavorites, removeFromFavorites, isFavorite } = useFavorites();
const { addToFavorites, removeFromFavorites, isFavorite, favorites } = useFavorites();
// Проверяем, есть ли товар в избранном
const isItemFavorite = isFavorite(productId, offerKey, articleNumber, brand);
@ -34,9 +34,18 @@ export default function InfoCard({
e.stopPropagation();
if (isItemFavorite) {
// Создаем ID для удаления
const id = `${productId || offerKey || ''}:${articleNumber}:${brand}`;
removeFromFavorites(id);
// Находим товар в избранном по правильному ID
const favoriteItem = favorites.find((fav: any) => {
// Проверяем по разным комбинациям идентификаторов
if (productId && fav.productId === productId) return true;
if (offerKey && fav.offerKey === offerKey) return true;
if (fav.article === articleNumber && fav.brand === brand) return true;
return false;
});
if (favoriteItem) {
removeFromFavorites(favoriteItem.id);
}
} else {
// Добавляем в избранное
addToFavorites({

View File

@ -1,96 +1,47 @@
import React from "react";
import React, { useEffect, useState } from "react";
import { useQuery } from "@apollo/client";
import { PARTS_INDEX_SEARCH_BY_ARTICLE } from "@/lib/graphql";
interface ProductCharacteristicsProps {
result?: any;
}
const ProductCharacteristics = ({ result }: ProductCharacteristicsProps) => {
const [partsIndexData, setPartsIndexData] = useState<any>(null);
// Функция для рендеринга характеристик из нашей базы данных
const renderInternalCharacteristics = () => {
if (!result?.characteristics || result.characteristics.length === 0) return null;
// Запрос к Parts Index для получения дополнительных характеристик
const { data: partsIndexResult, loading: partsIndexLoading } = useQuery(PARTS_INDEX_SEARCH_BY_ARTICLE, {
variables: {
articleNumber: result?.articleNumber || '',
brandName: result?.brand || '',
lang: 'ru'
},
skip: !result?.articleNumber || !result?.brand,
errorPolicy: 'ignore'
});
return (
<div className="w-layout-vflex flex-block-53">
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29" style={{ fontWeight: 'bold', color: '#333' }}>
Характеристики товара:
</span>
</div>
{result.characteristics.map((char: any, index: number) => (
<div key={index} className="w-layout-hflex flex-block-55">
<span className="text-block-29">{char.characteristic.name}:</span>
<span className="text-block-28">{char.value}</span>
useEffect(() => {
if (partsIndexResult?.partsIndexSearchByArticle) {
setPartsIndexData(partsIndexResult.partsIndexSearchByArticle);
}
}, [partsIndexResult]);
// Функция для рендеринга параметров из Parts Index
const renderPartsIndexParameters = () => {
if (!partsIndexData?.parameters) return null;
return partsIndexData.parameters.map((paramGroup: any, groupIndex: number) => (
<div key={groupIndex} className="w-layout-vflex flex-block-53">
{paramGroup.params?.map((param: any, paramIndex: number) => (
<div key={paramIndex} className="w-layout-hflex flex-block-55">
<span className="text-block-29">{param.title}:</span>
<span className="text-block-28">
{param.values?.map((value: any) => value.value).join(', ') || 'Нет данных'}
</span>
</div>
))}
</div>
);
};
// Функция для рендеринга характеристик из Parts Index
const renderPartsIndexCharacteristics = () => {
if (!result?.partsIndexCharacteristics || result.partsIndexCharacteristics.length === 0) return null;
return (
<div className="w-layout-vflex flex-block-53">
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29" style={{ fontWeight: 'bold', color: '#333' }}>
Дополнительные характеристики:
</span>
</div>
{result.partsIndexCharacteristics.map((char: any, index: number) => (
<div key={index} className="w-layout-hflex flex-block-55">
<span className="text-block-29">{char.name}:</span>
<span className="text-block-28">{char.value}</span>
</div>
))}
</div>
);
};
// Функция для рендеринга изображений из нашей базы данных
const renderInternalImages = () => {
if (!result?.images || result.images.length === 0) return null;
return (
<div className="w-layout-vflex flex-block-53" style={{ marginTop: '20px' }}>
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29" style={{ fontWeight: 'bold', color: '#333' }}>
Изображения товара:
</span>
</div>
<div className="w-layout-hflex" style={{ flexWrap: 'wrap', gap: '10px', marginTop: '10px' }}>
{result.images.slice(0, 6).map((image: any, index: number) => (
<div key={image.id || index} style={{
border: '1px solid #e0e0e0',
borderRadius: '8px',
overflow: 'hidden',
width: '120px',
height: '120px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#f9f9f9'
}}>
<img
src={image.url}
alt={image.alt || `${result?.brand} ${result?.articleNumber} - изображение ${index + 1}`}
style={{
maxWidth: '100%',
maxHeight: '100%',
objectFit: 'contain',
cursor: 'pointer'
}}
onError={(e) => {
(e.target as HTMLImageElement).style.display = 'none';
}}
onClick={() => window.open(image.url, '_blank')}
/>
</div>
))}
</div>
</div>
);
));
};
return (
@ -111,27 +62,33 @@ const ProductCharacteristics = ({ result }: ProductCharacteristicsProps) => {
<span className="text-block-29">Название:</span>
<span className="text-block-28">{result.name}</span>
</div>
{result?.description && (
{partsIndexData?.originalName && (
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29">Оригинальное название:</span>
<span className="text-block-28">{partsIndexData.originalName}</span>
</div>
)}
{partsIndexData?.description && (
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29">Описание:</span>
<span className="text-block-28" style={{ maxWidth: '400px', wordWrap: 'break-word' }}>
{result.description}
</span>
<span className="text-block-28">{partsIndexData.description}</span>
</div>
)}
</div>
{/* Характеристики из нашей базы данных */}
{renderInternalCharacteristics()}
{/* Дополнительные характеристики из Parts Index */}
{renderPartsIndexCharacteristics()}
{partsIndexLoading ? (
<div className="w-layout-vflex flex-block-53">
<div className="w-layout-hflex flex-block-55">
<span className="text-block-29">Загрузка характеристик...</span>
</div>
</div>
) : (
renderPartsIndexParameters()
)}
</>
)}
</div>
{/* Изображения из нашей базы данных */}
{renderInternalImages()}
</>
);
};