refactor(catalog): unify commands and embed guarded catalog workspace
CI / check (push) Successful in 1m16s
CI / deploy (push) Successful in 28s

This commit is contained in:
Simo committed 2026-09-06 19:40:52 +02:00
1 parent 16f35568f5
commit 193b6686a9
57 files changed
+3268 -728

No files matched your search

@@ -22,12 +22,12 @@ import { useCallback, useState } from "react";
import { toast } from "sonner";
import {
deleteTreePage,
reorderTreePage,
reorderCatalogPages,
toggleCatalogPage,
} from "@/actions/catalog";
import {
deleteBcTreePage,
reorderBcTreePage,
reorderBcCatalogPages,
toggleBcPage,
} from "@/actions/catalog-bc";
import { CatalogIcon } from "@/components/admin/catalog-tree";
@@ -40,6 +40,7 @@ import {
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu";
import { requestCatalogNavigation } from "@/features/catalog/client/use-catalog-navigation";
import { cn } from "@/lib/utils";
import { useCatalogManager } from "./use-catalog-store";
@@ -54,6 +55,7 @@ interface RootTabsProps {
onEditTab: (id: number) => void | Promise<void>;
onCreateRoot: () => void;
loading?: boolean;
onMutation?: () => void;
}
export function RootTabs({
@@ -63,6 +65,7 @@ export function RootTabs({
onEditTab,
onCreateRoot,
loading,
onMutation,
}: RootTabsProps) {
const { catalogType, canEdit } = useCatalogManager();
const { confirm, dialog: confirmDialog } = useConfirmDialog();
@@ -85,26 +88,26 @@ export function RootTabs({
const newIndex = tabs.findIndex((t) => t.id === over.id);
if (oldIndex === -1 || newIndex === -1) return;
if (!canEdit) return;
if (!canEdit || !requestCatalogNavigation()) return;
const newOrder = arrayMove(tabs, oldIndex, newIndex);
// Batch reorder
try {
const reorder =
catalogType === "bc" ? reorderBcTreePage : reorderTreePage;
const results = await Promise.allSettled(
newOrder.map((tab, idx) =>
reorder({ pageId: tab.id, newOrderNum: idx + 1 }),
),
);
const failed = results.filter((r) => r.status === "rejected").length;
if (failed) toast.error(`${failed} reorder(s) failed`);
else toast.success("Tabs reordered");
catalogType === "bc" ? reorderBcCatalogPages : reorderCatalogPages;
const result = await reorder({
parentId: -1,
ids: newOrder.map((tab) => tab.id),
expectedIds: tabs.map((tab) => tab.id),
});
if (!result.ok) throw Error("Failed to reorder tabs");
toast.success("Tabs reordered");
onMutation?.();
} catch {
toast.error("Failed to reorder tabs");
}
},
[tabs, canEdit, catalogType],
[tabs, canEdit, catalogType, onMutation],
);
const handleToggle = async (tab: RootTab) => {
@@ -118,6 +121,7 @@ export function RootTabs({
toast.success(
`${tab.caption} ${tab.enabled === "1" ? "disabled" : "enabled"}`,
);
onMutation?.();
} catch {
toast.error("Failed to toggle");
}
@@ -138,6 +142,7 @@ export function RootTabs({
await deleteTreePage({ pageId: tab.id, mode: "reparent" });
}
toast.success(`"${tab.caption}" deleted`);
onMutation?.();
} catch {
toast.error("Failed to delete");
}