Refactor sidebar with Shadcn

This commit is contained in:
gpt-engineer-app[bot]
2025-10-11 01:50:31 +00:00
parent 5353c62dd7
commit 7f9ba890af
3 changed files with 369 additions and 319 deletions

View File

@@ -1,5 +1,4 @@
import { useState } from "react"; import { Link } from "react-router-dom";
import { Link, useLocation } from "react-router-dom";
import { useAuth } from "@/contexts/AuthContext"; import { useAuth } from "@/contexts/AuthContext";
import { import {
Sidebar, Sidebar,
@@ -10,312 +9,16 @@ import {
SidebarMenu, SidebarMenu,
SidebarMenuItem, SidebarMenuItem,
SidebarMenuButton, SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
useSidebar, useSidebar,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { import { LogOut } from "lucide-react";
Collapsible, import { menuGroups } from "@/config/sidebar";
CollapsibleContent, import { SidebarMenuRenderer } from "@/components/sidebar/SidebarMenuRenderer";
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
Home,
Plus,
Wallet,
List,
MessageSquare,
Star,
BookOpen,
Heart,
FileText,
User,
Users,
Settings,
LogOut,
CreditCard,
BarChart3,
MapPin,
DollarSign,
AlertTriangle,
Car,
Target,
Zap,
Eye,
Megaphone,
ChevronDown,
ChevronRight,
Hotel,
UtensilsCrossed,
Brain,
DoorOpen,
BellRing,
Key,
Receipt,
ChefHat,
Grid3x3,
Package,
Globe,
Compass,
Map,
Shield,
Radio,
Sparkles,
Leaf,
Store,
Navigation,
QrCode,
} from "lucide-react";
export function AppSidebar() { export function AppSidebar() {
const { open, openMobile, isMobile } = useSidebar(); const { open, openMobile, isMobile } = useSidebar();
const collapsed = !open && !isMobile; const collapsed = !open && !isMobile;
const location = useLocation();
const { logout } = useAuth(); const { logout } = useAuth();
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>({});
const toggleExpanded = (itemPath: string) => {
setExpandedItems((prev) => ({
...prev,
[itemPath]: !prev[itemPath],
}));
};
const menuItems = [
{ icon: Home, label: "Dashboard", path: "/dashboard" },
{
icon: Settings,
label: "Admin Panel",
path: "/dashboard/admin",
subItems: [
{ icon: BarChart3, label: "Resumen General", path: "/dashboard/admin?tab=overview" },
{ icon: Users, label: "Usuarios", path: "/dashboard/admin?tab=users" },
{ icon: MapPin, label: "Proveedores", path: "/dashboard/admin?tab=services" },
{ icon: DollarSign, label: "Financiero", path: "/dashboard/admin?tab=financial" },
{
icon: FileText,
label: "Contenido",
path: "/dashboard/admin?tab=content",
subItems: [
{ icon: Globe, label: "Destinos", path: "/dashboard/admin?tab=content-destinations" },
{ icon: MapPin, label: "Lugares", path: "/dashboard/admin?tab=content-places" },
{ icon: BookOpen, label: "Guías", path: "/dashboard/admin?tab=content-guides" },
{ icon: Car, label: "Taxis", path: "/dashboard/admin?tab=content-taxis" },
{ icon: Navigation, label: "Geolocalización", path: "/dashboard/admin?tab=content-geolocation" },
{ icon: Megaphone, label: "Promocional", path: "/dashboard/admin?tab=content-promotional" },
{ icon: Sparkles, label: "AI Guías", path: "/dashboard/admin?tab=content-ai-guides" },
{ icon: Eye, label: "AR Content", path: "/dashboard/admin?tab=content-ar" },
],
},
{
icon: Map,
label: "Geolocalización",
path: "/dashboard/admin?tab=geofences",
subItems: [
{ icon: Target, label: "Geofences", path: "/dashboard/admin?tab=geofences" },
{ icon: BarChart3, label: "Analytics", path: "/dashboard/admin?tab=analytics" },
{ icon: Zap, label: "Testing", path: "/dashboard/admin?tab=testing" },
{ icon: Shield, label: "Emergencia Geo", path: "/dashboard/admin?tab=emergency-geo" },
{ icon: Compass, label: "Navegación", path: "/dashboard/admin?tab=navigation" },
],
},
{ icon: AlertTriangle, label: "Emergencias", path: "/dashboard/admin?tab=emergency" },
{ icon: MessageSquare, label: "Soporte", path: "/dashboard/admin?tab=support" },
{ icon: Settings, label: "Configuración", path: "/dashboard/admin?tab=config" },
],
},
{
icon: Plus,
label: "Channel Manager",
path: "/dashboard/channel-manager",
subItems: [
{ icon: BarChart3, label: "Resumen", path: "/dashboard/channel-manager?tab=overview" },
{ icon: Zap, label: "Canales", path: "/dashboard/channel-manager?tab=channels" },
{ icon: Home, label: "Propiedades", path: "/dashboard/channel-manager?tab=listings" },
{ icon: BookOpen, label: "Reservas", path: "/dashboard/channel-manager?tab=reservations" },
{ icon: BarChart3, label: "Analytics", path: "/dashboard/channel-manager?tab=analytics" },
],
},
{
icon: Hotel,
label: "Hotel Management",
path: "/dashboard/hotel",
subItems: [
{ icon: Home, label: "Habitaciones", path: "/dashboard/hotel/rooms" },
{ icon: DoorOpen, label: "Check-in", path: "/dashboard/hotel/checkin" },
{ icon: BellRing, label: "Room Service", path: "/dashboard/hotel/room-service" },
{ icon: Key, label: "Acceso", path: "/dashboard/hotel/keyless" },
{ icon: Users, label: "Personal", path: "/dashboard/hotel/staff" },
],
},
{
icon: UtensilsCrossed,
label: "Restaurant POS",
path: "/dashboard/restaurant",
subItems: [
{ icon: CreditCard, label: "POS Terminal", path: "/dashboard/restaurant/pos" },
{ icon: Receipt, label: "Pedidos", path: "/dashboard/restaurant/orders" },
{ icon: ChefHat, label: "Cocina", path: "/dashboard/restaurant/kitchen" },
{ icon: Receipt, label: "Cuentas", path: "/dashboard/restaurant/bills" },
{ icon: Grid3x3, label: "Mesas", path: "/dashboard/restaurant/tables" },
{ icon: UtensilsCrossed, label: "Menú", path: "/dashboard/restaurant/menu" },
{ icon: Package, label: "Inventario", path: "/dashboard/restaurant/inventory" },
{ icon: Users, label: "Personal", path: "/dashboard/restaurant/staff" },
],
},
{ icon: Brain, label: "Personalization", path: "/dashboard/personalization" },
{ icon: Shield, label: "Security", path: "/dashboard/security" },
{ icon: Car, label: "Vehicle Management", path: "/dashboard/vehicle-management" },
{ icon: Leaf, label: "Sustainability", path: "/dashboard/sustainability" },
{ icon: Store, label: "Comercios", path: "/dashboard/establishments" },
{ icon: Wallet, label: "Wallet", path: "/dashboard/wallet" },
{ icon: MessageSquare, label: "Message", path: "/dashboard/messages", badge: "2" },
];
const listingItems = [
{ icon: List, label: "My Listing", path: "/dashboard/my-listings" },
{ icon: Star, label: "Reviews", path: "/dashboard/reviews" },
{ icon: BookOpen, label: "Bookings", path: "/dashboard/bookings" },
{ icon: Heart, label: "Bookmark", path: "/dashboard/bookmarks" },
{ icon: FileText, label: "Invoice", path: "/dashboard/invoices" },
];
const accountItems = [
{ icon: User, label: "Edit Profile", path: "/dashboard/profile" },
{ icon: CreditCard, label: "Wallet", path: "/dashboard/wallet" },
{ icon: Settings, label: "Setting", path: "/dashboard/settings" },
];
const isActive = (path: string) => {
if (path.includes("?tab=")) {
const [basePath, tabQuery] = path.split("?tab=");
return (
location.pathname === basePath &&
location.search.includes(tabQuery)
);
}
return location.pathname === path || location.pathname.startsWith(path + "/");
};
const hasActiveChild = (items: any[]) => {
return items.some((item) => {
if (isActive(item.path)) return true;
if (item.subItems) return hasActiveChild(item.subItems);
return false;
});
};
const renderMenuItem = (item: any, level = 0) => {
const Icon = item.icon;
const active = isActive(item.path);
const hasSubItems = item.subItems && item.subItems.length > 0;
const isExpanded = expandedItems[item.path] || hasActiveChild(item.subItems || []);
if (hasSubItems) {
return (
<Collapsible
key={item.path}
open={isExpanded}
onOpenChange={() => toggleExpanded(item.path)}
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton
className={`${
active ? "bg-primary text-primary-foreground" : ""
} ${collapsed && level === 0 ? "justify-center" : ""}`}
>
<Icon className="h-4 w-4" />
{!collapsed && <span>{item.label}</span>}
{!collapsed && (
<ChevronRight
className={`ml-auto h-4 w-4 transition-transform ${
isExpanded ? "rotate-90" : ""
}`}
/>
)}
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.subItems.map((subItem: any) =>
renderSubMenuItem(subItem, level + 1)
)}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
);
}
return (
<SidebarMenuItem key={item.path}>
<SidebarMenuButton asChild isActive={active}>
<Link to={item.path} className={collapsed && level === 0 ? "justify-center" : ""}>
<Icon className="h-4 w-4" />
{!collapsed && <span>{item.label}</span>}
{!collapsed && item.badge && (
<span className="ml-auto bg-green-500 text-white text-xs px-2 py-0.5 rounded-full">
{item.badge}
</span>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
);
};
const renderSubMenuItem = (item: any, level: number) => {
const Icon = item.icon;
const active = isActive(item.path);
const hasSubItems = item.subItems && item.subItems.length > 0;
const isExpanded = expandedItems[item.path] || hasActiveChild(item.subItems || []);
if (hasSubItems) {
return (
<Collapsible
key={item.path}
open={isExpanded}
onOpenChange={() => toggleExpanded(item.path)}
>
<SidebarMenuSubItem>
<CollapsibleTrigger asChild>
<SidebarMenuSubButton
className={active ? "bg-primary/10 text-primary" : ""}
>
<Icon className="h-4 w-4" />
<span>{item.label}</span>
<ChevronRight
className={`ml-auto h-4 w-4 transition-transform ${
isExpanded ? "rotate-90" : ""
}`}
/>
</SidebarMenuSubButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.subItems.map((subItem: any) =>
renderSubMenuItem(subItem, level + 1)
)}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuSubItem>
</Collapsible>
);
}
return (
<SidebarMenuSubItem key={item.path}>
<SidebarMenuSubButton asChild isActive={active}>
<Link to={item.path}>
<Icon className="h-4 w-4" />
<span>{item.label}</span>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
);
};
return ( return (
<Sidebar className={collapsed ? "w-14" : "w-80"} collapsible="icon"> <Sidebar className={collapsed ? "w-14" : "w-80"} collapsible="icon">
@@ -331,28 +34,20 @@ export function AppSidebar() {
</Link> </Link>
</div> </div>
{/* Main Menu */} {/* Menu Groups */}
<SidebarGroup> {menuGroups.map((group) => (
{!collapsed && <SidebarGroupLabel>Main Menu</SidebarGroupLabel>} <SidebarGroup key={group.label}>
<SidebarGroupContent> {!collapsed && <SidebarGroupLabel>{group.label}</SidebarGroupLabel>}
<SidebarMenu>{menuItems.map((item) => renderMenuItem(item))}</SidebarMenu> <SidebarGroupContent>
</SidebarGroupContent> <SidebarMenuRenderer items={group.items} />
</SidebarGroup> </SidebarGroupContent>
</SidebarGroup>
))}
{/* Listing */} {/* Logout */}
<SidebarGroup> <SidebarGroup>
{!collapsed && <SidebarGroupLabel>Listing</SidebarGroupLabel>}
<SidebarGroupContent>
<SidebarMenu>{listingItems.map((item) => renderMenuItem(item))}</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
{/* Account */}
<SidebarGroup>
{!collapsed && <SidebarGroupLabel>Account</SidebarGroupLabel>}
<SidebarGroupContent> <SidebarGroupContent>
<SidebarMenu> <SidebarMenu>
{accountItems.map((item) => renderMenuItem(item))}
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton onClick={logout} className={collapsed ? "justify-center" : ""}> <SidebarMenuButton onClick={logout} className={collapsed ? "justify-center" : ""}>
<LogOut className="h-4 w-4" /> <LogOut className="h-4 w-4" />

View File

@@ -0,0 +1,185 @@
import { Link, useLocation } from "react-router-dom";
import {
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
useSidebar,
} from "@/components/ui/sidebar";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import { ChevronRight } from "lucide-react";
import { MenuItem } from "@/config/sidebar";
import { useState, useEffect } from "react";
interface SidebarMenuRendererProps {
items: MenuItem[];
level?: number;
}
export function SidebarMenuRenderer({ items, level = 0 }: SidebarMenuRendererProps) {
const { open, isMobile } = useSidebar();
const collapsed = !open && !isMobile;
const location = useLocation();
const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>({});
const isActive = (path: string) => {
if (path.includes("?tab=")) {
const [basePath, tabQuery] = path.split("?tab=");
return (
location.pathname === basePath &&
location.search.includes(tabQuery)
);
}
return location.pathname === path || location.pathname.startsWith(path + "/");
};
const hasActiveChild = (items: MenuItem[]): boolean => {
return items.some((item) => {
if (isActive(item.path)) return true;
if (item.subItems) return hasActiveChild(item.subItems);
return false;
});
};
const toggleExpanded = (itemPath: string) => {
setExpandedItems((prev) => ({
...prev,
[itemPath]: !prev[itemPath],
}));
};
// Auto-expand groups with active children
useEffect(() => {
items.forEach((item) => {
if (item.subItems && hasActiveChild(item.subItems)) {
setExpandedItems((prev) => ({
...prev,
[item.path]: true,
}));
}
});
}, [location.pathname, location.search]);
const renderMenuItem = (item: MenuItem) => {
const Icon = item.icon;
const active = isActive(item.path);
const hasSubItems = item.subItems && item.subItems.length > 0;
const isExpanded = expandedItems[item.path] || (hasSubItems && hasActiveChild(item.subItems));
if (hasSubItems) {
return (
<Collapsible
key={item.path}
open={isExpanded}
onOpenChange={() => toggleExpanded(item.path)}
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton
className={`${
active ? "bg-primary text-primary-foreground" : ""
} ${collapsed && level === 0 ? "justify-center" : ""}`}
>
<Icon className="h-4 w-4" />
{!collapsed && <span>{item.label}</span>}
{!collapsed && (
<ChevronRight
className={`ml-auto h-4 w-4 transition-transform ${
isExpanded ? "rotate-90" : ""
}`}
/>
)}
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.subItems!.map((subItem) =>
renderSubMenuItem(subItem)
)}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
);
}
return (
<SidebarMenuItem key={item.path}>
<SidebarMenuButton asChild isActive={active}>
<Link to={item.path} className={collapsed && level === 0 ? "justify-center" : ""}>
<Icon className="h-4 w-4" />
{!collapsed && <span>{item.label}</span>}
{!collapsed && item.badge && (
<span className="ml-auto bg-green-500 text-white text-xs px-2 py-0.5 rounded-full">
{item.badge}
</span>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
);
};
const renderSubMenuItem = (item: MenuItem): JSX.Element => {
const Icon = item.icon;
const active = isActive(item.path);
const hasSubItems = item.subItems && item.subItems.length > 0;
const isExpanded = expandedItems[item.path] || (hasSubItems && hasActiveChild(item.subItems));
if (hasSubItems) {
return (
<Collapsible
key={item.path}
open={isExpanded}
onOpenChange={() => toggleExpanded(item.path)}
>
<SidebarMenuSubItem>
<CollapsibleTrigger asChild>
<SidebarMenuSubButton
className={active ? "bg-primary/10 text-primary" : ""}
>
<Icon className="h-4 w-4" />
<span>{item.label}</span>
<ChevronRight
className={`ml-auto h-4 w-4 transition-transform ${
isExpanded ? "rotate-90" : ""
}`}
/>
</SidebarMenuSubButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.subItems!.map((subItem) =>
renderSubMenuItem(subItem)
)}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuSubItem>
</Collapsible>
);
}
return (
<SidebarMenuSubItem key={item.path}>
<SidebarMenuSubButton asChild isActive={active}>
<Link to={item.path}>
<Icon className="h-4 w-4" />
<span>{item.label}</span>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
);
};
return (
<SidebarMenu>
{items.map((item) => renderMenuItem(item))}
</SidebarMenu>
);
}

170
src/config/sidebar.ts Normal file
View File

@@ -0,0 +1,170 @@
import {
Home,
Plus,
Wallet,
List,
MessageSquare,
Star,
BookOpen,
Heart,
FileText,
User,
Users,
Settings,
LogOut,
CreditCard,
BarChart3,
MapPin,
DollarSign,
AlertTriangle,
Car,
Target,
Zap,
Eye,
Megaphone,
Hotel,
UtensilsCrossed,
Brain,
DoorOpen,
BellRing,
Key,
Receipt,
ChefHat,
Grid3x3,
Package,
Globe,
Compass,
Map,
Shield,
Sparkles,
Leaf,
Store,
Navigation,
} from "lucide-react";
export interface MenuItem {
icon: any;
label: string;
path: string;
badge?: string;
subItems?: MenuItem[];
}
export interface MenuGroup {
label: string;
items: MenuItem[];
}
export const menuGroups: MenuGroup[] = [
{
label: "Main Menu",
items: [
{ icon: Home, label: "Dashboard", path: "/dashboard" },
{
icon: Settings,
label: "Admin Panel",
path: "/dashboard/admin",
subItems: [
{ icon: BarChart3, label: "Resumen General", path: "/dashboard/admin?tab=overview" },
{ icon: Users, label: "Usuarios", path: "/dashboard/admin?tab=users" },
{ icon: MapPin, label: "Proveedores", path: "/dashboard/admin?tab=services" },
{ icon: DollarSign, label: "Financiero", path: "/dashboard/admin?tab=financial" },
{
icon: FileText,
label: "Contenido",
path: "/dashboard/admin?tab=content",
subItems: [
{ icon: Globe, label: "Destinos", path: "/dashboard/admin?tab=content-destinations" },
{ icon: MapPin, label: "Lugares", path: "/dashboard/admin?tab=content-places" },
{ icon: BookOpen, label: "Guías", path: "/dashboard/admin?tab=content-guides" },
{ icon: Car, label: "Taxis", path: "/dashboard/admin?tab=content-taxis" },
{ icon: Navigation, label: "Geolocalización", path: "/dashboard/admin?tab=content-geolocation" },
{ icon: Megaphone, label: "Promocional", path: "/dashboard/admin?tab=content-promotional" },
{ icon: Sparkles, label: "AI Guías", path: "/dashboard/admin?tab=content-ai-guides" },
{ icon: Eye, label: "AR Content", path: "/dashboard/admin?tab=content-ar" },
],
},
{
icon: Map,
label: "Geolocalización",
path: "/dashboard/admin?tab=geofences",
subItems: [
{ icon: Target, label: "Geofences", path: "/dashboard/admin?tab=geofences" },
{ icon: BarChart3, label: "Analytics", path: "/dashboard/admin?tab=analytics" },
{ icon: Zap, label: "Testing", path: "/dashboard/admin?tab=testing" },
{ icon: Shield, label: "Emergencia Geo", path: "/dashboard/admin?tab=emergency-geo" },
{ icon: Compass, label: "Navegación", path: "/dashboard/admin?tab=navigation" },
],
},
{ icon: AlertTriangle, label: "Emergencias", path: "/dashboard/admin?tab=emergency" },
{ icon: MessageSquare, label: "Soporte", path: "/dashboard/admin?tab=support" },
{ icon: Settings, label: "Configuración", path: "/dashboard/admin?tab=config" },
],
},
{
icon: Plus,
label: "Channel Manager",
path: "/dashboard/channel-manager",
subItems: [
{ icon: BarChart3, label: "Resumen", path: "/dashboard/channel-manager?tab=overview" },
{ icon: Zap, label: "Canales", path: "/dashboard/channel-manager?tab=channels" },
{ icon: Home, label: "Propiedades", path: "/dashboard/channel-manager?tab=listings" },
{ icon: BookOpen, label: "Reservas", path: "/dashboard/channel-manager?tab=reservations" },
{ icon: BarChart3, label: "Analytics", path: "/dashboard/channel-manager?tab=analytics" },
],
},
{
icon: Hotel,
label: "Hotel Management",
path: "/dashboard/hotel",
subItems: [
{ icon: Home, label: "Habitaciones", path: "/dashboard/hotel/rooms" },
{ icon: DoorOpen, label: "Check-in", path: "/dashboard/hotel/checkin" },
{ icon: BellRing, label: "Room Service", path: "/dashboard/hotel/room-service" },
{ icon: Key, label: "Acceso", path: "/dashboard/hotel/keyless" },
{ icon: Users, label: "Personal", path: "/dashboard/hotel/staff" },
],
},
{
icon: UtensilsCrossed,
label: "Restaurant POS",
path: "/dashboard/restaurant",
subItems: [
{ icon: CreditCard, label: "POS Terminal", path: "/dashboard/restaurant/pos" },
{ icon: Receipt, label: "Pedidos", path: "/dashboard/restaurant/orders" },
{ icon: ChefHat, label: "Cocina", path: "/dashboard/restaurant/kitchen" },
{ icon: Receipt, label: "Cuentas", path: "/dashboard/restaurant/bills" },
{ icon: Grid3x3, label: "Mesas", path: "/dashboard/restaurant/tables" },
{ icon: UtensilsCrossed, label: "Menú", path: "/dashboard/restaurant/menu" },
{ icon: Package, label: "Inventario", path: "/dashboard/restaurant/inventory" },
{ icon: Users, label: "Personal", path: "/dashboard/restaurant/staff" },
],
},
{ icon: Brain, label: "Personalization", path: "/dashboard/personalization" },
{ icon: Shield, label: "Security", path: "/dashboard/security" },
{ icon: Car, label: "Vehicle Management", path: "/dashboard/vehicle-management" },
{ icon: Leaf, label: "Sustainability", path: "/dashboard/sustainability" },
{ icon: Store, label: "Comercios", path: "/dashboard/establishments" },
{ icon: Wallet, label: "Wallet", path: "/dashboard/wallet" },
{ icon: MessageSquare, label: "Message", path: "/dashboard/messages", badge: "2" },
],
},
{
label: "Listing",
items: [
{ icon: List, label: "My Listing", path: "/dashboard/my-listings" },
{ icon: Star, label: "Reviews", path: "/dashboard/reviews" },
{ icon: BookOpen, label: "Bookings", path: "/dashboard/bookings" },
{ icon: Heart, label: "Bookmark", path: "/dashboard/bookmarks" },
{ icon: FileText, label: "Invoice", path: "/dashboard/invoices" },
],
},
{
label: "Account",
items: [
{ icon: User, label: "Edit Profile", path: "/dashboard/profile" },
{ icon: CreditCard, label: "Wallet", path: "/dashboard/wallet" },
{ icon: Settings, label: "Setting", path: "/dashboard/settings" },
],
},
];