@faststore/core 2.1.83 → 2.2.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/.turbo/turbo-build.log +9 -7
  2. package/.turbo/turbo-test.log +25 -0
  3. package/@generated/graphql/index.ts +183 -79
  4. package/@generated/graphql/persisted.json +5 -5
  5. package/@generated/graphql/schema.graphql +1053 -0
  6. package/api/index.ts +15 -0
  7. package/codegen.yml +2 -1
  8. package/generate.sh +71 -0
  9. package/index.ts +15 -0
  10. package/jest.config.js +6 -0
  11. package/package.json +33 -18
  12. package/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx +1 -2
  13. package/src/components/cms/RenderSections.tsx +4 -5
  14. package/src/components/product/ProductGrid/ProductGrid.tsx +4 -3
  15. package/src/components/sections/Breadcrumb/Breadcrumb.tsx +17 -22
  16. package/src/components/sections/CrossSellingShelf/CrossSellingShelf.tsx +8 -6
  17. package/src/components/sections/ProductDetails/ProductDetails.tsx +23 -33
  18. package/src/components/sections/ProductGallery/ProductGallery.tsx +15 -26
  19. package/src/components/sections/ProductShelf/ProductShelf.tsx +1 -1
  20. package/src/components/sections/ProductTiles/ProductTiles.tsx +4 -3
  21. package/src/components/templates/ProductListingPage/ProductListing.tsx +95 -0
  22. package/src/components/templates/ProductListingPage/ProductListingPage.tsx +34 -68
  23. package/src/components/templates/SearchPage/SearchPage.tsx +81 -0
  24. package/src/components/templates/SearchPage/index.ts +2 -0
  25. package/src/components/ui/ProductGallery/ProductGallery.tsx +24 -16
  26. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +8 -7
  27. package/src/components/ui/ProductGallery/useDelayedFacets.ts +3 -3
  28. package/src/components/ui/ProductShelf/ProductShelf.tsx +3 -2
  29. package/src/customizations/GlobalOverrides.tsx +0 -2
  30. package/src/customizations/fragments/ClientProduct.ts +9 -0
  31. package/src/customizations/fragments/ClientProductGallery.ts +19 -0
  32. package/src/customizations/fragments/ClientProducts.ts +19 -0
  33. package/src/customizations/fragments/ServerCollectionPage.ts +9 -0
  34. package/src/customizations/fragments/ServerProductPage.ts +9 -0
  35. package/src/customizations/graphql/thirdParty/resolvers/index.ts +3 -0
  36. package/src/customizations/graphql/vtex/resolvers/index.ts +3 -0
  37. package/src/pages/[...slug].tsx +5 -3
  38. package/src/pages/[slug]/p.tsx +38 -18
  39. package/src/pages/s.tsx +22 -34
  40. package/src/sdk/graphql/useQuery.ts +17 -13
  41. package/src/sdk/overrides/PageProvider.tsx +78 -0
  42. package/src/sdk/product/useLocalizedVariables.ts +33 -0
  43. package/src/sdk/product/usePageProductsQuery.ts +139 -0
  44. package/src/{components/sections/ProductGallery/useGalleryQuery.ts → sdk/product/useProductGalleryQuery.ts} +12 -13
  45. package/src/sdk/product/{useProduct.ts → useProductQuery.ts} +10 -7
  46. package/src/sdk/product/useProductsPrefetch.ts +72 -0
  47. package/src/sdk/product/useProductsQuery.ts +17 -63
  48. package/src/server/generator/generateGraphQLSchemaFile.ts +3 -0
  49. package/src/server/generator/schema.ts +82 -0
  50. package/src/server/index.ts +34 -21
  51. package/src/server/options.ts +16 -0
  52. package/test/server/index.test.ts +146 -0
  53. package/.next/BUILD_ID +0 -1
  54. package/.next/build-manifest.json +0 -129
  55. package/.next/cache/.tsbuildinfo +0 -1
  56. package/.next/cache/config.json +0 -7
  57. package/.next/cache/eslint/.cache_1gneedd +0 -1
  58. package/.next/cache/next-server.js.nft.json +0 -1
  59. package/.next/cache/webpack/client-production/0.pack +0 -0
  60. package/.next/cache/webpack/client-production/index.pack +0 -0
  61. package/.next/cache/webpack/server-production/0.pack +0 -0
  62. package/.next/cache/webpack/server-production/index.pack +0 -0
  63. package/.next/export-marker.json +0 -1
  64. package/.next/images-manifest.json +0 -1
  65. package/.next/next-server.js.nft.json +0 -1
  66. package/.next/package.json +0 -1
  67. package/.next/prerender-manifest.json +0 -1
  68. package/.next/react-loadable-manifest.json +0 -44
  69. package/.next/required-server-files.json +0 -1
  70. package/.next/routes-manifest.json +0 -1
  71. package/.next/server/chunks/143.js +0 -106
  72. package/.next/server/chunks/177.js +0 -120
  73. package/.next/server/chunks/183.js +0 -94
  74. package/.next/server/chunks/184.js +0 -61
  75. package/.next/server/chunks/186.js +0 -113
  76. package/.next/server/chunks/289.js +0 -239
  77. package/.next/server/chunks/312.js +0 -697
  78. package/.next/server/chunks/350.js +0 -143
  79. package/.next/server/chunks/483.js +0 -650
  80. package/.next/server/chunks/487.js +0 -9142
  81. package/.next/server/chunks/53.js +0 -61
  82. package/.next/server/chunks/530.js +0 -626
  83. package/.next/server/chunks/576.js +0 -94
  84. package/.next/server/chunks/650.js +0 -9142
  85. package/.next/server/chunks/676.js +0 -32
  86. package/.next/server/chunks/693.js +0 -58
  87. package/.next/server/chunks/71.js +0 -1254
  88. package/.next/server/chunks/74.js +0 -4054
  89. package/.next/server/chunks/753.js +0 -509
  90. package/.next/server/chunks/779.js +0 -58
  91. package/.next/server/chunks/825.js +0 -4039
  92. package/.next/server/chunks/854.js +0 -72
  93. package/.next/server/chunks/859.js +0 -959
  94. package/.next/server/chunks/907.js +0 -1911
  95. package/.next/server/chunks/933.js +0 -517
  96. package/.next/server/chunks/98.js +0 -124
  97. package/.next/server/chunks/988.js +0 -211
  98. package/.next/server/chunks/font-manifest.json +0 -1
  99. package/.next/server/font-manifest.json +0 -1
  100. package/.next/server/middleware-build-manifest.js +0 -1
  101. package/.next/server/middleware-manifest.json +0 -6
  102. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  103. package/.next/server/pages/404.js +0 -386
  104. package/.next/server/pages/404.js.nft.json +0 -1
  105. package/.next/server/pages/500.js +0 -388
  106. package/.next/server/pages/500.js.nft.json +0 -1
  107. package/.next/server/pages/[...slug].js +0 -1005
  108. package/.next/server/pages/[...slug].js.nft.json +0 -1
  109. package/.next/server/pages/[slug]/p.js +0 -2269
  110. package/.next/server/pages/[slug]/p.js.nft.json +0 -1
  111. package/.next/server/pages/_app.js +0 -280
  112. package/.next/server/pages/_app.js.nft.json +0 -1
  113. package/.next/server/pages/_document.js +0 -374
  114. package/.next/server/pages/_document.js.nft.json +0 -1
  115. package/.next/server/pages/_error.js +0 -164
  116. package/.next/server/pages/_error.js.nft.json +0 -1
  117. package/.next/server/pages/account.js +0 -363
  118. package/.next/server/pages/account.js.nft.json +0 -1
  119. package/.next/server/pages/api/graphql.js +0 -365
  120. package/.next/server/pages/api/graphql.js.nft.json +0 -1
  121. package/.next/server/pages/api/health/live.js +0 -31
  122. package/.next/server/pages/api/health/live.js.nft.json +0 -1
  123. package/.next/server/pages/api/health/ready.js +0 -31
  124. package/.next/server/pages/api/health/ready.js.nft.json +0 -1
  125. package/.next/server/pages/api/preview.js +0 -148
  126. package/.next/server/pages/api/preview.js.nft.json +0 -1
  127. package/.next/server/pages/checkout.js +0 -363
  128. package/.next/server/pages/checkout.js.nft.json +0 -1
  129. package/.next/server/pages/en-US/404.html +0 -81
  130. package/.next/server/pages/en-US/404.json +0 -1
  131. package/.next/server/pages/en-US/500.html +0 -81
  132. package/.next/server/pages/en-US/500.json +0 -1
  133. package/.next/server/pages/en-US/account.html +0 -81
  134. package/.next/server/pages/en-US/account.json +0 -1
  135. package/.next/server/pages/en-US/checkout.html +0 -81
  136. package/.next/server/pages/en-US/checkout.json +0 -1
  137. package/.next/server/pages/en-US/login.html +0 -81
  138. package/.next/server/pages/en-US/login.json +0 -1
  139. package/.next/server/pages/en-US/s.html +0 -81
  140. package/.next/server/pages/en-US/s.json +0 -1
  141. package/.next/server/pages/en-US.html +0 -81
  142. package/.next/server/pages/en-US.json +0 -1
  143. package/.next/server/pages/index.js +0 -439
  144. package/.next/server/pages/index.js.nft.json +0 -1
  145. package/.next/server/pages/login.js +0 -368
  146. package/.next/server/pages/login.js.nft.json +0 -1
  147. package/.next/server/pages/s.js +0 -466
  148. package/.next/server/pages/s.js.nft.json +0 -1
  149. package/.next/server/pages-manifest.json +0 -18
  150. package/.next/server/webpack-api-runtime.js +0 -229
  151. package/.next/server/webpack-runtime.js +0 -229
  152. package/.next/static/chunks/143.dd8a556e6957baa1.js +0 -1
  153. package/.next/static/chunks/148.3bb7e05cc5d1c1c4.js +0 -1
  154. package/.next/static/chunks/238-e5e4b2094f0e1df8.js +0 -1
  155. package/.next/static/chunks/243-8f5650ed908aa75c.js +0 -1
  156. package/.next/static/chunks/530.848b014622932b93.js +0 -1
  157. package/.next/static/chunks/548-ab84e9e8b49413ab.js +0 -1
  158. package/.next/static/chunks/603-d1c069aa8a349c86.js +0 -1
  159. package/.next/static/chunks/651.7142f31ce1e052b3.js +0 -1
  160. package/.next/static/chunks/709.7bc5a25ce30abda6.js +0 -1
  161. package/.next/static/chunks/738-67a288ca3569cdbb.js +0 -1
  162. package/.next/static/chunks/741.52f7fb873418346f.js +0 -1
  163. package/.next/static/chunks/98.97381d2021f86cd9.js +0 -1
  164. package/.next/static/chunks/988.d10040040cdfebbb.js +0 -1
  165. package/.next/static/chunks/framework-dfd14d7ce6600b03.js +0 -1
  166. package/.next/static/chunks/main-fd466221927468fd.js +0 -1
  167. package/.next/static/chunks/pages/404-af78f7cd1d3c1f60.js +0 -1
  168. package/.next/static/chunks/pages/500-f6346ca5f9dc4fef.js +0 -1
  169. package/.next/static/chunks/pages/[...slug]-ca533c74c22cb787.js +0 -1
  170. package/.next/static/chunks/pages/[slug]/p-7bb760bb3fcfc0bb.js +0 -1
  171. package/.next/static/chunks/pages/_app-895781b1c7b5bf56.js +0 -1
  172. package/.next/static/chunks/pages/_error-a7a0c1d9bfbb4f38.js +0 -1
  173. package/.next/static/chunks/pages/account-05bd79fb78365e88.js +0 -1
  174. package/.next/static/chunks/pages/checkout-c973786e68f25a39.js +0 -1
  175. package/.next/static/chunks/pages/index-d521ce4f4e2b89a6.js +0 -1
  176. package/.next/static/chunks/pages/login-8deb9243376b6aa1.js +0 -1
  177. package/.next/static/chunks/pages/s-0e516ab36bb49c99.js +0 -1
  178. package/.next/static/chunks/polyfills-c67a75d1b6f99dc8.js +0 -1
  179. package/.next/static/chunks/webpack-062512aedeb4b39e.js +0 -1
  180. package/.next/static/css/0d056c673d2869bb.css +0 -1
  181. package/.next/static/css/4b7138899cd07c63.css +0 -1
  182. package/.next/static/css/527e334fa69cf40a.css +0 -1
  183. package/.next/static/css/6e1a7434f061d0ef.css +0 -1
  184. package/.next/static/css/9e76fef1c9ca89af.css +0 -1
  185. package/.next/static/css/a2eefb25a4608343.css +0 -1
  186. package/.next/static/css/cb7d1fcea42fab9c.css +0 -1
  187. package/.next/static/css/df588bb98c0b0ca6.css +0 -1
  188. package/.next/static/css/e3b039e8f5daf95f.css +0 -1
  189. package/.next/static/css/f0e2d1b8832e935d.css +0 -1
  190. package/.next/static/jxv75E0IlXYBYk71TulQP/_buildManifest.js +0 -1
  191. package/.next/static/jxv75E0IlXYBYk71TulQP/_ssgManifest.js +0 -1
  192. package/.next/trace +0 -80
  193. package/public/~partytown/debug/partytown-atomics.js +0 -556
  194. package/public/~partytown/debug/partytown-media.js +0 -374
  195. package/public/~partytown/debug/partytown-sandbox-sw.js +0 -543
  196. package/public/~partytown/debug/partytown-sw.js +0 -59
  197. package/public/~partytown/debug/partytown-ww-atomics.js +0 -1789
  198. package/public/~partytown/debug/partytown-ww-sw.js +0 -1781
  199. package/public/~partytown/debug/partytown.js +0 -72
  200. package/public/~partytown/partytown-atomics.js +0 -2
  201. package/public/~partytown/partytown-media.js +0 -2
  202. package/public/~partytown/partytown-sw.js +0 -2
  203. package/public/~partytown/partytown.js +0 -2
  204. package/src/components/ui/ProductGallery/usePageProducts.ts +0 -48
  205. package/src/customizations/components/overrides/ThirdPartyScripts.tsx +0 -9
  206. package/src/customizations/scripts/ThirdPartyScripts.tsx +0 -8
@@ -0,0 +1,95 @@
1
+ import type { ServerCollectionPageQueryQuery } from '@generated/graphql'
2
+ import Breadcrumb from 'src/components/sections/Breadcrumb'
3
+ import Hero from 'src/components/sections/Hero'
4
+ import ProductGallery from 'src/components/sections/ProductGallery'
5
+ import ProductShelf from 'src/components/sections/ProductShelf'
6
+ import ScrollToTopButton from 'src/components/sections/ScrollToTopButton'
7
+ import { ITEMS_PER_PAGE } from 'src/constants'
8
+ import deepmerge from 'deepmerge'
9
+ import { useSearch } from '@faststore/sdk'
10
+
11
+ import type { ComponentType } from 'react'
12
+ import RenderSections from 'src/components/cms/RenderSections'
13
+ import CUSTOM_COMPONENTS from 'src/customizations/components'
14
+ import { PLPContentType } from 'src/server/cms'
15
+
16
+ import {
17
+ useCreateUseGalleryPage,
18
+ UseGalleryPageContext,
19
+ } from 'src/sdk/product/usePageProductsQuery'
20
+ import { useProductGalleryQuery } from 'src/sdk/product/useProductGalleryQuery'
21
+ import PageProvider, { PLPContext } from 'src/sdk/overrides/PageProvider'
22
+
23
+ export type ProductListingPageProps = {
24
+ data: ServerCollectionPageQueryQuery
25
+ page: PLPContentType
26
+ }
27
+
28
+ /**
29
+ * Sections: Components imported from each store's custom components and '../components/sections' only.
30
+ * Do not import or render components from any other folder in here.
31
+ */
32
+ const COMPONENTS: Record<string, ComponentType<any>> = {
33
+ Breadcrumb,
34
+ Hero,
35
+ ProductGallery,
36
+ ProductShelf,
37
+ ...CUSTOM_COMPONENTS,
38
+ }
39
+
40
+ // Array merging strategy from deepmerge that makes client arrays overwrite server array
41
+ // https://www.npmjs.com/package/deepmerge
42
+ const overwriteMerge = (_, sourceArray) => sourceArray
43
+
44
+ export default function ProductListing({
45
+ page: { sections, settings },
46
+ data: server,
47
+ }: ProductListingPageProps) {
48
+ const {
49
+ state: { sort, term, selectedFacets },
50
+ } = useSearch()
51
+ const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE
52
+
53
+ const { data: pageProductGalleryData } = useProductGalleryQuery({
54
+ term,
55
+ sort,
56
+ selectedFacets,
57
+ itemsPerPage,
58
+ })
59
+
60
+ const { pages, useGalleryPage } = useCreateUseGalleryPage()
61
+
62
+ const context = {
63
+ data: {
64
+ ...deepmerge(
65
+ { ...server },
66
+ { ...pageProductGalleryData },
67
+ { arrayMerge: overwriteMerge }
68
+ ),
69
+ pages,
70
+ },
71
+ } as PLPContext
72
+
73
+ return (
74
+ <>
75
+ {/*
76
+ WARNING: Do not import or render components from any
77
+ other folder than '../components/sections' in here.
78
+
79
+ This is necessary to keep the integration with the CMS
80
+ easy and consistent, enabling the change and reorder
81
+ of elements on this page.
82
+
83
+ If needed, wrap your component in a <Section /> component
84
+ (not the HTML tag) before rendering it here.
85
+ */}
86
+ <PageProvider context={context}>
87
+ <UseGalleryPageContext.Provider value={useGalleryPage}>
88
+ <RenderSections sections={sections} components={COMPONENTS} />
89
+ </UseGalleryPageContext.Provider>
90
+ </PageProvider>
91
+
92
+ <ScrollToTopButton />
93
+ </>
94
+ )
95
+ }
@@ -9,38 +9,21 @@ import { useRouter } from 'next/router'
9
9
  import { useMemo } from 'react'
10
10
 
11
11
  import type { ServerCollectionPageQueryQuery } from '@generated/graphql'
12
- import Breadcrumb from 'src/components/sections/Breadcrumb'
13
- import Hero from 'src/components/sections/Hero'
14
- import ProductGallery from 'src/components/sections/ProductGallery'
15
- import ProductShelf from 'src/components/sections/ProductShelf'
16
- import ScrollToTopButton from 'src/components/sections/ScrollToTopButton'
17
12
  import { ITEMS_PER_PAGE } from 'src/constants'
18
13
  import { useApplySearchState } from 'src/sdk/search/state'
19
14
 
20
- import type { ComponentType } from 'react'
21
- import RenderSections from 'src/components/cms/RenderSections'
22
- import CUSTOM_COMPONENTS from 'src/customizations/components'
23
15
  import { PLPContentType } from 'src/server/cms'
24
16
 
25
17
  import storeConfig from '../../../../faststore.config'
18
+ import ProductListing from './ProductListing'
26
19
 
27
- export type ProductListingPageProps = ServerCollectionPageQueryQuery & {
20
+ export type ProductListingPageProps = {
21
+ data: ServerCollectionPageQueryQuery
28
22
  page: PLPContentType
29
23
  }
30
24
 
31
- /**
32
- * Sections: Components imported from each store's custom components and '../components/sections' only.
33
- * Do not import or render components from any other folder in here.
34
- */
35
- const COMPONENTS: Record<string, ComponentType<any>> = {
36
- Breadcrumb,
37
- Hero,
38
- ProductGallery,
39
- ProductShelf,
40
- ...CUSTOM_COMPONENTS,
41
- }
42
-
43
- type UseSearchParams = ServerCollectionPageQueryQuery & {
25
+ type UseSearchParams = {
26
+ collection: ServerCollectionPageQueryQuery['collection']
44
27
  sort: SearchState['sort']
45
28
  }
46
29
  const useSearchParams = ({
@@ -71,14 +54,15 @@ const useSearchParams = ({
71
54
  }
72
55
 
73
56
  export default function ProductListingPage({
74
- page: { sections, settings },
75
- ...otherProps
57
+ page: plpContentType,
58
+ data: server,
76
59
  }: ProductListingPageProps) {
77
- const { collection } = otherProps
60
+ const { settings } = plpContentType
61
+ const collection = server.collection
78
62
  const router = useRouter()
79
63
  const applySearchState = useApplySearchState()
80
64
  const searchParams = useSearchParams({
81
- ...otherProps,
65
+ collection,
82
66
  sort: settings?.productGallery?.sortBySelection as SearchState['sort'],
83
67
  })
84
68
 
@@ -90,49 +74,31 @@ export default function ProductListingPage({
90
74
  const sortQuery = !!sort ? `${separator}sort=${sort}` : ''
91
75
  const [pathname] = router.asPath.split('?')
92
76
  const canonical = `${storeConfig.storeUrl}${pathname}${pageQuery}${sortQuery}`
77
+ const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE
93
78
 
94
79
  return (
95
- <>
96
- <SearchProvider
97
- onChange={applySearchState}
98
- itemsPerPage={settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE}
99
- {...searchParams}
100
- >
101
- {/* SEO */}
102
- <NextSeo
103
- title={title}
104
- description={description}
105
- titleTemplate={storeConfig.seo.titleTemplate}
106
- canonical={canonical}
107
- openGraph={{
108
- type: 'website',
109
- title,
110
- description,
111
- }}
112
- />
113
- <BreadcrumbJsonLd
114
- itemListElements={collection?.breadcrumbList.itemListElement ?? []}
115
- />
116
-
117
- {/*
118
- WARNING: Do not import or render components from any
119
- other folder than '../components/sections' in here.
120
-
121
- This is necessary to keep the integration with the CMS
122
- easy and consistent, enabling the change and reorder
123
- of elements on this page.
124
-
125
- If needed, wrap your component in a <Section /> component
126
- (not the HTML tag) before rendering it here.
127
- */}
128
- <RenderSections
129
- context={collection}
130
- sections={sections}
131
- components={COMPONENTS}
132
- />
133
-
134
- <ScrollToTopButton />
135
- </SearchProvider>
136
- </>
80
+ <SearchProvider
81
+ onChange={applySearchState}
82
+ itemsPerPage={itemsPerPage}
83
+ {...searchParams}
84
+ >
85
+ {/* SEO */}
86
+ <NextSeo
87
+ title={title}
88
+ description={description}
89
+ titleTemplate={storeConfig.seo.titleTemplate}
90
+ canonical={canonical}
91
+ openGraph={{
92
+ type: 'website',
93
+ title,
94
+ description,
95
+ }}
96
+ />
97
+ <BreadcrumbJsonLd
98
+ itemListElements={collection?.breadcrumbList.itemListElement ?? []}
99
+ />
100
+
101
+ <ProductListing page={plpContentType} data={server} />
102
+ </SearchProvider>
137
103
  )
138
104
  }
@@ -0,0 +1,81 @@
1
+ import { useSearch } from '@faststore/sdk'
2
+ import type { ComponentType } from 'react'
3
+
4
+ import Breadcrumb from 'src/components/sections/Breadcrumb'
5
+ import ProductGallery from 'src/components/sections/ProductGallery'
6
+ import { ITEMS_PER_PAGE } from 'src/constants'
7
+ import CUSTOM_COMPONENTS from 'src/customizations/components'
8
+ import RenderSections from 'src/components/cms/RenderSections'
9
+ import { SearchContentType } from 'src/server/cms'
10
+ import { useProductGalleryQuery } from 'src/sdk/product/useProductGalleryQuery'
11
+ import PageProvider, { SearchPageContext } from 'src/sdk/overrides/PageProvider'
12
+ import {
13
+ useCreateUseGalleryPage,
14
+ UseGalleryPageContext,
15
+ } from 'src/sdk/product/usePageProductsQuery'
16
+ import { SearchPageContextType } from 'src/pages/s'
17
+
18
+ /**
19
+ * Sections: Components imported from each store's custom components and '../components/sections' only.
20
+ * Do not import or render components from any other folder in here.
21
+ */
22
+ const COMPONENTS: Record<string, ComponentType<any>> = {
23
+ Breadcrumb,
24
+ ProductGallery,
25
+ ...CUSTOM_COMPONENTS,
26
+ }
27
+
28
+ export type SearchPageProps = {
29
+ data: SearchPageContextType
30
+ page: SearchContentType
31
+ }
32
+
33
+ function SearchPage({
34
+ page: { sections, settings },
35
+ data: server,
36
+ }: SearchPageProps) {
37
+ const {
38
+ state: { sort, term, selectedFacets },
39
+ } = useSearch()
40
+ const itemsPerPage = settings?.productGallery?.itemsPerPage ?? ITEMS_PER_PAGE
41
+
42
+ const { data: pageProductGalleryData } = useProductGalleryQuery({
43
+ term,
44
+ sort,
45
+ selectedFacets,
46
+ itemsPerPage,
47
+ })
48
+
49
+ const { pages, useGalleryPage } = useCreateUseGalleryPage()
50
+
51
+ const context = {
52
+ data: {
53
+ ...server,
54
+ ...pageProductGalleryData,
55
+ pages,
56
+ },
57
+ } as SearchPageContext
58
+
59
+ return (
60
+ <>
61
+ {/*
62
+ WARNING: Do not import or render components from any
63
+ other folder than '../components/sections' in here.
64
+
65
+ This is necessary to keep the integration with the CMS
66
+ easy and consistent, enabling the change and reorder
67
+ of elements on this page.
68
+
69
+ If needed, wrap your component in a <Section /> component
70
+ (not the HTML tag) before rendering it here.
71
+ */}
72
+ <PageProvider context={context}>
73
+ <UseGalleryPageContext.Provider value={useGalleryPage}>
74
+ <RenderSections sections={sections} components={COMPONENTS} />
75
+ </UseGalleryPageContext.Provider>
76
+ </PageProvider>
77
+ </>
78
+ )
79
+ }
80
+
81
+ export default SearchPage
@@ -0,0 +1,2 @@
1
+ export { default } from './SearchPage'
2
+ export type { SearchPageProps } from './SearchPage'
@@ -9,31 +9,34 @@ import Sort from 'src/components/search/Sort'
9
9
  import FilterSkeleton from 'src/components/skeletons/FilterSkeleton'
10
10
  import ProductGridSkeleton from 'src/components/skeletons/ProductGridSkeleton'
11
11
 
12
- import { ProductGalleryQueryQuery } from '@generated/graphql'
13
12
  import { ProductCardProps } from 'src/components/product/ProductCard'
14
13
  import { FilterSliderProps } from 'src/components/search/Filter/FilterSlider'
15
14
  import { SortProps } from 'src/components/search/Sort/Sort'
16
- import { useDelayedFacets } from './useDelayedFacets'
17
- import { useDelayedPagination } from './useDelayedPagination'
18
- import { useProductsPrefetch } from './usePageProducts'
19
15
  import {
20
- MobileFilterButton,
16
+ FilterButtonSkeleton,
21
17
  FilterIcon,
18
+ LinkButtonNext,
19
+ LinkButtonPrev,
20
+ MobileFilterButton,
22
21
  PrevIcon,
23
22
  ResultsCountSkeleton,
24
23
  SortSkeleton,
25
- FilterButtonSkeleton,
26
- LinkButtonPrev,
27
- LinkButtonNext,
28
24
  } from 'src/components/sections/ProductGallery/Overrides'
25
+ import { useDelayedFacets } from './useDelayedFacets'
26
+ import { useDelayedPagination } from './useDelayedPagination'
27
+ import {
28
+ PLPContext,
29
+ SearchPageContext,
30
+ usePage,
31
+ } from 'src/sdk/overrides/PageProvider'
32
+ import { useProductsPrefetch } from 'src/sdk/product/useProductsPrefetch'
29
33
 
30
- const GalleryPage = lazy(() => import('./ProductGalleryPage'))
34
+ const ProductGalleryPage = lazy(() => import('./ProductGalleryPage'))
31
35
  const GalleryPageSkeleton = <ProductGridSkeleton loading />
32
36
 
33
37
  export interface ProductGalleryProps {
34
38
  title?: string
35
39
  searchTerm?: string
36
- productGalleryData?: ProductGalleryQueryQuery
37
40
  totalCount?: number
38
41
  searchTermLabel?: string
39
42
  totalCountLabel?: string
@@ -69,7 +72,6 @@ export interface ProductGalleryProps {
69
72
  function ProductGallery({
70
73
  title,
71
74
  searchTerm,
72
- productGalleryData,
73
75
  totalCount,
74
76
  searchTermLabel,
75
77
  totalCountLabel,
@@ -80,13 +82,18 @@ function ProductGallery({
80
82
  productCard,
81
83
  }: ProductGalleryProps) {
82
84
  const { openFilter } = useUI()
83
- const { pages, addNextPage, addPrevPage } = useSearch()
84
- const facets = useDelayedFacets(productGalleryData)
85
+ const { pages, addNextPage, addPrevPage, itemsPerPage } = useSearch()
86
+ const context = usePage<SearchPageContext | PLPContext>()
87
+ const data = context?.data
88
+ const facets = useDelayedFacets(data) ?? []
85
89
  const { next, prev } = useDelayedPagination(totalCount)
86
90
 
87
91
  useProductsPrefetch(prev ? prev.cursor : null)
88
92
  useProductsPrefetch(next ? next.cursor : null)
89
93
 
94
+ const hasFacets =
95
+ Boolean(data?.search?.facets) && data.search.facets.length > 0
96
+
90
97
  return (
91
98
  <section data-testid="product-gallery" data-fs-product-listing>
92
99
  {searchTerm && (
@@ -115,7 +122,7 @@ function ProductGallery({
115
122
  {...ResultsCountSkeleton.props}
116
123
  // Dynamic props shouldn't be overridable
117
124
  // This decision can be reviewed later if needed
118
- loading={!productGalleryData}
125
+ loading={!data?.search}
119
126
  >
120
127
  <h2 data-testid="total-product-count">
121
128
  {totalCount} {totalCountLabel}
@@ -212,14 +219,15 @@ function ProductGallery({
212
219
  </div>
213
220
  )}
214
221
  {/* Render ALL products */}
215
- {productGalleryData ? (
222
+ {hasFacets ? (
216
223
  <Suspense fallback={GalleryPageSkeleton}>
217
224
  {pages.map((page) => (
218
- <GalleryPage
225
+ <ProductGalleryPage
219
226
  key={`gallery-page-${page}`}
220
227
  page={page}
221
228
  title={title}
222
229
  productCard={productCard}
230
+ itemsPerPage={itemsPerPage}
223
231
  />
224
232
  ))}
225
233
  </Suspense>
@@ -1,20 +1,21 @@
1
- import { useSearch } from '@faststore/sdk'
2
-
3
1
  import ProductGrid from 'src/components/product/ProductGrid'
4
2
  import Sentinel from 'src/sdk/search/Sentinel'
5
3
 
6
4
  import { ProductCardProps } from 'src/components/product/ProductCard'
7
- import { useProducts } from './usePageProducts'
5
+ import { memo } from 'react'
6
+ import { useGalleryPage } from 'src/sdk/product/usePageProductsQuery'
8
7
 
9
8
  interface Props {
10
9
  page: number
11
10
  title: string
12
11
  productCard?: Pick<ProductCardProps, 'showDiscountBadge' | 'bordered'>
12
+ itemsPerPage: number
13
13
  }
14
14
 
15
- function GalleryPage({ page, title, productCard }: Props) {
16
- const products = useProducts(page) ?? []
17
- const { itemsPerPage } = useSearch()
15
+ function ProductGalleryPage({ page, title, productCard, itemsPerPage }: Props) {
16
+ const { data } = useGalleryPage(page)
17
+
18
+ const products = data?.search?.products?.edges ?? []
18
19
 
19
20
  return (
20
21
  <>
@@ -34,4 +35,4 @@ function GalleryPage({ page, title, productCard }: Props) {
34
35
  )
35
36
  }
36
37
 
37
- export default GalleryPage
38
+ export default memo(ProductGalleryPage)
@@ -1,16 +1,16 @@
1
1
  import { useMemo, useRef } from 'react'
2
2
 
3
3
  import type {
4
+ ClientProductGalleryQueryQuery,
4
5
  Filter_FacetsFragment,
5
- ProductGalleryQueryQuery,
6
6
  } from '@generated/graphql'
7
7
 
8
- export const useDelayedFacets = (data?: ProductGalleryQueryQuery) => {
8
+ export const useDelayedFacets = (data?: ClientProductGalleryQueryQuery) => {
9
9
  const facets = useRef<Filter_FacetsFragment[]>([])
10
10
 
11
11
  return useMemo(() => {
12
12
  if (data) {
13
- facets.current = data.search.facets
13
+ facets.current = data.search?.facets
14
14
  }
15
15
 
16
16
  return facets.current
@@ -45,12 +45,13 @@ function ProductShelf({
45
45
  bordered = ProductCard.props.bordered,
46
46
  showDiscountBadge = ProductCard.props.showDiscountBadge,
47
47
  } = {},
48
- ...variables
48
+ ...otherProps
49
49
  }: ProductShelfProps) {
50
50
  const titleId = textToKebabCase(title)
51
51
  const id = useId()
52
52
  const viewedOnce = useRef(false)
53
- const products = useProductsQuery(variables)
53
+ const data = useProductsQuery(otherProps)
54
+ const products = data?.search?.products
54
55
  const productEdges = products?.edges ?? []
55
56
  const aspectRatio = 1
56
57
 
@@ -1,11 +1,9 @@
1
1
  import WebFontsOverrides from 'src/customizations/components/overrides/WebFonts'
2
2
  import { default as CoreWebFonts } from 'src/fonts/WebFonts'
3
- import ThirdPartyScriptsOverrides from 'src/customizations/components/overrides/ThirdPartyScripts'
4
3
 
5
4
  const Components = {
6
5
  WebFonts: CoreWebFonts,
7
6
  ...WebFontsOverrides.components,
8
- ...ThirdPartyScriptsOverrides.components,
9
7
  }
10
8
 
11
9
  export const WebFonts = Components.WebFonts
@@ -0,0 +1,9 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+
3
+ export const fragment = gql`
4
+ fragment ClientProduct on Query {
5
+ product(locator: $locator) {
6
+ id: productID
7
+ }
8
+ }
9
+ `
@@ -0,0 +1,19 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+
3
+ export const fragment = gql`
4
+ fragment ClientProductGallery on Query {
5
+ search(
6
+ first: $first
7
+ after: $after
8
+ sort: $sort
9
+ term: $term
10
+ selectedFacets: $selectedFacets
11
+ ) {
12
+ products {
13
+ pageInfo {
14
+ totalCount
15
+ }
16
+ }
17
+ }
18
+ }
19
+ `
@@ -0,0 +1,19 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+
3
+ export const fragment = gql`
4
+ fragment ClientProducts on Query {
5
+ search(
6
+ first: $first
7
+ after: $after
8
+ sort: $sort
9
+ term: $term
10
+ selectedFacets: $selectedFacets
11
+ ) {
12
+ products {
13
+ pageInfo {
14
+ totalCount
15
+ }
16
+ }
17
+ }
18
+ }
19
+ `
@@ -0,0 +1,9 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+
3
+ export const fragment = gql`
4
+ fragment ServerCollectionPage on Query {
5
+ collection(slug: $slug) {
6
+ id
7
+ }
8
+ }
9
+ `
@@ -0,0 +1,9 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+
3
+ export const fragment = gql`
4
+ fragment ServerProductPage on Query {
5
+ product(locator: $locator) {
6
+ id: productID
7
+ }
8
+ }
9
+ `
@@ -0,0 +1,3 @@
1
+ const resolvers = {}
2
+
3
+ export default resolvers
@@ -0,0 +1,3 @@
1
+ const resolvers = {}
2
+
3
+ export default resolvers
@@ -29,10 +29,11 @@ type BaseProps = {
29
29
 
30
30
  type Props = BaseProps &
31
31
  (
32
- | ({
32
+ | {
33
33
  type: 'plp'
34
34
  page: PLPContentType
35
- } & ServerCollectionPageQueryQuery)
35
+ data: ServerCollectionPageQueryQuery
36
+ }
36
37
  | {
37
38
  type: 'page'
38
39
  page: PageContentType
@@ -52,6 +53,7 @@ function Page({ globalSections, type, ...otherProps }: Props) {
52
53
 
53
54
  const query = gql`
54
55
  query ServerCollectionPageQuery($slug: String!) {
56
+ ...ServerCollectionPage
55
57
  collection(slug: $slug) {
56
58
  seo {
57
59
  title
@@ -123,7 +125,7 @@ export const getStaticProps: GetStaticProps<
123
125
 
124
126
  return {
125
127
  props: {
126
- ...data,
128
+ data,
127
129
  page,
128
130
  globalSections: await globalSectionsPromise,
129
131
  type: 'plp',