VIBN Frontend for Coolify deployment
This commit is contained in:
164
components/layout/left-rail.tsx
Normal file
164
components/layout/left-rail.tsx
Normal file
@@ -0,0 +1,164 @@
|
||||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
LayoutGrid,
|
||||
Inbox,
|
||||
Users,
|
||||
Receipt,
|
||||
Globe,
|
||||
FileText,
|
||||
MessageCircle,
|
||||
Settings,
|
||||
HelpCircle,
|
||||
User,
|
||||
DollarSign,
|
||||
Key,
|
||||
Palette,
|
||||
Target,
|
||||
Megaphone,
|
||||
ClipboardList,
|
||||
Code2,
|
||||
Sparkles,
|
||||
Cog,
|
||||
GitBranch,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import Link from "next/link";
|
||||
import { toast } from "sonner";
|
||||
|
||||
type NavSection = "home" | "ai-chat" | "docs" | "plan" | "design" | "tech" | "journey" | "settings";
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ id: "plan" as NavSection, icon: ClipboardList, label: "Plan", href: "/project/{projectId}/plan" },
|
||||
{ id: "docs" as NavSection, icon: FileText, label: "Docs", href: "/project/{projectId}/docs" },
|
||||
{ id: "design" as NavSection, icon: Palette, label: "Design", href: "/project/{projectId}/design" },
|
||||
{ id: "tech" as NavSection, icon: Cog, label: "Tech", href: "/project/{projectId}/tech" },
|
||||
{ id: "journey" as NavSection, icon: GitBranch, label: "Journey", href: "/project/{projectId}/journey" },
|
||||
];
|
||||
|
||||
interface LeftRailProps {
|
||||
activeSection: string;
|
||||
onSectionChange: (section: string) => void;
|
||||
projectName?: string;
|
||||
projectId?: string;
|
||||
workspace?: string;
|
||||
}
|
||||
|
||||
export function LeftRail({ activeSection, onSectionChange, projectName, projectId, workspace = 'marks-account' }: LeftRailProps) {
|
||||
return (
|
||||
<div className="flex w-16 flex-col items-center border-r bg-card">
|
||||
{/* Vib'n Logo */}
|
||||
<Link href={`/${workspace}/projects`} className="flex h-14 w-16 items-center justify-center border-b">
|
||||
<img
|
||||
src="/vibn-black-circle-logo.png"
|
||||
alt="Vib'n"
|
||||
className="h-10 w-10 cursor-pointer hover:opacity-80 transition-opacity"
|
||||
/>
|
||||
</Link>
|
||||
|
||||
<div className="w-full flex flex-col items-center">
|
||||
{/* Main Navigation Items */}
|
||||
<div className="flex flex-col gap-2 w-full items-center">
|
||||
{/* AI Chat - Always visible */}
|
||||
{projectName && projectId && (
|
||||
<Link
|
||||
href={`/${workspace}/project/${projectId}/v_ai_chat`}
|
||||
className={cn(
|
||||
"flex flex-col items-center gap-1 w-full py-2 px-2 transition-all relative",
|
||||
activeSection === "ai-chat"
|
||||
? "text-primary bg-primary/5"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||
)}
|
||||
title="AI Chat"
|
||||
>
|
||||
<Sparkles className="h-5 w-5" />
|
||||
<span className="text-[10px] font-medium">AI Chat</span>
|
||||
{activeSection === "ai-chat" && (
|
||||
<div className="absolute left-0 top-1/2 -translate-y-1/2 h-10 w-1 bg-primary" />
|
||||
)}
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{/* Other Nav Items */}
|
||||
{NAV_ITEMS.map((item) => {
|
||||
if (!projectId) return null;
|
||||
const fullHref = `/${workspace}${item.href.replace('{projectId}', projectId)}`;
|
||||
return (
|
||||
<Link
|
||||
key={item.id}
|
||||
href={fullHref}
|
||||
onClick={() => onSectionChange(item.id)}
|
||||
className={cn(
|
||||
"flex flex-col items-center gap-1 w-full py-2 px-2 transition-all relative",
|
||||
activeSection === item.id
|
||||
? "text-primary bg-primary/5"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||
)}
|
||||
title={item.label}
|
||||
>
|
||||
<item.icon className="h-5 w-5" />
|
||||
<span className="text-[10px] font-medium">{item.label}</span>
|
||||
{activeSection === item.id && (
|
||||
<div className="absolute left-0 top-1/2 -translate-y-1/2 h-10 w-1 bg-primary" />
|
||||
)}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{/* Bottom Items */}
|
||||
<div className="mt-auto flex flex-col gap-1 w-full items-center pb-4">
|
||||
<Separator className="w-8 mb-1" />
|
||||
|
||||
<Link href={`/${workspace}/keys`}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-10 w-10"
|
||||
title="API Keys"
|
||||
>
|
||||
<Key className="h-5 w-5" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Link href={`/${workspace}/connections`}>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-10 w-10"
|
||||
title="Settings & Connections"
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-10 w-10"
|
||||
title="Help - Coming Soon"
|
||||
onClick={() => toast.info("Help Center - Coming Soon")}
|
||||
>
|
||||
<HelpCircle className="h-5 w-5" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-10 w-10 rounded-full"
|
||||
title="Profile - Coming Soon"
|
||||
onClick={() => toast.info("Profile Settings - Coming Soon")}
|
||||
>
|
||||
<div className="h-8 w-8 rounded-full bg-primary/10 flex items-center justify-center">
|
||||
<User className="h-4 w-4" />
|
||||
</div>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user