337 lines
14 KiB
TypeScript
337 lines
14 KiB
TypeScript
"use client"
|
||
|
||
import { useAuth } from '@/hooks/useAuth'
|
||
import { useSidebar } from '@/hooks/useSidebar'
|
||
import { Button } from '@/components/ui/button'
|
||
import { Card } from '@/components/ui/card'
|
||
import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'
|
||
import { useRouter, usePathname } from 'next/navigation'
|
||
import {
|
||
Settings,
|
||
LogOut,
|
||
Store,
|
||
MessageCircle,
|
||
Wrench,
|
||
Warehouse,
|
||
Users,
|
||
Truck,
|
||
Handshake,
|
||
ChevronLeft,
|
||
ChevronRight
|
||
} from 'lucide-react'
|
||
|
||
export function Sidebar() {
|
||
const { user, logout } = useAuth()
|
||
const router = useRouter()
|
||
const pathname = usePathname()
|
||
const { isCollapsed, toggleSidebar } = useSidebar()
|
||
|
||
const getInitials = () => {
|
||
const orgName = getOrganizationName()
|
||
return orgName.charAt(0).toUpperCase()
|
||
}
|
||
|
||
const getOrganizationName = () => {
|
||
if (user?.organization?.name) {
|
||
return user.organization.name
|
||
}
|
||
if (user?.organization?.fullName) {
|
||
return user.organization.fullName
|
||
}
|
||
return 'Организация'
|
||
}
|
||
|
||
const getCabinetType = () => {
|
||
if (!user?.organization?.type) return 'Кабинет'
|
||
|
||
switch (user.organization.type) {
|
||
case 'FULFILLMENT':
|
||
return 'Фулфилмент'
|
||
case 'SELLER':
|
||
return 'Селлер'
|
||
case 'LOGIST':
|
||
return 'Логистика'
|
||
case 'WHOLESALE':
|
||
return 'Оптовик'
|
||
default:
|
||
return 'Кабинет'
|
||
}
|
||
}
|
||
|
||
const handleSettingsClick = () => {
|
||
router.push('/settings')
|
||
}
|
||
|
||
const handleMarketClick = () => {
|
||
router.push('/market')
|
||
}
|
||
|
||
const handleMessengerClick = () => {
|
||
router.push('/messenger')
|
||
}
|
||
|
||
const handleServicesClick = () => {
|
||
router.push('/services')
|
||
}
|
||
|
||
const handleWarehouseClick = () => {
|
||
router.push('/warehouse')
|
||
}
|
||
|
||
const handleEmployeesClick = () => {
|
||
router.push('/employees')
|
||
}
|
||
|
||
const handleSuppliesClick = () => {
|
||
// Для фулфилмент кабинетов используем новый роут
|
||
if (user?.organization?.type === 'FULFILLMENT') {
|
||
router.push('/fulfillment-supplies')
|
||
} else {
|
||
router.push('/supplies')
|
||
}
|
||
}
|
||
|
||
const handlePartnersClick = () => {
|
||
router.push('/partners')
|
||
}
|
||
|
||
|
||
|
||
const isSettingsActive = pathname === '/settings'
|
||
const isMarketActive = pathname.startsWith('/market')
|
||
const isMessengerActive = pathname.startsWith('/messenger')
|
||
const isServicesActive = pathname.startsWith('/services')
|
||
const isWarehouseActive = pathname.startsWith('/warehouse')
|
||
const isEmployeesActive = pathname.startsWith('/employees')
|
||
const isSuppliesActive = pathname.startsWith('/supplies') || pathname.startsWith('/fulfillment-supplies')
|
||
const isPartnersActive = pathname.startsWith('/partners')
|
||
|
||
return (
|
||
<div className={`fixed left-4 top-4 bottom-4 ${isCollapsed ? 'w-14' : 'w-72'} bg-white/10 backdrop-blur-xl border border-white/20 rounded-2xl ${isCollapsed ? 'p-2' : 'p-3'} transition-all duration-300 ease-in-out z-50`}>
|
||
<div className="flex flex-col h-full">
|
||
{/* Кнопка сворачивания */}
|
||
<div className={`flex ${isCollapsed ? 'justify-center' : 'justify-end'} ${isCollapsed ? 'mb-2' : 'mb-3'}`}>
|
||
<Button
|
||
variant="ghost"
|
||
size="icon"
|
||
onClick={toggleSidebar}
|
||
className={`${isCollapsed ? 'h-7 w-7' : 'h-8 w-8'} text-white/60 hover:text-white hover:bg-white/10 transition-all duration-200`}
|
||
>
|
||
{isCollapsed ? (
|
||
<ChevronRight className="h-4 w-4" />
|
||
) : (
|
||
<ChevronLeft className="h-4 w-4" />
|
||
)}
|
||
</Button>
|
||
</div>
|
||
|
||
{/* Информация о пользователе */}
|
||
<Card className="bg-gradient-to-br from-white/15 to-white/5 backdrop-blur border border-white/30 p-4 mb-4 shadow-lg">
|
||
{!isCollapsed ? (
|
||
// Развернутое состояние
|
||
<div className="flex items-center space-x-3">
|
||
<div className="relative flex-shrink-0">
|
||
<Avatar className="h-12 w-12 ring-2 ring-white/20">
|
||
{user?.avatar ? (
|
||
<AvatarImage
|
||
src={user.avatar}
|
||
alt="Аватар пользователя"
|
||
className="w-full h-full object-cover"
|
||
/>
|
||
) : null}
|
||
<AvatarFallback className="bg-gradient-to-br from-purple-500 to-purple-600 text-white text-sm font-semibold">
|
||
{getInitials()}
|
||
</AvatarFallback>
|
||
</Avatar>
|
||
<div className="absolute -bottom-0.5 -right-0.5 w-3 h-3 bg-green-400 rounded-full border-2 border-white/20"></div>
|
||
</div>
|
||
<div className="flex-1 min-w-0">
|
||
<p className="text-white text-sm font-semibold mb-1 break-words" title={getOrganizationName()}>
|
||
{getOrganizationName()}
|
||
</p>
|
||
<div className="flex items-center space-x-1">
|
||
<div className="w-2 h-2 bg-purple-400 rounded-full flex-shrink-0"></div>
|
||
<p className="text-white/70 text-xs font-medium">
|
||
{getCabinetType()}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
// Свернутое состояние
|
||
<div className="flex flex-col items-center">
|
||
<div className="relative mb-2">
|
||
<Avatar className="h-10 w-10 ring-2 ring-white/20">
|
||
{user?.avatar ? (
|
||
<AvatarImage
|
||
src={user.avatar}
|
||
alt="Аватар пользователя"
|
||
className="w-full h-full object-cover"
|
||
/>
|
||
) : null}
|
||
<AvatarFallback className="bg-gradient-to-br from-purple-500 to-purple-600 text-white text-xs font-semibold">
|
||
{getInitials()}
|
||
</AvatarFallback>
|
||
</Avatar>
|
||
<div className="absolute -bottom-0.5 -right-0.5 w-2.5 h-2.5 bg-green-400 rounded-full border border-white/20"></div>
|
||
</div>
|
||
<div className="text-center">
|
||
<p className="text-white text-[10px] font-semibold leading-tight max-w-full break-words"
|
||
title={getOrganizationName()}
|
||
style={{ fontSize: '9px', lineHeight: '11px' }}>
|
||
{getOrganizationName().length > 12
|
||
? getOrganizationName().substring(0, 12) + '...'
|
||
: getOrganizationName()
|
||
}
|
||
</p>
|
||
<div className="flex items-center justify-center mt-1">
|
||
<div className="w-1.5 h-1.5 bg-purple-400 rounded-full"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</Card>
|
||
|
||
{/* Навигация */}
|
||
<div className="space-y-1 mb-3 flex-1">
|
||
<Button
|
||
variant={isMarketActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isMarketActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleMarketClick}
|
||
title={isCollapsed ? "Маркет" : ""}
|
||
>
|
||
<Store className={`${isCollapsed ? 'h-4 w-4' : 'h-4 w-4'} flex-shrink-0`} />
|
||
{!isCollapsed && <span className="ml-3">Маркет</span>}
|
||
</Button>
|
||
|
||
<Button
|
||
variant={isMessengerActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isMessengerActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleMessengerClick}
|
||
title={isCollapsed ? "Мессенджер" : ""}
|
||
>
|
||
<MessageCircle className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Мессенджер</span>}
|
||
</Button>
|
||
|
||
<Button
|
||
variant={isPartnersActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isPartnersActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handlePartnersClick}
|
||
title={isCollapsed ? "Партнёры" : ""}
|
||
>
|
||
<Handshake className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Партнёры</span>}
|
||
</Button>
|
||
|
||
{/* Услуги - только для фулфилмент центров */}
|
||
{user?.organization?.type === 'FULFILLMENT' && (
|
||
<Button
|
||
variant={isServicesActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isServicesActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleServicesClick}
|
||
title={isCollapsed ? "Услуги" : ""}
|
||
>
|
||
<Wrench className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Услуги</span>}
|
||
</Button>
|
||
)}
|
||
|
||
{/* Сотрудники - только для фулфилмент центров */}
|
||
{user?.organization?.type === 'FULFILLMENT' && (
|
||
<Button
|
||
variant={isEmployeesActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isEmployeesActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleEmployeesClick}
|
||
title={isCollapsed ? "Сотрудники" : ""}
|
||
>
|
||
<Users className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Сотрудники</span>}
|
||
</Button>
|
||
)}
|
||
|
||
{/* Поставки - для селлеров и фулфилмент */}
|
||
{(user?.organization?.type === 'SELLER' || user?.organization?.type === 'FULFILLMENT') && (
|
||
<Button
|
||
variant={isSuppliesActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isSuppliesActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleSuppliesClick}
|
||
title={isCollapsed ? "Поставки" : ""}
|
||
>
|
||
<Truck className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Поставки</span>}
|
||
</Button>
|
||
)}
|
||
|
||
{/* Склад - только для оптовиков */}
|
||
{user?.organization?.type === 'WHOLESALE' && (
|
||
<Button
|
||
variant={isWarehouseActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isWarehouseActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleWarehouseClick}
|
||
title={isCollapsed ? "Склад" : ""}
|
||
>
|
||
<Warehouse className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Склад</span>}
|
||
</Button>
|
||
)}
|
||
|
||
<Button
|
||
variant={isSettingsActive ? "secondary" : "ghost"}
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-left transition-all duration-200 text-xs ${
|
||
isSettingsActive
|
||
? 'bg-white/20 text-white hover:bg-white/30'
|
||
: 'text-white/80 hover:bg-white/10 hover:text-white'
|
||
} cursor-pointer`}
|
||
onClick={handleSettingsClick}
|
||
title={isCollapsed ? "Настройки профиля" : ""}
|
||
>
|
||
<Settings className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Настройки профиля</span>}
|
||
</Button>
|
||
</div>
|
||
|
||
{/* Кнопка выхода */}
|
||
<div>
|
||
<Button
|
||
variant="ghost"
|
||
className={`w-full ${isCollapsed ? 'justify-center px-2 h-9' : 'justify-start h-10'} text-white/80 hover:bg-red-500/20 hover:text-red-300 cursor-pointer text-xs transition-all duration-200`}
|
||
onClick={logout}
|
||
title={isCollapsed ? "Выйти" : ""}
|
||
>
|
||
<LogOut className="h-4 w-4 flex-shrink-0" />
|
||
{!isCollapsed && <span className="ml-3">Выйти</span>}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|