Обновлены компоненты для отображения статистики и данных о складах. Заменены моковые данные на нулевые значения, чтобы отразить отсутствие информации. Изменены комментарии для улучшения понимания кода. Добавлен автоматический выбор активных кампаний в AdvertisingTab для удобства пользователя.
This commit is contained in:
@ -56,14 +56,14 @@ export function FulfillmentWarehouse2Demo() {
|
|||||||
const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
|
const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
|
||||||
const [expandedStores, setExpandedStores] = useState<Set<string>>(new Set());
|
const [expandedStores, setExpandedStores] = useState<Set<string>>(new Set());
|
||||||
|
|
||||||
// Мок данные для статистики
|
// Данные для статистики - показываем только реальные данные
|
||||||
const warehouseStats: WarehouseStats = {
|
const warehouseStats: WarehouseStats = {
|
||||||
products: { current: 2856, change: 124 },
|
products: { current: 0, change: 0 }, // Нет данных о продуктах
|
||||||
goods: { current: 1391, change: 87 },
|
goods: { current: 0, change: 0 }, // Нет данных о товарах
|
||||||
defects: { current: 43, change: -12 },
|
defects: { current: 0, change: 0 }, // Нет данных о браке
|
||||||
pvzReturns: { current: 256, change: 34 },
|
pvzReturns: { current: 0, change: 0 }, // Нет данных о возвратах с ПВЗ
|
||||||
fulfillmentSupplies: { current: 189, change: 23 },
|
fulfillmentSupplies: { current: 0, change: 0 }, // Нет данных о расходниках ФФ
|
||||||
sellerSupplies: { current: 534, change: 67 },
|
sellerSupplies: { current: 0, change: 0 }, // Нет данных о расходниках селлера
|
||||||
};
|
};
|
||||||
|
|
||||||
// Мок данные для магазинов
|
// Мок данные для магазинов
|
||||||
@ -252,6 +252,7 @@ export function FulfillmentWarehouse2Demo() {
|
|||||||
</div>
|
</div>
|
||||||
<span className="text-white text-xs font-semibold">{title}</span>
|
<span className="text-white text-xs font-semibold">{title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Показываем изменения всегда */}
|
||||||
<div
|
<div
|
||||||
className={`flex items-center space-x-1 px-1.5 py-0.5 rounded-full ${
|
className={`flex items-center space-x-1 px-1.5 py-0.5 rounded-full ${
|
||||||
change >= 0 ? "bg-green-500/20" : "bg-red-500/20"
|
change >= 0 ? "bg-green-500/20" : "bg-red-500/20"
|
||||||
|
@ -46,38 +46,38 @@ export function FulfillmentStatisticsDashboard() {
|
|||||||
quickActions: true,
|
quickActions: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Мок данные для статистики
|
// Реальные данные для статистики (пока отсутствуют)
|
||||||
const statisticsData = {
|
const statisticsData = {
|
||||||
// Данные за все время
|
// Данные за все время
|
||||||
totalProducts: 15678,
|
totalProducts: 0,
|
||||||
totalDefects: 145,
|
totalDefects: 0,
|
||||||
totalSupplies: 2341,
|
totalSupplies: 0,
|
||||||
totalRevenue: 45670000,
|
totalRevenue: 0,
|
||||||
totalOrders: 8934,
|
totalOrders: 0,
|
||||||
|
|
||||||
// Отправка на маркетплейсы
|
// Отправка на маркетплейсы
|
||||||
sentToWildberries: 8934,
|
sentToWildberries: 0,
|
||||||
sentToOzon: 4523,
|
sentToOzon: 0,
|
||||||
sentToOthers: 1876,
|
sentToOthers: 0,
|
||||||
|
|
||||||
// Аналитика производительности
|
// Аналитика производительности
|
||||||
avgProcessingTime: 2.4,
|
avgProcessingTime: 0,
|
||||||
defectRate: 0.92,
|
defectRate: 0,
|
||||||
returnRate: 4.3,
|
returnRate: 0,
|
||||||
customerSatisfaction: 4.8,
|
customerSatisfaction: 0,
|
||||||
|
|
||||||
// Тренды
|
// Тренды
|
||||||
revenueTrend: 18,
|
revenueTrend: 0,
|
||||||
ordersTrend: 12,
|
ordersTrend: 0,
|
||||||
defectsTrend: -8,
|
defectsTrend: 0,
|
||||||
satisfactionTrend: 5,
|
satisfactionTrend: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Данные склада (перенесено из fulfillment-warehouse)
|
// Данные склада (пока отсутствуют)
|
||||||
const warehouseStats = {
|
const warehouseStats = {
|
||||||
efficiency: 94.5,
|
efficiency: 0,
|
||||||
turnover: 2.3,
|
turnover: 0,
|
||||||
utilizationRate: 87,
|
utilizationRate: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatNumber = (num: number) => {
|
const formatNumber = (num: number) => {
|
||||||
|
@ -389,8 +389,8 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
products: {
|
products: {
|
||||||
current: totalProductsFromOrders, // Реальное количество товаров на складе
|
current: 0, // Нет данных о готовых продуктах для продажи
|
||||||
change: productsReceivedToday - productsUsedToday, // Реальное изменение за сутки
|
change: 0, // Нет данных об изменениях продуктов
|
||||||
},
|
},
|
||||||
goods: {
|
goods: {
|
||||||
current: 0, // Нет реальных данных о готовых товарах
|
current: 0, // Нет реальных данных о готовых товарах
|
||||||
@ -695,20 +695,8 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Реальные изменения товаров для этого партнера
|
// Нет данных об изменениях продуктов для этого партнера
|
||||||
const partnerProductsChange =
|
const partnerProductsChange = 0;
|
||||||
totalProducts > 0
|
|
||||||
? Math.floor(
|
|
||||||
(totalProducts /
|
|
||||||
(allProducts.reduce(
|
|
||||||
(sum, p: any) => sum + (p.orderedQuantity || 0),
|
|
||||||
0
|
|
||||||
) || 1)) *
|
|
||||||
(productsReceivedToday - productsUsedToday)
|
|
||||||
)
|
|
||||||
: Math.floor(
|
|
||||||
(productsReceivedToday - productsUsedToday) / totalVirtualPartners
|
|
||||||
);
|
|
||||||
|
|
||||||
// Реальные изменения расходников селлера для этого партнера
|
// Реальные изменения расходников селлера для этого партнера
|
||||||
const partnerSuppliesChange =
|
const partnerSuppliesChange =
|
||||||
@ -720,9 +708,9 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
sum + (supply.currentStock || 0),
|
sum + (supply.currentStock || 0),
|
||||||
0
|
0
|
||||||
) || 1)) *
|
) || 1)) *
|
||||||
suppliesReceivedToday
|
(suppliesReceivedToday - suppliesUsedToday)
|
||||||
)
|
)
|
||||||
: Math.floor(suppliesReceivedToday / totalVirtualPartners);
|
: Math.floor((suppliesReceivedToday - suppliesUsedToday) / totalVirtualPartners);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: `virtual-partner-${index + 1}`,
|
id: `virtual-partner-${index + 1}`,
|
||||||
@ -977,9 +965,6 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
change: number;
|
change: number;
|
||||||
description: string;
|
description: string;
|
||||||
}) => {
|
}) => {
|
||||||
// Генерируем случайные значения для положительных и отрицательных изменений
|
|
||||||
const positiveChange = Math.floor(Math.random() * 50) + 10; // от 10 до 59
|
|
||||||
const negativeChange = Math.floor(Math.random() * 30) + 5; // от 5 до 34
|
|
||||||
const percentChange = current > 0 ? (change / current) * 100 : 0;
|
const percentChange = current > 0 ? (change / current) * 100 : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -993,7 +978,7 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
</div>
|
</div>
|
||||||
<span className="text-white text-xs font-semibold">{title}</span>
|
<span className="text-white text-xs font-semibold">{title}</span>
|
||||||
</div>
|
</div>
|
||||||
{/* Процентное изменение */}
|
{/* Процентное изменение - всегда показываем */}
|
||||||
<div className="flex items-center space-x-0.5 px-1.5 py-0.5 rounded bg-blue-500/20">
|
<div className="flex items-center space-x-0.5 px-1.5 py-0.5 rounded bg-blue-500/20">
|
||||||
{change >= 0 ? (
|
{change >= 0 ? (
|
||||||
<TrendingUp className="h-3 w-3 text-green-400" />
|
<TrendingUp className="h-3 w-3 text-green-400" />
|
||||||
@ -1013,17 +998,15 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
<div className="text-lg font-bold text-white">
|
<div className="text-lg font-bold text-white">
|
||||||
{formatNumber(current)}
|
{formatNumber(current)}
|
||||||
</div>
|
</div>
|
||||||
|
{/* Изменения - всегда показываем */}
|
||||||
<div className="flex items-center space-x-1">
|
<div className="flex items-center space-x-1">
|
||||||
{/* Положительное изменение */}
|
<div className={`flex items-center space-x-0.5 px-1 py-0.5 rounded ${
|
||||||
<div className="flex items-center space-x-0.5 px-1 py-0.5 rounded bg-green-500/20">
|
change >= 0 ? 'bg-green-500/20' : 'bg-red-500/20'
|
||||||
<span className="text-xs font-bold text-green-400">
|
}`}>
|
||||||
+{positiveChange}
|
<span className={`text-xs font-bold ${
|
||||||
</span>
|
change >= 0 ? 'text-green-400' : 'text-red-400'
|
||||||
</div>
|
}`}>
|
||||||
{/* Отрицательное изменение */}
|
{change >= 0 ? '+' : ''}{change}
|
||||||
<div className="flex items-center space-x-0.5 px-1 py-0.5 rounded bg-red-500/20">
|
|
||||||
<span className="text-xs font-bold text-red-400">
|
|
||||||
-{negativeChange}
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1483,12 +1466,12 @@ export function FulfillmentWarehouseDashboard() {
|
|||||||
<div className="flex items-center justify-end space-x-1">
|
<div className="flex items-center justify-end space-x-1">
|
||||||
<div className="flex items-center space-x-0.5">
|
<div className="flex items-center space-x-0.5">
|
||||||
<span className="text-[9px] font-bold text-green-400">
|
<span className="text-[9px] font-bold text-green-400">
|
||||||
+0 {/* ТЕСТ: Временно захардкожено для проверки */}
|
+{Math.max(totals.sellerSuppliesChange, 0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-0.5">
|
<div className="flex items-center space-x-0.5">
|
||||||
<span className="text-[9px] font-bold text-red-400">
|
<span className="text-[9px] font-bold text-red-400">
|
||||||
-0 {/* ТЕСТ: Временно захардкожено для проверки */}
|
-{Math.max(-totals.sellerSuppliesChange, 0)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center space-x-0.5">
|
<div className="flex items-center space-x-0.5">
|
||||||
|
@ -153,7 +153,7 @@ const CompactCampaignSelector = ({
|
|||||||
selectedCampaigns: number[],
|
selectedCampaigns: number[],
|
||||||
loading: boolean
|
loading: boolean
|
||||||
}) => {
|
}) => {
|
||||||
const [isExpanded, setIsExpanded] = useState(false)
|
const [isExpanded, setIsExpanded] = useState(true) // Автоматически разворачиваем для удобства
|
||||||
const [showManualInput, setShowManualInput] = useState(false)
|
const [showManualInput, setShowManualInput] = useState(false)
|
||||||
const [manualIds, setManualIds] = useState('')
|
const [manualIds, setManualIds] = useState('')
|
||||||
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set(selectedCampaigns))
|
const [selectedIds, setSelectedIds] = useState<Set<number>>(new Set(selectedCampaigns))
|
||||||
@ -166,6 +166,20 @@ const CompactCampaignSelector = ({
|
|||||||
|
|
||||||
const campaigns = campaignsData?.getWildberriesCampaignsList?.data?.adverts || []
|
const campaigns = campaignsData?.getWildberriesCampaignsList?.data?.adverts || []
|
||||||
|
|
||||||
|
// Автоматически выбираем активные кампании при загрузке данных
|
||||||
|
useEffect(() => {
|
||||||
|
if (campaigns.length > 0 && selectedIds.size === 0) {
|
||||||
|
const activeCampaigns = campaigns
|
||||||
|
.filter((group: CampaignGroup) => group.status === 9) // Активные кампании
|
||||||
|
.flatMap((group: CampaignGroup) => group.advert_list.map((item: CampaignListItem) => item.advertId))
|
||||||
|
.slice(0, 3) // Берем первые 3 активные кампании
|
||||||
|
|
||||||
|
if (activeCampaigns.length > 0) {
|
||||||
|
setSelectedIds(new Set(activeCampaigns))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [campaigns])
|
||||||
|
|
||||||
// Функции для получения названий типов и статусов
|
// Функции для получения названий типов и статусов
|
||||||
const getCampaignTypeName = (type: number) => {
|
const getCampaignTypeName = (type: number) => {
|
||||||
const types: Record<number, string> = {
|
const types: Record<number, string> = {
|
||||||
@ -280,7 +294,7 @@ const CompactCampaignSelector = ({
|
|||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Search className="h-3 w-3 mr-1" />
|
<Search className="h-3 w-3 mr-1" />
|
||||||
Загрузить
|
{selectedIds.size > 0 ? `Загрузить (${selectedIds.size})` : 'Выбрать'}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
@ -1001,10 +1015,23 @@ export function AdvertisingTab({ selectedPeriod, useCustomDates, startDate, endD
|
|||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<TrendingUp className="h-12 w-12 text-white/40 mx-auto mb-4" />
|
<TrendingUp className="h-12 w-12 text-white/40 mx-auto mb-4" />
|
||||||
<h3 className="text-lg font-semibold text-white mb-2">Статистика рекламных кампаний</h3>
|
<h3 className="text-lg font-semibold text-white mb-2">Статистика рекламных кампаний</h3>
|
||||||
<p className="text-white/60 mb-4">Выберите кампании для получения детальной статистики</p>
|
<p className="text-white/60 mb-4">Выберите кампании выше и нажмите “Загрузить” для получения статистики</p>
|
||||||
<p className="text-white/40 text-sm">
|
<p className="text-white/40 text-sm mb-4">
|
||||||
Поддерживается API Wildberries /adv/v2/fullstats
|
Поддерживается API Wildberries /adv/v2/fullstats
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
{/* Инструкция для пользователя */}
|
||||||
|
<div className="bg-white/5 rounded-lg p-4 border border-white/10">
|
||||||
|
<h4 className="text-white font-medium mb-2 flex items-center gap-2">
|
||||||
|
<Target className="h-4 w-4" />
|
||||||
|
Как начать работу:
|
||||||
|
</h4>
|
||||||
|
<ol className="text-white/60 text-sm space-y-1 list-decimal list-inside">
|
||||||
|
<li>Разверните селектор кампаний выше (нажмите кнопку с иконкой)</li>
|
||||||
|
<li>Выберите нужные кампании из списка или введите ID вручную</li>
|
||||||
|
<li>Нажмите кнопку “Загрузить” для получения статистики</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
@ -35,49 +35,7 @@ export function FulfillmentWarehouseTab() {
|
|||||||
const [searchTerm, setSearchTerm] = useState('')
|
const [searchTerm, setSearchTerm] = useState('')
|
||||||
const [selectedStatus, setSelectedStatus] = useState<string>('all')
|
const [selectedStatus, setSelectedStatus] = useState<string>('all')
|
||||||
|
|
||||||
const [orders, setOrders] = useState<FulfillmentOrder[]>([
|
const [orders, setOrders] = useState<FulfillmentOrder[]>([])
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
orderId: 'FL-2024-001',
|
|
||||||
customerName: 'Иван Петров',
|
|
||||||
items: [
|
|
||||||
{ name: 'Товар A', quantity: 2, sku: 'SKU-001' },
|
|
||||||
{ name: 'Товар B', quantity: 1, sku: 'SKU-002' }
|
|
||||||
],
|
|
||||||
status: 'pending',
|
|
||||||
priority: 'high',
|
|
||||||
createdAt: '2024-01-15T10:30:00',
|
|
||||||
shippingAddress: 'Москва, ул. Ленина, 10',
|
|
||||||
totalValue: 3500
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
orderId: 'FL-2024-002',
|
|
||||||
customerName: 'Анна Сидорова',
|
|
||||||
items: [
|
|
||||||
{ name: 'Товар C', quantity: 1, sku: 'SKU-003' }
|
|
||||||
],
|
|
||||||
status: 'processing',
|
|
||||||
priority: 'medium',
|
|
||||||
createdAt: '2024-01-14T15:20:00',
|
|
||||||
shippingAddress: 'СПб, пр. Невский, 25',
|
|
||||||
totalValue: 1200
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
orderId: 'FL-2024-003',
|
|
||||||
customerName: 'Олег Козлов',
|
|
||||||
items: [
|
|
||||||
{ name: 'Товар D', quantity: 3, sku: 'SKU-004' },
|
|
||||||
{ name: 'Товар E', quantity: 2, sku: 'SKU-005' }
|
|
||||||
],
|
|
||||||
status: 'shipped',
|
|
||||||
priority: 'low',
|
|
||||||
createdAt: '2024-01-13T09:15:00',
|
|
||||||
shippingAddress: 'Екатеринбург, ул. Мира, 45',
|
|
||||||
totalValue: 5600
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const stats: FulfillmentStats = {
|
const stats: FulfillmentStats = {
|
||||||
totalOrders: orders.length,
|
totalOrders: orders.length,
|
||||||
|
Reference in New Issue
Block a user