165 lines
4.5 KiB
TypeScript
165 lines
4.5 KiB
TypeScript
import Link from "next/link";
|
|
import { getTranslations } from "next-intl/server";
|
|
import { notFound } from "next/navigation";
|
|
import { prisma } from "@/lib/prisma";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
type CatalogPageRow = {
|
|
id: number;
|
|
caption: string;
|
|
parentId: number;
|
|
pageLayout: string;
|
|
minRank: number;
|
|
visible: string;
|
|
enabled: string;
|
|
clubOnly: string;
|
|
vipOnly: string;
|
|
};
|
|
|
|
type CatalogItemRow = {
|
|
id: number;
|
|
catalogName: string;
|
|
itemIds: string;
|
|
amount: number;
|
|
costCredits: number;
|
|
costPoints: number;
|
|
pointsType: number;
|
|
limitedStack: number;
|
|
limitedSells: number;
|
|
orderNumber: number;
|
|
clubOnly: string;
|
|
};
|
|
|
|
export default async function AdminCatalogPage({
|
|
params,
|
|
}: {
|
|
params: Promise<{ id: string }>;
|
|
}) {
|
|
const t = await getTranslations("pages.admin.catalog");
|
|
|
|
const { id } = await params;
|
|
const pageId = Number(id);
|
|
if (!Number.isInteger(pageId)) notFound();
|
|
|
|
let page: CatalogPageRow | null = null;
|
|
try {
|
|
page = await prisma.catalogPages.findUnique({
|
|
where: { id: pageId },
|
|
select: {
|
|
id: true,
|
|
caption: true,
|
|
parentId: true,
|
|
pageLayout: true,
|
|
minRank: true,
|
|
visible: true,
|
|
enabled: true,
|
|
clubOnly: true,
|
|
vipOnly: true,
|
|
},
|
|
});
|
|
} catch {
|
|
page = null;
|
|
}
|
|
if (!page) notFound();
|
|
|
|
let items: CatalogItemRow[] = [];
|
|
try {
|
|
items = await prisma.catalogItems.findMany({
|
|
where: { pageId },
|
|
select: {
|
|
id: true,
|
|
catalogName: true,
|
|
itemIds: true,
|
|
amount: true,
|
|
costCredits: true,
|
|
costPoints: true,
|
|
pointsType: true,
|
|
limitedStack: true,
|
|
limitedSells: true,
|
|
orderNumber: true,
|
|
clubOnly: true,
|
|
},
|
|
orderBy: [{ orderNumber: "asc" }, { id: "asc" }],
|
|
take: 500,
|
|
});
|
|
} catch {
|
|
items = [];
|
|
}
|
|
|
|
const hidden = page.visible !== "1" || page.enabled !== "1";
|
|
|
|
return (
|
|
<main>
|
|
<p className="muted">
|
|
<Link href="/admin/catalog">← {t("title")}</Link>
|
|
</p>
|
|
<h1>{page.caption}</h1>
|
|
<p className="muted">
|
|
{t("pageLabel", { id: page.id })} · {t("layoutLabel", { layout: page.pageLayout })} · {t("minRankLabel", { rank: page.minRank })} ·{" "}
|
|
{hidden ? t("statusHidden") : t("statusVisible")}
|
|
{page.parentId > 0 ? ` · ${t("parentLabel", { id: page.parentId })}` : ""}
|
|
{page.clubOnly === "1" ? ` · ${t("hcOnly")}` : ""}
|
|
{page.vipOnly === "1" ? ` · ${t("vipOnly")}` : ""}
|
|
</p>
|
|
|
|
<h2 style={{ marginTop: "1.5rem" }}>{t("items")}</h2>
|
|
{items.length === 0 ? (
|
|
<p className="muted">{t("noItems")}</p>
|
|
) : (
|
|
<table style={{ width: "100%", borderCollapse: "collapse" }}>
|
|
<thead>
|
|
<tr style={{ textAlign: "left", color: "var(--muted)" }}>
|
|
<th>{t("colId")}</th>
|
|
<th>{t("catalogName")}</th>
|
|
<th>{t("itemIds")}</th>
|
|
<th>{t("amount")}</th>
|
|
<th>{t("colCostCredits")}</th>
|
|
<th>{t("colCostPoints")}</th>
|
|
<th>{t("colLimited")}</th>
|
|
<th>{t("colOrder")}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{items.map((it) => (
|
|
<tr key={it.id} style={{ borderTop: "1px solid var(--border-subtle)" }}>
|
|
<td>{it.id}</td>
|
|
<td>
|
|
{it.catalogName}
|
|
{it.clubOnly === "1" ? (
|
|
<span className="muted"> · {t("hc")}</span>
|
|
) : null}
|
|
</td>
|
|
<td className="muted">{it.itemIds}</td>
|
|
<td>{it.amount}</td>
|
|
<td>
|
|
{it.costCredits > 0 ? (
|
|
<span className="currency">{it.costCredits}</span>
|
|
) : (
|
|
<span className="muted">—</span>
|
|
)}
|
|
</td>
|
|
<td className="muted">
|
|
{it.costPoints > 0
|
|
? `${it.costPoints} (${t("typeLabel", { type: it.pointsType })})`
|
|
: "—"}
|
|
</td>
|
|
<td className="muted">
|
|
{it.limitedStack > 0
|
|
? `${it.limitedSells}/${it.limitedStack}`
|
|
: "—"}
|
|
</td>
|
|
<td>{it.orderNumber}</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
|
|
<p className="muted" style={{ marginTop: "1rem" }}>
|
|
{t("itemCount", { count: items.length })}
|
|
</p>
|
|
</main>
|
|
);
|
|
}
|