fix(catalog): route item-table writes to the catalog they belong to
Gitea Actions Runner Test / test-job (push) Successful in 0s
CI / check (push) Successful in 32s
CI / tests-integration (push) Successful in 1m43s
CI / tests-unit (push) Successful in 1m48s
CI / tests-ui (push) Successful in 2m37s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m16s

The items table is shared between both catalogs, but its four mutating
actions were normal-only: moving, reordering, creating and updating a
Builder Club offer wrote to catalog_items, so a BC edit either landed in
the wrong catalog or hit an unknown column.

Pass the catalog from the table through the actions and let the server
resolve it. BC rows have no price, points or currency column, so the BC
commands strip those fields instead of rejecting them. Moving and
reordering now share one command that locks the category and writes the
table for the same catalog, and BC writes revalidate the BC route.
This commit is contained in:
openhands committed 2026-09-30 20:06:48 +02:00
1 parent e0efbef30d
commit cede541813
3 files changed
+155 -50

No files matched your search

@@ -471,6 +471,7 @@ export function CatalogItemsTable({
() =>
updateCatalogItem({
id: item.id,
catalog,
catalogFields: {
catalogName: item.catalogName,
itemIds: item.itemIds,
@@ -514,6 +515,7 @@ export function CatalogItemsTable({
const result = await updateCatalogItem({
id: item.id,
catalog,
catalogFields: {
catalogName: item.catalogName,
itemIds: item.itemIds,
@@ -600,6 +602,7 @@ export function CatalogItemsTable({
moveCatalogItems({
ids: [...selected],
targetPageId: moveTargetPageId,
catalog,
}),
{
successMessage: `Moved ${selected.size} item(s) to page #${moveTargetPageId}.`,
@@ -666,7 +669,7 @@ export function CatalogItemsTable({
async function handleSaveOrder() {
const orders = itemOrder.map((id, idx) => ({ id, orderNumber: idx + 1 }));
run(() => reorderCatalogItems({ orders }), {
run(() => reorderCatalogItems({ orders, catalog }), {
successMessage: "Item order saved.",
errorMessage: "Failed to save order.",
onSuccess: () => onRefresh(),
@@ -697,12 +700,15 @@ export function CatalogItemsTable({
async function handleAddItem() {
run(
() =>
createCatalogItem({
...newItem,
pageId,
haveOffer: newItem.haveOffer as "0" | "1",
clubOnly: newItem.clubOnly as "0" | "1",
}),
createCatalogItem(
{
...newItem,
pageId,
haveOffer: newItem.haveOffer as "0" | "1",
clubOnly: newItem.clubOnly as "0" | "1",
},
catalog,
),
{
successMessage: "Item added.",
errorMessage: "Failed to add item",
@@ -723,7 +729,12 @@ export function CatalogItemsTable({
});
if (!ok) return;
run(
() => deleteCatalogItems({ ids: [id], requestKey: crypto.randomUUID() }),
() =>
deleteCatalogItems({
ids: [id],
requestKey: crypto.randomUUID(),
catalog,
}),
{
successMessage: "Item deleted.",
errorMessage: "Failed to delete item.",
@@ -760,7 +771,12 @@ export function CatalogItemsTable({
});
}
run(
() => moveCatalogItems({ ids: [moveOneId], targetPageId: moveOneTarget }),
() =>
moveCatalogItems({
ids: [moveOneId],
targetPageId: moveOneTarget,
catalog,
}),
{
successMessage: `Item #${moveOneId} moved to page #${moveOneTarget}.`,
errorMessage: "Failed to move item.",
@@ -776,23 +792,26 @@ export function CatalogItemsTable({
async function handleDuplicateItem(item: CatalogItemData) {
run(
() =>
createCatalogItem({
pageId,
itemIds: item.itemIds,
catalogName: item.catalogName,
costCredits: item.costCredits,
costPoints: item.costPoints,
pointsType: item.pointsType,
amount: item.amount,
limitedSells: 0,
limitedStack: item.limitedStack,
orderNumber: item.orderNumber + 1,
offerId: item.offerId,
songId: item.songId,
haveOffer: item.haveOffer as "0" | "1",
clubOnly: item.clubOnly as "0" | "1",
extradata: item.extradata,
}),
createCatalogItem(
{
pageId,
itemIds: item.itemIds,
catalogName: item.catalogName,
costCredits: item.costCredits,
costPoints: item.costPoints,
pointsType: item.pointsType,
amount: item.amount,
limitedSells: 0,
limitedStack: item.limitedStack,
orderNumber: item.orderNumber + 1,
offerId: item.offerId,
songId: item.songId,
haveOffer: item.haveOffer as "0" | "1",
clubOnly: item.clubOnly as "0" | "1",
extradata: item.extradata,
},
catalog,
),
{
successMessage: `Item #${item.id} duplicated.`,
errorMessage: "Failed to duplicate item.",
@@ -807,6 +826,7 @@ export function CatalogItemsTable({
() =>
updateCatalogItem({
id: editingItem.id,
catalog,
catalogFields: {
catalogName: editingItem.catalogName,
itemIds: editingItem.itemIds,
@@ -1338,7 +1358,12 @@ export function CatalogItemsTable({
)
}
className="h-8 text-xs w-16"
title="Credits"
disabled={catalog === "bc"}
title={
catalog === "bc"
? "A Builder Club offer has no price of its own"
: "Credits"
}
/>
<span className="text-xs text-[var(--admin-warning)]">
c
@@ -1356,7 +1381,12 @@ export function CatalogItemsTable({
)
}
className="h-8 text-xs w-16"
title="Points"
disabled={catalog === "bc"}
title={
catalog === "bc"
? "A Builder Club offer has no price of its own"
: "Points"
}
/>
<span className={`text-xs ${pts.color}`}>
{pts.label.charAt(0)}