641 lines
29 KiB
TypeScript
641 lines
29 KiB
TypeScript
import { useState } from 'react'
|
|
import { NavLink, useNavigate, useLocation } from 'react-router-dom'
|
|
import { useTranslation } from 'react-i18next'
|
|
import {
|
|
LayoutDashboard,
|
|
Package,
|
|
PackageOpen,
|
|
Ruler,
|
|
Settings,
|
|
LogOut,
|
|
ChevronRight,
|
|
ShoppingCart,
|
|
ShoppingBag,
|
|
BookOpen,
|
|
TrendingUp,
|
|
Tags,
|
|
Ticket,
|
|
BarChart3,
|
|
Layers,
|
|
Globe2,
|
|
Users,
|
|
Image as ImageIcon,
|
|
MessageSquare,
|
|
Store,
|
|
CreditCard,
|
|
Palette,
|
|
FileText,
|
|
Wrench,
|
|
ChevronDown,
|
|
Sparkles,
|
|
Calculator,
|
|
Info,
|
|
ChevronLeft,
|
|
DatabaseBackup,
|
|
FileJson,
|
|
FolderArchive,
|
|
Map,
|
|
} from 'lucide-react'
|
|
|
|
interface SidebarProps {
|
|
isCollapsed: boolean
|
|
onToggle: () => void
|
|
}
|
|
|
|
export default function Sidebar({ isCollapsed, onToggle }: SidebarProps) {
|
|
const { t } = useTranslation()
|
|
const navigate = useNavigate()
|
|
const location = useLocation()
|
|
|
|
const isInProduct = ['/categories', '/products', '/product-attributes', '/raw-materials'].some(p => location.pathname.startsWith(p))
|
|
const isInSales = ['/orders', '/promotions', '/coupons', '/global-analytics'].some(p => location.pathname.startsWith(p))
|
|
const isInBusinessAnalytics = location.pathname.startsWith('/business-analytics')
|
|
const isInTools = location.pathname.startsWith('/tools')
|
|
const isInTiktokLegacy = location.pathname === '/tiktok' || location.pathname.startsWith('/tiktok-analysis')
|
|
const isInTiktok = location.pathname.startsWith('/tiktok') && !isInTiktokLegacy
|
|
const isInShopee = location.pathname.startsWith('/shopee')
|
|
const isInLazada = location.pathname.startsWith('/lazada')
|
|
const isInCms = ['/page-builder', '/cms-mockup', '/media', '/articles'].some(p => location.pathname.startsWith(p))
|
|
const isInCustomer = ['/customers', '/subscribers', '/contacts'].some(p => location.pathname.startsWith(p))
|
|
const isInMenuManager = location.pathname.startsWith('/menu-manager')
|
|
const isInBackup = location.pathname.startsWith('/backup')
|
|
const isInSettings = location.pathname.startsWith('/settings')
|
|
|
|
const [productOpen, setProductOpen] = useState(isInProduct)
|
|
const [salesOpen, setSalesOpen] = useState(isInSales)
|
|
const [businessAnalyticsOpen, setBusinessAnalyticsOpen] = useState(isInBusinessAnalytics)
|
|
const [toolsOpen, setToolsOpen] = useState(isInTools)
|
|
const [tiktokOpen, setTiktokOpen] = useState(isInTiktok)
|
|
const [tiktokLegacyOpen, setTiktokLegacyOpen] = useState(isInTiktokLegacy)
|
|
const [shopeeOpen, setShopeeOpen] = useState(isInShopee)
|
|
const [lazadaOpen, setLazadaOpen] = useState(isInLazada)
|
|
const [cmsOpen, setCmsOpen] = useState(isInCms)
|
|
const [customerOpen, setCustomerOpen] = useState(isInCustomer)
|
|
const [menuManagerOpen, setMenuManagerOpen] = useState(isInMenuManager)
|
|
const [backupOpen, setBackupOpen] = useState(isInBackup)
|
|
const [settingsOpen, setSettingsOpen] = useState(isInSettings)
|
|
|
|
const MAIN_MENU = [
|
|
{ icon: LayoutDashboard, label: t('nav.dashboard', 'Dashboard'), to: '/' },
|
|
]
|
|
|
|
const PRODUCT_MENU = [
|
|
{ icon: Tags, label: t('nav.categories', 'Categories'), to: '/categories' },
|
|
{ icon: Package, label: t('nav.products', 'Products'), to: '/products' },
|
|
{ icon: Ruler, label: t('nav.productAttributes', 'Product Attributes'), to: '/product-attributes' },
|
|
{ icon: PackageOpen, label: t('nav.rawMaterials', 'Raw Materials'), to: '/raw-materials' },
|
|
]
|
|
|
|
const SALES_MENU = [
|
|
{ icon: ShoppingCart, label: t('nav.orders', 'Orders'), to: '/orders' },
|
|
{ icon: Ticket, label: t('nav.promotions', 'Promotions'), to: '/promotions' },
|
|
{ icon: Ticket, label: t('nav.coupons', 'Coupons'), to: '/coupons' },
|
|
{ icon: Globe2, label: t('nav.globalAnalytics', 'All Analytics'), to: '/global-analytics' },
|
|
]
|
|
|
|
const BUSINESS_ANALYTICS_MENU = [
|
|
{ icon: Globe2, label: t('nav.omnichannelSalesMap', 'Omnichannel Sales Map'), to: '/business-analytics/sales-map' },
|
|
{ icon: Package, label: t('nav.productSalesMap', 'Product Sales Map'), to: '/business-analytics/sales-map-products' },
|
|
{ icon: Map, label: t('nav.malaysiaSalesMap', 'Malaysia Map'), to: '/business-analytics/malaysia-map' },
|
|
{ icon: Map, label: t('nav.vietnamSalesMap', 'Vietnam Map'), to: '/business-analytics/vietnam-map' },
|
|
]
|
|
|
|
const TOOL_MENU = [
|
|
{ icon: Package, label: t('nav.marketplaceProducts', 'Marketplace Products'), to: '/tools/marketplace-products' },
|
|
]
|
|
|
|
const TIKTOK_MENU = [
|
|
{ icon: ShoppingCart, label: t('nav.tiktokOrders', 'TikTok Orders'), to: '/tiktok-order' },
|
|
{ icon: Map, label: t('nav.thailandSalesMap', 'Thailand Sales Map'), to: '/tiktok-sales-map' },
|
|
{ icon: BarChart3, label: t('nav.tiktokAnalytics', 'TikTok Analytics'), to: '/tiktok-analytics' },
|
|
{ icon: Layers, label: t('nav.tiktokOverview', 'TikTok All Shops'), to: '/tiktok-overview' },
|
|
{ icon: Calculator, label: t('nav.tiktokPriceSimulator', 'TikTok Price Simulator'), to: '/tiktok-price-simulator' },
|
|
{ icon: Info, label: t('nav.tiktokShopCase', 'TikTok Shop Case'), to: '/tiktok-shop-case' },
|
|
]
|
|
|
|
const TIKTOK_LEGACY_MENU = [
|
|
{ icon: TrendingUp, label: t('nav.tiktokReportImport', 'TikTok Report Import'), to: '/tiktok' },
|
|
{ icon: TrendingUp, label: t('nav.productSkuAnalysis', 'Product SKU Analysis'), to: '/tiktok-analysis' },
|
|
]
|
|
|
|
const SHOPEE_MENU = [
|
|
{ icon: ShoppingBag, label: t('nav.shopeeHomAroma', 'Shopee (Hom Aroma)'), to: '/shopee' },
|
|
{ icon: Map, label: t('nav.shopeeSalesMap', 'Thailand Sales Map'), to: '/shopee-sales-map' },
|
|
{ icon: BarChart3, label: t('nav.shopeeAnalytics', 'Shopee Analytics'), to: '/shopee-analytics' },
|
|
{ icon: Layers, label: t('nav.shopeeOverview', 'Shopee All Shops'), to: '/shopee-overview' },
|
|
{ icon: Info, label: t('nav.shopeeShopCase', 'Shopee Shop Case'), to: '/shopee-shop-case' },
|
|
]
|
|
|
|
const LAZADA_MENU = [
|
|
{ icon: ShoppingCart, label: t('nav.lazadaOrders', 'Lazada Orders'), to: '/lazada-order' },
|
|
{ icon: BarChart3, label: t('nav.lazadaAnalytics', 'Lazada Analytics'), to: '/lazada-analytics' },
|
|
{ icon: Layers, label: t('nav.lazadaOverview', 'Lazada All Shops'), to: '/lazada-overview' },
|
|
]
|
|
|
|
const CMS_MENU = [
|
|
{ icon: Layers, label: t('nav.pageBuilder', 'Page Builder (CMS)'), to: '/page-builder' },
|
|
{ icon: Sparkles, label: t('nav.cmsBlockShowcase', 'CMS Block Showcase'), to: '/cms-mockup' },
|
|
{ icon: ImageIcon, label: t('nav.mediaLibrary', 'Media Library'), to: '/media' },
|
|
{ icon: BookOpen, label: t('nav.scentGuide', 'Scent Guide'), to: '/articles' },
|
|
]
|
|
|
|
const CUSTOMER_MENU = [
|
|
{ icon: Users, label: t('nav.customerList', 'Customers'), to: '/customers' },
|
|
{ icon: Users, label: t('nav.newsletterSubscribers', 'Subscribers'), to: '/subscribers' },
|
|
{ icon: MessageSquare, label: t('nav.contactMessages', 'Contact Messages'), to: '/contacts' },
|
|
]
|
|
|
|
const MENU_MANAGER_MENU = [
|
|
{ icon: Layers, label: t('nav.mainNavigation', 'Main Navigation'), to: '/menu-manager/main-navigation' },
|
|
{ icon: FileText, label: t('nav.footerExplore', 'Footer Explore'), to: '/menu-manager/footer-explore' },
|
|
{ icon: MessageSquare, label: t('nav.footerSupport', 'Footer Support'), to: '/menu-manager/footer-support' },
|
|
{ icon: Store, label: t('nav.footerBrand', 'Footer Brand'), to: '/menu-manager/footer-brand' },
|
|
]
|
|
|
|
const BACKUP_MENU = [
|
|
{ icon: DatabaseBackup, label: t('nav.backupDatabase', 'Database Backup'), to: '/backup/database' },
|
|
{ icon: Package, label: t('nav.backupCatalog', 'Catalog Backup'), to: '/backup/catalog' },
|
|
{ icon: ShoppingCart, label: t('nav.backupOrders', 'Orders Backup'), to: '/backup/orders' },
|
|
{ icon: FileJson, label: t('nav.backupCms', 'CMS Pages Backup'), to: '/backup/cms' },
|
|
{ icon: FolderArchive, label: t('nav.backupMedia', 'Media Backup'), to: '/backup/media' },
|
|
]
|
|
|
|
const SETTINGS_MENU = [
|
|
{ icon: Store, label: t('nav.storeSettings', 'Store Settings'), to: '/settings' },
|
|
{ icon: CreditCard, label: t('nav.paymentSettings', 'Payment & Shipping'), to: '/settings/payments' },
|
|
{ icon: Palette, label: t('nav.themeSettings', 'Theme & Design'), to: '/settings/theme' },
|
|
{ icon: FileText, label: t('nav.contentSettings', 'Content'), to: '/settings/content' },
|
|
{ icon: Wrench, label: t('nav.systemMaintenance', 'System'), to: '/settings/system' },
|
|
]
|
|
|
|
const handleLogout = () => {
|
|
localStorage.removeItem('homaroma_admin_token')
|
|
localStorage.removeItem('homaroma_admin_user')
|
|
navigate('/login')
|
|
}
|
|
|
|
const handleGroupClick = (setOpen: React.Dispatch<React.SetStateAction<boolean>>) => {
|
|
if (isCollapsed) {
|
|
onToggle()
|
|
setOpen(true)
|
|
} else {
|
|
setOpen(v => !v)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<aside className={`h-screen fixed left-0 top-0 bg-night-900 border-r border-white/5 flex flex-col z-50 transition-all duration-300 ${isCollapsed ? 'w-20' : 'w-72'}`}>
|
|
{/* Brand & Toggle Header */}
|
|
<div className={`p-6 flex items-center ${isCollapsed ? 'justify-center' : 'justify-between'} border-b border-white/5`}>
|
|
{!isCollapsed && (
|
|
<div className="text-xl font-bold tracking-widest text-white uppercase italic truncate">
|
|
HomAroma <span className="text-cyan-glow text-xs not-italic font-light opacity-60">Admin</span>
|
|
</div>
|
|
)}
|
|
<button
|
|
onClick={onToggle}
|
|
title={isCollapsed ? 'Expand' : 'Collapse'}
|
|
className="p-1.5 rounded-lg bg-white/5 border border-white/10 text-slate-400 hover:text-white transition-colors cursor-pointer"
|
|
>
|
|
{isCollapsed ? <ChevronRight className="w-4 h-4" /> : <ChevronLeft className="w-4 h-4" />}
|
|
</button>
|
|
</div>
|
|
|
|
{/* Navigation — scrollable */}
|
|
<nav className="flex-1 min-h-0 overflow-y-auto px-4 py-2 space-y-1 sidebar-nav">
|
|
{MAIN_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
end={item.to === '/'}
|
|
title={isCollapsed ? item.label : undefined}
|
|
className={({ isActive }) =>
|
|
`sidebar-link ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'} ${isCollapsed ? 'justify-center px-0' : ''}`
|
|
}
|
|
>
|
|
<item.icon className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1">{item.label}</span>}
|
|
{!isCollapsed && <ChevronRight className="w-4 h-4 opacity-0 group-hover:opacity-40 transition-opacity" />}
|
|
</NavLink>
|
|
))}
|
|
|
|
{/* Catalog Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setProductOpen)}
|
|
title={isCollapsed ? t('nav.catalog', 'Catalog & Products') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInProduct ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Package className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.catalog', 'Catalog & Products')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${productOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && productOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{PRODUCT_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Sales & Marketing Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setSalesOpen)}
|
|
title={isCollapsed ? t('nav.sales', 'Sales & Marketing') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInSales ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<ShoppingCart className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.sales', 'Sales & Marketing')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${salesOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && salesOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{SALES_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Business Analytics Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setBusinessAnalyticsOpen)}
|
|
title={isCollapsed ? t('nav.businessAnalytics', 'Business Analytics') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInBusinessAnalytics ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<BarChart3 className="w-5 h-5 shrink-0 text-orange-400" />
|
|
{!isCollapsed && <span className="flex-1 text-left font-bold text-orange-300">{t('nav.businessAnalytics', 'Business Analytics')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${businessAnalyticsOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && businessAnalyticsOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{BUSINESS_ANALYTICS_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-orange-400" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Tools Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setToolsOpen)}
|
|
title={isCollapsed ? t('nav.tools', 'Tools') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInTools ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Wrench className="w-5 h-5 shrink-0 text-emerald-400" />
|
|
{!isCollapsed && <span className="flex-1 text-left font-bold text-emerald-300">{t('nav.tools', 'Tools')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${toolsOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && toolsOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{TOOL_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-emerald-400" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* TikTok Channel Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setTiktokOpen)}
|
|
title={isCollapsed ? t('nav.tiktok', 'TikTok Channel') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInTiktok ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<ShoppingCart className="w-5 h-5 shrink-0 text-pink-400" />
|
|
{!isCollapsed && <span className="flex-1 text-left font-bold text-pink-300">{t('nav.tiktok', 'TikTok Channel')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${tiktokOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && tiktokOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{TIKTOK_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-pink-400" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* TikTok Report / Analysis (Legacy) */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setTiktokLegacyOpen)}
|
|
title={isCollapsed ? 'TikTok Legacy' : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInTiktokLegacy ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<TrendingUp className="w-5 h-5 shrink-0 text-pink-300/80" />
|
|
{!isCollapsed && <span className="flex-1 text-left text-pink-200/80">TikTok Report/Analysis</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${tiktokLegacyOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && tiktokLegacyOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{TIKTOK_LEGACY_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-pink-300/80" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Shopee Channel Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setShopeeOpen)}
|
|
title={isCollapsed ? t('nav.shopee', 'Shopee Channel') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInShopee ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<ShoppingBag className="w-5 h-5 shrink-0 text-amber-400" />
|
|
{!isCollapsed && <span className="flex-1 text-left font-bold text-amber-300">{t('nav.shopee', 'Shopee Channel')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${shopeeOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && shopeeOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{SHOPEE_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-amber-400" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Lazada Channel Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setLazadaOpen)}
|
|
title={isCollapsed ? t('nav.lazada', 'Lazada Channel') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInLazada ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<ShoppingCart className="w-5 h-5 shrink-0 text-blue-400" />
|
|
{!isCollapsed && <span className="flex-1 text-left font-bold text-blue-300">{t('nav.lazada', 'Lazada Channel')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${lazadaOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && lazadaOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{LAZADA_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0 text-blue-400" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* CMS Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setCmsOpen)}
|
|
title={isCollapsed ? t('nav.cms', 'Content & CMS') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInCms ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Layers className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.cms', 'Content & CMS')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${cmsOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && cmsOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{CMS_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Customers Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setCustomerOpen)}
|
|
title={isCollapsed ? t('nav.customers', 'Customers') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInCustomer ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Users className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.customers', 'Customers')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${customerOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && customerOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{CUSTOMER_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Menu Manager Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setMenuManagerOpen)}
|
|
title={isCollapsed ? t('nav.menuManager', 'Menu Manager') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInMenuManager ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Layers className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.menuManager', 'Menu Manager')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${menuManagerOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && menuManagerOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{MENU_MANAGER_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Backup & Restore Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setBackupOpen)}
|
|
title={isCollapsed ? t('nav.backup', 'Backup & Restore') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInBackup ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<DatabaseBackup className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.backup', 'Backup & Restore')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${backupOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && backupOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{BACKUP_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Settings Group */}
|
|
<div className="pt-1">
|
|
<button
|
|
onClick={() => handleGroupClick(setSettingsOpen)}
|
|
title={isCollapsed ? t('nav.settings', 'Settings') : undefined}
|
|
className={`sidebar-link sidebar-link-inactive w-full ${isInSettings ? 'text-white' : ''} ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<Settings className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span className="flex-1 text-left">{t('nav.settings', 'Settings')}</span>}
|
|
{!isCollapsed && <ChevronDown className={`w-4 h-4 transition-transform duration-200 ${settingsOpen ? 'rotate-180' : ''}`} />}
|
|
</button>
|
|
|
|
{!isCollapsed && settingsOpen && (
|
|
<div className="mt-1 ml-4 pl-4 border-l border-white/10 space-y-1">
|
|
{SETTINGS_MENU.map((item) => (
|
|
<NavLink
|
|
key={item.to}
|
|
to={item.to}
|
|
end={item.to === '/settings'}
|
|
className={({ isActive }) =>
|
|
`sidebar-link text-sm ${isActive ? 'sidebar-link-active' : 'sidebar-link-inactive'}`
|
|
}
|
|
>
|
|
<item.icon className="w-4 h-4 shrink-0" />
|
|
<span className="flex-1">{item.label}</span>
|
|
</NavLink>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</nav>
|
|
|
|
{/* User / Bottom */}
|
|
<div className={`p-4 border-t border-white/5 space-y-2 ${isCollapsed ? 'items-center justify-center' : ''}`}>
|
|
|
|
<div className={`flex items-center gap-3 px-4 py-3 rounded-xl hover:bg-white/5 transition-all group ${isCollapsed ? 'justify-center px-0' : ''}`} title={isCollapsed ? t('common.adminAccount', 'Admin Account') : undefined}>
|
|
<div className="w-9 h-9 rounded-full bg-cyan-glow/20 flex items-center justify-center text-cyan-glow font-bold text-xs border border-cyan-glow/30 shrink-0">
|
|
A
|
|
</div>
|
|
{!isCollapsed && (
|
|
<div className="flex-1 overflow-hidden">
|
|
<p className="text-sm font-bold text-white truncate">{t('common.adminAccount', 'Admin Account')}</p>
|
|
<p className="text-[10px] uppercase tracking-wider text-slate-500">{t('common.systemManager', 'System Manager')}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<button
|
|
onClick={handleLogout}
|
|
title={isCollapsed ? t('common.logout', 'Logout') : undefined}
|
|
className={`w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-medium text-rose-500 hover:bg-rose-500/10 transition-all cursor-pointer ${isCollapsed ? 'justify-center px-0' : ''}`}
|
|
>
|
|
<LogOut className="w-5 h-5 shrink-0" />
|
|
{!isCollapsed && <span>{t('common.logout', 'Logout')}</span>}
|
|
</button>
|
|
</div>
|
|
</aside>
|
|
)
|
|
}
|