import { Server, Wifi, WifiOff, Trash2, ChevronDown, ChevronUp, RefreshCw, Cpu, MemoryStick, ArrowUp, ArrowDown, Pencil, BarChart2, CloudDownload, Copy, Check } from 'lucide-react' import { useState } from 'react' import ContainerRow from './ContainerRow' import { tagColor } from './TagInput' function formatBytes(bps) { if (bps < 1024) return `${bps.toFixed(0)} B/s` if (bps < 1024 * 1024) return `${(bps / 1024).toFixed(1)} KB/s` return `${(bps / 1024 / 1024).toFixed(1)} MB/s` } function formatRam(bytes) { if (bytes < 1024 ** 3) return `${(bytes / 1024 ** 2).toFixed(0)} MB` return `${(bytes / 1024 ** 3).toFixed(1)} GB` } export default function VpsCard({ vps, onAction, onLogs, onDelete, onUpdate, onEdit, onStats, onUpdateAgent, onExport }) { const [collapsed, setCollapsed] = useState(false) const [updatingProject, setUpdatingProject] = useState(null) const [updatingAgent, setUpdatingAgent] = useState(false) const [exported, setExported] = useState(false) const handleExport = async () => { await onExport(vps.id) setExported(true) setTimeout(() => setExported(false), 2000) } const running = vps.containers.filter(c => c.status === 'running').length const total = vps.containers.length const composeProjects = [...new Set(vps.containers.map(c => c.compose_project).filter(Boolean))] const handleUpdate = async (project) => { setUpdatingProject(project) try { await onUpdate(vps.id, project) } finally { setUpdatingProject(null) } } const handleUpdateAgent = async () => { setUpdatingAgent(true) try { await onUpdateAgent(vps.id) } finally { setUpdatingAgent(false) } } return (
{/* Header */}

{vps.name}

{vps.host}

{vps.online ? ( {running}/{total} actifs ) : ( Hors ligne )} {vps.online && ( )}
{/* Erreur de connexion */} {!vps.online && vps.error && (
{vps.error}
)} {/* Version de l'agent + bouton mise à jour */} {vps.online && (
Agent : {vps.agent_version ? ( {vps.agent_up_to_date ? '✓' : '⚠'} v{vps.agent_version} ) : ( inconnu )} {(!vps.agent_up_to_date || vps.agent_version === 'unknown') && ( )}
)} {/* Boutons de mise à jour par projet compose */} {vps.online && composeProjects.length > 0 && (
{composeProjects.map(project => ( ))}
)} {/* Informations système */} {vps.online && vps.system && !collapsed && (
CPU 80 ? 'text-red-400' : vps.system.cpu_percent > 60 ? 'text-yellow-400' : 'text-emerald-400'}`}>{vps.system.cpu_percent.toFixed(1)}% RAM 80 ? 'text-red-400' : vps.system.ram_percent > 60 ? 'text-yellow-400' : 'text-emerald-400'}`}>{formatRam(vps.system.ram_used)}/{formatRam(vps.system.ram_total)} ({vps.system.ram_percent.toFixed(0)}%) {formatBytes(vps.system.net_sent_per_sec)} {formatBytes(vps.system.net_recv_per_sec)}
)} {/* Tags */} {vps.tags?.length > 0 && !collapsed && (
{vps.tags.map(tag => ( {tag} ))}
)} {/* Description */} {vps.description && !collapsed && (

{vps.description}

)} {/* Conteneurs */} {!collapsed && vps.online && (
{total === 0 ? (

Aucun conteneur détecté.

) : ( vps.containers.map(c => ( onAction(vps.id, c.id, action)} onLogs={() => onLogs(vps.id, c.id, `${vps.name} / ${c.name}`)} /> )) )}
)} {/* Footer stats */} {!collapsed && vps.online && total > 0 && (
{running} en cours {total - running} arrêtés {total} total
)}
) }