import Link from "next/link"; import Image from "next/image"; import { useRouter } from "next/router"; import { signOut } from "next-auth/react"; import { useEffect, useRef, useState } from "react"; import { RiLayoutGridLine, RiFlowChart, RiFileList3Line, RiLogoutBoxLine, RiUserSettingsLine, RiArrowUpCircleLine, RiBuildingLine, RiContactsLine, RiInboxLine, RiMailCheckLine, RiCheckboxCircleLine, RiQuestionLine, RiCompassLine, RiPlayCircleLine, } from "react-icons/ri"; import { pathToTourPage, replayPageTour } from "@/lib/tour"; const LEARNING_PLAYLIST_URL = "https://www.youtube.com/playlist?list=PLBf6xNJOmsIQ"; const mainNav = [ { href: "/", label: "Dashboard", icon: RiLayoutGridLine, color: "#5aa2ff", tour: "nav-dashboard" }, { href: "/lists", label: "Lists", icon: RiFileList3Line, color: "#32d583", tour: "nav-lists" }, { href: "/contacts", label: "Contacts", icon: RiContactsLine, color: "#34d399", tour: "nav-contacts" }, { href: "/companies", label: "Companies", icon: RiBuildingLine, color: "#a78bfa", tour: "nav-companies" }, { href: "/workflows", label: "Campaigns", icon: RiFlowChart, color: "#f4b740", tour: "nav-workflows" }, { href: "/inbox", label: "Inbox", icon: RiInboxLine, color: "#38bdf8", tour: "nav-inbox" }, { href: "/email-health", label: "Email Health", icon: RiMailCheckLine, color: "#f4b740", tour: "nav-email-health" }, ]; // Nav items that only exist in the commercial build (ee/). Filtered out when premium absent. const premiumNav = [ { href: "/todos", label: "Todos", icon: RiCheckboxCircleLine, color: "#fb923c", tour: "nav-todos" }, ]; export const SIDEBAR_WIDTH_EXPANDED = 52; export const SIDEBAR_WIDTH_COLLAPSED = 52; export default function Sidebar({ onCollapse }: { onCollapse?: (collapsed: boolean) => void }) { const router = useRouter(); const [updateAvailable, setUpdateAvailable] = useState(false); const [latestVersion, setLatestVersion] = useState(null); const [currentVersion, setCurrentVersion] = useState(null); const [hovered, setHovered] = useState(false); const [helpOpen, setHelpOpen] = useState(false); const helpRef = useRef(null); const tourPage = pathToTourPage(router.pathname); // Open-core: hide premium-only nav (Todos) in the public build. const [hasPremium, setHasPremium] = useState(true); const nav = hasPremium ? [...mainNav, ...premiumNav] : mainNav; useEffect(() => { if (!helpOpen) return; function onClick(e: MouseEvent) { if (helpRef.current && !helpRef.current.contains(e.target as Node)) setHelpOpen(false); } document.addEventListener("mousedown", onClick); return () => document.removeEventListener("mousedown", onClick); }, [helpOpen]); useEffect(() => { onCollapse?.(false); }, [onCollapse]); useEffect(() => { fetch("/api/premium-status").then((r) => r.ok ? r.json() : null) .then((d) => { if (d) setHasPremium(!!d.hasPremium); }).catch(() => {}); }, []); useEffect(() => { fetch("/api/system/update") .then((r) => r.json()) .then((d) => { setCurrentVersion(d.current ?? null); if (d.updateAvailable) { setUpdateAvailable(true); setLatestVersion(d.latest); } }) .catch(() => {}); }, []); function isActive(href: string) { if (href === "/") return router.pathname === "/"; if (href === "/settings") { return ["/settings", "/accounts"].some((p) => router.pathname.startsWith(p)); } return router.pathname.startsWith(href); } return ( ); }