import { useState } from 'react'; import { useParams, Link } from 'react-router'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Plus, Network, Wifi, WifiOff } from 'lucide-react'; import { api } from '@/lib/api'; import { formatBytes } from '@/lib/utils'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from '@/components/ui/dialog'; interface NodeItem { id: string; name: string; fqdn: string; daemonPort: number; grpcPort: number; memoryTotal: number; diskTotal: number; isOnline: boolean; } interface PaginatedResponse { data: T[]; meta: { total: number }; } export function NodesPage() { const { orgId } = useParams(); const queryClient = useQueryClient(); const [open, setOpen] = useState(false); const [name, setName] = useState(''); const [fqdn, setFqdn] = useState(''); const [daemonPort, setDaemonPort] = useState(8443); const [grpcPort, setGrpcPort] = useState(50051); const [memoryTotal, setMemoryTotal] = useState(8192); const [diskTotal, setDiskTotal] = useState(51200); const { data } = useQuery({ queryKey: ['nodes', orgId], queryFn: () => api.get>(`/organizations/${orgId}/nodes`), }); const createMutation = useMutation({ mutationFn: (body: Record) => api.post(`/organizations/${orgId}/nodes`, body), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['nodes', orgId] }); setOpen(false); setName(''); setFqdn(''); }, }); const nodes = data?.data ?? []; return (

Nodes

Manage your daemon nodes

Add Node
{ e.preventDefault(); createMutation.mutate({ name, fqdn, daemonPort, grpcPort, memoryTotal: memoryTotal * 1024 * 1024, diskTotal: diskTotal * 1024 * 1024, }); }} className="space-y-4" >
setName(e.target.value)} required />
setFqdn(e.target.value)} placeholder="node1.example.com" required />
setDaemonPort(Number(e.target.value))} />
setGrpcPort(Number(e.target.value))} />
setMemoryTotal(Number(e.target.value))} />
setDiskTotal(Number(e.target.value))} />
{nodes.map((node) => (
{node.name}
{node.isOnline ? ( <> Online ) : ( <> Offline )}

{node.fqdn}:{node.daemonPort}

{formatBytes(node.memoryTotal)} RAM {formatBytes(node.diskTotal)} Disk
))}
); }