Merge pull request #60 from beatz174-bit/codex/sort-product-list-alphabetically-z5figo
Deduplicate pick list products by name
This commit is contained in:
@@ -174,6 +174,66 @@ describe('ActivePickListScreen product search', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('deduplicates product options with the same id', async () => {
|
||||
const duplicateProducts = [...defaultProducts, { ...defaultProducts[0] }];
|
||||
productsMock.mockReturnValue(duplicateProducts);
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
<MemoryRouter initialEntries={['/pick-lists/1']}>
|
||||
<Routes>
|
||||
<Route path="/pick-lists/:id" element={<ActivePickListScreen />} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
await user.click(combobox);
|
||||
|
||||
const listbox = await screen.findByRole('listbox');
|
||||
const options = within(listbox).getAllByRole('option');
|
||||
|
||||
expect(options).toHaveLength(3);
|
||||
expect(options.map((option) => option.textContent)).toEqual([
|
||||
'Apple Juice (Drinks)',
|
||||
'Chips (Snacks)',
|
||||
'Cola (Drinks)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('deduplicates product options with the same name', async () => {
|
||||
const duplicateNameProducts: Product[] = [
|
||||
...defaultProducts,
|
||||
{ ...defaultProducts[0], id: 'prod-duplicate', barcode: '999', updated_at: 5 },
|
||||
];
|
||||
|
||||
productsMock.mockReturnValue(duplicateNameProducts);
|
||||
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
<MemoryRouter initialEntries={['/pick-lists/1']}>
|
||||
<Routes>
|
||||
<Route path="/pick-lists/:id" element={<ActivePickListScreen />} />
|
||||
</Routes>
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
const combobox = screen.getByRole('combobox');
|
||||
await user.click(combobox);
|
||||
|
||||
const listbox = await screen.findByRole('listbox');
|
||||
const options = within(listbox).getAllByRole('option');
|
||||
|
||||
expect(options).toHaveLength(3);
|
||||
expect(options.map((option) => option.textContent)).toEqual([
|
||||
'Apple Juice (Drinks)',
|
||||
'Chips (Snacks)',
|
||||
'Cola (Drinks)',
|
||||
]);
|
||||
});
|
||||
|
||||
it('updates an existing pick item when the same packaging is selected', async () => {
|
||||
pickItemsMock.mockReturnValue([
|
||||
{
|
||||
|
||||
@@ -48,35 +48,22 @@ export const ActivePickListScreen = () => {
|
||||
[areas, pickList?.area_id],
|
||||
);
|
||||
|
||||
const productMap = useMemo(
|
||||
() => new Map(products.map((product) => [product.id, product])),
|
||||
[products],
|
||||
);
|
||||
const sortedProducts = useMemo(() => {
|
||||
const uniqueProducts = new Map<string, Product>();
|
||||
|
||||
const sortedProducts = useMemo(
|
||||
() =>
|
||||
[...products].sort((a, b) =>
|
||||
a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }),
|
||||
),
|
||||
[products],
|
||||
);
|
||||
products.forEach((product) => {
|
||||
const normalizedName = product.name.trim().toLowerCase();
|
||||
const existing = uniqueProducts.get(normalizedName);
|
||||
|
||||
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);
|
||||
if (!existing || product.updated_at > existing.updated_at) {
|
||||
uniqueProducts.set(normalizedName, product);
|
||||
}
|
||||
});
|
||||
}, [items, productMap]);
|
||||
|
||||
return Array.from(uniqueProducts.values()).sort((a, b) =>
|
||||
a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }),
|
||||
);
|
||||
}, [products]);
|
||||
|
||||
const filteredProducts = useMemo(() => {
|
||||
const normalizedQuery = query.trim().toLowerCase();
|
||||
|
||||
Reference in New Issue
Block a user