vulnzap-mcp
Version:
Multi-ecosystem vulnerability scanning service with MCP interface for LLMs
134 lines (130 loc) • 5.87 kB
JSX
import React from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useAuth } from '../../contexts/auth-context';
const sidebarNavItems = [
{
title: 'Overview',
href: '/dashboard',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<rect width="7" height="9" x="3" y="3" rx="1" />
<rect width="7" height="5" x="14" y="3" rx="1" />
<rect width="7" height="9" x="14" y="12" rx="1" />
<rect width="7" height="5" x="3" y="16" rx="1" />
</svg>
),
},
{
title: 'Scans',
href: '/dashboard/scans',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<path d="M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5z" />
<line x1="16" x2="2" y1="8" y2="22" />
<line x1="17.5" x2="9" y1="15" y2="15" />
</svg>
),
},
{
title: 'Projects',
href: '/dashboard/projects',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
</svg>
),
},
{
title: 'API Keys',
href: '/dashboard/api-keys',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" />
</svg>
),
},
{
title: 'Billing',
href: '/dashboard/billing',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<rect width="20" height="14" x="2" y="5" rx="2" />
<line x1="2" x2="22" y1="10" y2="10" />
</svg>
),
},
{
title: 'Settings',
href: '/dashboard/settings',
icon: (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="w-5 h-5">
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
<circle cx="12" cy="12" r="3" />
</svg>
),
},
];
export function DashboardLayout({ children }) {
const { user } = useAuth();
const pathname = usePathname();
return (
<div className="grid min-h-screen grid-cols-1 md:grid-cols-[240px_1fr]">
{/* Sidebar */}
<aside className="border-r border-border bg-card">
<div className="flex h-full max-h-screen flex-col gap-2">
<div className="flex h-14 items-center border-b border-border px-4">
<Link href="/" className="flex items-center gap-2 font-semibold">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="h-6 w-6">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" />
</svg>
<span className="text-lg font-bold">
<span className="text-primary">Vuln</span>
<span>Zap</span>
</span>
</Link>
</div>
<div className="flex-1 overflow-auto py-2">
<nav className="grid items-start px-2 text-sm font-medium">
{sidebarNavItems.map((item, index) => (
<Link
key={index}
href={item.href}
className={`flex items-center gap-3 rounded-lg px-3 py-2 transition-all ${
pathname === item.href
? 'bg-primary text-primary-foreground'
: 'hover:bg-accent'
}`}
>
{item.icon}
{item.title}
</Link>
))}
</nav>
</div>
<div className="mt-auto p-4">
<div className="flex items-center gap-2 rounded-lg border border-border p-4">
<div className="grid gap-1">
<p className="text-sm font-medium leading-none">
{user?.user_metadata?.full_name || user?.email || 'User'}
</p>
<p className="text-xs text-muted-foreground">
{user?.email || ''}
</p>
</div>
</div>
</div>
</div>
</aside>
{/* Main content */}
<main className="flex flex-col">
<header className="sticky top-0 z-10 flex h-14 items-center gap-4 border-b border-border bg-background px-4 lg:px-6">
<div className="flex-1">
<h1 className="text-lg font-semibold">Dashboard</h1>
</div>
</header>
<div className="flex-1 p-4 lg:p-8">{children}</div>
</main>
</div>
);
}