"use client";
import {
AlertTriangle,
ChevronDown,
ChevronRight,
FolderTree,
Loader2,
RefreshCw,
Search,
X,
} from "lucide-react";
import { memo, useMemo, useState, useTransition } from "react";
import {
refreshCatalogTree,
useLiveCatalog,
} from "@/features/catalog/client/use-live-catalog";
import { cn } from "@/lib/utils";
import type { TreeNode } from "@/types/catalog";
/**
* A refresh that fails must be visible. Every number and category below is
* presented as current, so silently keeping the previous tree after a failed
* read would show pre-import data as if nothing had happened — and a staff
* member has no other signal that the import they just ran is not on screen.
*/
function LiveCatalogNotice() {
const { refreshError, refreshing } = useLiveCatalog();
const [retrying, startRetry] = useTransition();
if (!refreshError && !refreshing) return null;
return (
{refreshError ? (
<>
Catalog could not refresh.
>
) : (
<>
Updating catalog…
>
)}
);
}
export const CatalogRail = memo(function CatalogRail({
tree,
selectedId,
onSelect,
onClose,
}: {
tree: TreeNode[];
selectedId: number | null;
onSelect: (id: number | null) => void;
onClose?: () => void;
}) {
const [collapsed, setCollapsed] = useState>(new Set());
const [search, setSearch] = useState("");
const visible = useMemo(() => {
if (search.trim())
return tree.filter((node) =>
node.caption.toLowerCase().includes(search.trim().toLowerCase()),
);
const hidden = new Set();
for (const node of tree)
if (hidden.has(node.parentId) || collapsed.has(node.parentId))
hidden.add(node.id);
return tree.filter((node) => !hidden.has(node.id));
}, [tree, collapsed, search]);
function toggle(id: number) {
setCollapsed((previous) => {
const next = new Set(previous);
if (next.has(id)) next.delete(id);
else next.add(id);
return next;
});
}
return (
);
});