Some checks failed
Build Frontend / build (push) Failing after 7s
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
124 lines
4.0 KiB
TypeScript
124 lines
4.0 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import Link from "next/link"
|
|
import { useRouter, usePathname } from "next/navigation"
|
|
import { ShoppingCart, LogOut, Shield } from "lucide-react"
|
|
import { NavItem } from "./nav-item"
|
|
import { Button } from "@/components/common/button"
|
|
import { sidebarConfig } from "@/config/sidebar"
|
|
import { adminSidebarConfig } from "@/config/admin-sidebar"
|
|
import { logoutUser } from "@/lib/utils/auth"
|
|
import { toast } from "sonner"
|
|
import { useUser } from "@/lib/hooks/useUser"
|
|
|
|
const Sidebar: React.FC = () => {
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
|
const router = useRouter()
|
|
const pathname = usePathname()
|
|
const { isAdmin } = useUser()
|
|
|
|
// Optimize mobile menu closing - use useCallback to prevent unnecessary re-renders
|
|
const handleMobileMenuClose = () => {
|
|
setIsMobileMenuOpen(false)
|
|
}
|
|
|
|
// Determine if we're in admin area
|
|
const isAdminArea = pathname?.startsWith('/dashboard/admin')
|
|
|
|
// Filter sidebar config based on admin status
|
|
const getFilteredConfig = () => {
|
|
if (isAdminArea) {
|
|
return adminSidebarConfig
|
|
}
|
|
|
|
// Filter out admin section for non-admin users
|
|
return sidebarConfig.filter(section => {
|
|
if (section.title === "Administration") {
|
|
return isAdmin
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
const currentConfig = getFilteredConfig()
|
|
const homeLink = isAdminArea ? '/dashboard/admin' : '/dashboard'
|
|
const icon = isAdminArea ? Shield : ShoppingCart
|
|
|
|
const handleLogout = async () => {
|
|
try {
|
|
// Show toast notification for better user experience
|
|
toast.success("Logging out...");
|
|
|
|
// Perform the logout
|
|
await logoutUser();
|
|
|
|
// The logoutUser function will handle the redirect
|
|
} catch (error) {
|
|
console.error("Error during logout:", error);
|
|
toast.error("Failed to logout. Please try again.");
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<nav
|
|
className={`
|
|
fixed inset-y-0 left-0 z-[70] w-64 bg-background transform transition-transform duration-150 ease-out
|
|
lg:translate-x-0 lg:static lg:w-56 xl:w-64 border-r border-border
|
|
${isMobileMenuOpen ? "translate-x-0" : "-translate-x-full"}
|
|
`}
|
|
>
|
|
<div className="h-full flex flex-col">
|
|
<Link href={homeLink} className="h-16 px-6 flex items-center border-b border-border">
|
|
<div className="flex items-center gap-3">
|
|
{icon === Shield ? <Shield className="h-6 w-6 text-foreground" /> : <ShoppingCart className="h-6 w-6 text-foreground" />}
|
|
<span className="text-lg font-semibold text-foreground">Ember</span>
|
|
</div>
|
|
</Link>
|
|
|
|
<div className="flex-1 overflow-y-auto py-4 px-4 space-y-6">
|
|
{currentConfig.map((section, index) => (
|
|
<div key={index}>
|
|
<div className="px-3 mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
|
|
{section.title}
|
|
</div>
|
|
<div className="space-y-1">
|
|
{section.items.map((item, idx) => (
|
|
<NavItem key={idx} href={item.href} icon={item.icon} onClick={handleMobileMenuClose}>
|
|
{item.name}
|
|
</NavItem>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<div className="p-4 border-t border-border">
|
|
<Button
|
|
onClick={handleLogout}
|
|
variant="ghost"
|
|
className="w-full justify-start text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-500 hover:bg-background"
|
|
>
|
|
<LogOut className="h-5 w-5 mr-3 flex-shrink-0" />
|
|
Logout
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
{isMobileMenuOpen && (
|
|
<div
|
|
className="fixed inset-0 bg-black bg-opacity-50 z-[65] lg:hidden"
|
|
onClick={handleMobileMenuClose}
|
|
/>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default Sidebar
|
|
|
|
|
|
|