Add initial project files
This commit is contained in:
+161
@@ -0,0 +1,161 @@
|
||||
import { Badge, ChevronDown, FileText, Settings, SquareCode, UserCircle } from 'lucide-react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { AccordionMenu, AccordionMenuClassNames, AccordionMenuGroup, AccordionMenuItem, AccordionMenuLabel } from '#shared/ui/AccordionMenu';
|
||||
import { Button } from '#shared/ui/Button';
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '#shared/ui/DropdownMenu';
|
||||
|
||||
interface DropdownItem {
|
||||
title: string;
|
||||
path: string;
|
||||
icon: React.ComponentType<{ className?: string }>;
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
interface MenuItem {
|
||||
title: string;
|
||||
path?: string;
|
||||
active?: boolean;
|
||||
}
|
||||
|
||||
interface MenuLabel {
|
||||
label: string;
|
||||
}
|
||||
|
||||
type MenuNode = MenuItem | MenuLabel;
|
||||
|
||||
export function SidebarMenuDashboard() {
|
||||
const { pathname } = useLocation();
|
||||
|
||||
const dropdownItems: DropdownItem[] = [
|
||||
{
|
||||
title: 'Client API',
|
||||
path: '/account/home/user-profile',
|
||||
icon: SquareCode,
|
||||
active: true
|
||||
},
|
||||
{
|
||||
title: 'Profile',
|
||||
path: '/public-profile/profiles/company',
|
||||
icon: UserCircle
|
||||
},
|
||||
{
|
||||
title: 'My Account',
|
||||
path: '/account/integrations',
|
||||
icon: Settings
|
||||
},
|
||||
{
|
||||
title: 'Projects',
|
||||
path: '/public-profile/projects/3-columns',
|
||||
icon: FileText
|
||||
},
|
||||
{
|
||||
title: 'Personal info',
|
||||
path: '/public-profile/profiles/creator',
|
||||
icon: Badge
|
||||
}
|
||||
];
|
||||
|
||||
const currentDropdownItem = dropdownItems[0];
|
||||
|
||||
const menuItems = useMemo<MenuNode[]>(
|
||||
() => [
|
||||
{ label: 'Configuration' },
|
||||
{ title: 'API Setup', path: '/account/api-keys' },
|
||||
{ title: 'Team Settings', path: '/account/home/settings-sidebar' },
|
||||
{ title: 'Authentication', path: '/authentication/classic/sign-in' },
|
||||
{ title: 'Endpoints Configs', path: '/account/appearance' },
|
||||
{ title: 'Rate Limiting', path: '/public-profile/network' },
|
||||
{ label: 'Security' },
|
||||
{ title: 'Data Encryption', path: '/account/billing/enterprise' },
|
||||
{ title: 'Text', path: '/account/security/overview' },
|
||||
{ title: 'Access Control', path: '/account/security/privacy-settings' },
|
||||
{ label: 'Analytics' },
|
||||
{
|
||||
title: 'Incident Response',
|
||||
path: '/account/security/current-sessions'
|
||||
},
|
||||
{ title: 'Fetching Data', path: '/account/members/team-info' },
|
||||
{ title: 'Custom Reports', path: '/account/home/user-profile' },
|
||||
{
|
||||
title: 'Real Time Analytics',
|
||||
path: '/account/home/settings-enterprise'
|
||||
},
|
||||
{ title: 'Exporting Data', path: '/account/members/import-members' },
|
||||
{ title: 'Dashboard Integration', path: '/account/members/team-info' }
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
const classNames: AccordionMenuClassNames = {
|
||||
root: 'space-y-1',
|
||||
label: 'uppercase text-xs font-medium text-muted-foreground/80 pt-6 mb-2 pb-0',
|
||||
item: 'h-8 hover:bg-background border-accent text-accent-foreground hover:text-primary data-[selected=true]:text-primary data-[selected=true]:bg-background data-[selected=true]:font-medium'
|
||||
};
|
||||
|
||||
const matchPath = useCallback(
|
||||
(path: string): boolean => path === pathname || (path.length > 1 && pathname.startsWith(path)),
|
||||
[pathname]
|
||||
);
|
||||
|
||||
const buildDropdown = () => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="outline" mode="input" className="w-full justify-between">
|
||||
<span className="flex items-center gap-2">
|
||||
<currentDropdownItem.icon />
|
||||
{currentDropdownItem.title}
|
||||
</span>
|
||||
<ChevronDown className="size-3.5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-(--radix-dropdown-menu-trigger-width)">
|
||||
{dropdownItems.map((item, index) => (
|
||||
<DropdownMenuItem key={index} asChild>
|
||||
<Link to={item.path}>
|
||||
<item.icon />
|
||||
<span>{item.title}</span>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
|
||||
const buildMenu = () => {
|
||||
return (
|
||||
<AccordionMenu
|
||||
selectedValue={'/account/home/settings-sidebar'}
|
||||
matchPath={matchPath}
|
||||
type="single"
|
||||
collapsible
|
||||
classNames={classNames}
|
||||
>
|
||||
<AccordionMenuGroup>
|
||||
{menuItems.map((item, index) =>
|
||||
'label' in item ? (
|
||||
<AccordionMenuLabel key={index}>{item.label}</AccordionMenuLabel>
|
||||
) : (
|
||||
<AccordionMenuItem
|
||||
key={index}
|
||||
value={item.path || `item-${index}`}
|
||||
className="text-sm"
|
||||
>
|
||||
<Link to={item.path || '#'}>{item.title}</Link>
|
||||
</AccordionMenuItem>
|
||||
)
|
||||
)}
|
||||
</AccordionMenuGroup>
|
||||
</AccordionMenu>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full space-y-1">
|
||||
{buildDropdown()}
|
||||
{buildMenu()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user