'use client' import { useQuery } from '@apollo/client' import { ArrowLeft, Package, CalendarIcon, Building } from 'lucide-react' import { useRouter } from 'next/navigation' import React, { useState, useMemo, useCallback } from 'react' import { Sidebar } from '@/components/dashboard/sidebar' import { Button } from '@/components/ui/button' import { Card } from '@/components/ui/card' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { GET_MY_COUNTERPARTIES, GET_ORGANIZATION_LOGISTICS } from '@/graphql/queries' import { useSidebar } from '@/hooks/useSidebar' import { apolloClient } from '@/lib/apollo-client' import { DirectSupplyCreation } from './direct-supply-creation' // Компонент создания поставки товаров с новым интерфейсом interface Organization { id: string name?: string fullName?: string type: string } const CreateSupplyPage = React.memo(() => { const router = useRouter() const { getSidebarMargin } = useSidebar() const [canCreateSupply, setCanCreateSupply] = useState(false) const [isCreatingSupply, setIsCreatingSupply] = useState(false) // Состояния для полей формы const [deliveryDate, setDeliveryDate] = useState('') const [selectedFulfillment, setSelectedFulfillment] = useState('') const [goodsVolume, setGoodsVolume] = useState(0) const [cargoPlaces, setCargoPlaces] = useState(0) const [goodsPrice, setGoodsPrice] = useState(0) const [fulfillmentServicesPrice, setFulfillmentServicesPrice] = useState(0) const [logisticsPrice, setLogisticsPrice] = useState(0) const [selectedServicesCost, setSelectedServicesCost] = useState(0) const [selectedConsumablesCost, setSelectedConsumablesCost] = useState(0) const [hasItemsInSupply, setHasItemsInSupply] = useState(false) // Загружаем контрагентов-фулфилментов const { data: counterpartiesData } = useQuery(GET_MY_COUNTERPARTIES) // Фильтруем только фулфилмент организации const fulfillmentOrgs = useMemo(() => (counterpartiesData?.myCounterparties || []).filter( (org: Organization) => org.type === 'FULFILLMENT', ), [counterpartiesData?.myCounterparties], ) const formatCurrency = useCallback((amount: number) => { return new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB', minimumFractionDigits: 0, }).format(amount) }, []) // Функция для обновления цены товаров из поставки const handleItemsUpdate = useCallback((totalItemsPrice: number) => { setGoodsPrice(totalItemsPrice) }, []) // Функция для обновления статуса наличия товаров const handleItemsCountChange = useCallback((hasItems: boolean) => { setHasItemsInSupply(hasItems) }, []) // Функция для обновления объема товаров из поставки const handleVolumeUpdate = useCallback((totalVolume: number) => { setGoodsVolume(totalVolume) // После обновления объема пересчитываем логистику (если есть поставщик) // calculateLogisticsPrice будет вызван из handleSuppliersUpdate }, []) // Функция для обновления информации о поставщиках (для расчета логистики) const handleSuppliersUpdate = (suppliersData: unknown[]) => { // Находим рынок из выбранного поставщика const selectedSupplier = suppliersData.find((supplier: unknown) => (supplier as { selected?: boolean }).selected) const supplierMarket = (selectedSupplier as { market?: string })?.market console.warn('Обновление поставщиков:', { selectedSupplier, supplierMarket, volume: goodsVolume, }) // Пересчитываем логистику с учетом рынка поставщика calculateLogisticsPrice(goodsVolume, supplierMarket) } // Функция для расчета логистики по рынку поставщика и объему const calculateLogisticsPrice = async (volume: number, supplierMarket?: string) => { // Логистика рассчитывается ТОЛЬКО если есть: // 1. Выбранный фулфилмент // 2. Объем товаров > 0 // 3. Рынок поставщика (откуда везти) if (!selectedFulfillment || !volume || volume <= 0 || !supplierMarket) { setLogisticsPrice(0) return } try { console.warn(`Расчет логистики: ${supplierMarket} → ${selectedFulfillment}, объем: ${volume.toFixed(4)} м³`) // Получаем логистику выбранного фулфилмента из БД const { data: logisticsData } = await apolloClient.query({ query: GET_ORGANIZATION_LOGISTICS, variables: { organizationId: selectedFulfillment }, fetchPolicy: 'network-only', }) const logistics = logisticsData?.organizationLogistics || [] console.warn(`Логистика фулфилмента ${selectedFulfillment}:`, logistics) // Ищем логистику для данного рынка const logisticsRoute = logistics.find( (route: { fromLocation: string; toLocation: string; pricePerCubicMeter: number }) => route.fromLocation.toLowerCase().includes(supplierMarket.toLowerCase()) || supplierMarket.toLowerCase().includes(route.fromLocation.toLowerCase()), ) if (!logisticsRoute) { console.warn(`Логистика для рынка "${supplierMarket}" не найдена`) setLogisticsPrice(0) return } // Выбираем цену в зависимости от объема const pricePerM3 = volume <= 1 ? logisticsRoute.priceUnder1m3 : logisticsRoute.priceOver1m3 const calculatedPrice = volume * pricePerM3 console.warn(`Найдена логистика: ${logisticsRoute.fromLocation} → ${logisticsRoute.toLocation}`) console.warn( `Цена: ${pricePerM3}₽/м³ (${ volume <= 1 ? 'до 1м³' : 'больше 1м³' }) × ${volume.toFixed(4)}м³ = ${calculatedPrice.toFixed(2)}₽`, ) setLogisticsPrice(calculatedPrice) } catch (error) { console.error('Error calculating logistics price:', error) setLogisticsPrice(0) } } const getTotalSum = useMemo(() => { return goodsPrice + selectedServicesCost + selectedConsumablesCost + logisticsPrice }, [goodsPrice, selectedServicesCost, selectedConsumablesCost, logisticsPrice]) const handleSupplyComplete = useCallback(() => { router.push('/supplies') }, [router]) const handleCreateSupplyClick = useCallback(() => { setIsCreatingSupply(true) }, []) const handleCanCreateSupplyChange = useCallback((canCreate: boolean) => { setCanCreateSupply(canCreate) }, []) // Пересчитываем логистику при изменении фулфилмента (если есть поставщик) React.useEffect(() => { // Логистика пересчитается автоматически через handleSuppliersUpdate // когда будет выбран поставщик с рынком }, [selectedFulfillment, goodsVolume]) const handleSupplyCompleted = useCallback(() => { setIsCreatingSupply(false) handleSupplyComplete() }, [handleSupplyComplete]) // Главная страница с табами в новом стиле интерфейса return (
{/* Заголовок */}

Создание поставки товаров

Выберите карточки товаров Wildberries для создания поставки

{/* Основной контент - карточки Wildberries */}
{/* Левая колонка - карточки товаров */}
{/* Правая колонка - Форма поставки */}

Параметры поставки

{/* Первая строка */}
{/* 1. Модуль выбора даты */}
setDeliveryDate(e.target.value)} className="w-full h-8 rounded-lg border-0 bg-white/20 backdrop-blur px-3 py-1 text-white placeholder:text-white/50 focus:bg-white/30 focus:outline-none focus:ring-1 focus:ring-white/20 text-xs font-medium" min={new Date().toISOString().split('T')[0]} />
{/* 2. Модуль выбора фулфилмента */}
{/* 3. Объём товаров (автоматически) */}
{goodsVolume > 0 ? `${goodsVolume.toFixed(2)} м³` : 'Рассчитывается автоматически'}
{/* 4. Грузовые места */}
setCargoPlaces(parseInt(e.target.value) || 0)} placeholder="шт" className="h-8 bg-white/20 border-0 text-white placeholder:text-white/50 focus:bg-white/30 focus:ring-1 focus:ring-white/20 text-xs" />
{/* Вторая группа - цены */}
{/* 5. Цена товаров (автоматически) */}
{goodsPrice > 0 ? formatCurrency(goodsPrice) : 'Рассчитывается автоматически'}
{/* 6. Цена услуг фулфилмента (автоматически) */}
{selectedServicesCost > 0 ? formatCurrency(selectedServicesCost) : 'Выберите услуги'}
{/* 7. Цена расходников фулфилмента (автоматически) */}
{selectedConsumablesCost > 0 ? formatCurrency(selectedConsumablesCost) : 'Выберите расходники'}
{/* 8. Цена логистики (автоматически) */}
{logisticsPrice > 0 ? formatCurrency(logisticsPrice) : 'Выберите поставщика'}
{/* 9. Итоговая сумма */}
{formatCurrency(getTotalSum)}
{/* 10. Кнопка создания поставки */}
) }) CreateSupplyPage.displayName = 'CreateSupplyPage' export { CreateSupplyPage }