Files
Minikura/apps/web/app/dashboard/servers/page.tsx
T

108 lines
3.7 KiB
TypeScript
Raw Normal View History

2026-02-13 15:52:13 +07:00
"use client";
2026-08-13 01:58:15 +07:00
import { Globe, Plus, Server, ServerCog } from "lucide-react";
2026-02-13 15:52:13 +07:00
import { useRouter } from "next/navigation";
2026-08-13 01:58:15 +07:00
import { useState } from "react";
import { ConfirmDialog } from "@/components/confirm-dialog";
import { PageHeader, PageShell, StatePanel } from "@/components/page-layout";
import { ResourceSection } from "@/components/section-card";
import { ServerTable } from "@/components/servers/server-table";
2026-02-13 15:52:13 +07:00
import { Button } from "@/components/ui/button";
2026-08-13 01:58:15 +07:00
import { useServerList } from "@/hooks/use-server-list";
2026-08-13 03:29:33 +07:00
import { useSession } from "@/lib/auth-client";
2026-02-13 15:52:13 +07:00
export default function ServersPage() {
const router = useRouter();
2026-08-13 03:29:33 +07:00
const { data: session } = useSession();
const isAdmin = session?.user.role === "admin";
2026-08-13 01:58:15 +07:00
const { normalServers, reverseProxies, loading, error, deleteServer } = useServerList();
2026-02-13 15:52:13 +07:00
const [deleteTarget, setDeleteTarget] = useState<{
id: string;
type: "normal" | "proxy";
} | null>(null);
const handleDelete = async () => {
if (!deleteTarget) return;
try {
2026-08-13 01:58:15 +07:00
await deleteServer(deleteTarget.id, deleteTarget.type);
2026-02-13 15:52:13 +07:00
setDeleteTarget(null);
2026-02-17 18:12:02 +07:00
} catch (_error) {}
2026-02-13 15:52:13 +07:00
};
return (
2026-08-13 01:58:15 +07:00
<PageShell>
<PageHeader
eyebrow="Workloads"
title="Servers"
description="Provision Minecraft runtimes and route traffic through edge proxies."
actions={
2026-08-13 03:29:33 +07:00
isAdmin ? (
<Button size="lg" onClick={() => router.push("/dashboard/servers/create")}>
<Plus className="size-4" />
Create Server
</Button>
) : undefined
2026-08-13 01:58:15 +07:00
}
/>
2026-02-13 15:52:13 +07:00
2026-08-13 01:58:15 +07:00
{loading ? (
<StatePanel loading title="Discovering workloads..." className="h-64" />
) : error ? (
<StatePanel title="Unable to load workloads" description={error} tone="error" />
) : (
<>
<ResourceSection
title="Minecraft Workloads"
description="Manage your normal Minecraft server instances"
icon={<ServerCog className="size-5 text-primary" />}
count={normalServers.length}
emptyIcon={<Server className="size-6" />}
emptyTitle="No workloads"
emptyDescription="Create a server to begin."
>
<ServerTable
type="normal"
servers={normalServers}
2026-08-13 03:29:33 +07:00
onEdit={isAdmin ? (id) => router.push(`/dashboard/servers/edit/${id}`) : undefined}
onDelete={isAdmin ? (id) => setDeleteTarget({ id, type: "normal" }) : undefined}
2026-08-13 01:58:15 +07:00
/>
</ResourceSection>
2026-02-13 15:52:13 +07:00
2026-08-13 01:58:15 +07:00
<ResourceSection
title="Edge Proxies"
description="Manage your Velocity and BungeeCord proxy servers"
icon={<Globe className="size-5 text-primary" />}
count={reverseProxies.length}
emptyIcon={<Globe className="size-6" />}
emptyTitle="No edge proxies"
emptyDescription="Proxy workloads will appear here."
>
<ServerTable
type="proxy"
servers={reverseProxies}
2026-08-13 03:29:33 +07:00
onEdit={isAdmin ? (id) => router.push(`/dashboard/servers/edit/${id}`) : undefined}
onDelete={isAdmin ? (id) => setDeleteTarget({ id, type: "proxy" }) : undefined}
2026-08-13 01:58:15 +07:00
/>
</ResourceSection>
</>
)}
2026-02-13 15:52:13 +07:00
2026-08-13 01:58:15 +07:00
<ConfirmDialog
open={!!deleteTarget}
title="Delete Server"
description={
<>
Are you sure you want to delete this{" "}
{deleteTarget?.type === "normal" ? "server" : "reverse proxy"}? This action cannot be
undone.
</>
}
confirmLabel="Delete"
onConfirm={handleDelete}
onOpenChange={(open) => !open && setDeleteTarget(null)}
/>
</PageShell>
2026-02-13 15:52:13 +07:00
);
}