1- import { GetAllProductsQuery } from '@/graphql/types/graphql' ;
1+ 'use client' ;
2+
3+ import { GET_VARIABLE_PRODUCTS_QUERY } from '@/graphql/queries/products' ;
4+ import { GetAllProductsQuery , StockStatusEnum } from '@/graphql/types/graphql' ;
5+ import useCustomSearchParams from '@/hooks/useCustomSearchParams' ;
6+ import { sortOptions } from '@/static/sortOptions' ;
7+ import { useQuery , useSuspenseQuery } from '@apollo/client' ;
28import { Grid } from '@mui/material' ;
3- import { FC } from 'react' ;
4- import { VariableProductItem } from '../VariableProductItem' ;
9+ import { FC , useEffect } from 'react' ;
10+ import { useIntersectionObserver } from 'usehooks-ts' ;
11+ import {
12+ VariableProductItem ,
13+ VariableProductItemSkeleton ,
14+ } from '../VariableProductItem' ;
515import NotFoundItem from '../common/NotFoundItem' ;
616
7- export interface ProductsListProps {
8- items ?: NonNullable < GetAllProductsQuery [ 'products' ] > [ 'nodes' ] ;
9- }
10- const ProductsList : FC < ProductsListProps > = ( { items } ) => {
11- if ( ! items ?. length ) {
17+ export interface ProductsListProps { }
18+ const ProductsList : FC < ProductsListProps > = ( ) => {
19+ const { inStock, categoryId, sort, q } = useCustomSearchParams ( ) ;
20+
21+ const variables = {
22+ stockStatus : inStock ? StockStatusEnum . InStock : null ,
23+ categoryIdIn : categoryId ? [ + categoryId ] : null ,
24+ q,
25+ orderBy : [ sortOptions . find ( ( item ) => item . key === sort ) ?. props ] ,
26+ first : 15 ,
27+ } ;
28+
29+ const initQuery = useSuspenseQuery < GetAllProductsQuery > (
30+ GET_VARIABLE_PRODUCTS_QUERY ,
31+ {
32+ variables,
33+ } ,
34+ ) ;
35+
36+ const { isIntersecting, ref } = useIntersectionObserver ( {
37+ threshold : 0.1 ,
38+ } ) ;
39+
40+ const paginateQuery = useQuery < GetAllProductsQuery > (
41+ GET_VARIABLE_PRODUCTS_QUERY ,
42+ {
43+ variables,
44+ skip : true ,
45+ } ,
46+ ) ;
47+
48+ useEffect ( ( ) => {
49+ if ( isIntersecting ) {
50+ paginateQuery . fetchMore ( {
51+ variables : {
52+ ...variables ,
53+ after :
54+ paginateQuery . data ?. products ?. pageInfo . endCursor ||
55+ initQuery . data ?. products ?. pageInfo . endCursor ,
56+ } ,
57+ updateQuery : ( previousQueryResult , { fetchMoreResult } ) => {
58+ const newNodes = fetchMoreResult . products ?. nodes || [ ] ;
59+ const pageInfo = fetchMoreResult . products ?. pageInfo ! ;
60+
61+ return newNodes ?. length !
62+ ? {
63+ ...previousQueryResult ,
64+
65+ products : {
66+ ...previousQueryResult . products ,
67+
68+ nodes : [
69+ ...( previousQueryResult . products ?. nodes || [ ] ) ,
70+ ...newNodes ,
71+ ] ,
72+
73+ pageInfo,
74+ } ,
75+ }
76+ : previousQueryResult ;
77+ } ,
78+ } ) ;
79+ }
80+ } , [ isIntersecting ] ) ;
81+
82+ if ( ! initQuery . data ?. products ?. nodes ?. length ) {
1283 return < NotFoundItem /> ;
1384 }
1485
86+ const items = [
87+ ...initQuery . data . products . nodes ,
88+ ...( paginateQuery . data ?. products ?. nodes || [ ] ) ,
89+ ] ;
90+
1591 return (
1692 < Grid container spacing = { 1 } >
1793 { items ?. map ( ( item ) => {
@@ -23,6 +99,27 @@ const ProductsList: FC<ProductsListProps> = ({ items }) => {
2399 ) ;
24100 }
25101 } ) }
102+
103+ { ( initQuery . data . products . pageInfo . hasNextPage ||
104+ paginateQuery . data ?. products ?. pageInfo . hasNextPage ) && (
105+ < >
106+ { new Array ( 4 - ( items . length % 4 ) ) . fill ( 1 ) . map ( ( _ , index ) => {
107+ return (
108+ < Grid
109+ ref = { index === 0 ? ref : null }
110+ key = { index . toString ( ) }
111+ item
112+ xs = { 12 }
113+ md = { 6 }
114+ lg = { 4 }
115+ xl = { 3 }
116+ >
117+ < VariableProductItemSkeleton />
118+ </ Grid >
119+ ) ;
120+ } ) }
121+ </ >
122+ ) }
26123 </ Grid >
27124 ) ;
28125} ;
0 commit comments