// Enhanced Peers UI functions let peerChart = null; // Render peers list - uses generic pagination system async function renderPeers() { if (window.genericFetch) { await window.genericFetch('peers', true); } renderPeerGraph(); } // Filter peers - uses generic filter system function filterPeers() { if (window.genericFilter) { window.genericFilter('peers'); } } // Show peer details modal async function showPeerDetails(peerId) { try { const [peerRes, historyRes] = await Promise.all([ fetch(`/api/peers/${encodeURIComponent(peerId)}`), fetch(`/api/peers/${encodeURIComponent(peerId)}/history`) ]); if (!peerRes.ok || !historyRes.ok) { throw new Error('Failed to fetch peer details'); } const peer = await peerRes.json(); const history = await historyRes.json(); const modal = document.getElementById('peerDetailsModal'); if (!modal) return; const content = document.getElementById('peer-details-content'); if (!content) return; const uptime = peer.uptime ? (window.formatUptime ? window.formatUptime(peer.uptime) : `${Math.floor(peer.uptime / 1000)}s`) : 'N/A'; const connectTime = peer.connectTime ? new Date(peer.connectTime).toLocaleString() : 'N/A'; const lastSeen = peer.metrics?.lastSeen ? new Date(peer.metrics.lastSeen).toLocaleString() : 'N/A'; content.innerHTML = `
ID: ${peer.id}
Status: ${peer.connected ? 'Connected' : 'Disconnected'}
Uptime: ${uptime}
Connected At: ${connectTime}
Blocked: ${peer.isBlocked ? 'Yes' : 'No'}
Total Connections: ${peer.metrics?.connections || 0}
Total Duration: ${peer.metrics?.totalDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.totalDuration) : `${Math.floor(peer.metrics.totalDuration / 1000)}s`) : '0s'}
Average Duration: ${peer.metrics?.avgDuration ? (window.formatDuration ? window.formatDuration(peer.metrics.avgDuration) : `${Math.floor(peer.metrics.avgDuration / 1000)}s`) : 'N/A'}
Last Seen: ${lastSeen}
No history available
' : history.slice(-50).reverse().map(event => `