import { useState } from "react"; import { Plus, Pencil, Trash2, X, Tag, ChevronLeft } from "lucide-react"; import { useCatalogCategories, useAttributes, useAttributeValues, useAttributeMutations, useAttributeValueMutations, type AttributeRow, type AttributeValueRow, } from "~/requestHandler/use-admin-hooks"; import { AdminTable, AdminPagination, AdminToolbar, AdminSearch, AdminPageTitle, StatusBadge, faNum, useDebouncedValue, type Column, } from "~/components/admin/DataTable"; const PAGE_SIZE = 25; export default function AdminCatalog() { const [selected, setSelected] = useState(null); return (
ویژگی‌های کاتالوگ {selected ? ( setSelected(null)} /> ) : ( )}
); } /* ------------------------------ attributes ------------------------------ */ function AttributesPanel({ onSelect }: { onSelect: (a: AttributeRow) => void }) { const [page, setPage] = useState(1); const [search, setSearch] = useState(""); const [editing, setEditing] = useState(null); const [creating, setCreating] = useState(false); const debouncedSearch = useDebouncedValue(search); const { data, isLoading } = useAttributes({ page, page_size: PAGE_SIZE, search: debouncedSearch }); const { remove } = useAttributeMutations(); const columns: Column[] = [ { header: "نام", render: (r) => {r.name} }, { header: "دسته‌ها", render: (r) => (
{r.categoryNames.length ? ( r.categoryNames.map((c) => ) ) : ( )}
), }, { header: "مقادیر", render: (r) => ( ), }, { header: "", render: (r) => (
), }, ]; return (
{ setSearch(v); setPage(1); }} placeholder="جستجوی نام ویژگی…" /> r.id} emptyText="ویژگی‌ای ثبت نشده است" /> {(creating || editing) && { setCreating(false); setEditing(null); }} />}
); } function AttributeModal({ row, onClose }: { row: AttributeRow | null; onClose: () => void }) { const [name, setName] = useState(row?.name ?? ""); const [cats, setCats] = useState(row?.categories ?? []); const [error, setError] = useState(""); const { data: categories } = useCatalogCategories(); const { create, update } = useAttributeMutations(); const busy = create.isPending || update.isPending; const toggleCat = (id: string) => setCats((prev) => (prev.includes(id) ? prev.filter((c) => c !== id) : [...prev, id])); const submit = () => { setError(""); if (!name.trim()) return setError("نام الزامی است."); const payload = { name: name.trim(), categories: cats }; const onErr = (e: unknown) => setError(e instanceof Error ? e.message : "خطا در ذخیره"); if (row) update.mutate({ id: row.id, data: payload }, { onSuccess: onClose, onError: onErr }); else create.mutate(payload, { onSuccess: onClose, onError: onErr }); }; return (
e.stopPropagation()}>

{row ? "ویرایش ویژگی" : "ویژگی جدید"}

setName(e.target.value)} />
{(categories || []).map((c) => ( ))} {!categories?.length &&

دسته‌ای موجود نیست.

}
{error &&

{error}

}
); } /* --------------------------- attribute values --------------------------- */ function ValuesPanel({ attribute, onBack }: { attribute: AttributeRow; onBack: () => void }) { const [page, setPage] = useState(1); const { data, isLoading } = useAttributeValues({ page, page_size: PAGE_SIZE, attribute: attribute.id }); const { create, update, remove } = useAttributeValueMutations(); const [newValue, setNewValue] = useState(""); const [editingId, setEditingId] = useState(null); const [editingText, setEditingText] = useState(""); const add = () => { if (!newValue.trim()) return; create.mutate({ attribute: attribute.id, value: newValue.trim() }, { onSuccess: () => setNewValue("") }); }; const saveEdit = (id: string) => { update.mutate({ id, data: { value: editingText.trim() } }, { onSuccess: () => setEditingId(null) }); }; const columns: Column[] = [ { header: "مقدار", render: (r) => editingId === r.id ? ( setEditingText(e.target.value)} onKeyDown={(e) => e.key === "Enter" && saveEdit(r.id)} className="rounded-lg border border-GRAY px-2 py-1 text-[13px]" /> ) : ( {r.value} ), }, { header: "", render: (r) => (
{editingId === r.id ? ( ) : ( )}
), }, ]; return (

مقادیر «{attribute.name}»

setNewValue(e.target.value)} onKeyDown={(e) => e.key === "Enter" && add()} placeholder="مقدار جدید (مثلاً قرمز)…" className="flex-1 rounded-xl border border-WHITE3 bg-WHITE px-3 py-2 text-[13.5px] focus:outline-none focus:border-GRAY" />
r.id} emptyText="مقداری ثبت نشده است" />
); }