import { useGpu } from "./hooks/useGpu.js"; import { useCurve } from "./hooks/useCurve.js"; import { useMonitor } from "./hooks/useMonitor.js"; import { useDashboard } from "./hooks/useDashboard.js"; import { StatusBar } from "./components/Monitor/StatusBar.js"; import { LiveMonitor } from "./components/Monitor/LiveMonitor.js"; import { Dashboard } from "./components/Dashboard/Dashboard.js"; import { CurveEditor } from "./components/CurveEditor/CurveEditor.js"; import { PointTable } from "./components/PointTable/PointTable.js"; import { PerformancePanel } from "./components/Limits/PerformancePanel.js"; import { PerformanceMonitor } from "./components/Monitor/PerformanceMonitor.js"; import { ProcessList } from "./components/Monitor/ProcessList.js"; import { FanMonitor } from "./components/Monitor/FanMonitor.js"; import { FanCurveEditor } from "./components/Fans/FanCurveEditor.js"; import { WireViewPanel } from "./components/WireView/WireViewPanel.js"; import { ProfilePanel } from "./components/Profiles/ProfilePanel.js"; import { api, onUnauthorized } from "./api/client.js"; import { LoginScreen } from "./components/Auth/LoginScreen.js"; import { useCurveStore } from "./store/curveStore.js"; import { useWireview } from "./hooks/useWireview.js"; import { useWireviewImbalance } from "./hooks/useWireviewImbalance.js"; import { Toaster } from "sonner"; import { Loader, ChevronDown } from "lucide-react"; import { useState, useRef, useEffect } from "react"; import type { FanState } from "./types.js"; type AuthState = "checking" | "login" | "ok"; export default function App() { const [authState, setAuthState] = useState("checking"); const [authUser, setAuthUser] = useState(null); useEffect(() => { let cancelled = false; api .authStatus() .then((s) => { if (cancelled) return; if (s.auth_required && !s.authenticated) { setAuthState("login"); } else { setAuthUser(s.username); setAuthState("ok"); } }) .catch(() => { // Server unreachable — fall through to the normal (no-auth) flow. if (!cancelled) setAuthState("ok"); }); return () => { cancelled = true; }; }, []); useEffect(() => { onUnauthorized(() => setAuthState("login")); return () => onUnauthorized(null); }, []); function handleLogout() { api.logout().catch(() => {}); setAuthUser(null); setAuthState("login"); } if (authState === "checking") { return (
); } if (authState === "login") { return ( { setAuthUser(username); setAuthState("ok"); }} /> ); } return ; } function MainApp({ user, onLogout, }: { user: string | null; onLogout: () => void; }) { const gpuInfo = useGpu(); const { curve, wsStatus: curveWsStatus } = useCurve(); const { monitor, monitorHistory, wsStatus: monitorWsStatus } = useMonitor(); const { dashboard, loading: dashboardLoading } = useDashboard(); const { setCurve, activeProfile, setActiveProfile, selectedGpuIndex } = useCurveStore(); const wireview = useWireview(); const wireImbalance = useWireviewImbalance(wireview.sample); const [activeTab, setActiveTab] = useState< "dashboard" | "curve" | "performance" | "fans" | "wireview" >("dashboard"); const [fanState, setFanState] = useState(null); const [activeDomain, setActiveDomain] = useState<"gpu" | "memory">("gpu"); const [isProfileOpen, setIsProfileOpen] = useState(false); const profileRef = useRef(null); const currentVoltageMv = monitor?.voltage_mv ?? null; function handleRefresh() { api.curve(selectedGpuIndex).then(setCurve).catch(console.error); } useEffect(() => { function handleClickOutside(event: MouseEvent) { if ( profileRef.current && !profileRef.current.contains(event.target as Node) ) { setIsProfileOpen(false); } } document.addEventListener("mousedown", handleClickOutside); // Fetch initial active profile api .profiles(selectedGpuIndex) .then((data) => setActiveProfile(data.active)) .catch(console.error); return () => document.removeEventListener("mousedown", handleClickOutside); }, [selectedGpuIndex, setActiveProfile]); function refreshFans() { api.fans(selectedGpuIndex).then(setFanState).catch(console.error); } useEffect(() => { if (activeTab === "fans") { refreshFans(); } }, [activeTab, selectedGpuIndex]); // Worst connection status wins const wsStatus = monitorWsStatus === "disconnected" || curveWsStatus === "disconnected" ? "disconnected" : monitorWsStatus === "connecting" || curveWsStatus === "connecting" ? "connecting" : "connected"; return (
{wsStatus !== "connected" && (
{wsStatus === "connecting" ? "Reconnecting to backend..." : "Connection lost. Retrying..."}
)} {wireImbalance && (
⚠ WireView: current imbalance {wireImbalance.diff.toFixed(1)} A — Pin {wireImbalance.hiPin} ({wireImbalance.maxI.toFixed(1)} A) vs Pin {wireImbalance.loPin} ({wireImbalance.minI.toFixed(1)} A) Bad pin contact — reduce load, replace cable/adapter
)}
{/* Tab Header and Profile Selector */}
{wireview.available && ( )}
{isProfileOpen && (
)}
{/* Main content area */}
{activeTab === "dashboard" ? ( ) : activeTab === "curve" ? ( <>
{curve ? ( ) : (
Loading curve…
)}
{curve && (
p.domain === activeDomain, )} currentVoltageMv={ activeDomain === "gpu" ? currentVoltageMv : null } readOnly={activeDomain === "memory"} />
)} ) : activeTab === "performance" ? (
) : activeTab === "wireview" ? ( ) : (
)}
); }