diff --git a/frontend/app/inventory/page.tsx b/frontend/app/inventory/page.tsx index e055c5de..98333ac0 100644 --- a/frontend/app/inventory/page.tsx +++ b/frontend/app/inventory/page.tsx @@ -6,12 +6,11 @@ import { inventoryApi } from '@/lib/api'; import PageShell from '@/components/PageShell'; import Scanner from '@/components/Scanner'; import StatCard from '@/components/StatCard'; +import InventoryTable from '@/components/InventoryTable'; import { useInventoryFilter } from '@/hooks/useInventoryFilter'; import { toast } from 'react-hot-toast'; import { Package, - ChevronRight, - ChevronDown, BarChart3, Layers, Plus, @@ -303,85 +302,23 @@ export default function InventoryPage() { - {/* Categorized List (Accordion) */} - - {filteredCategories.map(cat => ( - - setExpandedCategory(expandedCategory === cat ? null : cat)} - > - - - - - - {cat} - - {inventory.filter(i => i.category === cat).length} Item types in stock - - - - - {expandedCategory === cat ? : } - { - e.stopPropagation(); - const categoryObj = categoriesList.find(c => c.name === cat); - if (categoryObj) { - setEditingCategory(categoryObj); - setCatEditedName(categoryObj.name); - setCatEditedDesc(categoryObj.description || ''); - } - }} - className="p-2 hover:bg-slate-800 rounded-full text-muted hover:text-primary transition-colors relative z-10" - > - - - - - - {expandedCategory === cat && ( - - - {getFilteredItems(cat).map(item => ( - setSelectedItem(item)} - className="bg-background/40 border border-slate-800/50 p-4 rounded-2xl flex items-center justify-between hover:border-primary/40 cursor-pointer transition-all active:scale-[0.98]" - > - - - - - - {item.name} - {item.specs} - - - - - {item.quantity} - - Stock - - - ))} - - )} - - ))} - - {filteredCategories.length === 0 && ( - - - No results found - - )} - + {/* Inventory Table */} + { + const categoryObj = categoriesList.find(c => c.name === cat); + if (categoryObj) { + setEditingCategory(categoryObj); + setCatEditedName(categoryObj.name); + setCatEditedDesc(categoryObj.description || ''); + } + }} + categoriesList={categoriesList} + /> {/* Stock Adjustment / Edit Item Overlay */} diff --git a/frontend/components/InventoryTable.tsx b/frontend/components/InventoryTable.tsx new file mode 100644 index 00000000..e16ce9eb --- /dev/null +++ b/frontend/components/InventoryTable.tsx @@ -0,0 +1,133 @@ +'use client'; + +import { useState } from 'react'; +import { Item } from '@/lib/db'; +import { ChevronRight, ChevronDown, Layers, Package } from 'lucide-react'; +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + +interface InventoryTableProps { + items: Item[]; + categories: string[]; + expandedCategory: string | null; + onExpandCategory: (category: string | null) => void; + onItemClick: (item: Item) => void; + onEditCategory?: (category: string) => void; + categoriesList?: any[]; +} + +export default function InventoryTable({ + items, + categories, + expandedCategory, + onExpandCategory, + onItemClick, + onEditCategory, + categoriesList = [] +}: InventoryTableProps) { + if (categories.length === 0) { + return ( + + + No results found + + ); + } + + return ( + + {categories.map(cat => { + const categoryItems = items.filter(i => i.category === cat); + return ( + + onExpandCategory(expandedCategory === cat ? null : cat)} + > + + + + + + {cat} + + {categoryItems.length} Item types in stock + + + + + {expandedCategory === cat ? : } + {onEditCategory && ( + { + e.stopPropagation(); + onEditCategory(cat); + }} + className="p-2 hover:bg-slate-800 rounded-full text-muted hover:text-primary transition-colors relative z-10" + > + + + )} + + + + {expandedCategory === cat && ( + + + {categoryItems.map(item => ( + onItemClick(item)} + className="bg-background/40 border border-slate-800/50 p-4 rounded-2xl flex items-center justify-between hover:border-primary/40 cursor-pointer transition-all active:scale-[0.98]" + > + + + + + + {item.name} + {item.specs} + + + + + {item.quantity} + + Stock + + + ))} + + )} + + ); + })} + + ); +} + +// EditIcon component (lucide-react equivalent) +function EditIcon({ size = 24 }: { size?: number }) { + return ( + + + + ); +}
- {inventory.filter(i => i.category === cat).length} Item types in stock -
{item.specs}
Stock
No results found
+ {categoryItems.length} Item types in stock +