Harden catalog admin: fix translate/quick-add, RCON sync, and confirm UX.
Local Build and Deploy / deploy (push) Successful in 1m18s

Restore broken Quick Add search, correct Translate saves to items_base and FurnitureData, reparent page deletes, sync RCON on create/toggle/BC mutations, and replace native confirms/prompts with dialogs.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
SimoandCursor committed 2026-07-17 21:12:58 +02:00
1 parent de9f837da1
commit b52e25578d
20 files changed
+557 -216

No files matched your search

+16 -32
View File
@@ -5,6 +5,7 @@ import { requirePermission } from "@/lib/admin/guard";
import { PERMS } from "@/lib/permissions";
import { prisma } from "@/lib/prisma";
import type { ActionResult } from "@/lib/safe-action-shared";
import { deletePage, movePage } from "@/lib/services/catalog-tree";
import { rcon } from "@/lib/services/rcon";
import { logStaffActivity } from "@/lib/services/staff-activity";
@@ -28,7 +29,7 @@ export async function updateCatalogPage({
export async function deleteCatalogPage({ id }: { id: number }) {
const staff = await requirePermission(PERMS.CATALOG_EDIT);
await prisma.catalogPages.delete({ where: { id } });
await deletePage(id, "reparent");
await rcon.updateCatalog();
await logStaffActivity({
staffId: staff.id,
@@ -60,6 +61,7 @@ export async function toggleCatalogPage({
where: { id },
data: { [field]: current === "1" ? "0" : "1" },
});
await rcon.updateCatalog();
revalidatePath("/admin/catalog");
return { ok: true as const, data: {} };
}
@@ -95,6 +97,7 @@ export async function createCatalogPage(input: {
includes: "",
},
});
await rcon.updateCatalog();
await logStaffActivity({
staffId: staff.id,
action: "catalog_page_create",
@@ -112,14 +115,19 @@ export async function reorderTreePage(input: {
newOrderNum: number;
}) {
await requirePermission(PERMS.CATALOG_EDIT);
if (input.newParentId !== undefined) {
try {
await movePage(input.pageId, input.newParentId);
} catch (err) {
return {
ok: false as const,
error: err instanceof Error ? err.message : "Invalid move",
};
}
}
await prisma.catalogPages.update({
where: { id: input.pageId },
data: {
orderNum: input.newOrderNum,
...(input.newParentId === undefined
? {}
: { parentId: input.newParentId }),
},
data: { orderNum: input.newOrderNum },
});
await rcon.updateCatalog();
revalidatePath("/admin/catalog");
@@ -131,31 +139,7 @@ export async function deleteTreePage(input: {
mode: "reparent" | "cascade";
}) {
await requirePermission(PERMS.CATALOG_EDIT);
if (input.mode === "cascade") {
const children = await prisma.catalogPages.findMany({
where: { parentId: input.pageId },
select: { id: true },
});
const pageIds = [input.pageId, ...children.map((child) => child.id)];
await prisma.$transaction([
prisma.catalogItems.deleteMany({ where: { pageId: { in: pageIds } } }),
prisma.catalogPages.deleteMany({ where: { id: { in: pageIds } } }),
]);
} else {
const page = await prisma.catalogPages.findUnique({
where: { id: input.pageId },
select: { parentId: true },
});
if (!page) return { ok: false as const, error: "Catalog page not found" };
await prisma.$transaction([
prisma.catalogPages.updateMany({
where: { parentId: input.pageId },
data: { parentId: page.parentId },
}),
prisma.catalogItems.deleteMany({ where: { pageId: input.pageId } }),
prisma.catalogPages.delete({ where: { id: input.pageId } }),
]);
}
await deletePage(input.pageId, input.mode);
await rcon.updateCatalog();
revalidatePath("/admin/catalog");
return { ok: true as const, data: {} };