"use client"; import { useState, useEffect } from "react"; import PropTypes from "prop-types"; import Link from "next/link"; import { usePathname } from "next/navigation"; import { cn } from "@/shared/utils/cn"; import { APP_CONFIG } from "@/shared/constants/config"; import OmniRouteLogo from "./OmniRouteLogo"; import Button from "./Button"; import { ConfirmModal } from "./Modal"; import CloudSyncStatus from "./CloudSyncStatus"; const navItems = [ { href: "/dashboard", label: "Home", icon: "home", exact: true }, { href: "/dashboard/endpoint", label: "Endpoint", icon: "api" }, { href: "/dashboard/providers", label: "Providers", icon: "dns" }, { href: "/dashboard/combos", label: "Combos", icon: "layers" }, { href: "/dashboard/logs", label: "Logs", icon: "description" }, { href: "/dashboard/costs", label: "Costs", icon: "account_balance_wallet" }, { href: "/dashboard/analytics", label: "Analytics", icon: "analytics" }, { href: "/dashboard/limits", label: "Limits & Quotas", icon: "tune" }, { href: "/dashboard/health", label: "Health", icon: "health_and_safety" }, { href: "/dashboard/cli-tools", label: "CLI Tools", icon: "terminal" }, ]; // Debug items (only show when ENABLE_REQUEST_LOGS=true) const debugItems = [{ href: "/dashboard/translator", label: "Translator", icon: "translate" }]; const systemItems = [{ href: "/dashboard/settings", label: "Settings", icon: "settings" }]; const helpItems = [ { href: "/docs", label: "Docs", icon: "menu_book" }, { href: "https://github.com/diegosouzapw/OmniRoute/issues", label: "Issues", icon: "bug_report", external: true, }, ]; export default function Sidebar({ onClose, collapsed = false, onToggleCollapse, }: { onClose?: any; collapsed?: boolean; onToggleCollapse?: any; }) { const pathname = usePathname(); const [showShutdownModal, setShowShutdownModal] = useState(false); const [showRestartModal, setShowRestartModal] = useState(false); const [isShuttingDown, setIsShuttingDown] = useState(false); const [isRestarting, setIsRestarting] = useState(false); const [isDisconnected, setIsDisconnected] = useState(false); const [showDebug, setShowDebug] = useState(false); // Check if debug mode is enabled useEffect(() => { fetch("/api/settings") .then((res) => res.json()) .then((data) => setShowDebug(data?.enableRequestLogs === true)) .catch(() => {}); }, []); const isActive = (href, exact) => { if (exact) { return pathname === href; } return pathname.startsWith(href); }; const handleShutdown = async () => { setIsShuttingDown(true); try { await fetch("/api/shutdown", { method: "POST" }); } catch (e) { // Expected to fail as server shuts down; ignore error } setIsShuttingDown(false); setShowShutdownModal(false); setIsDisconnected(true); }; const handleRestart = async () => { setIsRestarting(true); try { await fetch("/api/restart", { method: "POST" }); } catch (e) { // Expected to fail as server restarts } setIsRestarting(false); setShowRestartModal(false); // Show reconnecting state, then try to reload after a delay setIsDisconnected(true); setTimeout(() => { globalThis.location.reload(); }, 3000); }; const renderNavLink = (item) => { const active = !item.external && isActive(item.href, item.exact); const className = cn( "flex items-center gap-3 rounded-lg transition-all group", collapsed ? "justify-center px-2 py-2.5" : "px-4 py-2", active ? "bg-primary/10 text-primary" : "text-text-muted hover:bg-surface/50 hover:text-text-main" ); const iconClassName = cn( "material-symbols-outlined text-[18px]", active ? "fill-1" : "group-hover:text-primary transition-colors" ); const content = ( <> {item.icon} {!collapsed && {item.label}} > ); if (item.external) { return ( {content} ); } return ( {content} ); }; return ( <> {/* Shutdown Confirmation Modal */} setShowShutdownModal(false)} onConfirm={handleShutdown} title="Close Proxy" message="Are you sure you want to close the proxy server?" confirmText="Close" cancelText="Cancel" variant="danger" loading={isShuttingDown} /> {/* Restart Confirmation Modal */} setShowRestartModal(false)} onConfirm={handleRestart} title="Restart Proxy" message="Are you sure you want to restart the proxy server? It will be back online in a few seconds." confirmText="Restart" cancelText="Cancel" variant="warning" loading={isRestarting} /> {/* Disconnected Overlay */} {isDisconnected && ( power_off Server Disconnected The proxy server has been stopped or is restarting. globalThis.location.reload()}> Reload Page )} > ); } Sidebar.propTypes = { onClose: PropTypes.func, collapsed: PropTypes.bool, onToggleCollapse: PropTypes.func, };
The proxy server has been stopped or is restarting.