"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, Building2, TrendingUp, AlertTriangle, DollarSign, Warehouse, } from "lucide-react"; // Типы данных для товаров ФФ interface ProductParameter { id: string; name: string; value: string; unit?: string; } interface Product { id: string; name: string; sku: string; category: string; plannedQty: number; actualQty: number; defectQty: number; productPrice: number; parameters: ProductParameter[]; } interface Wholesaler { id: string; name: string; inn: string; contact: string; address: string; products: Product[]; totalAmount: number; } interface Route { id: string; from: string; fromAddress: string; to: string; toAddress: string; wholesalers: Wholesaler[]; totalProductPrice: number; fulfillmentServicePrice: number; logisticsPrice: number; totalAmount: number; } interface FulfillmentSupply { id: string; number: number; deliveryDate: string; createdDate: string; routes: Route[]; plannedTotal: number; actualTotal: number; defectTotal: number; totalProductPrice: number; totalFulfillmentPrice: number; totalLogisticsPrice: number; grandTotal: number; status: "planned" | "in-transit" | "delivered" | "completed"; } // Моковые данные для товаров ФФ const mockFulfillmentGoods: FulfillmentSupply[] = [ { id: "ff1", number: 1001, deliveryDate: "2024-01-15", createdDate: "2024-01-10", status: "delivered", plannedTotal: 180, actualTotal: 173, defectTotal: 2, totalProductPrice: 3750000, totalFulfillmentPrice: 43000, totalLogisticsPrice: 27000, grandTotal: 3820000, routes: [ { id: "ffr1", from: "Садовод", fromAddress: "Москва, 14-й км МКАД", to: "SFERAV Logistics ФФ", toAddress: "Москва, ул. Складская, 15", totalProductPrice: 3600000, fulfillmentServicePrice: 25000, logisticsPrice: 15000, totalAmount: 3640000, wholesalers: [ { id: "ffw1", name: 'ООО "ТехноСнаб"', inn: "7701234567", contact: "+7 (495) 123-45-67", address: "Москва, ул. Торговая, 1", totalAmount: 3600000, products: [ { id: "ffp1", name: "Смартфон iPhone 15 Pro", sku: "APL-IP15P-256", category: "Электроника", plannedQty: 50, actualQty: 48, defectQty: 2, productPrice: 75000, parameters: [ { id: "param1", name: "Цвет", value: "Титановый" }, { id: "param2", name: "Память", value: "256", unit: "ГБ" }, { id: "param3", name: "Гарантия", value: "12", unit: "мес" }, ], }, ], }, ], }, ], }, { id: "ff2", number: 1002, deliveryDate: "2024-01-20", createdDate: "2024-01-12", status: "in-transit", plannedTotal: 30, actualTotal: 30, defectTotal: 0, totalProductPrice: 750000, totalFulfillmentPrice: 18000, totalLogisticsPrice: 12000, grandTotal: 780000, routes: [ { id: "ffr2", from: "Садовод", fromAddress: "Москва, 14-й км МКАД", to: "MegaFulfillment", toAddress: "Подольск, ул. Складская, 25", totalProductPrice: 750000, fulfillmentServicePrice: 18000, logisticsPrice: 12000, totalAmount: 780000, wholesalers: [ { id: "ffw2", name: 'ООО "АудиоТех"', inn: "7702345678", contact: "+7 (495) 555-12-34", address: "Москва, ул. Звуковая, 8", totalAmount: 750000, products: [ { id: "ffp2", name: "Наушники AirPods Pro 2", sku: "APL-AP-PRO2-USB", category: "Аудио", plannedQty: 30, actualQty: 30, defectQty: 0, productPrice: 25000, parameters: [ { id: "param4", name: "Тип", value: "Беспроводные" }, { id: "param5", name: "Шумоподавление", value: "Активное" }, { id: "param6", name: "Время работы", value: "6", unit: "ч" }, ], }, ], }, ], }, ], }, ]; export function FulfillmentGoodsTab() { const [expandedSupplies, setExpandedSupplies] = useState>( new Set() ); const [expandedRoutes, setExpandedRoutes] = useState>(new Set()); const [expandedWholesalers, setExpandedWholesalers] = 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 toggleWholesalerExpansion = (wholesalerId: string) => { const newExpanded = new Set(expandedWholesalers); if (newExpanded.has(wholesalerId)) { newExpanded.delete(wholesalerId); } else { newExpanded.add(wholesalerId); } setExpandedWholesalers(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: FulfillmentSupply["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: Product) => { 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 (
{/* Статистика товаров ФФ */} sum + supply.grandTotal, 0 ) )} icon={TrendingUp} iconColor="text-green-400" iconBg="bg-green-500/20" trend={{ value: 8, 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: 3, isPositive: false }} subtitle="Требуют внимания" /> {/* Таблица поставок товаров ФФ */}
{mockFulfillmentGoods.map((supply) => { const isSupplyExpanded = expandedSupplies.has(supply.id); return ( {/* Основная строка поставки */} toggleSupplyExpansion(supply.id)} > {/* Развернутые уровни - аналогично оригинальному коду */} {isSupplyExpanded && supply.routes.map((route) => { const isRouteExpanded = expandedRoutes.has(route.id); return ( {/* Остальные уровни развертывания аналогично */} {isRouteExpanded && route.wholesalers.map((wholesaler) => { const isWholesalerExpanded = expandedWholesalers.has(wholesaler.id); return ( {/* Товары */} {isWholesalerExpanded && wholesaler.products.map((product) => { const isProductExpanded = expandedProducts.has(product.id); return ( {/* Параметры товара */} {isProductExpanded && ( )} ); })} ); })} ); })} ); })}
Дата поставки Дата создания План Факт Брак Цена товаров Услуги ФФ Логистика до ФФ Итого сумма Статус
{supply.number}
{formatDate(supply.deliveryDate)}
{formatDate(supply.createdDate)} {supply.plannedTotal} {supply.actualTotal} 0 ? "text-red-400" : "text-white" }`} > {supply.defectTotal} {formatCurrency(supply.totalProductPrice)} {formatCurrency(supply.totalFulfillmentPrice)} {formatCurrency(supply.totalLogisticsPrice)}
{formatCurrency(supply.grandTotal)}
{getStatusBadge(supply.status)}
Маршрут
{route.from} {route.to}
{route.fromAddress} → {route.toAddress}
{route.wholesalers.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.plannedQty, 0 ), 0 )} {route.wholesalers.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.actualQty, 0 ), 0 )} {route.wholesalers.reduce( (sum, w) => sum + w.products.reduce( (pSum, p) => pSum + p.defectQty, 0 ), 0 )} {formatCurrency(route.totalProductPrice)} {formatCurrency( route.fulfillmentServicePrice )} {formatCurrency(route.logisticsPrice)} {formatCurrency(route.totalAmount)}
Оптовик
{wholesaler.name}
ИНН: {wholesaler.inn}
{wholesaler.address}
{wholesaler.contact}
{wholesaler.products.reduce( (sum, p) => sum + p.plannedQty, 0 )} {wholesaler.products.reduce( (sum, p) => sum + p.actualQty, 0 )} {wholesaler.products.reduce( (sum, p) => sum + p.defectQty, 0 )} {formatCurrency( wholesaler.products.reduce( (sum, p) => sum + calculateProductTotal(p), 0 ) )} {formatCurrency( wholesaler.totalAmount )}
Товар
{product.name}
Артикул: {product.sku}
{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 ) )}

📋 Параметры товара:

{product.parameters.map( (param) => (
{param.name}
{param.value}{" "} {param.unit || ""}
) )}
); }