Обновление компонентов интерфейса и оптимизация логики

- Добавлен компонент AppShell в RootLayout для улучшения структуры
- Обновлен компонент Sidebar для предотвращения дублирования при рендеринге
- Оптимизированы импорты в компонентах AdvertisingTab и SalesTab
- Реализована логика кэширования статистики селлера в GraphQL резолверах
This commit is contained in:
Bivekich
2025-08-08 09:24:15 +03:00
parent b43269073f
commit 547e6e7d95
13 changed files with 610 additions and 275 deletions

View File

@ -2,24 +2,24 @@
import { useQuery } from '@apollo/client'
import {
Settings,
LogOut,
Store,
MessageCircle,
Wrench,
Warehouse,
Users,
Truck,
Handshake,
ChevronLeft,
ChevronRight,
BarChart3,
Home,
DollarSign,
BarChart3,
ChevronLeft,
ChevronRight,
DollarSign,
Handshake,
Home,
LogOut,
MessageCircle,
Settings,
Store,
Truck,
Users,
Warehouse,
Wrench,
} from 'lucide-react'
import { useRouter, usePathname } from 'next/navigation'
import { usePathname, useRouter } from 'next/navigation'
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import { GET_CONVERSATIONS, GET_INCOMING_REQUESTS, GET_PENDING_SUPPLIES_COUNT } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth'
@ -83,7 +83,17 @@ function WholesaleOrdersNotification() {
)
}
export function Sidebar() {
declare global {
interface Window {
__SIDEBAR_ROOT_MOUNTED__?: boolean
}
}
export function Sidebar({ isRootInstance = false }: { isRootInstance?: boolean } = {}) {
// Если уже есть корневой сайдбар и это не корневой экземпляр — не рендерим дубликат
if (typeof window !== 'undefined' && !isRootInstance && (window as any).__SIDEBAR_ROOT_MOUNTED__) {
return null
}
const { user, logout } = useAuth()
const router = useRouter()
const pathname = usePathname()
@ -236,6 +246,11 @@ export function Sidebar() {
pathname.startsWith('/supplier-orders')
const isPartnersActive = pathname.startsWith('/partners')
// Помечаем, что корневой экземпляр смонтирован
if (typeof window !== 'undefined' && isRootInstance) {
;(window as any).__SIDEBAR_ROOT_MOUNTED__ = true
}
return (
<div className="relative">
{/* Основной сайдбар */}
@ -255,7 +270,6 @@ export function Sidebar() {
size="icon"
onClick={toggleSidebar}
className="relative h-12 w-12 rounded-full bg-gradient-to-br from-white/20 to-white/5 border border-white/30 hover:from-white/30 hover:to-white/10 transition-all duration-300 ease-out hover:scale-110 active:scale-95 backdrop-blur-xl shadow-lg hover:shadow-xl hover:shadow-purple-500/20 group-hover:border-purple-300/50"
title={isCollapsed ? 'Развернуть сайдбар' : 'Свернуть сайдбар'}
>
{/* Простая анимированная иконка */}
<div className="transition-transform duration-300 ease-out group-hover:scale-110">
@ -270,17 +284,7 @@ export function Sidebar() {
<div className="absolute inset-0 rounded-full bg-gradient-to-r from-purple-500/0 to-blue-500/0 group-hover:from-purple-500/10 group-hover:to-blue-500/10 transition-all duration-500"></div>
</Button>
{/* Подсказка только в свернутом состоянии */}
{isCollapsed && (
<div className="absolute left-full ml-3 top-1/2 -translate-y-1/2 whitespace-nowrap opacity-0 group-hover:opacity-100 transition-all duration-300">
<div className="bg-gradient-to-r from-purple-500/20 to-blue-500/20 backdrop-blur-xl border border-white/20 rounded-lg px-3 py-2">
<div className="text-sm text-white font-medium flex items-center space-x-2">
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
<span> Развернуть</span>
</div>
</div>
</div>
)}
{/* Убраны текстовые подсказки при наведении */}
</div>
</div>