"use client"; import React, { useState } from "react"; import { Card } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { StatsCard } from "../ui/stats-card"; import { StatsGrid } from "../ui/stats-grid"; import { ChevronDown, ChevronRight, Calendar, Package, MapPin, TrendingUp, AlertTriangle, DollarSign, Truck, ShoppingBag, } from "lucide-react"; // Типы данных для поставок на Wildberries interface WbProduct { id: string; name: string; sku: string; nmId: number; category: string; plannedQty: number; actualQty: number; defectQty: number; productPrice: number; } interface WbWarehouse { id: string; name: string; address: string; warehouseId: number; products: WbProduct[]; totalAmount: number; } interface WbRoute { id: string; from: string; fromAddress: string; to: string; toAddress: string; warehouses: WbWarehouse[]; totalProductPrice: number; logisticsPrice: number; totalAmount: number; } interface WbSupply { id: string; number: number; supplyId: string; deliveryDate: string; createdDate: string; routes: WbRoute[]; plannedTotal: number; actualTotal: number; defectTotal: number; totalProductPrice: number; totalLogisticsPrice: number; grandTotal: number; status: "planned" | "in-transit" | "delivered" | "completed"; } // Моковые данные для поставок на Wildberries const mockWbSupplies: WbSupply[] = [ { id: "wb1", number: 4001, supplyId: "WB24010001", deliveryDate: "2024-01-22", createdDate: "2024-01-16", status: "delivered", plannedTotal: 120, actualTotal: 118, defectTotal: 2, totalProductPrice: 2400000, totalLogisticsPrice: 18000, grandTotal: 2418000, routes: [ { id: "wbr1", from: "Садовод", fromAddress: "Москва, 14-й км МКАД", to: "WB Подольск", toAddress: "Подольск, ул. Складская, 25", totalProductPrice: 2400000, logisticsPrice: 18000, totalAmount: 2418000, warehouses: [ { id: "wbw1", name: "Склад WB Подольск", address: "Подольск, ул. Складская, 25", warehouseId: 117501, totalAmount: 2400000, products: [ { id: "wbp1", name: "Смартфон Samsung Galaxy S24", sku: "SAMS-GS24-256", nmId: 123456789, category: "Смартфоны и гаджеты", plannedQty: 40, actualQty: 39, defectQty: 1, productPrice: 65000, }, { id: "wbp2", name: "Чехол для Samsung Galaxy S24", sku: "CASE-GS24-BLK", nmId: 987654321, category: "Аксессуары для телефонов", plannedQty: 80, actualQty: 79, defectQty: 1, productPrice: 1200, }, ], }, ], }, ], }, { id: "wb2", number: 4002, supplyId: "WB24010002", deliveryDate: "2024-01-28", createdDate: "2024-01-20", status: "in-transit", plannedTotal: 60, actualTotal: 60, defectTotal: 0, totalProductPrice: 1800000, totalLogisticsPrice: 15000, grandTotal: 1815000, routes: [ { id: "wbr2", from: "ТЯК Москва", fromAddress: "Москва, Алтуфьевское шоссе, 27", to: "WB Электросталь", toAddress: "Электросталь, ул. Промышленная, 10", totalProductPrice: 1800000, logisticsPrice: 15000, totalAmount: 1815000, warehouses: [ { id: "wbw2", name: "Склад WB Электросталь", address: "Электросталь, ул. Промышленная, 10", warehouseId: 117986, totalAmount: 1800000, products: [ { id: "wbp3", name: "Наушники Sony WH-1000XM5", sku: "SONY-WH1000XM5", nmId: 555666777, category: "Наушники и аудио", plannedQty: 30, actualQty: 30, defectQty: 0, productPrice: 35000, }, { id: "wbp4", name: "Кабель USB-C", sku: "CABLE-USBC-2M", nmId: 111222333, category: "Кабели и адаптеры", plannedQty: 30, actualQty: 30, defectQty: 0, productPrice: 800, }, ], }, ], }, ], }, ]; export function WildberriesSuppliesTab() { const [expandedSupplies, setExpandedSupplies] = useState>( new Set() ); const [expandedRoutes, setExpandedRoutes] = useState>(new Set()); const [expandedWarehouses, setExpandedWarehouses] = useState>( new Set() ); const [expandedProducts, setExpandedProducts] = useState>( new Set() ); const toggleSupplyExpansion = (supplyId: string) => { const newExpanded = new Set(expandedSupplies); if (newExpanded.has(supplyId)) { newExpanded.delete(supplyId); } else { newExpanded.add(supplyId); } setExpandedSupplies(newExpanded); }; const toggleRouteExpansion = (routeId: string) => { const newExpanded = new Set(expandedRoutes); if (newExpanded.has(routeId)) { newExpanded.delete(routeId); } else { newExpanded.add(routeId); } setExpandedRoutes(newExpanded); }; const toggleWarehouseExpansion = (warehouseId: string) => { const newExpanded = new Set(expandedWarehouses); if (newExpanded.has(warehouseId)) { newExpanded.delete(warehouseId); } else { newExpanded.add(warehouseId); } setExpandedWarehouses(newExpanded); }; const toggleProductExpansion = (productId: string) => { const newExpanded = new Set(expandedProducts); if (newExpanded.has(productId)) { newExpanded.delete(productId); } else { newExpanded.add(productId); } setExpandedProducts(newExpanded); }; const getStatusBadge = (status: WbSupply["status"]) => { const statusMap = { planned: { label: "Запланирована", color: "bg-blue-500/20 text-blue-300 border-blue-500/30", }, "in-transit": { label: "В пути", color: "bg-yellow-500/20 text-yellow-300 border-yellow-500/30", }, delivered: { label: "Доставлена", color: "bg-green-500/20 text-green-300 border-green-500/30", }, completed: { label: "Завершена", color: "bg-purple-500/20 text-purple-300 border-purple-500/30", }, }; const { label, color } = statusMap[status]; return {label}; }; const formatCurrency = (amount: number) => { return new Intl.NumberFormat("ru-RU", { style: "currency", currency: "RUB", minimumFractionDigits: 0, }).format(amount); }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString("ru-RU", { day: "2-digit", month: "2-digit", year: "numeric", }); }; const calculateProductTotal = (product: WbProduct) => { return product.actualQty * product.productPrice; }; const getEfficiencyBadge = ( planned: number, actual: number, defect: number ) => { const efficiency = ((actual - defect) / planned) * 100; if (efficiency >= 95) { return ( Отлично ); } else if (efficiency >= 90) { return ( Хорошо ); } else { return ( Проблемы ); } }; return (
{/* Статистика поставок на Wildberries */} sum + supply.grandTotal, 0) )} icon={TrendingUp} iconColor="text-green-400" iconBg="bg-green-500/20" trend={{ value: 22, isPositive: true }} subtitle="Общая стоимость" /> supply.status === "in-transit") .length } icon={Calendar} iconColor="text-yellow-400" iconBg="bg-yellow-500/20" subtitle="Активные поставки" /> supply.defectTotal > 0).length } icon={AlertTriangle} iconColor="text-red-400" iconBg="bg-red-500/20" trend={{ value: 1, isPositive: false }} subtitle="Требуют проверки" /> {/* Таблица поставок на Wildberries */}
{mockWbSupplies.map((supply) => { const isSupplyExpanded = expandedSupplies.has(supply.id); return ( {/* Основная строка поставки на WB */} toggleSupplyExpansion(supply.id)} > {/* Развернутые уровни */} {isSupplyExpanded && supply.routes.map((route) => { const isRouteExpanded = expandedRoutes.has(route.id); return ( {/* Склады WB */} {isRouteExpanded && route.warehouses.map((warehouse) => { const isWarehouseExpanded = expandedWarehouses.has(warehouse.id); return ( {/* Товары WB */} {isWarehouseExpanded && warehouse.products.map((product) => ( ))} ); })} ); })} ); })}
ID поставки Дата поставки Дата создания План Факт Брак Цена товаров Логистика Итого сумма Статус
{supply.number}
{supply.supplyId}
{formatDate(supply.deliveryDate)}
{formatDate(supply.createdDate)} {supply.plannedTotal} {supply.actualTotal} 0 ? "text-red-400" : "text-white" }`} > {supply.defectTotal} {formatCurrency(supply.totalProductPrice)} {formatCurrency(supply.totalLogisticsPrice)}
{formatCurrency(supply.grandTotal)}
{getStatusBadge(supply.status)}
Маршрут
{route.from} {route.to}
{route.fromAddress} → {route.toAddress}
{route.warehouses.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.plannedQty, 0 ), 0 )} {route.warehouses.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.actualQty, 0 ), 0 )} {route.warehouses.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.defectQty, 0 ), 0 )} {formatCurrency(route.totalProductPrice)} {formatCurrency(route.logisticsPrice)} {formatCurrency(route.totalAmount)}
Склад WB
{warehouse.name}
ID: {warehouse.warehouseId}
{warehouse.address}
{warehouse.products.reduce( (sum, p) => sum + p.plannedQty, 0 )} {warehouse.products.reduce( (sum, p) => sum + p.actualQty, 0 )} {warehouse.products.reduce( (sum, p) => sum + p.defectQty, 0 )} {formatCurrency( warehouse.products.reduce( (sum, p) => sum + calculateProductTotal(p), 0 ) )} {formatCurrency( warehouse.totalAmount )}
Товар WB
{product.name}
Артикул: {product.sku}
NM ID: {product.nmId}
{product.category}
{product.plannedQty} {product.actualQty} 0 ? "text-red-400" : "text-white" }`} > {product.defectQty}
{formatCurrency( calculateProductTotal(product) )}
{formatCurrency( product.productPrice )}{" "} за шт.
{getEfficiencyBadge( product.plannedQty, product.actualQty, product.defectQty )} {formatCurrency( calculateProductTotal(product) )}
); }