"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useEffect } from "react";
import { cn } from "@/lib/utils";
import { useAuth } from "@/hooks/use-auth";
import { useTotalUnread } from "@/hooks/use-total-unread";
import { isFlowsEnabled } from "@/lib/flows/feature-flag";
import {
LayoutDashboard,
MessageSquare,
Users,
GitBranch,
Radio,
Zap,
Workflow,
Settings,
LogOut,
User,
X,
} from "lucide-react";
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/components/ui/avatar";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
interface NavItem {
href: string;
label: string;
icon: typeof LayoutDashboard;
/**
* If set, only included in the rendered nav when the predicate
* returns true. Used to gate beta-only entries (e.g. /flows) on
* `profiles.beta_features`.
*/
betaKey?: string;
}
const navItems: NavItem[] = [
{ href: "/dashboard", label: "Dashboard", icon: LayoutDashboard },
{ href: "/inbox", label: "Inbox", icon: MessageSquare },
{ href: "/contacts", label: "Contacts", icon: Users },
{ href: "/pipelines", label: "Pipelines", icon: GitBranch },
{ href: "/broadcasts", label: "Broadcasts", icon: Radio },
{ href: "/automations", label: "Automations", icon: Zap },
// Flows is gated on the per-account beta flag; the entry is invisible
// for accounts that haven't opted in. Server-side route guards make
// this a UX choice, not a security one — the API + pages 404 anyway.
{ href: "/flows", label: "Flows", icon: Workflow, betaKey: "flows" },
];
const bottomNavItems = [
{ href: "/settings", label: "Settings", icon: Settings },
];
interface SidebarProps {
/** Controlled on mobile by the Header's hamburger button. Ignored on lg+. */
open?: boolean;
onClose?: () => void;
}
export function Sidebar({ open = false, onClose }: SidebarProps) {
const pathname = usePathname();
const { profile, signOut } = useAuth();
const totalUnread = useTotalUnread();
// Close the drawer when route changes — users opened it to navigate,
// so once they pick a destination the drawer should get out of the way.
useEffect(() => {
onClose?.();
// Only pathname drives this — onClose identity doesn't need to re-run it.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pathname]);
// Lock body scroll and allow Escape to close while the drawer is open on
// mobile. No-ops on desktop because the sidebar isn't positioned there.
useEffect(() => {
if (!open) return;
const prev = document.body.style.overflow;
document.body.style.overflow = "hidden";
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onClose?.();
};
window.addEventListener("keydown", onKey);
return () => {
document.body.style.overflow = prev;
window.removeEventListener("keydown", onKey);
};
}, [open, onClose]);
return (
<>
{/* Backdrop — only exists on mobile and only when open. Clicking
it closes the drawer. Hidden from lg+ since the sidebar is
part of the main flex row there. */}
>
);
}