From 37d55fa4bcd23e98d7bf4fb174d46863d009228c Mon Sep 17 00:00:00 2001 From: Bharathidasan Elangovan Date: Fri, 10 Oct 2025 19:09:54 +0530 Subject: [PATCH 1/2] PWA-3613: RI-Wishlist pagination fix --- .../customerWishlist.gql.ce.js | 2 +- .../useCustomerWishlistSkus.js | 17 +--- .../__snapshots__/useWishlist.spec.js.snap | 3 - .../lib/talons/WishlistPage/useWishlist.js | 93 +++++++++++++++---- .../lib/talons/WishlistPage/wishlist.gql.js | 4 +- 5 files changed, 80 insertions(+), 39 deletions(-) diff --git a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/customerWishlist.gql.ce.js b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/customerWishlist.gql.ce.js index 4b0e3d53ec..fcd6d46744 100644 --- a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/customerWishlist.gql.ce.js +++ b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/customerWishlist.gql.ce.js @@ -7,7 +7,7 @@ export const GET_WISHLIST_ITEMS = gql` customer { wishlists { id - items_v2(currentPage: $currentPage, pageSize: 10) { + items_v2(currentPage: $currentPage, pageSize: 20) { items { id # eslint-disable-next-line @graphql-eslint/require-id-when-available diff --git a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js index 3a333c4a1a..f451ca56bc 100644 --- a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js +++ b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js @@ -1,4 +1,3 @@ -import { useState } from 'react'; import { useQuery } from '@apollo/client'; import { useUserContext } from '../../context/user'; import mergeOperations from '../../util/shallowMerge'; @@ -16,19 +15,16 @@ export const useCustomerWishlistSkus = (props = {}) => { const operations = mergeOperations(defaultOperations, props.operations); const [{ isSignedIn }] = useUserContext(); - const [currentPage, setCurrentPage] = useState(1); - const { client, data: { customerWishlistProducts } } = useQuery(operations.getProductsInWishlistsQuery); useQuery(operations.getWishlistItemsQuery, { - fetchPolicy: 'cache-and-network', + fetchPolicy: 'cache-first', onCompleted: data => { const itemsToAdd = new Set(); const wishlists = data.customer.wishlists; - let shouldFetchMore = false; wishlists.map(wishlist => { const items = wishlist.items_v2.items; items.map(item => { @@ -37,12 +33,6 @@ export const useCustomerWishlistSkus = (props = {}) => { itemsToAdd.add(sku); } }); - - const pageInfo = wishlist.items_v2.page_info; - - if (pageInfo.total_pages > pageInfo.current_page) { - shouldFetchMore = true; - } }); if (itemsToAdd.size) { @@ -57,13 +47,10 @@ export const useCustomerWishlistSkus = (props = {}) => { }); } - if (shouldFetchMore) { - setCurrentPage(current => ++current); - } }, skip: !isSignedIn, variables: { - currentPage + currentPage: 1 } }); }; diff --git a/packages/peregrine/lib/talons/WishlistPage/__tests__/__snapshots__/useWishlist.spec.js.snap b/packages/peregrine/lib/talons/WishlistPage/__tests__/__snapshots__/useWishlist.spec.js.snap index 900dee6d98..2de5741986 100644 --- a/packages/peregrine/lib/talons/WishlistPage/__tests__/__snapshots__/useWishlist.spec.js.snap +++ b/packages/peregrine/lib/talons/WishlistPage/__tests__/__snapshots__/useWishlist.spec.js.snap @@ -36,9 +36,6 @@ Object { Object { "name": "item1", }, - Object { - "name": "item2", - }, ], } `; diff --git a/packages/peregrine/lib/talons/WishlistPage/useWishlist.js b/packages/peregrine/lib/talons/WishlistPage/useWishlist.js index ceeaab252d..98b50e1ac4 100644 --- a/packages/peregrine/lib/talons/WishlistPage/useWishlist.js +++ b/packages/peregrine/lib/talons/WishlistPage/useWishlist.js @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import { useLazyQuery } from '@apollo/client'; import mergeOperations from '../../util/shallowMerge'; import defaultOperations from './wishlist.gql'; @@ -21,15 +21,16 @@ export const useWishlist = (props = {}) => { const [fetchWishlistItems, queryResult] = useLazyQuery( operations.getCustomerWishlistItems, { - fetchPolicy: 'cache-and-network', + fetchPolicy: 'cache-first', nextFetchPolicy: 'cache-first', variables: { id, - currentPage: 1 + currentPage: 1, + pageSize: 20 } } ); - const { data, error, loading, fetchMore } = queryResult; + const { data, error, loading, fetchMore, called } = queryResult; const handleContentToggle = () => { setIsOpen(currentValue => !currentValue); @@ -38,27 +39,83 @@ export const useWishlist = (props = {}) => { const handleLoadMore = useCallback(async () => { setIsFetchingMore(true); const currentPage = page + 1; - await fetchMore({ - variables: { - id, - currentPage - } - }); - setPage(currentPage); - setIsFetchingMore(false); + try { + await fetchMore({ + variables: { + id, + currentPage, + pageSize: 20 + }, + updateQuery: (prevResult, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return prevResult; + } + + const prevWishlist = prevResult.customer.wishlist_v2; + const newWishlist = fetchMoreResult.customer.wishlist_v2; + + if (prevWishlist.id !== newWishlist.id) { + return prevResult; + } + + const prevItems = prevWishlist.items_v2.items || []; + const newItems = newWishlist.items_v2.items || []; + + const existingIds = new Set(prevItems.map(item => item.id)); + const uniqueNewItems = newItems.filter( + item => !existingIds.has(item.id) + ); + + return { + ...prevResult, + customer: { + ...prevResult.customer, + wishlist_v2: { + ...prevWishlist, + items_v2: { + ...prevWishlist.items_v2, + items: [...prevItems, ...uniqueNewItems] + } + } + } + }; + } + }); + + setPage(currentPage); + } catch (error) { + console.error('Error loading more wishlist items:', error); + } finally { + setIsFetchingMore(false); + } }, [id, fetchMore, page]); useEffect(() => { - if (itemsCount >= 1 && isOpen === true && !data) { + if (itemsCount >= 1 && isOpen === true && !called) { fetchWishlistItems(); } - }, [itemsCount, isOpen, fetchWishlistItems, data]); + }, [itemsCount, isOpen, called]); + + const items = useMemo(() => { + if (!data || !data.customer || !data.customer.wishlist_v2) { + return []; + } + + const allItems = data.customer.wishlist_v2.items_v2?.items || []; + + const uniqueItems = []; + const seenIds = new Set(); + + for (const item of allItems) { + if (!seenIds.has(item.id)) { + seenIds.add(item.id); + uniqueItems.push(item); + } + } - const items = - data && data.customer.wishlist_v2.items_v2.items - ? data.customer.wishlist_v2.items_v2.items - : []; + return uniqueItems; + }, [data]); return { handleContentToggle, diff --git a/packages/peregrine/lib/talons/WishlistPage/wishlist.gql.js b/packages/peregrine/lib/talons/WishlistPage/wishlist.gql.js index 6c3bc7f43a..56ac24db87 100644 --- a/packages/peregrine/lib/talons/WishlistPage/wishlist.gql.js +++ b/packages/peregrine/lib/talons/WishlistPage/wishlist.gql.js @@ -17,12 +17,12 @@ export const GET_CUSTOMER_WISHLIST = gql` `; export const GET_CUSTOMER_WISHLIST_ITEMS = gql` - query getCustomerWishlist($id: ID!, $currentPage: Int) { + query getCustomerWishlist($id: ID!, $currentPage: Int, $pageSize: Int) { # eslint-disable-next-line @graphql-eslint/require-id-when-available customer { wishlist_v2(id: $id) { id - items_v2(currentPage: $currentPage) { + items_v2(currentPage: $currentPage, pageSize: $pageSize) { items { id ...WishlistItemFragment From 6e12b3a6675652bfb5cb0aaf45f7f8c4011447c8 Mon Sep 17 00:00:00 2001 From: Bharathidasan Elangovan Date: Mon, 13 Oct 2025 12:43:58 +0530 Subject: [PATCH 2/2] PWA-3613:Fixed lint and prettier issues --- .../useCustomerWishlistSkus/useCustomerWishlistSkus.js | 1 - .../peregrine/lib/talons/WishlistPage/useWishlist.js | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js index f451ca56bc..4dc95cf8e1 100644 --- a/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js +++ b/packages/peregrine/lib/hooks/useCustomerWishlistSkus/useCustomerWishlistSkus.js @@ -46,7 +46,6 @@ export const useCustomerWishlistSkus = (props = {}) => { } }); } - }, skip: !isSignedIn, variables: { diff --git a/packages/peregrine/lib/talons/WishlistPage/useWishlist.js b/packages/peregrine/lib/talons/WishlistPage/useWishlist.js index 98b50e1ac4..8b73c49990 100644 --- a/packages/peregrine/lib/talons/WishlistPage/useWishlist.js +++ b/packages/peregrine/lib/talons/WishlistPage/useWishlist.js @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useLazyQuery } from '@apollo/client'; import mergeOperations from '../../util/shallowMerge'; import defaultOperations from './wishlist.gql'; @@ -17,6 +17,7 @@ export const useWishlist = (props = {}) => { const [page, setPage] = useState(1); const [isOpen, setIsOpen] = useState(!isCollapsed); const [isFetchingMore, setIsFetchingMore] = useState(false); + const hasFetchedRef = useRef(false); const [fetchWishlistItems, queryResult] = useLazyQuery( operations.getCustomerWishlistItems, @@ -30,7 +31,7 @@ export const useWishlist = (props = {}) => { } } ); - const { data, error, loading, fetchMore, called } = queryResult; + const { data, error, loading, fetchMore } = queryResult; const handleContentToggle = () => { setIsOpen(currentValue => !currentValue); @@ -92,10 +93,11 @@ export const useWishlist = (props = {}) => { }, [id, fetchMore, page]); useEffect(() => { - if (itemsCount >= 1 && isOpen === true && !called) { + if (itemsCount >= 1 && isOpen === true && !hasFetchedRef.current) { + hasFetchedRef.current = true; fetchWishlistItems(); } - }, [itemsCount, isOpen, called]); + }, [itemsCount, isOpen, fetchWishlistItems]); const items = useMemo(() => { if (!data || !data.customer || !data.customer.wishlist_v2) {