import React, { useMemo, useState } from 'react'; import { PlusIcon, MagnifyingGlassIcon, ArchiveBoxIcon } from '@heroicons/react/24/outline'; import ConfirmDialog from '../components/ui/ConfirmDialog'; import SearchableSelect from '../components/ui/SearchableSelect'; import { useInventory } from '../hooks/useInventory'; import type { InventoryItem, InventoryPackage, ItemPayload, PackagePayload } from '../hooks/useInventory'; import InventoryStatCards from '../components/inventory/InventoryStatCards'; import InventoryItemsTable from '../components/inventory/InventoryItemsTable'; import PackagesView from '../components/inventory/PackagesView'; import AddItemModal from '../components/inventory/AddItemModal'; import AddPackageModal from '../components/inventory/AddPackageModal'; type Tab = 'stock' | 'packages'; /** انبارداری — consumable stock items + packages. Ported from clinic-pro-tauri /inventory. */ export default function InventoryPage() { const { items, stats, packages, categories, meta, itemsLoading, packagesLoading, createItem, updateItem, deleteItem, createPackage, updatePackage, deletePackage, } = useInventory(); const [tab, setTab] = useState('stock'); const [search, setSearch] = useState(''); const [category, setCategory] = useState(''); const [itemModal, setItemModal] = useState<{ open: boolean; editing: InventoryItem | null }>({ open: false, editing: null }); const [pkgModal, setPkgModal] = useState<{ open: boolean; editing: InventoryPackage | null }>({ open: false, editing: null }); const [itemToDelete, setItemToDelete] = useState(null); const [pkgToDelete, setPkgToDelete] = useState(null); const filteredItems = useMemo(() => { const q = search.trim(); return items.filter((it) => (q === '' || it.name.includes(q)) && (category === '' || it.category === category) ); }, [items, search, category]); const saveItem = (payload: ItemPayload, uuid?: string) => { const opts = { onSuccess: () => setItemModal({ open: false, editing: null }) }; if (uuid) updateItem.mutate({ uuid, d: payload }, opts); else createItem.mutate(payload, opts); }; const savePackage = (payload: PackagePayload, uuid?: string) => { const opts = { onSuccess: () => setPkgModal({ open: false, editing: null }) }; if (uuid) updatePackage.mutate({ uuid, d: payload }, opts); else createPackage.mutate(payload, opts); }; return (
{/* Header */}

انبارداری

{tab === 'stock' ? (
setSearch(e.target.value)} placeholder="جستجو در کالاهای مصرفی..." style={{ border: 'none', background: 'transparent', flex: 1, padding: 0 }} />
({ value: c, label: c }))} value={category || null} onChange={(v) => setCategory(v ? String(v) : '')} placeholder="دسته‌بندی کالا را انتخاب کنید..." isClearable height={38} />
) : (
)}
{/* Body */} {tab === 'stock' ? ( <> {itemsLoading ? (
در حال بارگذاری...
) : filteredItems.length === 0 ? ( ) : ( setItemModal({ open: true, editing: item })} onDelete={setItemToDelete} /> )} ) : packagesLoading ? (
در حال بارگذاری...
) : packages.length === 0 ? ( ) : ( setPkgModal({ open: true, editing: pkg })} onDelete={setPkgToDelete} /> )} {/* Modals */} setItemModal({ open: false, editing: null })} onSave={saveItem} /> setPkgModal({ open: false, editing: null })} onSave={savePackage} /> itemToDelete && deleteItem.mutate(itemToDelete.uuid, { onSuccess: () => setItemToDelete(null) })} onCancel={() => setItemToDelete(null)} /> pkgToDelete && deletePackage.mutate(pkgToDelete.uuid, { onSuccess: () => setPkgToDelete(null) })} onCancel={() => setPkgToDelete(null)} />
); } function EmptyState({ label }: { label: string }) { return (
{label}
); }