Добавлены новые компоненты для отображения лучших цен и товаров дня с использованием GraphQL. Реализована логика загрузки данных, обработка ошибок и отображение состояния загрузки. Обновлены компоненты BestPriceSection, ProductOfDaySection и TopSalesSection для интеграции с новыми запросами. Улучшено взаимодействие с пользователем через уведомления и обработку кликов.
This commit is contained in:
@ -1,4 +1,7 @@
|
||||
import React from "react";
|
||||
import { useCart } from "@/contexts/CartContext";
|
||||
import { useFavorites } from "@/contexts/FavoritesContext";
|
||||
import toast from "react-hot-toast";
|
||||
|
||||
interface BestPriceItemProps {
|
||||
image: string;
|
||||
@ -7,6 +10,8 @@ interface BestPriceItemProps {
|
||||
oldPrice: string;
|
||||
title: string;
|
||||
brand: string;
|
||||
article?: string;
|
||||
productId?: string;
|
||||
onAddToCart?: (e: React.MouseEvent) => void;
|
||||
}
|
||||
|
||||
@ -17,14 +22,129 @@ const BestPriceItem: React.FC<BestPriceItemProps> = ({
|
||||
oldPrice,
|
||||
title,
|
||||
brand,
|
||||
article,
|
||||
productId,
|
||||
onAddToCart,
|
||||
}) => {
|
||||
const { addItem } = useCart();
|
||||
const { addToFavorites, removeFromFavorites, isFavorite, favorites } = useFavorites();
|
||||
|
||||
// Проверяем, есть ли товар в избранном
|
||||
const isItemFavorite = isFavorite(productId, undefined, article, brand);
|
||||
|
||||
// Функция для парсинга цены из строки
|
||||
const parsePrice = (priceStr: string): number => {
|
||||
const cleanPrice = priceStr.replace(/[^\d.,]/g, '').replace(',', '.');
|
||||
return parseFloat(cleanPrice) || 0;
|
||||
};
|
||||
|
||||
// Обработчик добавления в корзину
|
||||
const handleAddToCart = async (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Если передан кастомный обработчик, используем его
|
||||
if (onAddToCart) {
|
||||
onAddToCart(e);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const numericPrice = parsePrice(price);
|
||||
|
||||
if (numericPrice <= 0) {
|
||||
toast.error('Цена товара не найдена');
|
||||
return;
|
||||
}
|
||||
|
||||
// Добавляем товар в корзину
|
||||
const result = await addItem({
|
||||
productId: productId,
|
||||
name: title,
|
||||
description: `${brand} - ${title}`,
|
||||
brand: brand,
|
||||
article: article,
|
||||
price: numericPrice,
|
||||
currency: 'RUB',
|
||||
quantity: 1,
|
||||
image: image,
|
||||
supplier: 'Protek',
|
||||
deliveryTime: '1 день',
|
||||
isExternal: false
|
||||
});
|
||||
|
||||
if (result.success) {
|
||||
// Показываем успешный тоастер
|
||||
toast.success(
|
||||
<div>
|
||||
<div className="font-semibold" style={{ color: '#fff' }}>Товар добавлен в корзину!</div>
|
||||
<div className="text-sm" style={{ color: '#fff', opacity: 0.9 }}>{`${brand} - ${title}`}</div>
|
||||
</div>,
|
||||
{
|
||||
duration: 3000,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// Показываем ошибку
|
||||
toast.error(result.error || 'Ошибка при добавлении товара в корзину');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Ошибка добавления в корзину:', error);
|
||||
toast.error('Ошибка при добавлении товара в корзину');
|
||||
}
|
||||
};
|
||||
|
||||
// Обработчик клика по иконке избранного
|
||||
const handleFavoriteClick = (e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (isItemFavorite) {
|
||||
// Находим товар в избранном и удаляем
|
||||
const favoriteItem = favorites.find((fav: any) => {
|
||||
if (productId && fav.productId === productId) return true;
|
||||
if (fav.article === article && fav.brand === brand) return true;
|
||||
return false;
|
||||
});
|
||||
|
||||
if (favoriteItem) {
|
||||
removeFromFavorites(favoriteItem.id);
|
||||
toast.success('Товар удален из избранного');
|
||||
}
|
||||
} else {
|
||||
// Добавляем в избранное
|
||||
const numericPrice = parsePrice(price);
|
||||
addToFavorites({
|
||||
productId,
|
||||
name: title,
|
||||
brand: brand,
|
||||
article: article || '',
|
||||
price: numericPrice,
|
||||
currency: 'RUB',
|
||||
image: image
|
||||
});
|
||||
toast.success('Товар добавлен в избранное');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-layout-vflex bestpriceitem">
|
||||
<div className="favcardcat">
|
||||
<div
|
||||
className="favcardcat"
|
||||
onClick={handleFavoriteClick}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
color: isItemFavorite ? '#ef4444' : 'currentColor'
|
||||
}}
|
||||
title={isItemFavorite ? 'Удалить из избранного' : 'Добавить в избранное'}
|
||||
>
|
||||
<div className="icon-setting w-embed">
|
||||
<svg width="currenWidth" height="currentHeight" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M13.5996 3.5C15.8107 3.5 17.5 5.1376 17.5 7.19629C17.5 8.46211 16.9057 9.65758 15.7451 11.0117C14.8712 12.0314 13.7092 13.1034 12.3096 14.3311L10.833 15.6143L10.832 15.6152L10 16.3369L9.16797 15.6152L9.16699 15.6143L7.69043 14.3311C6.29084 13.1034 5.12883 12.0314 4.25488 11.0117C3.09428 9.65758 2.50003 8.46211 2.5 7.19629C2.5 5.1376 4.18931 3.5 6.40039 3.5C7.6497 3.50012 8.85029 4.05779 9.62793 4.92188L10 5.33398L10.3721 4.92188C11.1497 4.05779 12.3503 3.50012 13.5996 3.5Z" fill="currentColor" stroke="currentColor"></path>
|
||||
<path
|
||||
d="M13.5996 3.5C15.8107 3.5 17.5 5.1376 17.5 7.19629C17.5 8.46211 16.9057 9.65758 15.7451 11.0117C14.8712 12.0314 13.7092 13.1034 12.3096 14.3311L10.833 15.6143L10.832 15.6152L10 16.3369L9.16797 15.6152L9.16699 15.6143L7.69043 14.3311C6.29084 13.1034 5.12883 12.0314 4.25488 11.0117C3.09428 9.65758 2.50003 8.46211 2.5 7.19629C2.5 5.1376 4.18931 3.5 6.40039 3.5C7.6497 3.50012 8.85029 4.05779 9.62793 4.92188L10 5.33398L10.3721 4.92188C11.1497 4.05779 12.3503 3.50012 13.5996 3.5Z"
|
||||
fill={isItemFavorite ? 'currentColor' : 'none'}
|
||||
stroke="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
@ -46,7 +166,13 @@ const BestPriceItem: React.FC<BestPriceItemProps> = ({
|
||||
</div>
|
||||
<div className="w-layout-hflex flex-block-120">
|
||||
<div className="nameitembp">{title}</div>
|
||||
<a href="#" className="button-icon w-inline-block" onClick={onAddToCart}>
|
||||
<a
|
||||
href="#"
|
||||
className="button-icon w-inline-block"
|
||||
onClick={handleAddToCart}
|
||||
style={{ cursor: 'pointer' }}
|
||||
aria-label="Добавить в корзину"
|
||||
>
|
||||
<div className="div-block-26">
|
||||
<div className="icon-setting w-embed">
|
||||
<svg width="currentWidht" height="currentHeight" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
|
Reference in New Issue
Block a user