diff --git a/src/screens/ActivePickListScreen.test.tsx b/src/screens/ActivePickListScreen.test.tsx
index cb19de2..c228748 100644
--- a/src/screens/ActivePickListScreen.test.tsx
+++ b/src/screens/ActivePickListScreen.test.tsx
@@ -208,6 +208,65 @@ describe('ActivePickListScreen product search', () => {
expect(addMock).not.toHaveBeenCalled();
});
+ it('sorts pick list items by product name and packaging', () => {
+ pickItemsMock.mockReturnValue([
+ {
+ id: 'item-1',
+ pick_list_id: 'list-1',
+ product_id: 'prod-1',
+ quantity: 2,
+ is_carton: false,
+ status: 'pending',
+ created_at: 0,
+ updated_at: 0,
+ },
+ {
+ id: 'item-2',
+ pick_list_id: 'list-1',
+ product_id: 'prod-3',
+ quantity: 1,
+ is_carton: true,
+ status: 'pending',
+ created_at: 0,
+ updated_at: 0,
+ },
+ {
+ id: 'item-3',
+ pick_list_id: 'list-1',
+ product_id: 'prod-2',
+ quantity: 1,
+ is_carton: false,
+ status: 'pending',
+ created_at: 0,
+ updated_at: 0,
+ },
+ {
+ id: 'item-4',
+ pick_list_id: 'list-1',
+ product_id: 'prod-1',
+ quantity: 1,
+ is_carton: true,
+ status: 'pending',
+ created_at: 0,
+ updated_at: 0,
+ },
+ ]);
+
+ render(
+
+
+ } />
+
+ ,
+ );
+
+ const itemLabels = screen
+ .getAllByText(/Apple Juice|Chips|Cola/)
+ .map((element) => element.textContent);
+
+ expect(itemLabels).toEqual(['Apple Juice', 'Chips', 'Cola', 'Cola']);
+ });
+
it('hides picked items when show picked is unchecked', async () => {
pickItemsMock.mockReturnValue([
{
diff --git a/src/screens/ActivePickListScreen.tsx b/src/screens/ActivePickListScreen.tsx
index b80cf79..6c243ce 100644
--- a/src/screens/ActivePickListScreen.tsx
+++ b/src/screens/ActivePickListScreen.tsx
@@ -48,6 +48,11 @@ export const ActivePickListScreen = () => {
[areas, pickList?.area_id],
);
+ const productMap = useMemo(
+ () => new Map(products.map((product) => [product.id, product])),
+ [products],
+ );
+
const sortedProducts = useMemo(
() =>
[...products].sort((a, b) =>
@@ -56,6 +61,23 @@ export const ActivePickListScreen = () => {
[products],
);
+ const sortedItems = useMemo(() => {
+ return [...items].sort((a, b) => {
+ const productA = productMap.get(a.product_id);
+ const productB = productMap.get(b.product_id);
+
+ const nameA = productA?.name.toLowerCase() ?? '';
+ const nameB = productB?.name.toLowerCase() ?? '';
+
+ const nameComparison = nameA.localeCompare(nameB);
+ if (nameComparison !== 0) return nameComparison;
+
+ if (a.is_carton !== b.is_carton) return Number(a.is_carton) - Number(b.is_carton);
+
+ return (a.created_at ?? 0) - (b.created_at ?? 0);
+ });
+ }, [items, productMap]);
+
const filteredProducts = useMemo(() => {
const normalizedQuery = query.trim().toLowerCase();
if (!normalizedQuery) return sortedProducts;
@@ -80,7 +102,9 @@ export const ActivePickListScreen = () => {
}, [allItemsPicked, showPicked]);
const visibleItems = useMemo(() => {
- let filteredItems = showPicked ? items : items.filter((item) => item.status !== 'picked');
+ let filteredItems = showPicked
+ ? sortedItems
+ : sortedItems.filter((item) => item.status !== 'picked');
if (itemFilter === 'cartons') {
return filteredItems.filter((item) => item.is_carton);
@@ -299,7 +323,7 @@ export const ActivePickListScreen = () => {
p.id === item.product_id)}
+ product={productMap.get(item.product_id)}
onIncrementQuantity={() => handleIncrementQuantity(item.id)}
onDecrementQuantity={() => handleDecrementQuantity(item.id)}
onToggleCarton={() => handleToggleCarton(item.id)}