Next.js 16 + Tailwind v4 + shadcn v4 dashboard for managing a modded Forge 1.20.1 server. Includes server controls, player management, mod manager with Modrinth search and dependency resolution, world backups, snapshots, analytics, logs, and chat bridge. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
"use client";
|
|
|
|
import { useQuery } from "@tanstack/react-query";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Badge } from "@/components/ui/badge";
|
|
|
|
type Mod = {
|
|
modId: string;
|
|
displayName: string;
|
|
version: string;
|
|
filename: string;
|
|
size: string;
|
|
};
|
|
|
|
export function ModList() {
|
|
const { data: mods = [] } = useQuery<Mod[]>({
|
|
queryKey: ["mods"],
|
|
queryFn: () => fetch("/api/mods").then((r) => r.json()),
|
|
staleTime: 5 * 60 * 1000,
|
|
});
|
|
|
|
return (
|
|
<Card>
|
|
<CardHeader className="pb-0">
|
|
<CardTitle className="text-base">
|
|
Installed Mods ({mods.length})
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="">
|
|
<ul className="max-h-[350px] sm:max-h-[400px] overflow-y-auto -mx-1">
|
|
{mods.map((mod, i) => (
|
|
<li
|
|
key={mod.filename}
|
|
className={`flex justify-between items-center px-3 py-2.5 rounded-md ${
|
|
i % 2 === 1 ? "bg-muted/50" : ""
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-2 min-w-0">
|
|
<span className="text-sm font-medium truncate">
|
|
{mod.displayName}
|
|
</span>
|
|
{mod.version && (
|
|
<Badge variant="secondary" className="text-xs px-1.5 py-0 shrink-0 hidden sm:inline-flex">
|
|
{mod.version}
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
<span className="text-xs text-muted-foreground whitespace-nowrap ml-3 tabular-nums">
|
|
{mod.size}
|
|
</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|