import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { Badge } from "@/components/ui/badge"; import { Monitor, Wifi, WifiOff, Loader2, Maximize2, X } from "lucide-react"; import { useState } from "react"; import { cn } from "@/lib/utils"; import { FolderStatusPopover } from "../folder-status-popover"; import { useGetClientFolderStatusForDevice } from "@/hooks/queries"; import type { ClientFolderStatus } from "@/types/folder"; import { Button } from "@/components/ui/button"; import { getRemoteDesktopUrl } from "@/services/remote-control.service"; import { buildMeshProxyUrl } from "@/config/api"; import { toast } from "sonner"; export function ComputerCard({ device, position, folderStatus, isCheckingFolder, }: { device: any | undefined; position: number; folderStatus?: ClientFolderStatus; isCheckingFolder?: boolean; }) { const [isConnecting, setIsConnecting] = useState(false); const [showRemote, setShowRemote] = useState(false); const [proxyUrl, setProxyUrl] = useState(null); if (!device) { return (
{position}
Trống
); } const isOffline = device.isOffline; const firstNetworkInfo = device.networkInfos?.[0]; const agentVersion = device.version; const handleConnect = async () => { if (!device?.id) { toast.error("Không tìm thấy nodeID của thiết bị."); return; } try { setIsConnecting(true); const response = await getRemoteDesktopUrl(device.id); const originalUrl = new URL(response.url); const pathAndQuery = originalUrl.pathname + originalUrl.search; const proxyUrlFull = buildMeshProxyUrl(pathAndQuery); setProxyUrl(proxyUrlFull); setShowRemote(true); } catch (error: any) { toast.error( error?.response?.data?.message || "Không thể kết nối remote cho thiết bị này." ); } finally { setIsConnecting(false); } }; const handleCloseRemote = () => { setShowRemote(false); setProxyUrl(null); }; const handleFullscreen = () => { const iframe = document.getElementById(`mesh-iframe-${device.id}`) as HTMLIFrameElement; if (iframe?.requestFullscreen) { iframe.requestFullscreen(); } }; function DeviceFolderCheck() { const deviceId = device.id; const room = device.room; const [checking, setChecking] = useState(false); const { data: status, isLoading } = useGetClientFolderStatusForDevice( deviceId, room, checking ); const handleCheck = () => setChecking((s) => !s); return (
{checking && isLoading && (
Đang kiểm tra...
)} {checking && !isLoading && status && (
Các file trong thư mục Setup({status.currentFiles?.length ?? 0})
{(status.currentFiles ?? []).length === 0 ? (
Không có file hiện tại
) : ( (status.currentFiles ?? []).map((f: any) => (
{f.fileName}
{f.lastModified && (
{new Date(f.lastModified).toLocaleString()}
)}
)) )}
)} {checking && !isLoading && !status && (
Không có dữ liệu
)}
); } const DeviceInfo = () => (
Thời gian thiết bị
{new Date(device.deviceTime).toLocaleDateString("vi-VN")}
{new Date(device.deviceTime).toLocaleTimeString("vi-VN")}
Phiên bản
v{device.version}
Phòng
{device.room}
{device.networkInfos?.length > 0 && (
Thông tin mạng
{device.networkInfos.map((info: any, idx: number) => (
MAC: {info.macAddress ?? "-"}
IP: {info.ipAddress ?? "-"}
))}
)}
Kết nối
Kiểm tra thư mục
Trạng thái
{isOffline ? : } {isOffline ? "Offline" : "Online"}
); return ( <>
{position}
{/* Folder Status Icon */} {device && !isOffline && (
)} {firstNetworkInfo?.ipAddress && (
{firstNetworkInfo.ipAddress} {agentVersion && (
v{agentVersion}
)}
)}
{isOffline ? "Off" : "On"}
{showRemote && proxyUrl && (

Remote Session - {device.id}