/** * ХУКА ДЛЯ ЛОГИКИ КОРЗИНЫ ПОСТАВОК * * Выделена из create-suppliers-supply-page.tsx * Управляет корзиной товаров и настройками поставки */ import { useMutation } from '@apollo/client' import { useRouter } from 'next/navigation' import { useState, useMemo } from 'react' import { toast } from 'sonner' import { CREATE_SUPPLY_ORDER } from '@/graphql/mutations' import type { SelectedGoodsItem, GoodsSupplier, GoodsProduct, ProductRecipe, SupplyCreationFormData, } from '../types/supply-creation.types' interface UseSupplyCartProps { selectedSupplier: GoodsSupplier | null allCounterparties: GoodsSupplier[] productRecipes: Record } export function useSupplyCart({ selectedSupplier, allCounterparties, productRecipes }: UseSupplyCartProps) { const router = useRouter() // Состояния корзины и настроек const [selectedGoods, setSelectedGoods] = useState([]) const [deliveryDate, setDeliveryDate] = useState('') const [selectedLogistics, setSelectedLogistics] = useState('auto') const [selectedFulfillment, setSelectedFulfillment] = useState('') const [isCreatingSupply, setIsCreatingSupply] = useState(false) // Мутация создания поставки const [createSupplyOrder] = useMutation(CREATE_SUPPLY_ORDER) // Получаем логистические компании const logisticsCompanies = useMemo(() => { return allCounterparties?.filter((partner) => partner.type === 'LOGIST') || [] }, [allCounterparties]) // Добавление товара в корзину const addToCart = ( product: GoodsProduct, quantity: number, additionalData?: { completeness?: string recipe?: string specialRequirements?: string parameters?: Array<{ name: string; value: string }> }, ) => { if (!selectedSupplier) { toast.error('Сначала выберите поставщика') return } if (quantity <= 0) { toast.error('Укажите количество товара') return } const existingItemIndex = selectedGoods.findIndex((item) => item.id === product.id) if (existingItemIndex >= 0) { // Обновляем существующий товар setSelectedGoods((prev) => { const updated = [...prev] updated[existingItemIndex] = { ...updated[existingItemIndex], selectedQuantity: quantity, ...additionalData, } return updated }) toast.success('Количество товара обновлено') } else { // Добавляем новый товар const newItem: SelectedGoodsItem = { id: product.id, name: product.name, sku: product.article, price: product.price, selectedQuantity: quantity, unit: product.unit, category: product.category?.name, supplierId: selectedSupplier?.id || '', supplierName: selectedSupplier?.name || selectedSupplier?.fullName || '', completeness: additionalData?.completeness, recipe: additionalData?.recipe, specialRequirements: additionalData?.specialRequirements, parameters: additionalData?.parameters, } setSelectedGoods((prev) => [...prev, newItem]) toast.success('Товар добавлен в корзину') } } // Удаление товара из корзины const removeFromCart = (itemId: string) => { setSelectedGoods((prev) => prev.filter((item) => item.id !== itemId)) toast.success('Товар удален из корзины') } // Функция расчета полной стоимости товара с рецептурой const getProductTotalWithRecipe = useCallback( (productId: string, quantity: number) => { const product = selectedGoods.find((p) => p.id === productId) if (!product) return 0 const baseTotal = product.price * quantity const recipe = productRecipes[productId] if (!recipe) return baseTotal // Здесь будет логика расчета стоимости услуг и расходников // Пока возвращаем базовую стоимость return baseTotal }, [selectedGoods, productRecipes], ) // Расчеты для корзины const totalGoodsAmount = useMemo(() => { return selectedGoods.reduce((sum, item) => { return sum + getProductTotalWithRecipe(item.id, item.selectedQuantity) }, 0) }, [selectedGoods, getProductTotalWithRecipe]) const totalQuantity = useMemo(() => { return selectedGoods.reduce((sum, item) => sum + item.selectedQuantity, 0) }, [selectedGoods]) // Валидация формы const hasRequiredServices = useMemo(() => { return selectedGoods.every((item) => productRecipes[item.id]?.selectedServices?.length > 0) }, [selectedGoods, productRecipes]) const isFormValid = useMemo(() => { return selectedSupplier && selectedGoods.length > 0 && deliveryDate && selectedFulfillment && hasRequiredServices }, [selectedSupplier, selectedGoods.length, deliveryDate, selectedFulfillment, hasRequiredServices]) // Создание поставки const handleCreateSupply = async () => { if (!isFormValid) { if (!hasRequiredServices) { toast.error('Каждый товар должен иметь минимум 1 услугу фулфилмента') } else { toast.error('Заполните все обязательные поля') } return } if (!selectedSupplier) { toast.error('Поставщик не выбран') return } setIsCreatingSupply(true) try { await createSupplyOrder({ variables: { supplierId: selectedSupplier?.id || '', fulfillmentCenterId: selectedFulfillment, items: selectedGoods.map((item) => ({ productId: item.id, quantity: item.selectedQuantity, recipe: productRecipes[item.id] || { productId: item.id, selectedServices: [], selectedFFConsumables: [], selectedSellerConsumables: [], }, })), deliveryDate: deliveryDate, logistics: selectedLogistics, specialRequirements: selectedGoods .map((item) => item.specialRequirements) .filter(Boolean) .join('; '), } satisfies SupplyCreationFormData, }) toast.success('Поставка успешно создана!') router.push('/supplies') } catch (error) { console.error('❌ Ошибка создания поставки:', error) toast.error('Ошибка при создании поставки') } finally { setIsCreatingSupply(false) } } return { // Состояние корзины selectedGoods, setSelectedGoods, deliveryDate, setDeliveryDate, selectedLogistics, setSelectedLogistics, selectedFulfillment, setSelectedFulfillment, isCreatingSupply, // Данные logisticsCompanies, // Расчеты totalGoodsAmount, totalQuantity, // Валидация hasRequiredServices, isFormValid, // Функции управления корзиной addToCart, removeFromCart, getProductTotalWithRecipe, handleCreateSupply, } }