Добавлено обновление кэша для расходников фулфилмента в компонентах создания и отображения заказов. Реализованы новые GraphQL запросы для получения данных о расходниках. Удалены устаревшие компоненты уведомлений о непринятых поставках для упрощения интерфейса. Оптимизирована логика отображения и обновления данных о заказах.

This commit is contained in:
Veronika Smirnova
2025-07-29 17:45:29 +03:00
parent 7877f61d5a
commit 50438bb21f
18 changed files with 3693 additions and 191 deletions

View File

@ -1,6 +1,7 @@
"use client";
import { useState, useMemo } from "react";
import { useRouter } from "next/navigation";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
@ -8,6 +9,7 @@ import { Input } from "@/components/ui/input";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { Sidebar } from "@/components/dashboard/sidebar";
import { useSidebar } from "@/hooks/useSidebar";
import { useAuth } from "@/hooks/useAuth";
import { useQuery } from "@apollo/client";
import {
GET_MY_COUNTERPARTIES,
@ -158,7 +160,9 @@ interface SupplyOrder {
* - Контрастный цвет текста для лучшей читаемости
*/
export function FulfillmentWarehouseDashboard() {
const router = useRouter();
const { getSidebarMargin } = useSidebar();
const { user } = useAuth();
// Состояния для поиска и фильтрации
const [searchTerm, setSearchTerm] = useState("");
@ -387,6 +391,38 @@ export function FulfillmentWarehouseDashboard() {
0
);
// Подсчитываем расходники ФФ (расходники, которые получил фулфилмент-центр)
const fulfillmentConsumablesOrders = supplyOrders.filter((order) => {
// Заказы где текущий фулфилмент-центр является получателем
const isRecipient =
order.fulfillmentCenter?.id === user?.organization?.id;
// НО создатель заказа НЕ мы (т.е. селлер создал заказ для нас)
const isCreatedByOther =
order.organization?.id !== user?.organization?.id;
// И статус DELIVERED (получено)
const isDelivered = order.status === "DELIVERED";
return isRecipient && isCreatedByOther && isDelivered;
});
// Подсчитываем общее количество расходников ФФ из доставленных заказов
const totalFulfillmentSupplies = fulfillmentConsumablesOrders.reduce(
(sum, order) => sum + (order.totalItems || 0),
0
);
// Подсчитываем изменения за сегодня (расходники ФФ, полученные сегодня)
const today = new Date();
today.setHours(0, 0, 0, 0);
const fulfillmentSuppliesReceivedToday = fulfillmentConsumablesOrders
.filter((order) => {
const orderDate = new Date(order.updatedAt || order.createdAt);
orderDate.setHours(0, 0, 0, 0);
return orderDate.getTime() === today.getTime();
})
.reduce((sum, order) => sum + (order.totalItems || 0), 0);
return {
products: {
current: 0, // Нет данных о готовых продуктах для продажи
@ -405,8 +441,8 @@ export function FulfillmentWarehouseDashboard() {
change: 0, // Нет реальных данных об изменениях возвратов
},
fulfillmentSupplies: {
current: 0, // Нет реальных данных о расходниках ФФ
change: 0, // Нет реальных данных об изменениях расходников ФФ
current: totalFulfillmentSupplies, // Реальное количество расходников ФФ
change: fulfillmentSuppliesReceivedToday, // Расходники ФФ, полученные сегодня
},
sellerSupplies: {
current: totalSellerSupplies, // Реальное количество расходников селлера из базы
@ -422,6 +458,7 @@ export function FulfillmentWarehouseDashboard() {
suppliesUsedToday,
productsReceivedToday,
productsUsedToday,
user?.organization?.id,
]);
// Создаем структурированные данные склада на основе уникальных товаров
@ -710,7 +747,9 @@ export function FulfillmentWarehouseDashboard() {
) || 1)) *
(suppliesReceivedToday - suppliesUsedToday)
)
: Math.floor((suppliesReceivedToday - suppliesUsedToday) / totalVirtualPartners);
: Math.floor(
(suppliesReceivedToday - suppliesUsedToday) / totalVirtualPartners
);
return {
id: `virtual-partner-${index + 1}`,
@ -958,18 +997,23 @@ export function FulfillmentWarehouseDashboard() {
current,
change,
description,
onClick,
}: {
title: string;
icon: React.ComponentType<{ className?: string }>;
current: number;
change: number;
description: string;
onClick?: () => void;
}) => {
const percentChange = current > 0 ? (change / current) * 100 : 0;
return (
<div
className={`glass-card p-3 hover:bg-white/15 transition-all duration-300 relative overflow-hidden`}
className={`glass-card p-3 hover:bg-white/15 transition-all duration-300 relative overflow-hidden ${
onClick ? "cursor-pointer hover:scale-105" : ""
}`}
onClick={onClick}
>
<div className="flex items-center justify-between mb-2">
<div className="flex items-center space-x-2">
@ -1000,18 +1044,28 @@ export function FulfillmentWarehouseDashboard() {
</div>
{/* Изменения - всегда показываем */}
<div className="flex items-center space-x-1">
<div className={`flex items-center space-x-0.5 px-1 py-0.5 rounded ${
change >= 0 ? 'bg-green-500/20' : 'bg-red-500/20'
}`}>
<span className={`text-xs font-bold ${
change >= 0 ? 'text-green-400' : 'text-red-400'
}`}>
{change >= 0 ? '+' : ''}{change}
<div
className={`flex items-center space-x-0.5 px-1 py-0.5 rounded ${
change >= 0 ? "bg-green-500/20" : "bg-red-500/20"
}`}
>
<span
className={`text-xs font-bold ${
change >= 0 ? "text-green-400" : "text-red-400"
}`}
>
{change >= 0 ? "+" : ""}
{change}
</span>
</div>
</div>
</div>
<div className="text-white/60 text-[10px]">{description}</div>
{onClick && (
<div className="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity">
<ChevronRight className="h-3 w-3 text-white/60" />
</div>
)}
</div>
);
};
@ -1196,6 +1250,7 @@ export function FulfillmentWarehouseDashboard() {
current={warehouseStats.fulfillmentSupplies.current}
change={warehouseStats.fulfillmentSupplies.change}
description="Расходники, этикетки"
onClick={() => router.push("/fulfillment-warehouse/supplies")}
/>
<StatCard
title="Расходники селлеров"