diff --git a/frontend/app/inventory/page.tsx b/frontend/app/inventory/page.tsx index c38a3eed..e055c5de 100644 --- a/frontend/app/inventory/page.tsx +++ b/frontend/app/inventory/page.tsx @@ -6,6 +6,7 @@ import { inventoryApi } from '@/lib/api'; import PageShell from '@/components/PageShell'; import Scanner from '@/components/Scanner'; import StatCard from '@/components/StatCard'; +import { useInventoryFilter } from '@/hooks/useInventoryFilter'; import { toast } from 'react-hot-toast'; import { Package, @@ -39,9 +40,20 @@ export default function InventoryPage() { const [mounted, setMounted] = useState(false); const [inventory, setInventory] = useState([]); const [stats, setStats] = useState(null); - const [expandedCategory, setExpandedCategory] = useState(null); - const [searchQuery, setSearchQuery] = useState(''); const [currentUser, setCurrentUser] = useState(null); + + const { + searchQuery, + setSearchQuery, + expandedCategory, + setExpandedCategory, + boxSearchQuery, + setBoxSearchQuery, + categories, + filteredCategories, + getFilteredItems, + getFilteredBoxes + } = useInventoryFilter(inventory); // Stock Adjustment State const [selectedItem, setSelectedItem] = useState(null); @@ -66,7 +78,6 @@ export default function InventoryPage() { // Box Manager State const [showBoxManager, setShowBoxManager] = useState(false); const [selectedBoxLabel, setSelectedBoxLabel] = useState(null); - const [boxSearchQuery, setBoxSearchQuery] = useState(''); useEffect(() => { setMounted(true); @@ -225,13 +236,6 @@ export default function InventoryPage() { } }, [inventory]); - // Group items by category - const categories = Array.from(new Set(inventory.map(i => i.category))); - const filteredCategories = categories.filter(c => - c.toLowerCase().includes(searchQuery.toLowerCase()) || - inventory.some(i => i.category === c && i.name.toLowerCase().includes(searchQuery.toLowerCase())) - ); - // Extract unique item types and box labels for suggestions const existingTypes = Array.from(new Set(inventory.map(i => i.type).filter(Boolean))).sort() as string[]; const existingBoxes = Array.from(new Set(inventory.map(i => i.box_label).filter(Boolean))).sort() as string[]; @@ -340,10 +344,7 @@ export default function InventoryPage() { {expandedCategory === cat && (
- {inventory - .filter(i => i.category === cat) - .filter(i => i.name.toLowerCase().includes(searchQuery.toLowerCase())) - .map(item => ( + {getFilteredItems(cat).map(item => (
setSelectedItem(item)} @@ -717,7 +718,7 @@ export default function InventoryPage() {
- {existingBoxes.filter(b => b.toLowerCase().includes(boxSearchQuery.toLowerCase())).length === 0 ? ( + {getFilteredBoxes(existingBoxes).length === 0 ? (

{existingBoxes.length === 0 ? 'No box labels defined yet.' : 'No matching boxes found.'}

@@ -725,9 +726,7 @@ export default function InventoryPage() {
) : (
- {existingBoxes - .filter(box => box.toLowerCase().includes(boxSearchQuery.toLowerCase())) - .map(box => { + {getFilteredBoxes(existingBoxes).map(box => { const itemCount = inventory.filter(i => i.box_label === box).length; return (
diff --git a/frontend/hooks/useInventoryFilter.ts b/frontend/hooks/useInventoryFilter.ts new file mode 100644 index 00000000..b5e5f9d8 --- /dev/null +++ b/frontend/hooks/useInventoryFilter.ts @@ -0,0 +1,46 @@ +import { useState, useMemo } from 'react'; +import { Item } from '@/lib/db'; + +export function useInventoryFilter(inventory: Item[]) { + const [searchQuery, setSearchQuery] = useState(''); + const [expandedCategory, setExpandedCategory] = useState(null); + const [boxSearchQuery, setBoxSearchQuery] = useState(''); + + // Get unique categories from inventory + const categories = useMemo( + () => Array.from(new Set(inventory.map(i => i.category))), + [inventory] + ); + + // Filter categories based on search query + const filteredCategories = useMemo( + () => categories.filter(c => + c.toLowerCase().includes(searchQuery.toLowerCase()) || + inventory.some(i => i.category === c && i.name.toLowerCase().includes(searchQuery.toLowerCase())) + ), + [categories, inventory, searchQuery] + ); + + // Get filtered items within a specific category + const getFilteredItems = (category: string) => + inventory + .filter(i => i.category === category) + .filter(i => i.name.toLowerCase().includes(searchQuery.toLowerCase())); + + // Get filtered boxes based on search + const getFilteredBoxes = (boxes: string[]) => + boxes.filter(b => b.toLowerCase().includes(boxSearchQuery.toLowerCase())); + + return { + searchQuery, + setSearchQuery, + expandedCategory, + setExpandedCategory, + boxSearchQuery, + setBoxSearchQuery, + categories, + filteredCategories, + getFilteredItems, + getFilteredBoxes + }; +}