'use client'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { ColumnDef } from '@tanstack/react-table'; import { format } from 'date-fns'; import { Activity, Copy, Ellipsis, Monitor, Trash2 } from 'lucide-react'; import { useState } from 'react'; import { DataTable } from '@/components/data-table'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { apiClient } from '@/lib/api-client'; import { KeygenMachine } from '@/lib/types'; import { toast } from 'sonner'; export default function MachinesPage() { const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const [selectedMachine, setSelectedMachine] = useState(null); const copyLicenseKey = (key: string, message: string = 'Copied to clipboard') => { navigator.clipboard.writeText(key); toast(message); }; const queryClient = useQueryClient(); const { data, isLoading } = useQuery({ queryKey: ['machines'], queryFn: () => apiClient.getMachines(1, 100), }); const deleteMutation = useMutation({ mutationFn: (id: string) => apiClient.deleteMachine(id), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ['machines'] }); setIsDeleteDialogOpen(false); setSelectedMachine(null); toast.success('Machine deleted successfully'); }, onError: (error) => { toast.error(error.message); }, }); const handleDelete = async () => { if (selectedMachine) { await deleteMutation.mutateAsync(selectedMachine.id); } }; const getStatusColor = (lastValidated?: string) => { if (!lastValidated) return 'outline'; const lastValidatedDate = new Date(lastValidated); const now = new Date(); const diffInHours = (now.getTime() - lastValidatedDate.getTime()) / (1000 * 60 * 60); if (diffInHours < 24) return 'default'; // Active (green) if (diffInHours < 168) return 'secondary'; // Idle (yellow) return 'destructive'; // Inactive (red) }; const getStatusText = (lastValidated?: string) => { if (!lastValidated) return 'Never'; const lastValidatedDate = new Date(lastValidated); const now = new Date(); const diffInHours = (now.getTime() - lastValidatedDate.getTime()) / (1000 * 60 * 60); if (diffInHours < 1) return 'Active'; if (diffInHours < 24) return 'Recent'; if (diffInHours < 168) return 'Idle'; return 'Inactive'; }; const columns: ColumnDef[] = [ { accessorKey: 'attributes.name', header: 'Name', cell: ({ row }) => { const name = row.original.attributes.name; return name ? (
{name}
) : ( Unnamed ); }, }, { accessorKey: 'attributes.hostname', header: 'Hostname', cell: ({ row }) => ( {row.original.attributes.hostname} ), }, { accessorKey: 'attributes.platform', header: 'Platform', cell: ({ row }) => ( {row.original.attributes.platform} ), }, { accessorKey: 'attributes.cores', header: 'CPU Cores', cell: ({ row }) => ( {row.original.attributes.cores} ), }, { accessorKey: 'attributes.ip', header: 'IP Address', cell: ({ row }) => ( {row.original.attributes.ip} ), }, { accessorKey: 'attributes.lastValidated', header: 'Status', cell: ({ row }) => { const lastValidated = row.original.attributes.lastValidated; return (
{getStatusText(lastValidated)}
); }, }, { accessorKey: 'relationships.license.data.id', header: 'License id', cell: ({ row }) => { const licenseId = row.original.relationships?.license?.data?.id; return (
{licenseId?.substring(0, 4)}...{licenseId?.substring(licenseId?.length - 4)} {licenseId && ( copyLicenseKey(licenseId, 'License id copied to clipboard')} /> )}
); }, }, { accessorKey: 'relationships.user.data.id', header: 'User id', cell: ({ row }) => { const userId = row.original.relationships?.user?.data?.id; return (
{userId?.substring(0, 4)}...{userId?.substring(userId?.length - 4)} {userId && ( copyLicenseKey(userId, 'User id copied to clipboard')} /> )}
); }, }, { accessorKey: 'attributes.created', header: 'Created', cell: ({ row }) => format(new Date(row.original.attributes.created), 'MMM d, yyyy'), }, { id: 'actions', cell: ({ row }) => { const machine = row.original; return ( { setSelectedMachine(machine); setIsDeleteDialogOpen(true); }} className="text-red-600" > Delete ); }, }, ]; if (isLoading) { return ( <>

Loading machines...

); } return ( <>

Machines

Monitor registered machines and their license usage

{/* Delete Machine Dialog */} Delete Machine Are you sure you want to delete {selectedMachine?.attributes.hostname}? This action cannot be undone.
); }