Добавлен новый компонент для отображения бизнес-процессов в интерфейсе управления. Обновлен компонент UIKitSection для интеграции нового демо и улучшения навигации. Оптимизирована логика отображения данных и улучшена читаемость кода. Исправлены текстовые метки для повышения удобства использования.

This commit is contained in:
Veronika Smirnova
2025-07-27 20:10:39 +03:00
parent f198994400
commit ec28803549
17 changed files with 4304 additions and 1205 deletions

View File

@ -7,7 +7,11 @@ import { Card } from "@/components/ui/card";
import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar";
import { useRouter, usePathname } from "next/navigation";
import { useQuery } from "@apollo/client";
import { GET_CONVERSATIONS, GET_INCOMING_REQUESTS } from "@/graphql/queries";
import {
GET_CONVERSATIONS,
GET_INCOMING_REQUESTS,
GET_SUPPLY_ORDERS,
} from "@/graphql/queries";
import {
Settings,
LogOut,
@ -23,6 +27,36 @@ import {
BarChart3,
} from "lucide-react";
// Компонент для отображения уведомлений о новых заявках
function NewOrdersNotification() {
const { user } = useAuth();
// Загружаем заказы поставок для оптовика
const { data: ordersData } = useQuery(GET_SUPPLY_ORDERS, {
pollInterval: 30000, // Обновляем каждые 30 секунд для заявок
fetchPolicy: "cache-first",
errorPolicy: "ignore",
skip: user?.organization?.type !== "WHOLESALE",
});
if (user?.organization?.type !== "WHOLESALE") return null;
const orders = ordersData?.supplyOrders || [];
// Считаем заявки в статусе PENDING (ожидают одобрения оптовика)
const pendingOrders = orders.filter(
(order) =>
order.status === "PENDING" && order.partnerId === user?.organization?.id
);
if (pendingOrders.length === 0) return null;
return (
<div className="absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full min-w-[18px] h-[18px] flex items-center justify-center font-bold animate-pulse">
{pendingOrders.length > 99 ? "99+" : pendingOrders.length}
</div>
);
}
export function Sidebar() {
const { user, logout } = useAuth();
const router = useRouter();
@ -162,9 +196,7 @@ export function Sidebar() {
const isFulfillmentStatisticsActive = pathname.startsWith(
"/fulfillment-statistics"
);
const isSellerStatisticsActive = pathname.startsWith(
"/seller-statistics"
);
const isSellerStatisticsActive = pathname.startsWith("/seller-statistics");
const isEmployeesActive = pathname.startsWith("/employees");
const isSuppliesActive =
pathname.startsWith("/supplies") ||
@ -483,45 +515,45 @@ export function Sidebar() {
</Button>
)}
{/* Склад - для фулфилмент */}
{user?.organization?.type === "FULFILLMENT" && (
<Button
variant={isFulfillmentWarehouseActive ? "secondary" : "ghost"}
className={`w-full ${
isCollapsed ? "justify-center px-2 h-9" : "justify-start h-10"
} text-left transition-all duration-200 text-xs ${
isFulfillmentWarehouseActive
? "bg-white/20 text-white hover:bg-white/30"
: "text-white/80 hover:bg-white/10 hover:text-white"
} cursor-pointer`}
onClick={handleFulfillmentWarehouseClick}
title={isCollapsed ? "Склад" : ""}
>
<Warehouse className="h-4 w-4 flex-shrink-0" />
{!isCollapsed && <span className="ml-3">Склад</span>}
</Button>
)}
{/* Склад - для фулфилмент */}
{user?.organization?.type === "FULFILLMENT" && (
<Button
variant={isFulfillmentWarehouseActive ? "secondary" : "ghost"}
className={`w-full ${
isCollapsed ? "justify-center px-2 h-9" : "justify-start h-10"
} text-left transition-all duration-200 text-xs ${
isFulfillmentWarehouseActive
? "bg-white/20 text-white hover:bg-white/30"
: "text-white/80 hover:bg-white/10 hover:text-white"
} cursor-pointer`}
onClick={handleFulfillmentWarehouseClick}
title={isCollapsed ? "Склад" : ""}
>
<Warehouse className="h-4 w-4 flex-shrink-0" />
{!isCollapsed && <span className="ml-3">Склад</span>}
</Button>
)}
{/* Статистика - для фулфилмент */}
{user?.organization?.type === "FULFILLMENT" && (
<Button
variant={isFulfillmentStatisticsActive ? "secondary" : "ghost"}
className={`w-full ${
isCollapsed ? "justify-center px-2 h-9" : "justify-start h-10"
} text-left transition-all duration-200 text-xs ${
isFulfillmentStatisticsActive
? "bg-white/20 text-white hover:bg-white/30"
: "text-white/80 hover:bg-white/10 hover:text-white"
} cursor-pointer`}
onClick={handleFulfillmentStatisticsClick}
title={isCollapsed ? "Статистика" : ""}
>
<BarChart3 className="h-4 w-4 flex-shrink-0" />
{!isCollapsed && <span className="ml-3">Статистика</span>}
</Button>
)}
{/* Статистика - для фулфилмент */}
{user?.organization?.type === "FULFILLMENT" && (
<Button
variant={isFulfillmentStatisticsActive ? "secondary" : "ghost"}
className={`w-full ${
isCollapsed ? "justify-center px-2 h-9" : "justify-start h-10"
} text-left transition-all duration-200 text-xs ${
isFulfillmentStatisticsActive
? "bg-white/20 text-white hover:bg-white/30"
: "text-white/80 hover:bg-white/10 hover:text-white"
} cursor-pointer`}
onClick={handleFulfillmentStatisticsClick}
title={isCollapsed ? "Статистика" : ""}
>
<BarChart3 className="h-4 w-4 flex-shrink-0" />
{!isCollapsed && <span className="ml-3">Статистика</span>}
</Button>
)}
{/* Отгрузки - для оптовиков */}
{/* Заявки - для оптовиков */}
{user?.organization?.type === "WHOLESALE" && (
<Button
variant={isSuppliesActive ? "secondary" : "ghost"}
@ -531,12 +563,16 @@ export function Sidebar() {
isSuppliesActive
? "bg-white/20 text-white hover:bg-white/30"
: "text-white/80 hover:bg-white/10 hover:text-white"
} cursor-pointer`}
} cursor-pointer relative`}
onClick={handleSuppliesClick}
title={isCollapsed ? "Отгрузки" : ""}
title={isCollapsed ? "Заявки" : ""}
>
<Truck className="h-4 w-4 flex-shrink-0" />
{!isCollapsed && <span className="ml-3">Отгрузки</span>}
{!isCollapsed && <span className="ml-3">Заявки</span>}
{/* Уведомление о новых заявках */}
{user?.organization?.type === "WHOLESALE" && (
<NewOrdersNotification />
)}
</Button>
)}