"use client" import { cn } from "@/lib/utils" import { useT } from "../lib/i18n/provider" interface SriovInfo { role: "vf" | "pf-active" | "pf-idle" physfn?: string // VF only: parent PF BDF vfCount?: number // PF only: active VF count totalvfs?: number // PF only: maximum VFs } interface GpuSwitchModeIndicatorProps { mode: "lxc" | "vm" | "sriov" | "unknown" isEditing?: boolean pendingMode?: "lxc" | "vm" | null onToggle?: (e: React.MouseEvent) => void className?: string sriovInfo?: SriovInfo } export function GpuSwitchModeIndicator({ mode, isEditing = false, pendingMode = null, onToggle, className, sriovInfo, }: GpuSwitchModeIndicatorProps) { const t = useT() // SR-IOV is a non-editable hardware state. Pending toggles don't apply here. const displayMode = mode === "sriov" ? "sriov" : (pendingMode ?? mode) const isLxcActive = displayMode === "lxc" const isVmActive = displayMode === "vm" const isSriovActive = displayMode === "sriov" const hasChanged = mode !== "sriov" && pendingMode !== null && pendingMode !== mode // Colors const sriovColor = "#14b8a6" // teal-500 const activeColor = isSriovActive ? sriovColor : isLxcActive ? "#3b82f6" : isVmActive ? "#a855f7" : "#6b7280" const inactiveColor = "#374151" // gray-700 for dark theme const dimmedColor = "#4b5563" // gray-600 for dashed SR-IOV branches const lxcColor = isLxcActive ? "#3b82f6" : inactiveColor const vmColor = isVmActive ? "#a855f7" : inactiveColor const handleClick = (e: React.MouseEvent) => { // SR-IOV state can't be toggled — swallow the click so it doesn't reach // the card (which would open the detail modal unexpectedly from this // area). For lxc/vm, preserve the original behavior. if (isSriovActive) { e.stopPropagation() return } if (isEditing) { e.stopPropagation() if (onToggle) { onToggle(e) } } // When not editing, let the click propagate to the card to open the modal } // Build the VF count label shown in the SR-IOV badge. For PFs we know // exactly how many VFs are active; for a VF we show its parent PF. const sriovBadgeText = (() => { if (!isSriovActive) return "" if (sriovInfo?.role === "vf") return t("hardware.gpuSwitch.sriovVf") if (sriovInfo?.vfCount && sriovInfo.vfCount > 0) { return t("hardware.gpuSwitch.sriovCount", { count: sriovInfo.vfCount }) } return t("hardware.gpuSwitch.sriov") })() return (
{/* Large SVG Diagram */} {/* GPU Chip - Large with "GPU" text */} {/* Main chip body */} {/* Chip pins - top */} {/* Chip pins - bottom */} {/* GPU text */} {t("hardware.gpuSwitch.gpu")} {/* Connection line from GPU to switch */} {/* Central Switch Node - Large circle with inner dot */} {/* LXC Branch Line - going up-right. In SR-IOV mode the branch is dashed + dimmed to show that the target is theoretically reachable via a VF but not controlled by ProxMenux. */} {/* VM Branch Line - going down-right (dashed/dimmed in SR-IOV). */} {/* SR-IOV in-line connector + badge (only when mode === 'sriov'). A horizontal line from the switch node leads to a pill-shaped badge carrying the "SR-IOV ×N" label. Placed on the GPU's baseline to visually read as an in-line extension, not as a third branch. */} {isSriovActive && ( <> {sriovBadgeText} )} {/* LXC Container Icon - dimmed/smaller in SR-IOV mode. */} {!isSriovActive && ( )} {/* SR-IOV: compact dimmed LXC glyph so the geometry stays recognizable but it's clearly not the active target. */} {isSriovActive && ( )} {/* LXC Label */} {!isSriovActive && ( {t("hardware.gpuSwitch.lxc")} )} {isSriovActive && ( {t("hardware.gpuSwitch.lxc")} )} {/* VM Monitor Icon - active view */} {!isSriovActive && ( )} {/* SR-IOV: compact dimmed VM monitor glyph, mirror of the LXC glyph. */} {isSriovActive && ( )} {/* VM Label */} {!isSriovActive && ( {t("hardware.gpuSwitch.vm")} )} {isSriovActive && ( {t("hardware.gpuSwitch.vm")} )} {/* Status Text - Large like GPU name */}
{isSriovActive ? t("hardware.gpuSwitch.sriovActive") : isLxcActive ? t("hardware.gpuSwitch.readyForLxc") : isVmActive ? t("hardware.gpuSwitch.readyForVm") : t("hardware.gpuSwitch.modeUnknown")} {isSriovActive ? t("hardware.gpuSwitch.virtualFunctionsExternal") : isLxcActive ? t("hardware.gpuSwitch.nativeDriverActive") : isVmActive ? t("hardware.gpuSwitch.vfioDriverActive") : t("hardware.gpuSwitch.noDriverDetected")} {isSriovActive && sriovInfo && ( {sriovInfo.role === "vf" ? t( sriovInfo.physfn ? "hardware.gpuSwitch.virtualFunctionWithParent" : "hardware.gpuSwitch.virtualFunction", { parent: sriovInfo.physfn || "" }, ) : sriovInfo.vfCount !== undefined ? t( sriovInfo.totalvfs ? "hardware.gpuSwitch.physicalFunctionWithMax" : "hardware.gpuSwitch.physicalFunction", { count: sriovInfo.vfCount, max: sriovInfo.totalvfs || "", }, ) : null} )} {hasChanged && ( {t("hardware.gpuSwitch.changePending")} )}
) }