import { useState } from 'react'; import { useParams, useNavigate } from 'react-router'; import { useQuery, useMutation } from '@tanstack/react-query'; 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, CardDescription } from '@/components/ui/card'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; interface Game { id: string; name: string; slug: string; dockerImage: string; } interface Node { id: string; name: string; fqdn: string; memoryTotal: number; diskTotal: number; } interface Allocation { id: string; ip: string; port: number; serverId: string | null; } interface PaginatedResponse { data: T[]; meta: { total: number }; } export function CreateServerPage() { const { orgId } = useParams(); const navigate = useNavigate(); const [step, setStep] = useState(1); const [name, setName] = useState(''); const [description, setDescription] = useState(''); const [gameId, setGameId] = useState(''); const [nodeId, setNodeId] = useState(''); const [allocationId, setAllocationId] = useState(''); const [memoryLimit, setMemoryLimit] = useState(1024); const [diskLimit, setDiskLimit] = useState(5120); const [cpuLimit, setCpuLimit] = useState(100); const { data: gamesData } = useQuery({ queryKey: ['admin-games'], queryFn: () => api.get>('/admin/games'), }); const { data: nodesData } = useQuery({ queryKey: ['nodes', orgId], queryFn: () => api.get>(`/organizations/${orgId}/nodes`), }); const { data: allocationsData } = useQuery({ queryKey: ['allocations', orgId, nodeId], queryFn: () => api.get>( `/organizations/${orgId}/nodes/${nodeId}/allocations`, ), enabled: !!nodeId, }); const freeAllocations = (allocationsData?.data ?? []).filter((a) => !a.serverId); const createMutation = useMutation({ mutationFn: (body: Record) => api.post(`/organizations/${orgId}/servers`, body), onSuccess: () => { navigate(`/org/${orgId}/dashboard`); }, }); const games = gamesData?.data ?? []; const nodes = nodesData?.data ?? []; const handleCreate = () => { createMutation.mutate({ name, description: description || undefined, gameId, nodeId, allocationId, memoryLimit: memoryLimit * 1024 * 1024, diskLimit: diskLimit * 1024 * 1024, cpuLimit, }); }; return (

Create Server

Set up a new game server

{[1, 2, 3].map((s) => (
))}
{step === 1 && ( Basic Information Choose a name and game for your server
setName(e.target.value)} placeholder="My Awesome Server" />
setDescription(e.target.value)} placeholder="A short description" />
)} {step === 2 && ( Node & Allocation Choose where to host your server
{nodeId && (
{freeAllocations.length === 0 && nodeId && (

No free allocations on this node

)}
)}
)} {step === 3 && ( Resources Set resource limits for this server
setMemoryLimit(Number(e.target.value))} min={128} />

{formatBytes(memoryLimit * 1024 * 1024)}

setDiskLimit(Number(e.target.value))} min={256} />

{formatBytes(diskLimit * 1024 * 1024)}

setCpuLimit(Number(e.target.value))} min={10} max={10000} />

100% = 1 core

{createMutation.isError && (

Failed to create server. Please try again.

)}
)}
); }