feat(admin): items_base browser and AdminPageShell on core pages
Co-authored-by: Cursor <[email protected]>
This commit is contained in:
1 parent
7138ae4445
commit
98613af875
42 files changed
+2196
-698
No files matched your search
@@ -0,0 +1,115 @@
|
||||
"use server";
|
||||
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { z } from "zod";
|
||||
import { Prisma } from "@/generated/prisma/client";
|
||||
import { PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { adminAction } from "@/lib/safe-action";
|
||||
import { ActionError, actionOk } from "@/lib/safe-action-shared";
|
||||
import { rcon } from "@/lib/services/rcon";
|
||||
import { logStaffActivity } from "@/lib/services/staff-activity";
|
||||
|
||||
const ITEMS_BASE_FIELDS = [
|
||||
"publicName",
|
||||
"itemName",
|
||||
"type",
|
||||
"spriteId",
|
||||
"width",
|
||||
"length",
|
||||
"stackHeight",
|
||||
"allowStack",
|
||||
"allowSit",
|
||||
"allowLay",
|
||||
"allowWalk",
|
||||
"allowGift",
|
||||
"allowTrade",
|
||||
"allowRecycle",
|
||||
"allowMarketplaceSell",
|
||||
"allowInventoryStack",
|
||||
"interactionType",
|
||||
"interactionModesCount",
|
||||
"vendingIds",
|
||||
"multiheight",
|
||||
"customparams",
|
||||
"effectIdMale",
|
||||
"effectIdFemale",
|
||||
"clothingOnWalk",
|
||||
] as const;
|
||||
|
||||
const updateSchema = z.object({
|
||||
id: z.coerce.number().int().positive(),
|
||||
fields: z.record(z.string(), z.unknown()),
|
||||
});
|
||||
|
||||
function pickAllowed(
|
||||
fields: Record<string, unknown>,
|
||||
allowed: readonly string[],
|
||||
): Record<string, unknown> {
|
||||
const out: Record<string, unknown> = {};
|
||||
for (const key of allowed) {
|
||||
if (Object.hasOwn(fields, key) && fields[key] !== undefined) {
|
||||
out[key] = fields[key];
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
export const updateItemsBase = adminAction(
|
||||
{ permission: PERMS.CATALOG_EDIT, schema: updateSchema },
|
||||
async (ctx) => {
|
||||
const { id, fields } = ctx.data;
|
||||
const safe = pickAllowed(fields, ITEMS_BASE_FIELDS);
|
||||
if (Object.keys(safe).length === 0) {
|
||||
throw new ActionError("No valid fields to update");
|
||||
}
|
||||
|
||||
const existing = await prisma.itemsBase.findUnique({
|
||||
where: { id },
|
||||
select: { id: true },
|
||||
});
|
||||
if (!existing) throw new ActionError("Item not found");
|
||||
|
||||
// Coerce common numeric / decimal fields from form strings.
|
||||
const data: Record<string, unknown> = { ...safe };
|
||||
for (const key of [
|
||||
"spriteId",
|
||||
"width",
|
||||
"length",
|
||||
"allowStack",
|
||||
"allowSit",
|
||||
"allowLay",
|
||||
"allowWalk",
|
||||
"allowGift",
|
||||
"allowTrade",
|
||||
"allowRecycle",
|
||||
"allowMarketplaceSell",
|
||||
"allowInventoryStack",
|
||||
"interactionModesCount",
|
||||
"effectIdMale",
|
||||
"effectIdFemale",
|
||||
]) {
|
||||
if (data[key] !== undefined) data[key] = Number(data[key]);
|
||||
}
|
||||
if (data.stackHeight !== undefined) {
|
||||
data.stackHeight = new Prisma.Decimal(String(data.stackHeight));
|
||||
}
|
||||
|
||||
await prisma.itemsBase.update({
|
||||
where: { id },
|
||||
data: data as Prisma.ItemsBaseUpdateInput,
|
||||
});
|
||||
await rcon.updateCatalog().catch(() => false);
|
||||
await logStaffActivity({
|
||||
staffId: Number(ctx.session.user.id),
|
||||
action: "items_base_update",
|
||||
description: `Updated items_base #${id}`,
|
||||
targetType: "items_base",
|
||||
targetId: id,
|
||||
});
|
||||
revalidatePath("/admin/items");
|
||||
revalidatePath(`/admin/items/${id}`);
|
||||
revalidatePath("/admin/catalog");
|
||||
return actionOk({ id });
|
||||
},
|
||||
);
|
||||
Reference in new issue
Block a user