Files
sfera-new/src/components/supplies/supplies-dashboard.tsx

205 lines
8.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useState, useEffect } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Sidebar } from "@/components/dashboard/sidebar";
import { useSidebar } from "@/hooks/useSidebar";
import { useSearchParams } from "next/navigation";
import { useQuery } from "@apollo/client";
import {
Plus,
Package,
Wrench,
ChevronDown,
AlertTriangle,
} from "lucide-react";
import { GET_PENDING_SUPPLIES_COUNT } from "@/graphql/queries";
import { FulfillmentGoodsTab } from "./fulfillment-supplies/fulfillment-goods-tab";
import { RealSupplyOrdersTab } from "./fulfillment-supplies/real-supply-orders-tab";
import { SellerSupplyOrdersTab } from "./fulfillment-supplies/seller-supply-orders-tab";
import { AllSuppliesTab } from "./fulfillment-supplies/all-supplies-tab";
import { useAuth } from "@/hooks/useAuth";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export function SuppliesDashboard() {
const { getSidebarMargin } = useSidebar();
const searchParams = useSearchParams();
const [activeTab, setActiveTab] = useState("all");
const { user } = useAuth();
// Загружаем счетчик поставок, требующих одобрения
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
pollInterval: 30000, // Обновляем каждые 30 секунд
fetchPolicy: "cache-first",
errorPolicy: "ignore",
});
const pendingCount = pendingData?.pendingSuppliesCount;
const hasPendingItems = pendingCount && pendingCount.total > 0;
// Автоматически открываем нужную вкладку при загрузке
useEffect(() => {
const tab = searchParams.get("tab");
if (tab === "consumables") {
setActiveTab("supplies");
} else if (tab === "goods") {
setActiveTab("goods");
}
}, [searchParams]);
// Определяем тип организации для выбора правильного компонента
const isWholesale = user?.organization?.type === "WHOLESALE";
return (
<div className="h-screen flex overflow-hidden">
<Sidebar />
<main
className={`flex-1 ${getSidebarMargin()} px-2 py-2 overflow-hidden transition-all duration-300`}
>
<div className="h-full">
{/* Уведомляющий баннер */}
{hasPendingItems && (
<Alert className="mb-4 bg-blue-500/20 border-blue-400/30 text-blue-300 animate-pulse">
<AlertTriangle className="h-4 w-4" />
<AlertDescription>
У вас есть {pendingCount.total} элемент
{pendingCount.total > 1
? pendingCount.total < 5
? "а"
: "ов"
: ""}
, требующ{pendingCount.total > 1 ? "их" : "ий"} одобрения:
{pendingCount.supplyOrders > 0 &&
` ${pendingCount.supplyOrders} заказ${
pendingCount.supplyOrders > 1
? pendingCount.supplyOrders < 5
? "а"
: "ов"
: ""
} поставок`}
{pendingCount.incomingRequests > 0 &&
pendingCount.supplyOrders > 0 &&
", "}
{pendingCount.incomingRequests > 0 &&
` ${pendingCount.incomingRequests} заявк${
pendingCount.incomingRequests > 1
? pendingCount.incomingRequests < 5
? "и"
: ""
: "а"
} на партнерство`}
</AlertDescription>
</Alert>
)}
{/* Основные вкладки с кнопкой создания */}
<Tabs
value={activeTab}
onValueChange={setActiveTab}
className="w-full h-full flex flex-col"
>
<div className="flex items-center justify-between mb-1 flex-wrap gap-2">
<TabsList
className={`grid grid-cols-3 bg-white/10 backdrop-blur border-white/20 w-fit text-sm ${
hasPendingItems ? "ring-2 ring-blue-400/50" : ""
}`}
>
<TabsTrigger
value="all"
className="data-[state=active]:bg-gradient-to-r data-[state=active]:from-purple-500 data-[state=active]:to-pink-500 data-[state=active]:text-white text-white/60 px-3 sm:px-6"
>
Все
</TabsTrigger>
<TabsTrigger
value="goods"
className="data-[state=active]:bg-gradient-to-r data-[state=active]:from-purple-500 data-[state=active]:to-pink-500 data-[state=active]:text-white text-white/60 px-3 sm:px-6"
>
Товар
</TabsTrigger>
<TabsTrigger
value="supplies"
className={`data-[state=active]:bg-gradient-to-r data-[state=active]:from-purple-500 data-[state=active]:to-pink-500 data-[state=active]:text-white text-white/60 px-3 sm:px-6 relative ${
pendingCount?.supplyOrders > 0 ? "animate-pulse" : ""
}`}
>
Расходники
{pendingCount?.supplyOrders > 0 && (
<div className="absolute -top-1 -right-1 w-5 h-5 bg-blue-500 rounded-full flex items-center justify-center text-xs font-bold text-white">
{pendingCount.supplyOrders}
</div>
)}
</TabsTrigger>
</TabsList>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button
size="sm"
className="bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white shadow-lg"
>
<Plus className="h-3 w-3 mr-1" />
<span className="hidden sm:inline">Создать поставку</span>
<span className="sm:hidden">Создать</span>
<ChevronDown className="h-3 w-3 ml-1" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="bg-white/10 backdrop-blur border-white/20"
>
<DropdownMenuItem
onClick={() => {
window.location.href = "/supplies/create";
}}
className="text-white hover:bg-white/10 cursor-pointer"
>
<Package className="h-4 w-4 mr-2" />
Поставка товаров
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
window.location.href = "/supplies/create-consumables";
}}
className="text-white hover:bg-white/10 cursor-pointer"
>
<Wrench className="h-4 w-4 mr-2" />
Поставка расходников
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
<TabsContent value="all" className="mt-0 flex-1 overflow-hidden">
<AllSuppliesTab
pendingSupplyOrders={pendingCount?.supplyOrders || 0}
/>
</TabsContent>
<TabsContent value="goods" className="mt-0 flex-1 overflow-hidden">
<FulfillmentGoodsTab />
</TabsContent>
<TabsContent
value="supplies"
className="mt-0 flex-1 overflow-hidden"
>
{isWholesale ? (
<RealSupplyOrdersTab />
) : (
<SellerSupplyOrdersTab />
)}
</TabsContent>
</Tabs>
</div>
</main>
</div>
);
}