"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, Store, } from "lucide-react"; // Типы данных для поставок на Ozon interface OzonProduct { id: string; name: string; sku: string; offerId: string; category: string; plannedQty: number; actualQty: number; defectQty: number; productPrice: number; } interface OzonWarehouse { id: string; name: string; address: string; warehouseId: number; products: OzonProduct[]; totalAmount: number; } interface OzonRoute { id: string; from: string; fromAddress: string; to: string; toAddress: string; warehouses: OzonWarehouse[]; totalProductPrice: number; logisticsPrice: number; totalAmount: number; } interface OzonSupply { id: string; number: number; supplyId: string; deliveryDate: string; createdDate: string; routes: OzonRoute[]; plannedTotal: number; actualTotal: number; defectTotal: number; totalProductPrice: number; totalLogisticsPrice: number; grandTotal: number; status: "planned" | "in-transit" | "delivered" | "completed"; } // Моковые данные для поставок на Ozon const mockOzonSupplies: OzonSupply[] = [ { id: "oz1", number: 5001, supplyId: "OZ24010001", deliveryDate: "2024-01-25", createdDate: "2024-01-18", status: "delivered", plannedTotal: 90, actualTotal: 87, defectTotal: 3, totalProductPrice: 1950000, totalLogisticsPrice: 22000, grandTotal: 1972000, routes: [ { id: "ozr1", from: "ТЯК Москва", fromAddress: "Москва, Алтуфьевское шоссе, 27", to: "Ozon Тверь", toAddress: "Тверь, ул. Складская, 45", totalProductPrice: 1950000, logisticsPrice: 22000, totalAmount: 1972000, warehouses: [ { id: "ozw1", name: "Склад Ozon Тверь", address: "Тверь, ул. Складская, 45", warehouseId: 22341172, totalAmount: 1950000, products: [ { id: "ozp1", name: "Ноутбук ASUS VivoBook", sku: "ASUS-VB-15-512", offerId: "ASUS-001", category: "Ноутбуки", plannedQty: 15, actualQty: 14, defectQty: 1, productPrice: 85000, }, { id: "ozp2", name: "Мышь беспроводная Logitech", sku: "LOG-MX3-BLK", offerId: "LOG-002", category: "Компьютерные аксессуары", plannedQty: 75, actualQty: 73, defectQty: 2, productPrice: 4500, }, ], }, ], }, ], }, { id: "oz2", number: 5002, supplyId: "OZ24010002", deliveryDate: "2024-01-30", createdDate: "2024-01-22", status: "in-transit", plannedTotal: 45, actualTotal: 45, defectTotal: 0, totalProductPrice: 1125000, totalLogisticsPrice: 18000, grandTotal: 1143000, routes: [ { id: "ozr2", from: "Садовод", fromAddress: "Москва, 14-й км МКАД", to: "Ozon Рязань", toAddress: "Рязань, ул. Промышленная, 15", totalProductPrice: 1125000, logisticsPrice: 18000, totalAmount: 1143000, warehouses: [ { id: "ozw2", name: "Склад Ozon Рязань", address: "Рязань, ул. Промышленная, 15", warehouseId: 22341173, totalAmount: 1125000, products: [ { id: "ozp3", name: "Планшет iPad Air", sku: "APL-IPAD-AIR-64", offerId: "APL-003", category: "Планшеты", plannedQty: 20, actualQty: 20, defectQty: 0, productPrice: 45000, }, { id: "ozp4", name: "Клавиатура механическая", sku: "KEYB-MECH-RGB", offerId: "KEYB-004", category: "Клавиатуры", plannedQty: 25, actualQty: 25, defectQty: 0, productPrice: 12000, }, ], }, ], }, ], }, ]; export function OzonSuppliesTab() { 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: OzonSupply["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: OzonProduct) => { 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 (
{/* Статистика поставок на Ozon */} sum + supply.grandTotal, 0) )} icon={TrendingUp} iconColor="text-green-400" iconBg="bg-green-500/20" trend={{ value: 19, 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: 2, isPositive: false }} subtitle="Требуют проверки" /> {/* Таблица поставок на Ozon */}
{mockOzonSupplies.map((supply) => { const isSupplyExpanded = expandedSupplies.has(supply.id); return ( {/* Основная строка поставки на Ozon */} toggleSupplyExpansion(supply.id)} > {/* Развернутые уровни */} {isSupplyExpanded && supply.routes.map((route) => { const isRouteExpanded = expandedRoutes.has(route.id); return ( {/* Склады Ozon */} {isRouteExpanded && route.warehouses.map((warehouse) => { const isWarehouseExpanded = expandedWarehouses.has(warehouse.id); return ( {/* Товары Ozon */} {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)}
Склад Ozon
{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 )}
Товар Ozon
{product.name}
Артикул: {product.sku}
Offer ID: {product.offerId}
{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) )}
); }