'use client'; import Link from 'next/link'; import { Pencil, Trash2 } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { Button } from '@/components/ui/button'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { formatDateTime } from '@/lib/utils'; import type { NodeItem } from '@/lib/services/openflare'; import { NodeStatusBadge } from './node-status-badge'; import { formatRelativeTime, getApplyLabel, getApplyTone, getNodeStatusLabel, getNodeStatusTone, getNodeTypeLabel, getOpenrestyStatusLabel, getOpenrestyStatusTone, getRelayStatusLabel, getRelayStatusTone, isMeaningfulTime, isWSConnectedLastSeen, } from './node-utils'; export function NodesTable({ nodes, deletingId, onEdit, onDelete, }: { nodes: NodeItem[]; deletingId: number | null; onEdit: (node: NodeItem) => void; onDelete: (node: NodeItem) => void; }) { const t = useTranslations('nodes'); return (
{t('table.node')} {t('table.status')} {t('table.version')} {t('table.runHealth')} {t('table.currentVersion')} {t('table.latestApply')} {t('table.lastSeen')} {t('table.actions')} {nodes.map((node) => (

{node.name}

{t('ipLine', { ip: node.ip || '—' })} {node.ip_manual_override ? t('lockedSuffix') : ''}

{t('locationLine', { location: node.geo_name || t('noGeo'), })}

{node.version || 'unknown'} {node.node_type === 'tunnel_relay' ? ( ) : node.node_type === 'tunnel_client' ? ( ) : ( )} {node.current_version || (node.node_type === 'tunnel_relay' ? t('liveConfig') : t('notApplied'))} {node.node_type === 'tunnel_relay' ? ( — ) : ( )} {isWSConnectedLastSeen(node.last_seen_at) ? t('wsConnected') : isMeaningfulTime(node.last_seen_at) ? `${formatRelativeTime(node.last_seen_at, t)} · ${formatDateTime(node.last_seen_at)}` : t('na')}
))}
); }