Добавлено обновление кэша для расходников фулфилмента в компонентах создания и отображения заказов. Реализованы новые GraphQL запросы для получения данных о расходниках. Удалены устаревшие компоненты уведомлений о непринятых поставках для упрощения интерфейса. Оптимизирована логика отображения и обновления данных о заказах.
This commit is contained in:
@ -28,6 +28,7 @@ import {
|
||||
GET_MY_COUNTERPARTIES,
|
||||
GET_ALL_PRODUCTS,
|
||||
GET_SUPPLY_ORDERS,
|
||||
GET_MY_SUPPLIES,
|
||||
} from "@/graphql/queries";
|
||||
import { CREATE_SUPPLY_ORDER } from "@/graphql/mutations";
|
||||
import { OrganizationAvatar } from "@/components/market/organization-avatar";
|
||||
@ -232,7 +233,10 @@ export function CreateFulfillmentConsumablesSupplyPage() {
|
||||
})),
|
||||
},
|
||||
},
|
||||
refetchQueries: [{ query: GET_SUPPLY_ORDERS }],
|
||||
refetchQueries: [
|
||||
{ query: GET_SUPPLY_ORDERS }, // Обновляем заказы поставок
|
||||
{ query: GET_MY_SUPPLIES }, // Обновляем расходники фулфилмента
|
||||
],
|
||||
});
|
||||
|
||||
if (result.data?.createSupplyOrder?.success) {
|
||||
|
@ -36,57 +36,6 @@ import {
|
||||
AlertTriangle,
|
||||
} from "lucide-react";
|
||||
|
||||
// Компонент уведомлений о непринятых поставках
|
||||
function PendingSuppliesAlert() {
|
||||
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
|
||||
pollInterval: 30000, // Обновляем каждые 30 секунд
|
||||
fetchPolicy: "cache-first",
|
||||
errorPolicy: "ignore",
|
||||
});
|
||||
|
||||
const pendingCount = pendingData?.pendingSuppliesCount?.total || 0;
|
||||
const supplyOrdersCount =
|
||||
pendingData?.pendingSuppliesCount?.supplyOrders || 0;
|
||||
const incomingRequestsCount =
|
||||
pendingData?.pendingSuppliesCount?.incomingRequests || 0;
|
||||
|
||||
if (pendingCount === 0) return null;
|
||||
|
||||
return (
|
||||
<Card className="bg-gradient-to-r from-orange-500/20 to-red-500/20 backdrop-blur border-orange-400/30 p-3 mb-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-orange-500/20 rounded-full">
|
||||
<Bell className="h-5 w-5 text-orange-300 animate-pulse" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-orange-200 font-semibold text-sm flex items-center gap-2">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
Требует вашего внимания
|
||||
</h3>
|
||||
<div className="text-orange-100 text-xs mt-1 space-y-1">
|
||||
{supplyOrdersCount > 0 && (
|
||||
<p>
|
||||
• {supplyOrdersCount} поставок требуют вашего действия
|
||||
(подтверждение/получение)
|
||||
</p>
|
||||
)}
|
||||
{incomingRequestsCount > 0 && (
|
||||
<p>
|
||||
• {incomingRequestsCount} заявок на партнерство ожидают ответа
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="bg-orange-500 text-white text-xs font-bold rounded-full w-6 h-6 flex items-center justify-center">
|
||||
{pendingCount > 99 ? "99+" : pendingCount}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
interface SupplyOrder {
|
||||
id: string;
|
||||
partnerId: string;
|
||||
@ -147,7 +96,7 @@ export function FulfillmentConsumablesOrdersTab() {
|
||||
},
|
||||
refetchQueries: [
|
||||
{ query: GET_SUPPLY_ORDERS }, // Обновляем заказы поставок
|
||||
{ query: GET_MY_SUPPLIES }, // Обновляем склад фулфилмента
|
||||
{ query: GET_MY_SUPPLIES }, // Обновляем склад фулфилмента (расходники фф)
|
||||
{ query: GET_WAREHOUSE_PRODUCTS }, // Обновляем товары склада
|
||||
],
|
||||
onError: (error) => {
|
||||
@ -288,9 +237,6 @@ export function FulfillmentConsumablesOrdersTab() {
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
{/* Уведомления о непринятых поставках */}
|
||||
<PendingSuppliesAlert />
|
||||
|
||||
{/* Компактная статистика */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
|
||||
<Card className="bg-white/10 backdrop-blur border-white/20 p-2">
|
||||
|
@ -11,6 +11,8 @@ import { useQuery, useMutation } from "@apollo/client";
|
||||
import {
|
||||
GET_SUPPLY_ORDERS,
|
||||
GET_PENDING_SUPPLIES_COUNT,
|
||||
GET_MY_SUPPLIES,
|
||||
GET_WAREHOUSE_PRODUCTS,
|
||||
} from "@/graphql/queries";
|
||||
import { UPDATE_SUPPLY_ORDER_STATUS } from "@/graphql/mutations";
|
||||
import { useAuth } from "@/hooks/useAuth";
|
||||
@ -31,56 +33,7 @@ import {
|
||||
CheckCircle,
|
||||
} from "lucide-react";
|
||||
|
||||
// Компонент уведомлений о непринятых поставках
|
||||
function PendingSuppliesAlert() {
|
||||
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
|
||||
pollInterval: 30000, // Обновляем каждые 30 секунд
|
||||
fetchPolicy: "cache-first",
|
||||
errorPolicy: "ignore",
|
||||
});
|
||||
|
||||
const pendingCount = pendingData?.pendingSuppliesCount?.total || 0;
|
||||
const supplyOrdersCount =
|
||||
pendingData?.pendingSuppliesCount?.supplyOrders || 0;
|
||||
const incomingRequestsCount =
|
||||
pendingData?.pendingSuppliesCount?.incomingRequests || 0;
|
||||
|
||||
if (pendingCount === 0) return null;
|
||||
|
||||
return (
|
||||
<Card className="bg-gradient-to-r from-orange-500/20 to-red-500/20 backdrop-blur border-orange-400/30 p-3 mb-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-orange-500/20 rounded-full">
|
||||
<Bell className="h-5 w-5 text-orange-300 animate-pulse" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-orange-200 font-semibold text-sm flex items-center gap-2">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
Требует вашего внимания
|
||||
</h3>
|
||||
<div className="text-orange-100 text-xs mt-1 space-y-1">
|
||||
{supplyOrdersCount > 0 && (
|
||||
<p>
|
||||
• {supplyOrdersCount} поставок требуют вашего действия
|
||||
(подтверждение/получение)
|
||||
</p>
|
||||
)}
|
||||
{incomingRequestsCount > 0 && (
|
||||
<p>
|
||||
• {incomingRequestsCount} заявок на партнерство ожидают ответа
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="bg-orange-500 text-white text-xs font-bold rounded-full w-6 h-6 flex items-center justify-center">
|
||||
{pendingCount > 99 ? "99+" : pendingCount}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// Интерфейс для заказа
|
||||
interface SupplyOrder {
|
||||
@ -92,6 +45,7 @@ interface SupplyOrder {
|
||||
totalAmount: number;
|
||||
status: string;
|
||||
fulfillmentCenterId: string;
|
||||
number?: number; // Порядковый номер
|
||||
organization: {
|
||||
id: string;
|
||||
name?: string;
|
||||
@ -170,7 +124,11 @@ export function FulfillmentDetailedSuppliesTab() {
|
||||
|
||||
// Мутация для обновления статуса заказа
|
||||
const [updateSupplyOrderStatus] = useMutation(UPDATE_SUPPLY_ORDER_STATUS, {
|
||||
refetchQueries: [{ query: GET_SUPPLY_ORDERS }],
|
||||
refetchQueries: [
|
||||
{ query: GET_SUPPLY_ORDERS }, // Обновляем заказы поставок
|
||||
{ query: GET_MY_SUPPLIES }, // Обновляем склад фулфилмента (расходники фф)
|
||||
{ query: GET_WAREHOUSE_PRODUCTS }, // Обновляем товары склада
|
||||
],
|
||||
onError: (error) => {
|
||||
console.error("Error updating supply order status:", error);
|
||||
toast.error("Ошибка при обновлении статуса заказа");
|
||||
@ -197,7 +155,11 @@ export function FulfillmentDetailedSuppliesTab() {
|
||||
}
|
||||
);
|
||||
|
||||
// Убираем разделение на createdByUs и createdForUs, так как здесь только наши поставки
|
||||
// Генерируем порядковые номера для заказов (сверху вниз от большего к меньшему)
|
||||
const ordersWithNumbers = ourSupplyOrders.map((order, index) => ({
|
||||
...order,
|
||||
number: ourSupplyOrders.length - index, // Обратный порядок для новых заказов сверху
|
||||
}));
|
||||
|
||||
const toggleOrderExpansion = (orderId: string) => {
|
||||
const newExpanded = new Set(expandedOrders);
|
||||
@ -261,9 +223,6 @@ export function FulfillmentDetailedSuppliesTab() {
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
{/* Уведомления о непринятых поставках */}
|
||||
<PendingSuppliesAlert />
|
||||
|
||||
{/* Заголовок с кнопкой создания поставки */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
@ -380,7 +339,7 @@ export function FulfillmentDetailedSuppliesTab() {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ourSupplyOrders.map((order: SupplyOrder) => {
|
||||
{ordersWithNumbers.map((order: SupplyOrder) => {
|
||||
const isOrderExpanded = expandedOrders.has(order.id);
|
||||
|
||||
return (
|
||||
@ -393,7 +352,7 @@ export function FulfillmentDetailedSuppliesTab() {
|
||||
<td className="p-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-white font-bold text-lg">
|
||||
#{order.id.slice(-8)}
|
||||
{order.number}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -40,56 +40,7 @@ import {
|
||||
} from "lucide-react";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
|
||||
// Компонент уведомлений о непринятых поставках
|
||||
function PendingSuppliesAlert() {
|
||||
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
|
||||
pollInterval: 30000, // Обновляем каждые 30 секунд
|
||||
fetchPolicy: "cache-first",
|
||||
errorPolicy: "ignore",
|
||||
});
|
||||
|
||||
const pendingCount = pendingData?.pendingSuppliesCount?.total || 0;
|
||||
const supplyOrdersCount =
|
||||
pendingData?.pendingSuppliesCount?.supplyOrders || 0;
|
||||
const incomingRequestsCount =
|
||||
pendingData?.pendingSuppliesCount?.incomingRequests || 0;
|
||||
|
||||
if (pendingCount === 0) return null;
|
||||
|
||||
return (
|
||||
<Card className="bg-gradient-to-r from-orange-500/20 to-red-500/20 backdrop-blur border-orange-400/30 p-3 mb-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="p-2 bg-orange-500/20 rounded-full">
|
||||
<Bell className="h-5 w-5 text-orange-300 animate-pulse" />
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<h3 className="text-orange-200 font-semibold text-sm flex items-center gap-2">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
Требует вашего внимания
|
||||
</h3>
|
||||
<div className="text-orange-100 text-xs mt-1 space-y-1">
|
||||
{supplyOrdersCount > 0 && (
|
||||
<p>
|
||||
• {supplyOrdersCount} поставок требуют вашего действия
|
||||
(подтверждение/получение)
|
||||
</p>
|
||||
)}
|
||||
{incomingRequestsCount > 0 && (
|
||||
<p>
|
||||
• {incomingRequestsCount} заявок на партнерство ожидают ответа
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<div className="bg-orange-500 text-white text-xs font-bold rounded-full w-6 h-6 flex items-center justify-center">
|
||||
{pendingCount > 99 ? "99+" : pendingCount}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
// Интерфейсы для данных
|
||||
interface Employee {
|
||||
@ -712,9 +663,6 @@ export function FulfillmentGoodsTab() {
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col p-2 xl:p-4">
|
||||
{/* Уведомления о непринятых поставках */}
|
||||
<PendingSuppliesAlert />
|
||||
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
onValueChange={setActiveTab}
|
||||
|
@ -23,7 +23,12 @@ import {
|
||||
Minus,
|
||||
ShoppingCart,
|
||||
} from "lucide-react";
|
||||
import { GET_MY_COUNTERPARTIES, GET_ALL_PRODUCTS } from "@/graphql/queries";
|
||||
import {
|
||||
GET_MY_COUNTERPARTIES,
|
||||
GET_ALL_PRODUCTS,
|
||||
GET_SUPPLY_ORDERS,
|
||||
GET_MY_SUPPLIES,
|
||||
} from "@/graphql/queries";
|
||||
import { CREATE_SUPPLY_ORDER } from "@/graphql/mutations";
|
||||
import { OrganizationAvatar } from "@/components/market/organization-avatar";
|
||||
import { toast } from "sonner";
|
||||
@ -94,9 +99,10 @@ export function MaterialsOrderForm() {
|
||||
variables: { search: null, category: null },
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// Мутация для создания заказа поставки
|
||||
const [createSupplyOrder, { loading: isCreatingOrder }] = useMutation(CREATE_SUPPLY_ORDER);
|
||||
const [createSupplyOrder, { loading: isCreatingOrder }] =
|
||||
useMutation(CREATE_SUPPLY_ORDER);
|
||||
|
||||
// Фильтруем только поставщиков из партнеров
|
||||
const wholesalePartners = (counterpartiesData?.myCounterparties || []).filter(
|
||||
@ -178,19 +184,26 @@ export function MaterialsOrderForm() {
|
||||
input: {
|
||||
partnerId: selectedPartner.id,
|
||||
deliveryDate: deliveryDate,
|
||||
items: selectedProducts.map(product => ({
|
||||
items: selectedProducts.map((product) => ({
|
||||
productId: product.id,
|
||||
quantity: product.selectedQuantity
|
||||
}))
|
||||
}
|
||||
}
|
||||
quantity: product.selectedQuantity,
|
||||
})),
|
||||
},
|
||||
},
|
||||
refetchQueries: [
|
||||
{ query: GET_SUPPLY_ORDERS }, // Обновляем заказы поставок
|
||||
{ query: GET_MY_SUPPLIES }, // Обновляем расходники фулфилмента
|
||||
],
|
||||
});
|
||||
|
||||
if (result.data?.createSupplyOrder?.success) {
|
||||
toast.success("Заказ поставки создан успешно!");
|
||||
router.push("/fulfillment-supplies");
|
||||
} else {
|
||||
toast.error(result.data?.createSupplyOrder?.message || "Ошибка при создании заказа");
|
||||
toast.error(
|
||||
result.data?.createSupplyOrder?.message ||
|
||||
"Ошибка при создании заказа"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error creating supply order:", error);
|
||||
@ -447,14 +460,20 @@ export function MaterialsOrderForm() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Кнопка создания заказа */}
|
||||
<Button
|
||||
{/* Кнопка создания заказа */}
|
||||
<Button
|
||||
onClick={handleCreateOrder}
|
||||
disabled={selectedProducts.length === 0 || !deliveryDate || isCreatingOrder}
|
||||
disabled={
|
||||
selectedProducts.length === 0 ||
|
||||
!deliveryDate ||
|
||||
isCreatingOrder
|
||||
}
|
||||
className="w-full mt-4 bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white"
|
||||
>
|
||||
<ShoppingCart className="h-4 w-4 mr-2" />
|
||||
{isCreatingOrder ? "Создание заказа..." : "Создать заказ поставки"}
|
||||
{isCreatingOrder
|
||||
? "Создание заказа..."
|
||||
: "Создать заказ поставки"}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
|
Reference in New Issue
Block a user