VIBN Frontend for Coolify deployment
This commit is contained in:
150
components/layout/workspace-left-rail.tsx
Normal file
150
components/layout/workspace-left-rail.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname, useRouter } from "next/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
LayoutGrid,
|
||||
Cable,
|
||||
Key,
|
||||
Users,
|
||||
Settings,
|
||||
DollarSign,
|
||||
LogOut,
|
||||
} from "lucide-react";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import { signOut } from "@/lib/firebase/auth";
|
||||
import { toast } from "sonner";
|
||||
|
||||
interface WorkspaceLeftRailProps {
|
||||
activeSection?: string;
|
||||
onSectionChange: (section: string) => void;
|
||||
}
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
id: 'projects',
|
||||
label: 'Projects',
|
||||
icon: LayoutGrid,
|
||||
href: '/projects',
|
||||
},
|
||||
{
|
||||
id: 'connections',
|
||||
label: 'Connect',
|
||||
icon: Cable,
|
||||
href: '/connections',
|
||||
},
|
||||
{
|
||||
id: 'keys',
|
||||
label: 'Keys',
|
||||
icon: Key,
|
||||
href: '/keys',
|
||||
},
|
||||
{
|
||||
id: 'costs',
|
||||
label: 'Costs',
|
||||
icon: DollarSign,
|
||||
href: '/costs',
|
||||
},
|
||||
{
|
||||
id: 'users',
|
||||
label: 'Users',
|
||||
icon: Users,
|
||||
href: '/users',
|
||||
},
|
||||
];
|
||||
|
||||
export function WorkspaceLeftRail({ activeSection = 'projects', onSectionChange }: WorkspaceLeftRailProps) {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
// Extract workspace from pathname (e.g., /marks-account/projects -> marks-account)
|
||||
const workspace = pathname?.split('/')[1] || 'marks-account';
|
||||
|
||||
const handleSignOut = async () => {
|
||||
try {
|
||||
await signOut();
|
||||
toast.success("Signed out successfully");
|
||||
router.push("/auth");
|
||||
} catch (error: any) {
|
||||
toast.error(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex w-16 flex-col items-center border-r bg-card">
|
||||
{/* Vib'n Logo */}
|
||||
<Link
|
||||
href={`/${workspace}/projects`}
|
||||
onClick={() => onSectionChange('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="pt-4 w-full flex flex-col items-center gap-2">
|
||||
{/* Navigation Items */}
|
||||
<div className="flex flex-col gap-3 w-full items-center">
|
||||
{navItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const fullHref = `/${workspace}${item.href}`;
|
||||
const isActive = activeSection === item.id || pathname?.includes(item.href);
|
||||
|
||||
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",
|
||||
isActive
|
||||
? "text-primary bg-primary/5"
|
||||
: "text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||
)}
|
||||
>
|
||||
<Icon className="h-5 w-5" />
|
||||
<span className="text-[10px] font-medium">{item.label}</span>
|
||||
{isActive && (
|
||||
<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}/settings`}
|
||||
className={cn(
|
||||
"flex flex-col items-center gap-1 w-full py-2 px-2 transition-all",
|
||||
"text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||
)}
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
<span className="text-[10px] font-medium">Settings</span>
|
||||
</Link>
|
||||
|
||||
<button
|
||||
onClick={handleSignOut}
|
||||
className={cn(
|
||||
"flex flex-col items-center gap-1 w-full py-2 px-2 transition-all",
|
||||
"text-muted-foreground hover:text-foreground hover:bg-accent"
|
||||
)}
|
||||
>
|
||||
<LogOut className="h-5 w-5" />
|
||||
<span className="text-[10px] font-medium">Sign Out</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user