"use client" import React, { useState, useEffect } from 'react' import { Card } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Search, Plus, Minus, ShoppingCart, Calendar, Phone, User, MapPin, Package, Wrench, ArrowLeft, Check, X } from 'lucide-react' import { WildberriesService } from '@/services/wildberries-service' import { useAuth } from '@/hooks/useAuth' import { useQuery, useMutation } from '@apollo/client' import { GET_MY_COUNTERPARTIES } from '@/graphql/queries' import { CREATE_WILDBERRIES_SUPPLY } from '@/graphql/mutations' import { toast } from 'sonner' interface WildberriesCard { nmID: number vendorCode: string sizes: Array<{ chrtID: number techSize: string wbSize: string price: number discountedPrice: number quantity: number }> mediaFiles: string[] object: string parent: string countryProduction: string supplierVendorCode: string brand: string title: string description: string } interface SelectedCard { card: WildberriesCard selectedQuantity: number selectedMarket: string selectedPlace: string sellerName: string sellerPhone: string deliveryDate: string selectedServices: string[] } interface FulfillmentService { id: string name: string description?: string price: number organizationName: string } interface WBProductCardsProps { onBack: () => void onComplete: (selectedCards: SelectedCard[]) => void } export function WBProductCards({ onBack, onComplete }: WBProductCardsProps) { const { user } = useAuth() const [searchTerm, setSearchTerm] = useState('') const [loading, setLoading] = useState(false) const [wbCards, setWbCards] = useState([]) const [selectedCards, setSelectedCards] = useState([]) const [showSummary, setShowSummary] = useState(false) const [fulfillmentServices, setFulfillmentServices] = useState([]) // Загружаем контрагентов-фулфилментов const { data: counterpartiesData } = useQuery(GET_MY_COUNTERPARTIES) // Мутация для создания поставки const [createSupply, { loading: creatingSupply }] = useMutation(CREATE_WILDBERRIES_SUPPLY, { onCompleted: (data) => { if (data.createWildberriesSupply.success) { toast.success(data.createWildberriesSupply.message) onComplete(selectedCards) } else { toast.error(data.createWildberriesSupply.message) } }, onError: (error) => { toast.error('Ошибка при создании поставки') console.error('Error creating supply:', error) } }) // Моковые данные рынков const markets = [ { value: 'sadovod', label: 'Садовод' }, { value: 'luzhniki', label: 'Лужники' }, { value: 'tishinka', label: 'Тишинка' }, { value: 'food-city', label: 'Фуд Сити' } ] useEffect(() => { // Загружаем услуги фулфилмента из контрагентов if (counterpartiesData?.myCounterparties) { const fulfillmentOrganizations = counterpartiesData.myCounterparties.filter( (org: any) => org.type === 'FULFILLMENT' ) // В реальном приложении здесь был бы запрос услуг для каждой организации const mockServices: FulfillmentService[] = fulfillmentOrganizations.flatMap((org: any) => [ { id: `${org.id}-packaging`, name: 'Упаковка товаров', description: 'Профессиональная упаковка товаров', price: 50, organizationName: org.name || org.fullName }, { id: `${org.id}-labeling`, name: 'Маркировка товаров', description: 'Нанесение этикеток и штрих-кодов', price: 30, organizationName: org.name || org.fullName }, { id: `${org.id}-quality-check`, name: 'Контроль качества', description: 'Проверка качества товаров', price: 100, organizationName: org.name || org.fullName } ]) setFulfillmentServices(mockServices) } }, [counterpartiesData]) const searchCards = async () => { if (!searchTerm.trim()) return setLoading(true) try { const wbApiKey = user?.organization?.apiKeys?.find(key => key.marketplace === 'WILDBERRIES') if (!wbApiKey?.isActive) { throw new Error('API ключ Wildberries не настроен') } const validationData = wbApiKey.validationData as Record const apiToken = validationData?.token || validationData?.apiKey if (!apiToken) { throw new Error('API токен не найден') } const cards = await WildberriesService.searchCards(apiToken, searchTerm) setWbCards(cards) } catch (error) { console.error('Ошибка поиска карточек:', error) // Для демо загрузим моковые данные setWbCards([ { nmID: 123456789, vendorCode: 'SKU001', title: 'Смартфон Samsung Galaxy A54', description: 'Современный смартфон с отличной камерой', brand: 'Samsung', object: 'Смартфоны', parent: 'Электроника', countryProduction: 'Корея', supplierVendorCode: 'SUPPLIER-001', mediaFiles: ['/api/placeholder/300/300'], sizes: [ { chrtID: 123456, techSize: '128GB', wbSize: '128GB Черный', price: 25990, discountedPrice: 22990, quantity: 10 } ] }, { nmID: 987654321, vendorCode: 'SKU002', title: 'Наушники Apple AirPods Pro', description: 'Беспроводные наушники с шумоподавлением', brand: 'Apple', object: 'Наушники', parent: 'Электроника', countryProduction: 'Китай', supplierVendorCode: 'SUPPLIER-002', mediaFiles: ['/api/placeholder/300/300'], sizes: [ { chrtID: 987654, techSize: 'Standart', wbSize: 'Белый', price: 24990, discountedPrice: 19990, quantity: 5 } ] } ]) } finally { setLoading(false) } } const updateCardSelection = (card: WildberriesCard, field: keyof SelectedCard, value: any) => { setSelectedCards(prev => { const existing = prev.find(sc => sc.card.nmID === card.nmID) if (field === 'selectedQuantity' && value === 0) { return prev.filter(sc => sc.card.nmID !== card.nmID) } if (existing) { return prev.map(sc => sc.card.nmID === card.nmID ? { ...sc, [field]: value } : sc ) } else if (field === 'selectedQuantity' && value > 0) { const newSelectedCard: SelectedCard = { card, selectedQuantity: value, selectedMarket: '', selectedPlace: '', sellerName: '', sellerPhone: '', deliveryDate: '', selectedServices: [] } return [...prev, newSelectedCard] } return prev }) } const getSelectedQuantity = (card: WildberriesCard): number => { const selected = selectedCards.find(sc => sc.card.nmID === card.nmID) return selected ? selected.selectedQuantity : 0 } const formatCurrency = (amount: number) => { return new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB', minimumFractionDigits: 0 }).format(amount) } const getTotalAmount = () => { return selectedCards.reduce((sum, sc) => { const cardPrice = sc.card.sizes[0]?.discountedPrice || sc.card.sizes[0]?.price || 0 const servicesPrice = sc.selectedServices.reduce((serviceSum, serviceId) => { const service = fulfillmentServices.find(s => s.id === serviceId) return serviceSum + (service?.price || 0) }, 0) return sum + (cardPrice + servicesPrice) * sc.selectedQuantity }, 0) } const getTotalItems = () => { return selectedCards.reduce((sum, sc) => sum + sc.selectedQuantity, 0) } const applyServicesToAll = (serviceIds: string[]) => { setSelectedCards(prev => prev.map(sc => ({ ...sc, selectedServices: serviceIds })) ) } const handleCreateSupply = async () => { try { const supplyInput = { deliveryDate: selectedCards[0]?.deliveryDate || null, cards: selectedCards.map(sc => ({ nmId: sc.card.nmID.toString(), vendorCode: sc.card.vendorCode, title: sc.card.title, brand: sc.card.brand, price: sc.card.sizes[0]?.price || 0, discountedPrice: sc.card.sizes[0]?.discountedPrice || null, quantity: sc.card.sizes[0]?.quantity || 0, selectedQuantity: sc.selectedQuantity, selectedMarket: sc.selectedMarket, selectedPlace: sc.selectedPlace, sellerName: sc.sellerName, sellerPhone: sc.sellerPhone, deliveryDate: sc.deliveryDate || null, mediaFiles: sc.card.mediaFiles, selectedServices: sc.selectedServices })) } await createSupply({ variables: { input: supplyInput } }) } catch (error) { console.error('Error creating supply:', error) } } if (showSummary) { return (

Сводка заказа

Проверьте данные перед созданием поставки

{selectedCards.map((sc) => { const cardPrice = sc.card.sizes[0]?.discountedPrice || sc.card.sizes[0]?.price || 0 const servicesPrice = sc.selectedServices.reduce((sum, serviceId) => { const service = fulfillmentServices.find(s => s.id === serviceId) return sum + (service?.price || 0) }, 0) const totalPrice = (cardPrice + servicesPrice) * sc.selectedQuantity return (
{sc.card.title}

{sc.card.title}

{sc.card.vendorCode}

Количество: {sc.selectedQuantity}
Рынок: {markets.find(m => m.value === sc.selectedMarket)?.label || 'Не выбран'}
Место: {sc.selectedPlace || 'Не указано'}
Продавец: {sc.sellerName || 'Не указан'}
Телефон: {sc.sellerPhone || 'Не указан'}
Дата поставки: {sc.deliveryDate || 'Не выбрана'}
{sc.selectedServices.length > 0 && (

Услуги:

{sc.selectedServices.map(serviceId => { const service = fulfillmentServices.find(s => s.id === serviceId) return service ? ( {service.name} ({formatCurrency(service.price)}) ) : null })}
)}
{formatCurrency(totalPrice)}
) })}

Итого

Товаров: {getTotalItems()}
Карточек: {selectedCards.length}
Общая сумма: {formatCurrency(getTotalAmount())}
) } return (

Карточки товаров Wildberries

Найдите и выберите товары для поставки

{selectedCards.length > 0 && ( )}
{/* Поиск */}
setSearchTerm(e.target.value)} className="bg-white/5 border-white/20 text-white placeholder-white/50" onKeyPress={(e) => e.key === 'Enter' && searchCards()} />
{/* Карточки товаров */} {wbCards.length > 0 && (
{wbCards.map((card) => { const selectedQuantity = getSelectedQuantity(card) const isSelected = selectedQuantity > 0 const selectedCard = selectedCards.find(sc => sc.card.nmID === card.nmID) const mainSize = card.sizes[0] const maxQuantity = mainSize?.quantity || 0 const price = mainSize?.discountedPrice || mainSize?.price || 0 return (
{/* Изображение и основная информация */}
{card.title}

{card.title}

{card.vendorCode}

{formatCurrency(price)} 10 ? 'bg-green-500/20 text-green-300' : maxQuantity > 0 ? 'bg-yellow-500/20 text-yellow-300' : 'bg-red-500/20 text-red-300'}`}> {maxQuantity} шт.
{/* Количество */}
updateCardSelection(card, 'selectedQuantity', Math.min(maxQuantity, Math.max(0, parseInt(e.target.value) || 0)))} className="bg-white/5 border-white/20 text-white text-center w-20 h-8" />
{/* Детальные настройки для выбранных товаров */} {isSelected && selectedCard && (
{/* Рынок */}
{/* Место на рынке */}
updateCardSelection(card, 'selectedPlace', e.target.value)} className="bg-white/5 border-white/20 text-white placeholder-white/50" />
{/* Данные продавца */}
updateCardSelection(card, 'sellerName', e.target.value)} className="bg-white/5 border-white/20 text-white placeholder-white/50" />
updateCardSelection(card, 'sellerPhone', e.target.value)} className="bg-white/5 border-white/20 text-white placeholder-white/50" />
{/* Дата поставки */}
updateCardSelection(card, 'deliveryDate', e.target.value)} className="bg-white/5 border-white/20 text-white" />
{/* Услуги фулфилмента */} {fulfillmentServices.length > 0 && (
{fulfillmentServices.map((service) => ( ))}
{selectedCards.length > 1 && ( )}
)}
)}
) })}
)} {/* Плавающая корзина */} {selectedCards.length > 0 && !showSummary && (
)} {wbCards.length === 0 && !loading && (

Поиск товаров

Введите запрос в поле поиска, чтобы найти товары в вашем каталоге Wildberries

)}
) }