From 0cf759d5408bf8e8d03360d8200151b8c7b20d15 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Sun, 23 Nov 2025 16:16:40 +1000 Subject: [PATCH 1/2] Adjust packaging filter when only one type --- src/screens/ActivePickListScreen.test.tsx | 6 ++++-- src/screens/ActivePickListScreen.tsx | 24 ++++++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/screens/ActivePickListScreen.test.tsx b/src/screens/ActivePickListScreen.test.tsx index df07382..156ebf6 100644 --- a/src/screens/ActivePickListScreen.test.tsx +++ b/src/screens/ActivePickListScreen.test.tsx @@ -355,8 +355,9 @@ describe('ActivePickListScreen product search', () => { , ); + expect(screen.getByRole('radio', { name: /all/i })).toBeChecked(); expect(screen.getByRole('radio', { name: /cartons/i })).toBeDisabled(); - expect(screen.getByRole('radio', { name: /units/i })).toBeEnabled(); + expect(screen.getByRole('radio', { name: /units/i })).toBeDisabled(); }); it('resets the filter when the selected packaging type is unavailable', async () => { @@ -418,7 +419,8 @@ describe('ActivePickListScreen product search', () => { ); await waitFor(() => expect(screen.getByRole('radio', { name: /cartons/i })).toBeDisabled()); - expect(screen.getByRole('radio', { name: /units/i })).toBeChecked(); + expect(screen.getByRole('radio', { name: /all/i })).toBeChecked(); + expect(screen.getByRole('radio', { name: /units/i })).toBeDisabled(); }); it('hides picked items when show picked is unchecked', async () => { diff --git a/src/screens/ActivePickListScreen.tsx b/src/screens/ActivePickListScreen.tsx index 048bbe2..53e7d2b 100644 --- a/src/screens/ActivePickListScreen.tsx +++ b/src/screens/ActivePickListScreen.tsx @@ -100,6 +100,8 @@ export const ActivePickListScreen = () => { const hasCartonItems = useMemo(() => items.some((item) => item.is_carton), [items]); const hasUnitItems = useMemo(() => items.some((item) => !item.is_carton), [items]); + const packagingTypeCount = Number(hasCartonItems) + Number(hasUnitItems); + const singlePackagingType = packagingTypeCount === 1; const filteredProducts = useMemo(() => { const normalizedQuery = query.trim().toLowerCase(); @@ -125,12 +127,20 @@ export const ActivePickListScreen = () => { }, [allItemsPicked, showPicked]); useEffect(() => { - if (itemFilter === 'cartons' && !hasCartonItems) { - setItemFilter(hasUnitItems ? 'units' : 'all'); - } else if (itemFilter === 'units' && !hasUnitItems) { - setItemFilter(hasCartonItems ? 'cartons' : 'all'); + if (packagingTypeCount <= 1) { + if (itemFilter !== 'all') { + setItemFilter('all'); + } + + return; } - }, [itemFilter, hasCartonItems, hasUnitItems]); + + if (itemFilter === 'cartons' && !hasCartonItems) { + setItemFilter('units'); + } else if (itemFilter === 'units' && !hasUnitItems) { + setItemFilter('cartons'); + } + }, [itemFilter, hasCartonItems, hasUnitItems, packagingTypeCount]); const visibleItems = useMemo(() => { let filteredItems = showPicked @@ -326,13 +336,13 @@ export const ActivePickListScreen = () => { value="cartons" control={} label="Cartons" - disabled={!hasCartonItems} + disabled={singlePackagingType || !hasCartonItems} /> } label="Units" - disabled={!hasUnitItems} + disabled={singlePackagingType || !hasUnitItems} /> From 62147659bb0cab1b96142b157453b34892274d16 Mon Sep 17 00:00:00 2001 From: beatz174-bit Date: Sun, 23 Nov 2025 16:17:14 +1000 Subject: [PATCH 2/2] Filter pick list product options by categories --- src/screens/ActivePickListScreen.test.tsx | 49 +++++++++++++++++++---- src/screens/ActivePickListScreen.tsx | 18 +++++++-- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/screens/ActivePickListScreen.test.tsx b/src/screens/ActivePickListScreen.test.tsx index df07382..a929fa7 100644 --- a/src/screens/ActivePickListScreen.test.tsx +++ b/src/screens/ActivePickListScreen.test.tsx @@ -10,6 +10,7 @@ const addMock = vi.fn(); const updateMock = vi.fn(); const pickItemsMock = vi.fn(); const productsMock = vi.fn(); +const pickListMock = vi.fn(); const defaultProducts: Product[] = [ { @@ -84,13 +85,7 @@ vi.mock('../hooks/dataHooks', () => ({ updated_at: 0, }, ], - usePickList: () => ({ - id: 'list-1', - area_id: 'area-1', - created_at: 0, - categories: [], - auto_add_new_products: false, - }), + usePickList: () => pickListMock(), useAreas: () => [{ id: 'area-1', name: 'Front Counter', created_at: 0, updated_at: 0 }], })); @@ -111,6 +106,14 @@ describe('ActivePickListScreen product search', () => { updateMock.mockReset(); pickItemsMock.mockReturnValue([]); productsMock.mockReturnValue(defaultProducts); + pickListMock.mockReset(); + pickListMock.mockReturnValue({ + id: 'list-1', + area_id: 'area-1', + created_at: 0, + categories: ['Drinks', 'Snacks'], + auto_add_new_products: false, + }); }); it('filters the product list based on the search query', async () => { @@ -240,6 +243,38 @@ describe('ActivePickListScreen product search', () => { ]); }); + it('limits product options to the pick list categories', async () => { + pickListMock.mockReturnValue({ + id: 'list-1', + area_id: 'area-1', + created_at: 0, + categories: ['Drinks'], + auto_add_new_products: false, + }); + + const user = userEvent.setup(); + + render( + + + } /> + + , + ); + + const combobox = screen.getByRole('combobox'); + await user.click(combobox); + + const listbox = await screen.findByRole('listbox'); + const options = within(listbox).getAllByRole('option'); + + expect(options.map((option) => option.textContent)).toEqual([ + 'Apple Juice (Drinks)', + 'Cola (Drinks)', + ]); + expect(screen.queryByRole('option', { name: /chips \(snacks\)/i })).not.toBeInTheDocument(); + }); + it('updates an existing pick item when the same packaging is selected', async () => { pickItemsMock.mockReturnValue([ { diff --git a/src/screens/ActivePickListScreen.tsx b/src/screens/ActivePickListScreen.tsx index 048bbe2..c430a35 100644 --- a/src/screens/ActivePickListScreen.tsx +++ b/src/screens/ActivePickListScreen.tsx @@ -98,18 +98,30 @@ export const ActivePickListScreen = () => { ); }, [products]); + const categoryFilteredProducts = useMemo(() => { + if (!pickList?.categories?.length) return sortedProducts; + + const allowedCategories = new Set( + pickList.categories.map((category) => category.trim().toLowerCase()), + ); + + return sortedProducts.filter((product) => + allowedCategories.has(product.category.trim().toLowerCase()), + ); + }, [pickList?.categories, sortedProducts]); + const hasCartonItems = useMemo(() => items.some((item) => item.is_carton), [items]); const hasUnitItems = useMemo(() => items.some((item) => !item.is_carton), [items]); const filteredProducts = useMemo(() => { const normalizedQuery = query.trim().toLowerCase(); - if (!normalizedQuery) return sortedProducts; + if (!normalizedQuery) return categoryFilteredProducts; - return sortedProducts.filter((product) => { + return categoryFilteredProducts.filter((product) => { const searchableText = `${product.name} ${product.category} ${product.barcode ?? ''}`.toLowerCase(); return searchableText.includes(normalizedQuery); }); - }, [sortedProducts, query]); + }, [categoryFilteredProducts, query]); useEffect(() => { if (!selectedProduct) return;