Обновлена логика добавления товаров в корзину во всех компонентах. Теперь добавление происходит асинхронно с обработкой успешных и ошибочных результатов. Добавлена информация о наличии товара при добавлении в корзину. Улучшены уведомления о добавлении товара с учетом статуса операции.

This commit is contained in:
Bivekich
2025-07-06 02:21:33 +03:00
parent a8c8ae60bb
commit ac7b2de49f
10 changed files with 204 additions and 94 deletions

View File

@ -25,6 +25,8 @@ const initialState: CartState = {
// Типы действий
type CartAction =
| { type: 'ADD_ITEM'; payload: Omit<CartItem, 'id' | 'selected' | 'favorite'> }
| { type: 'ADD_ITEM_SUCCESS'; payload: { items: CartItem[]; summary: any } }
| { type: 'ADD_ITEM_ERROR'; payload: string }
| { type: 'REMOVE_ITEM'; payload: string }
| { type: 'UPDATE_QUANTITY'; payload: { id: string; quantity: number } }
| { type: 'TOGGLE_SELECT'; payload: string }
@ -44,6 +46,16 @@ type CartAction =
// Функция для генерации ID
const generateId = () => Math.random().toString(36).substr(2, 9)
// Утилитарная функция для парсинга количества в наличии
const parseStock = (stockStr: string | number | undefined): number => {
if (typeof stockStr === 'number') return stockStr;
if (typeof stockStr === 'string') {
const match = stockStr.match(/\d+/);
return match ? parseInt(match[0]) : 0;
}
return 0;
};
// Функция для расчета итогов
const calculateSummary = (items: CartItem[], deliveryPrice: number) => {
const selectedItems = items.filter(item => item.selected)
@ -78,9 +90,12 @@ const cartReducer = (state: CartState, action: CartAction): CartState => {
if (existingItemIndex >= 0) {
// Увеличиваем количество существующего товара
const existingItem = state.items[existingItemIndex];
const totalQuantity = existingItem.quantity + action.payload.quantity;
newItems = state.items.map((item, index) =>
index === existingItemIndex
? { ...item, quantity: item.quantity + action.payload.quantity }
? { ...item, quantity: totalQuantity }
: item
)
} else {
@ -335,8 +350,31 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children
}, [state.items, state.delivery, state.orderComment, isInitialized])
// Функции для работы с корзиной
const addItem = (item: Omit<CartItem, 'id' | 'selected' | 'favorite'>) => {
const addItem = async (item: Omit<CartItem, 'id' | 'selected' | 'favorite'>) => {
// Проверяем наличие товара на складе перед добавлением
const existingItemIndex = state.items.findIndex(
existingItem =>
(existingItem.productId && existingItem.productId === item.productId) ||
(existingItem.offerKey && existingItem.offerKey === item.offerKey)
)
let totalQuantity = item.quantity;
if (existingItemIndex >= 0) {
const existingItem = state.items[existingItemIndex];
totalQuantity = existingItem.quantity + item.quantity;
}
// Проверяем наличие товара на складе
const availableStock = parseStock(item.stock);
if (availableStock > 0 && totalQuantity > availableStock) {
const errorMessage = `Недостаточно товара в наличии. Доступно: ${availableStock} шт., запрошено: ${totalQuantity} шт.`;
dispatch({ type: 'SET_ERROR', payload: errorMessage });
return { success: false, error: errorMessage };
}
// Если проверка прошла успешно, добавляем товар
dispatch({ type: 'ADD_ITEM', payload: item })
return { success: true }
}
const removeItem = (id: string) => {
@ -344,6 +382,17 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children
}
const updateQuantity = (id: string, quantity: number) => {
// Найдем товар для проверки наличия
const item = state.items.find(item => item.id === id);
if (item) {
const availableStock = parseStock(item.stock);
if (availableStock > 0 && quantity > availableStock) {
// Показываем ошибку, но не изменяем количество
dispatch({ type: 'SET_ERROR', payload: `Недостаточно товара в наличии. Доступно: ${availableStock} шт.` });
return;
}
}
dispatch({ type: 'UPDATE_QUANTITY', payload: { id, quantity } })
}
@ -388,6 +437,10 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children
}
}
const clearError = () => {
dispatch({ type: 'SET_ERROR', payload: '' })
}
const contextValue: CartContextType = {
state,
addItem,
@ -401,7 +454,8 @@ export const CartProvider: React.FC<{ children: React.ReactNode }> = ({ children
removeAll,
removeSelected,
updateDelivery,
clearCart
clearCart,
clearError
}
return (