93 lines
3.8 KiB
TypeScript
93 lines
3.8 KiB
TypeScript
import { LayoutDashboard, Activity, CalendarRange, ListFilter, Settings2, UserCircle } from "lucide-react";
|
|
import { Link, useLocation } from "wouter";
|
|
import {
|
|
Sidebar,
|
|
SidebarContent,
|
|
SidebarFooter,
|
|
SidebarGroup,
|
|
SidebarGroupContent,
|
|
SidebarGroupLabel,
|
|
SidebarHeader,
|
|
SidebarMenu,
|
|
SidebarMenuButton,
|
|
SidebarMenuItem,
|
|
} from "@/components/ui/sidebar";
|
|
import { Logo } from "@/components/logo";
|
|
|
|
const NAV = [
|
|
{ title: "Dashboard", url: "/", icon: LayoutDashboard, testid: "nav-dashboard" },
|
|
{ title: "Gamma Levels", url: "/gamma", icon: Activity, testid: "nav-gamma" },
|
|
{ title: "Expiry Matrix", url: "/expiry", icon: CalendarRange, testid: "nav-expiry" },
|
|
{ title: "Screener", url: "/screener", icon: ListFilter, testid: "nav-screener" },
|
|
{ title: "Settings & API", url: "/settings", icon: Settings2, testid: "nav-settings" },
|
|
{ title: "Account", url: "/account", icon: UserCircle, testid: "nav-account" },
|
|
];
|
|
|
|
export function AppSidebar() {
|
|
const [location] = useLocation();
|
|
return (
|
|
<Sidebar data-testid="sidebar-main" className="border-r-0">
|
|
<SidebarHeader className="px-4 pt-5 pb-4">
|
|
<Link
|
|
href="/"
|
|
className="flex items-center gap-3 px-1"
|
|
data-testid="link-home"
|
|
>
|
|
<span className="inline-flex h-10 w-10 items-center justify-center rounded-xl bg-primary/10 border border-primary/20 text-primary neon-glow-sm">
|
|
<Logo className="h-6 w-6" />
|
|
</span>
|
|
<span className="flex flex-col leading-tight">
|
|
<span className="text-base font-bold tracking-tight text-foreground">GammaDesk</span>
|
|
<span className="text-[10px] text-muted-foreground tracking-[0.15em] uppercase font-medium">
|
|
Options Analytics
|
|
</span>
|
|
</span>
|
|
</Link>
|
|
</SidebarHeader>
|
|
<SidebarContent className="px-2">
|
|
<SidebarGroup>
|
|
<SidebarGroupLabel className="px-3 text-[10px] tracking-[0.15em] uppercase font-semibold text-muted-foreground">Workspace</SidebarGroupLabel>
|
|
<SidebarGroupContent>
|
|
<SidebarMenu className="gap-1">
|
|
{NAV.map((item) => {
|
|
const active =
|
|
item.url === "/"
|
|
? location === "/" || location === ""
|
|
: location.startsWith(item.url);
|
|
return (
|
|
<SidebarMenuItem key={item.title}>
|
|
<SidebarMenuButton
|
|
asChild
|
|
isActive={active}
|
|
data-testid={item.testid}
|
|
className={`h-10 rounded-lg transition-all ${
|
|
active
|
|
? "bg-primary/10 text-primary border-l-2 border-primary"
|
|
: "text-muted-foreground hover:text-foreground hover:bg-secondary"
|
|
}`}
|
|
>
|
|
<Link href={item.url} className="flex items-center gap-3 px-3 py-2">
|
|
<item.icon className={`h-4 w-4 ${active ? "text-primary" : "text-muted-foreground"}`} />
|
|
<span className={`text-sm font-medium ${active ? "font-semibold" : ""}`}>{item.title}</span>
|
|
</Link>
|
|
</SidebarMenuButton>
|
|
</SidebarMenuItem>
|
|
);
|
|
})}
|
|
</SidebarMenu>
|
|
</SidebarGroupContent>
|
|
</SidebarGroup>
|
|
</SidebarContent>
|
|
<SidebarFooter className="px-4 pb-5 pt-3 border-t border-border/50">
|
|
<p
|
|
className="text-[10px] leading-relaxed text-muted-foreground"
|
|
data-testid="text-sidebar-disclaimer"
|
|
>
|
|
Analytics & education only. Not financial advice. Data is simulated
|
|
ORATS-style mock data until an API key is provided.
|
|
</p>
|
|
</SidebarFooter>
|
|
</Sidebar>
|
|
);
|
|
}
|