traceability
This commit is contained in:
160
src/components/layout/AppSidebar.tsx
Normal file
160
src/components/layout/AppSidebar.tsx
Normal file
@@ -0,0 +1,160 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
FileText,
|
||||
Search,
|
||||
GitBranch,
|
||||
CheckSquare,
|
||||
AlertTriangle,
|
||||
Target,
|
||||
Layers,
|
||||
Bug,
|
||||
TestTube,
|
||||
Calendar,
|
||||
Milestone,
|
||||
FolderKanban,
|
||||
BookOpen,
|
||||
LayoutDashboard,
|
||||
ChevronDown,
|
||||
ChevronRight,
|
||||
} from "lucide-react";
|
||||
import { NavLink } from "@/components/NavLink";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarGroup,
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
useSidebar,
|
||||
} from "@/components/ui/sidebar";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const mainItems = [
|
||||
{ title: "Dashboard", url: "/", icon: LayoutDashboard },
|
||||
{ title: "Traceability Matrix", url: "/matrix", icon: GitBranch },
|
||||
{ title: "Documentation", url: "/documentation", icon: BookOpen },
|
||||
{ title: "Gap Analysis", url: "/analysis", icon: Search },
|
||||
];
|
||||
|
||||
const almItems = [
|
||||
{ title: "Features", url: "/alm/feature", icon: Target, type: "feature" },
|
||||
{ title: "Requirements", url: "/alm/requirements", icon: CheckSquare, type: "requirements" },
|
||||
{ title: "SW Requirements", url: "/alm/swreq", icon: FileText, type: "swreq" },
|
||||
{ title: "Test Cases", url: "/alm/test-case", icon: TestTube, type: "test case" },
|
||||
{ title: "Epics", url: "/alm/epic", icon: Layers, type: "epic" },
|
||||
{ title: "User Stories", url: "/alm/user-story", icon: FolderKanban, type: "user story" },
|
||||
{ title: "Tasks", url: "/alm/task", icon: CheckSquare, type: "task" },
|
||||
{ title: "Bugs", url: "/alm/bug", icon: Bug, type: "bug" },
|
||||
{ title: "Risks", url: "/alm/risk", icon: AlertTriangle, type: "risk" },
|
||||
{ title: "Milestones", url: "/alm/milestone", icon: Milestone, type: "milestone" },
|
||||
{ title: "Phases", url: "/alm/phase", icon: Calendar, type: "phase" },
|
||||
];
|
||||
|
||||
export function AppSidebar() {
|
||||
const { state } = useSidebar();
|
||||
const collapsed = state === "collapsed";
|
||||
const location = useLocation();
|
||||
const currentPath = location.pathname;
|
||||
|
||||
const [almExpanded, setAlmExpanded] = useState(
|
||||
almItems.some((item) => currentPath.startsWith(item.url))
|
||||
);
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon" className="border-r border-sidebar-border bg-sidebar-background">
|
||||
<SidebarContent className="pt-4">
|
||||
{/* Logo/Header */}
|
||||
<div className="px-4 pb-4 border-b border-sidebar-border mb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<img
|
||||
src="/images/nabd-logo.png"
|
||||
alt="NABD Solutions"
|
||||
className={cn(
|
||||
"transition-all duration-200",
|
||||
collapsed ? "h-8 w-8 object-contain" : "h-10"
|
||||
)}
|
||||
/>
|
||||
{!collapsed && (
|
||||
<div className="flex flex-col">
|
||||
<span className="font-bold text-base text-sidebar-foreground">Traceability</span>
|
||||
<span className="text-xs text-sidebar-foreground/60">ASF Sensor Hub</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Navigation */}
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel className="text-sidebar-foreground/60">Navigation</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{mainItems.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<NavLink
|
||||
to={item.url}
|
||||
end={item.url === "/"}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-2 py-1.5 rounded-md transition-colors",
|
||||
"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
||||
"text-sidebar-foreground"
|
||||
)}
|
||||
activeClassName="bg-sidebar-accent text-sidebar-primary font-medium"
|
||||
>
|
||||
<item.icon className="h-4 w-4 shrink-0" />
|
||||
{!collapsed && <span>{item.title}</span>}
|
||||
</NavLink>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
|
||||
{/* ALM Items */}
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel
|
||||
className="cursor-pointer flex items-center justify-between text-sidebar-foreground/60 hover:text-sidebar-foreground"
|
||||
onClick={() => setAlmExpanded(!almExpanded)}
|
||||
>
|
||||
<span>ALM Traceability</span>
|
||||
{!collapsed && (
|
||||
almExpanded ? (
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
) : (
|
||||
<ChevronRight className="h-4 w-4" />
|
||||
)
|
||||
)}
|
||||
</SidebarGroupLabel>
|
||||
{(almExpanded || collapsed) && (
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{almItems.map((item) => (
|
||||
<SidebarMenuItem key={item.title}>
|
||||
<SidebarMenuButton asChild>
|
||||
<NavLink
|
||||
to={item.url}
|
||||
className={cn(
|
||||
"flex items-center gap-2 px-2 py-1.5 rounded-md transition-colors",
|
||||
"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
||||
"text-sidebar-foreground"
|
||||
)}
|
||||
activeClassName="bg-sidebar-accent text-sidebar-primary font-medium"
|
||||
>
|
||||
<item.icon className="h-4 w-4 shrink-0" />
|
||||
{!collapsed && <span>{item.title}</span>}
|
||||
</NavLink>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
))}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
)}
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user