Files
protekauto-frontend/src/components/CartRecommended.tsx

133 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React from "react";
import CatalogProductCard from "./CatalogProductCard";
import { useArticleImage } from "@/hooks/useArticleImage";
import { useCart } from "@/contexts/CartContext";
import { toast } from "react-hot-toast";
import CartIcon from "./CartIcon";
interface CartRecommendedProps {
recommendedProducts?: any[];
isLoadingPrices?: boolean;
}
// Компонент для отдельной карточки рекомендуемого товара с реальным изображением
const RecommendedProductCard: React.FC<{
item: any;
isLoadingPrice: boolean;
formatPrice: (price: number | null, isLoading: boolean) => string;
}> = ({ item, isLoadingPrice, formatPrice }) => {
const { imageUrl } = useArticleImage(item.artId, { enabled: !!item.artId });
const { addItem } = useCart();
// Если нет изображения, используем заглушку с иконкой (но не мокап-фотку)
const displayImage = imageUrl || 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEwIiBoZWlnaHQ9IjE5MCIgdmlld0JveD0iMCAwIDIxMCAxOTAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIyMTAiIGhlaWdodD0iMTkwIiBmaWxsPSIjRjNGNEY2Ii8+CjxwYXRoIGQ9Ik04NSA5NUw5NSA4NUwxMjUgMTE1TDE0MCA5NUwxNjUgMTIwSDE2NVY5MEg0NVY5MEw4NSA5NVoiIGZpbGw9IiNEMUQ1REIiLz4KPGNpcmNsZSBjeD0iNzUiIGN5PSI3NSIgcj0iMTAiIGZpbGw9IiNEMUQ1REIiLz4KPHRleHQgeD0iMTA1IiB5PSIxNTAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxMiIgZmlsbD0iIzlDQTNBRiIgdGV4dC1hbmNob3I9Im1pZGRsZSI+Tm8gaW1hZ2U8L3RleHQ+Cjwvc3ZnPgo=';
// Обработчик добавления в корзину с тоастером
const handleAddToCart = async (e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
try {
// Извлекаем цену как число
const numericPrice = item.minPrice || 0;
if (numericPrice <= 0) {
toast.error('Цена товара не найдена');
return;
}
// Добавляем товар в корзину
const result = await addItem({
productId: String(item.artId) || undefined,
name: item.name || `${item.brand} ${item.articleNumber}`,
description: item.name || `${item.brand} ${item.articleNumber}`,
price: numericPrice,
currency: 'RUB',
quantity: 1,
stock: undefined, // информация о наличии не доступна для рекомендуемых товаров
image: displayImage,
brand: item.brand,
article: item.articleNumber,
supplier: 'AutoEuro',
deliveryTime: '1 день',
isExternal: true
});
if (result.success) {
// Показываем успешный тоастер
toast.success(
<div>
<div className="font-semibold" style={{ color: '#fff' }}>Товар добавлен в корзину!</div>
<div className="text-sm" style={{ color: '#fff', opacity: 0.9 }}>{item.name || `${item.brand} ${item.articleNumber}`}</div>
</div>,
{
duration: 3000,
icon: <CartIcon size={20} color="#fff" />,
}
);
} else {
// Показываем ошибку
toast.error(result.error || 'Ошибка при добавлении товара в корзину');
}
} catch (error) {
console.error('Ошибка добавления в корзину:', error);
toast.error('Ошибка при добавлении товара в корзину');
}
};
return (
<CatalogProductCard
image={displayImage}
discount=""
price={formatPrice(item.minPrice, isLoadingPrice && item.minPrice === undefined)}
oldPrice=""
title={item.name || `${item.brand} ${item.articleNumber}`}
brand={item.brand}
articleNumber={item.articleNumber}
brandName={item.brand}
artId={item.artId}
productId={item.artId ? String(item.artId) : undefined} // Добавляем productId для работы избранного
currency="RUB"
onAddToCart={handleAddToCart} // Передаем обработчик добавления в корзину
/>
);
};
const CartRecommended: React.FC<CartRecommendedProps> = ({
recommendedProducts = [],
isLoadingPrices = false
}) => {
// Фильтруем и ограничиваем количество рекомендаций
const validRecommendations = recommendedProducts
.filter(item => item && item.brand && item.articleNumber) // Фильтруем только валидные товары
.slice(0, 5); // Ограничиваем до 5 товаров
// Если нет валидных рекомендаций, не показываем блок
if (validRecommendations.length === 0) {
return null;
}
const formatPrice = (price: number | null, isLoading: boolean = false) => {
if (isLoading) return "Загрузка...";
if (!price) return "По запросу";
return `от ${price.toLocaleString('ru-RU')}`;
};
return (
<>
<h2 className="heading-11">Рекомендуемые</h2>
<div className="w-layout-hflex core-product-search">
{validRecommendations.map((item, idx) => (
<RecommendedProductCard
key={`${item.brand}-${item.articleNumber}-${idx}`}
item={item}
isLoadingPrice={isLoadingPrices}
formatPrice={formatPrice}
/>
))}
</div>
</>
);
};
export default CartRecommended;