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.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
)}
)
}