"use client" import { useState, useEffect, useMemo, useCallback } from "react" import { Badge } from "./ui/badge" import { Button } from "./ui/button" import { Tabs, TabsContent, TabsList, TabsTrigger } from "./ui/tabs" import { SystemOverview } from "./system-overview" import { StorageOverview } from "./storage-overview" import { NetworkMetrics } from "./network-metrics" import { VirtualMachines } from "./virtual-machines" import Hardware from "./hardware" import { SystemLogs } from "./system-logs" import { OnboardingCarousel } from "./onboarding-carousel" import { AuthSetup } from "./auth-setup" import { Login } from "./login" import { Settings } from "./settings" import { getApiUrl, getApiBaseUrl } from "../lib/api-config" import { RefreshCw, AlertTriangle, CheckCircle, XCircle, Server, Menu, LayoutDashboard, HardDrive, NetworkIcon, Box, Cpu, FileText, SettingsIcon, } from "lucide-react" import Image from "next/image" import { ThemeToggle } from "./theme-toggle" import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet" interface SystemStatus { status: "healthy" | "warning" | "critical" uptime: string lastUpdate: string serverName: string nodeId: string } interface FlaskSystemData { hostname: string node_id: string uptime: string cpu_usage: number memory_usage: number temperature: number load_average: number[] } console.log("[v0] ========================================") console.log("[v0] ProxmoxDashboard component file loaded!") console.log("[v0] Timestamp:", new Date().toISOString()) console.log("[v0] ========================================") export function ProxmoxDashboard() { console.log("[v0] ========================================") console.log("[v0] ProxmoxDashboard component MOUNTING") console.log("[v0] Window location:", typeof window !== "undefined" ? window.location.href : "SSR") console.log("[v0] API Base URL:", typeof window !== "undefined" ? getApiBaseUrl() : "SSR") console.log("[v0] ========================================") const [systemStatus, setSystemStatus] = useState({ status: "healthy", uptime: "Loading...", lastUpdate: new Date().toLocaleTimeString(), serverName: "Loading...", nodeId: "Loading...", }) const [isRefreshing, setIsRefreshing] = useState(false) const [isServerConnected, setIsServerConnected] = useState(true) const [componentKey, setComponentKey] = useState(0) const [mobileMenuOpen, setMobileMenuOpen] = useState(false) const [activeTab, setActiveTab] = useState("overview") const [showNavigation, setShowNavigation] = useState(true) const [lastScrollY, setLastScrollY] = useState(0) const [authChecked, setAuthChecked] = useState(false) const [authRequired, setAuthRequired] = useState(false) const [isAuthenticated, setIsAuthenticated] = useState(false) const [authDeclined, setAuthDeclined] = useState(false) const fetchSystemData = useCallback(async () => { console.log("[v0] Fetching system data from Flask server...") console.log("[v0] Current window location:", window.location.href) const apiUrl = getApiUrl("/api/system") console.log("[v0] API URL:", apiUrl) try { const response = await fetch(apiUrl, { method: "GET", headers: { "Content-Type": "application/json", }, cache: "no-store", }) console.log("[v0] Response status:", response.status) if (!response.ok) { throw new Error(`Server responded with status: ${response.status}`) } const data: FlaskSystemData = await response.json() console.log("[v0] System data received:", data) let status: "healthy" | "warning" | "critical" = "healthy" if (data.cpu_usage > 90 || data.memory_usage > 90) { status = "critical" } else if (data.cpu_usage > 75 || data.memory_usage > 75) { status = "warning" } setSystemStatus({ status, uptime: data.uptime, lastUpdate: new Date().toLocaleTimeString(), serverName: data.hostname, nodeId: data.node_id, }) setIsServerConnected(true) } catch (error) { console.error("[v0] Failed to fetch system data from Flask server:", error) console.error("[v0] Error details:", { message: error instanceof Error ? error.message : "Unknown error", apiUrl, windowLocation: window.location.href, }) setIsServerConnected(false) setSystemStatus((prev) => ({ ...prev, status: "critical", serverName: "Server Offline", nodeId: "Server Offline", uptime: "N/A", lastUpdate: new Date().toLocaleTimeString(), })) } }, []) useEffect(() => { fetchSystemData() const interval = setInterval(fetchSystemData, 10000) return () => clearInterval(interval) }, [fetchSystemData]) useEffect(() => { if ( systemStatus.serverName && systemStatus.serverName !== "Loading..." && systemStatus.serverName !== "Server Offline" ) { document.title = `${systemStatus.serverName} - ProxMenux Monitor` } else { document.title = "ProxMenux Monitor" } }, [systemStatus.serverName]) useEffect(() => { let hideTimeout: ReturnType | null = null let lastPosition = window.scrollY const handleScroll = () => { const currentScrollY = window.scrollY const delta = currentScrollY - lastPosition if (currentScrollY < 50) { setShowNavigation(true) } else if (delta > 2) { if (hideTimeout) clearTimeout(hideTimeout) hideTimeout = setTimeout(() => setShowNavigation(false), 20) } else if (delta < -2) { if (hideTimeout) clearTimeout(hideTimeout) setShowNavigation(true) } lastPosition = currentScrollY } window.addEventListener("scroll", handleScroll, { passive: true }) return () => { window.removeEventListener("scroll", handleScroll) if (hideTimeout) clearTimeout(hideTimeout) } }, []) const refreshData = async () => { setIsRefreshing(true) await fetchSystemData() setComponentKey((prev) => prev + 1) await new Promise((resolve) => setTimeout(resolve, 500)) setIsRefreshing(false) } const statusIcon = useMemo(() => { switch (systemStatus.status) { case "healthy": return case "warning": return case "critical": return } }, [systemStatus.status]) const statusColor = useMemo(() => { switch (systemStatus.status) { case "healthy": return "bg-green-500/10 text-green-500 border-green-500/20" case "warning": return "bg-yellow-500/10 text-yellow-500 border-yellow-500/20" case "critical": return "bg-red-500/10 text-red-500 border-red-500/20" } }, [systemStatus.status]) const getActiveTabLabel = () => { switch (activeTab) { case "overview": return "Overview" case "storage": return "Storage" case "network": return "Network" case "vms": return "VMs & LXCs" case "hardware": return "Hardware" case "logs": return "System Logs" case "settings": return "Settings" default: return "Navigation Menu" } } const setupTokenRefresh = () => { let refreshTimeout: ReturnType const refreshToken = async () => { const token = localStorage.getItem("proxmenux-auth-token") if (!token) return try { const response = await fetch(getApiUrl("/api/auth/refresh"), { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}`, }, }) if (response.ok) { const data = await response.json() localStorage.setItem("proxmenux-auth-token", data.token) console.log("[v0] Token refreshed successfully") } } catch (error) { console.error("[v0] Failed to refresh token:", error) } } const resetRefreshTimer = () => { clearTimeout(refreshTimeout) // Refresh token every 25 minutes (before 30 min expiry) refreshTimeout = setTimeout(refreshToken, 25 * 60 * 1000) } // Refresh on user activity const events = ["mousedown", "keydown", "scroll", "touchstart"] events.forEach((event) => { window.addEventListener(event, resetRefreshTimer, { passive: true }) }) resetRefreshTimer() return () => { clearTimeout(refreshTimeout) events.forEach((event) => { window.removeEventListener(event, resetRefreshTimer) }) } } const handleAuthSetupComplete = () => { setAuthDeclined(true) setIsAuthenticated(true) } const handleLoginSuccess = () => { setIsAuthenticated(true) setupTokenRefresh() } const handleLogout = () => { localStorage.removeItem("proxmenux-auth-token") setIsAuthenticated(false) } useEffect(() => { const checkAuth = async () => { console.log("[v0] ===== AUTH CHECK START =====") console.log("[v0] Current URL:", window.location.href) console.log("[v0] Window origin:", window.location.origin) try { const token = localStorage.getItem("proxmenux-auth-token") const headers: HeadersInit = { "Content-Type": "application/json" } if (token) { headers["Authorization"] = `Bearer ${token}` console.log("[v0] Token found in localStorage") } else { console.log("[v0] No token in localStorage") } const apiUrl = getApiUrl("/api/auth/status") console.log("[v0] Auth status API URL:", apiUrl) const response = await fetch(apiUrl, { headers }) console.log("[v0] Auth status response status:", response.status) console.log("[v0] Auth status response ok:", response.ok) if (!response.ok) { throw new Error(`Auth status check failed with status: ${response.status}`) } const data = await response.json() console.log("[v0] Auth status response data:", JSON.stringify(data, null, 2)) console.log("[v0] Setting authRequired to:", data.auth_enabled) console.log("[v0] Setting isAuthenticated to:", data.authenticated) console.log("[v0] auth_configured value:", data.auth_configured) setAuthRequired(data.auth_enabled) setIsAuthenticated(data.authenticated) // auth_configured will be true if user either set up auth OR declined it const shouldShowModal = !data.auth_configured console.log("[v0] Should show modal:", shouldShowModal) console.log("[v0] Setting authDeclined to:", data.auth_configured) setAuthDeclined(data.auth_configured) // If configured (either way), don't show modal setAuthChecked(true) if (data.authenticated && token) { setupTokenRefresh() } console.log("[v0] ===== AUTH CHECK SUCCESS =====") } catch (error) { console.error("[v0] ===== AUTH CHECK FAILED =====") console.error("[v0] Failed to check auth status:", error) console.error("[v0] Error message:", error instanceof Error ? error.message : "Unknown error") console.log("[v0] Setting authDeclined to false (show modal on error)") console.log("[v0] Setting authRequired to false (don't require login on error)") setAuthDeclined(false) // Show modal when API fails setAuthRequired(false) // Don't require login on error setAuthChecked(true) console.log("[v0] ===== AUTH CHECK ERROR HANDLED =====") } } checkAuth() }, []) if (!authChecked) { return (

Loading...

) } if (authRequired && !isAuthenticated) { return } return (
{!authDeclined && !authRequired && } {!isServerConnected && (
ProxMenux Server Connection Failed

• Check that the monitor.service is running correctly.

• The ProxMenux server should start automatically on port 8008

• Try accessing:{" "} {getApiUrl("/api/health")}

)}
{/* Logo and Title */}
{/* Logo and Title */}
ProxMenux Logo { console.log("[v0] Logo failed to load, using fallback icon") const target = e.target as HTMLImageElement target.style.display = "none" const fallback = target.parentElement?.querySelector(".fallback-icon") if (fallback) { fallback.classList.remove("hidden") } }} />

ProxMenux Monitor

Proxmox System Dashboard

Node: {systemStatus.serverName}
{/* Desktop Actions */}
Node: {systemStatus.serverName}
{statusIcon} {systemStatus.status}
Uptime: {systemStatus.uptime}
{authRequired && isAuthenticated && ( )}
{/* Mobile Actions */}
{statusIcon} {systemStatus.status} {authRequired && isAuthenticated && ( )}
{/* Mobile Server Info */}
Uptime: {systemStatus.uptime}
Overview Storage Network VMs & LXCs Hardware System Logs Settings
) }