import { useState, type ReactNode } from "react"; import { AlertTriangle, Eye, EyeOff, Monitor, MousePointerClick, Plug, ShieldCheck, Wifi, Wrench, } from "lucide-react"; import { useVncConsole, type VncConnectionState } from "../hooks/useVncConsole"; type ConsolePageProps = { theme: "dark" | "light"; }; const RADIUS = "rounded-[5px]"; export function ConsolePage({ theme }: ConsolePageProps) { const isDark = theme === "dark"; const vnc = useVncConsole({ websocketUrl: "ws://localhost:18450/ws/vnc", defaultHost: "198.19.0.176", defaultPort: 5900, }); const [passwordVisible, setPasswordVisible] = useState(false); const connectionLabel = getConnectionLabel(vnc.state); const hasFrame = vnc.frameSize.width > 0 && vnc.frameSize.height > 0; const frameAspectRatio = hasFrame ? `${vnc.frameSize.width} / ${vnc.frameSize.height}` : "800 / 480"; return (

Ecrã do controlador

{vnc.lastFrameAt ? `Último frame: ${vnc.lastFrameAt}` : "A aguardar imagem da consola"}

{!hasFrame && (

{vnc.state === "DISCONNECTED" ? "Sessão terminada" : "Consola indisponível"}

{vnc.state === "DISCONNECTED" ? "Inicie uma nova sessão para voltar a aceder ao controlador." : "Inicie uma sessão VNC para visualizar e controlar o controlador."}

)}
event.preventDefault()} className={ hasFrame ? "flex h-full w-full cursor-crosshair items-center justify-center overflow-hidden bg-black" : "pointer-events-none absolute h-px w-px overflow-hidden opacity-0" } >
); } function panelClass(isDark: boolean) { return isDark ? `${RADIUS} flex h-full min-h-0 flex-col border border-white/10 bg-[#071421] p-3 shadow-[0_14px_34px_rgba(0,0,0,0.22)]` : `${RADIUS} flex h-full min-h-0 flex-col border border-slate-200 bg-white p-3 shadow-[0_10px_26px_rgba(15,23,42,0.06)]`; } function panelTitleClass(isDark: boolean) { return isDark ? "text-base font-black text-slate-100" : "text-base font-black text-slate-950"; } function getConnectionLabel(state: VncConnectionState) { switch (state) { case "CONNECTING_WS": return "A ligar WS"; case "CONNECTING_VNC": return "A ligar VNC"; case "CONNECTED": return "Ligado"; case "FIRST_FRAME": return "Ativo"; case "DISCONNECTED": return "Desconectado"; case "ERROR": return "Erro"; case "IDLE": default: return "A aguardar..."; } } function Field({ theme, label, value, onChange, type = "text", disabled, rightElement, }: { theme: "dark" | "light"; label: string; value: string; onChange: (value: string) => void; type?: string; disabled?: boolean; rightElement?: ReactNode; }) { const isDark = theme === "dark"; return ( ); } function StatusCard({ theme, icon, title, value, color, }: { theme: "dark" | "light"; icon: ReactNode; title: string; value: string; color: "green" | "blue" | "purple"; }) { const isDark = theme === "dark"; const colors = { green: isDark ? "bg-[#13202F] text-[#4FD1C5]" : "bg-[#ECFDF5] text-[#0F766E]", blue: isDark ? "bg-[#13202F] text-[#7DD3FC]" : "bg-[#EFF6FF] text-[#0369A1]", purple: isDark ? "bg-[#171B2B] text-[#A5B4FC]" : "bg-[#EEF2FF] text-[#4F46E5]", }; return (
{icon}

{title}

{value}

); } function SmallInfo({ theme, icon, label, value, }: { theme: "dark" | "light"; icon: ReactNode; label: string; value: string; }) { const isDark = theme === "dark"; return (
{icon}

{label}

{value}

); } export default ConsolePage;