@faststore/core 2.2.0-alpha.1 → 2.2.0-alpha.12
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.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +74 -75
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/eslint/.cache_1gneedd +1 -1
- package/.next/cache/next-server.js.nft.json +1 -1
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/react-loadable-manifest.json +11 -8
- package/.next/required-server-files.json +1 -1
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/{647.js → 117.js} +32 -35
- package/.next/server/chunks/183.js +1 -0
- package/.next/server/chunks/289.js +25 -27
- package/.next/server/chunks/312.js +53 -72
- package/.next/server/chunks/350.js +8 -8
- package/.next/server/chunks/{483.js → 37.js} +121 -162
- package/.next/server/chunks/386.js +200 -0
- package/.next/server/chunks/{753.js → 387.js} +8 -12
- package/.next/server/chunks/574.js +42 -23
- package/.next/server/chunks/576.js +1 -0
- package/.next/server/chunks/{530.js → 585.js} +65 -51
- package/.next/server/chunks/{186.js → 692.js} +6 -8
- package/.next/server/chunks/{112.js → 732.js} +282 -457
- package/.next/server/chunks/74.js +247 -345
- package/.next/server/chunks/825.js +38 -3
- package/.next/server/chunks/{71.js → 897.js} +174 -181
- package/.next/server/chunks/98.js +42 -23
- package/.next/server/middleware-build-manifest.js +1 -1
- package/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/.next/server/pages/404.js +13 -13
- package/.next/server/pages/404.js.nft.json +1 -1
- package/.next/server/pages/500.js +14 -14
- package/.next/server/pages/500.js.nft.json +1 -1
- package/.next/server/pages/[...slug].js +141 -184
- package/.next/server/pages/[...slug].js.nft.json +1 -1
- package/.next/server/pages/[slug]/p.js +242 -219
- package/.next/server/pages/[slug]/p.js.nft.json +1 -1
- package/.next/server/pages/_app.js +3 -4
- package/.next/server/pages/_app.js.nft.json +1 -1
- package/.next/server/pages/_document.js +17 -33
- package/.next/server/pages/_document.js.nft.json +1 -1
- package/.next/server/pages/account.js +12 -12
- package/.next/server/pages/account.js.nft.json +1 -1
- package/.next/server/pages/api/graphql.js +15 -8
- package/.next/server/pages/api/graphql.js.nft.json +1 -1
- package/.next/server/pages/api/preview.js +2 -20
- package/.next/server/pages/checkout.js +12 -12
- package/.next/server/pages/checkout.js.nft.json +1 -1
- package/.next/server/pages/en-US/404.html +2 -2
- package/.next/server/pages/en-US/500.html +2 -2
- package/.next/server/pages/en-US/account.html +2 -2
- package/.next/server/pages/en-US/checkout.html +2 -2
- package/.next/server/pages/en-US/login.html +2 -2
- package/.next/server/pages/en-US/s.html +2 -2
- package/.next/server/pages/en-US.html +11 -2
- package/.next/server/pages/index.js +41 -48
- package/.next/server/pages/index.js.nft.json +1 -1
- package/.next/server/pages/login.js +15 -15
- package/.next/server/pages/login.js.nft.json +1 -1
- package/.next/server/pages/s.js +52 -52
- package/.next/server/pages/s.js.nft.json +1 -1
- package/.next/server/pages-manifest.json +2 -2
- package/.next/static/6R1hrzilfMwT81RW6cNqt/_buildManifest.js +1 -0
- package/.next/static/chunks/251.ffc4f3998ecb915a.js +1 -0
- package/.next/static/chunks/383-6217b37bd38ffd07.js +1 -0
- package/.next/static/chunks/386.d01e0db26c523f0f.js +1 -0
- package/.next/static/chunks/{574.d13dd0afe15cd635.js → 574.70612be06fd1365f.js} +1 -1
- package/.next/static/chunks/585.3350efefe61c9461.js +1 -0
- package/.next/static/chunks/635-666ee2cad2925bb7.js +1 -0
- package/.next/static/chunks/721-f1665b3f1d98b7a9.js +1 -0
- package/.next/static/chunks/722-d0cc87aacd616b5d.js +1 -0
- package/.next/static/chunks/783-ded9d8cda0d5c8d9.js +1 -0
- package/.next/static/chunks/{709.daf1eddebf1e7952.js → 800.851af48fe2ab4a4c.js} +1 -1
- package/.next/static/chunks/98.40c7e17d9de4eb8f.js +1 -0
- package/.next/static/chunks/988.afda042dd9ba11d1.js +1 -0
- package/.next/static/chunks/main-e4e873ee741162eb.js +1 -0
- package/.next/static/chunks/pages/{404-af78f7cd1d3c1f60.js → 404-6c674028b2f80cbb.js} +1 -1
- package/.next/static/chunks/pages/{500-f6346ca5f9dc4fef.js → 500-ff55de77265a7e43.js} +1 -1
- package/.next/static/chunks/pages/[...slug]-7f8dc13cc9542463.js +1 -0
- package/.next/static/chunks/pages/[slug]/p-2fb3fd9027f2923b.js +1 -0
- package/.next/static/chunks/pages/{_app-6d0e6ab9a4dd8106.js → _app-7db7de3d205714be.js} +1 -1
- package/.next/static/chunks/pages/{account-05bd79fb78365e88.js → account-b06035cba2c99604.js} +1 -1
- package/.next/static/chunks/pages/{checkout-c973786e68f25a39.js → checkout-f0c3e8d691cb8a54.js} +1 -1
- package/.next/static/chunks/pages/index-a141c747fcc197a1.js +1 -0
- package/.next/static/chunks/pages/{login-8deb9243376b6aa1.js → login-4e0e6cab7a07f1f3.js} +1 -1
- package/.next/static/chunks/pages/s-823f8e1cabbf63b3.js +1 -0
- package/.next/static/chunks/webpack-f3d0973d5a781e73.js +1 -0
- package/.next/static/css/6a7fdc5a21fbead5.css +1 -0
- package/.next/static/css/723835bce380750d.css +1 -0
- package/.next/static/css/8f93a4630936c20b.css +1 -0
- package/.next/static/css/9f79fa103f49bca1.css +1 -0
- package/.next/static/css/fd27ecc37832aa54.css +1 -0
- package/.next/trace +77 -80
- package/.turbo/turbo-build.log +24 -21
- package/.turbo/turbo-lint.log +3 -0
- package/.turbo/turbo-test.log +10 -10
- package/@generated/graphql/index.ts +38 -14
- package/@generated/graphql/persisted.json +6 -6
- package/README.md +3 -3
- package/cms/faststore/sections.json +24 -0
- package/cypress/global.js +8 -0
- package/cypress/integration/a11y.test.js +7 -24
- package/cypress/integration/analytics.test.js +78 -87
- package/cypress/integration/cart.test.js +4 -4
- package/cypress/integration/plp.test.js +6 -6
- package/cypress/integration/search.test.js +1 -1
- package/cypress/integration/seo.test.js +14 -14
- package/cypress.config.ts +19 -0
- package/faststore.config.js +1 -0
- package/index.ts +4 -0
- package/next.config.js +4 -0
- package/package.json +22 -18
- package/src/components/cart/CartSidebar/CartSidebar.tsx +41 -27
- package/src/components/product/NotAvailableButton/NotAvailableButton.tsx +13 -0
- package/src/components/product/NotAvailableButton/index.ts +1 -0
- package/src/components/product/ProductGrid/ProductGrid.tsx +2 -2
- package/src/components/search/Filter/Filter.tsx +1 -1
- package/src/components/search/Filter/FilterDesktop.tsx +1 -1
- package/src/components/search/Filter/FilterSlider.tsx +1 -1
- package/src/components/search/SearchInput/SearchInput.tsx +12 -1
- package/src/components/search/SearchTop/SearchTop.tsx +7 -1
- package/src/components/sections/CrossSellingShelf/CrossSellingShelf.tsx +0 -1
- package/src/components/sections/Newsletter/Overrides.tsx +4 -0
- package/src/components/sections/ProductDetails/Overrides.tsx +8 -4
- package/src/components/sections/ProductDetails/ProductDetails.tsx +26 -15
- package/src/components/sections/ProductTiles/ProductTiles.tsx +3 -2
- package/src/components/ui/ImageGallery/ImageGallery.tsx +13 -6
- package/src/components/ui/Newsletter/Newsletter.tsx +6 -44
- package/src/components/ui/Newsletter/NewsletterAddendum.tsx +86 -0
- package/src/components/ui/ProductDescription/ProductDescription.tsx +6 -1
- package/src/components/ui/ProductDetails/ProductDetailsSettings.tsx +97 -58
- package/src/components/ui/ProductGallery/ProductGallery.tsx +2 -2
- package/src/components/ui/ShippingSimulation/ShippingSimulation.tsx +12 -34
- package/src/customizations/fragments/{ClientProducts.ts → ClientManyProducts.ts} +1 -1
- package/src/customizations/fragments/ClientSearchSuggestions.ts +13 -0
- package/src/customizations/fragments/ClientShippingSimulation.ts +11 -0
- package/src/customizations/fragments/ClientTopSearchSuggestions.ts +13 -0
- package/src/customizations/fragments/{ServerProductPage.ts → ServerProduct.ts} +1 -1
- package/src/experimental/index.ts +36 -0
- package/src/pages/[...slug].tsx +5 -2
- package/src/pages/[slug]/p.tsx +7 -7
- package/src/sdk/analytics/index.tsx +1 -1
- package/src/sdk/analytics/platform/vtex/search.ts +53 -21
- package/src/sdk/analytics/types.ts +14 -0
- package/src/sdk/overrides/PageProvider.tsx +9 -5
- package/src/sdk/product/useLocalizedVariables.ts +2 -2
- package/src/sdk/product/usePageProductsQuery.ts +8 -8
- package/src/sdk/product/useProductGalleryQuery.ts +32 -3
- package/src/sdk/product/useProductsPrefetch.ts +4 -4
- package/src/sdk/product/useProductsQuery.ts +7 -7
- package/src/sdk/search/useSuggestions.ts +48 -16
- package/src/sdk/search/useTopSearch.ts +7 -12
- package/src/sdk/shipping/index.ts +6 -4
- package/src/{components/ui/ShippingSimulation → sdk/shipping}/useShippingSimulation.ts +33 -56
- package/src/server/generator/schema.ts +2 -1
- package/src/typings/overrides.ts +8 -2
- package/tsconfig.json +2 -1
- package/.next/static/chunks/148.3bb7e05cc5d1c1c4.js +0 -1
- package/.next/static/chunks/238-86838f629f3d0aa4.js +0 -1
- package/.next/static/chunks/243-ef9e49ef3df579c0.js +0 -1
- package/.next/static/chunks/530.848b014622932b93.js +0 -1
- package/.next/static/chunks/548-ab84e9e8b49413ab.js +0 -1
- package/.next/static/chunks/738-67a288ca3569cdbb.js +0 -1
- package/.next/static/chunks/932-33f45603c7d12a4b.js +0 -1
- package/.next/static/chunks/98.1632997dfd4d3a52.js +0 -1
- package/.next/static/chunks/988.d10040040cdfebbb.js +0 -1
- package/.next/static/chunks/main-fd466221927468fd.js +0 -1
- package/.next/static/chunks/pages/[...slug]-362204c7e0b533cf.js +0 -1
- package/.next/static/chunks/pages/[slug]/p-885042c4b2b4f8ed.js +0 -1
- package/.next/static/chunks/pages/index-79b05b0071c02fff.js +0 -1
- package/.next/static/chunks/pages/s-e1bb00f8de6a386e.js +0 -1
- package/.next/static/chunks/webpack-88d120cefa1c4c09.js +0 -1
- package/.next/static/css/20e4a3a45cdd65f4.css +0 -1
- package/.next/static/css/4b7138899cd07c63.css +0 -1
- package/.next/static/css/e3b039e8f5daf95f.css +0 -1
- package/.next/static/css/f0e2d1b8832e935d.css +0 -1
- package/.next/static/wPqgZ8bYrPY473PZzuIX_/_buildManifest.js +0 -1
- package/cypress.json +0 -9
- package/generate.sh +0 -71
- /package/.next/static/{wPqgZ8bYrPY473PZzuIX_ → 6R1hrzilfMwT81RW6cNqt}/_ssgManifest.js +0 -0
- /package/src/{components/ui/ProductGallery → sdk/search}/useDelayedFacets.ts +0 -0
- /package/src/{components/ui/ProductGallery → sdk/search}/useDelayedPagination.ts +0 -0
- /package/src/{components/search/Filter → sdk/search}/useFilter.ts +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Dispatch, SetStateAction } from 'react'
|
|
2
|
+
import { useMemo } from 'react'
|
|
2
3
|
|
|
3
4
|
import type { ProductDetailsFragment_ProductFragment } from '@generated/graphql'
|
|
4
5
|
|
|
@@ -13,6 +14,7 @@ import {
|
|
|
13
14
|
Icon,
|
|
14
15
|
Price,
|
|
15
16
|
QuantitySelector,
|
|
17
|
+
__experimentalNotAvailableButton as NotAvailableButton,
|
|
16
18
|
} from 'src/components/sections/ProductDetails/Overrides'
|
|
17
19
|
|
|
18
20
|
interface ProductDetailsSettingsProps {
|
|
@@ -25,6 +27,7 @@ interface ProductDetailsSettingsProps {
|
|
|
25
27
|
isValidating: boolean
|
|
26
28
|
quantity: number
|
|
27
29
|
setQuantity: Dispatch<SetStateAction<number>>
|
|
30
|
+
notAvailableButtonTitle: string
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
function ProductDetailsSettings({
|
|
@@ -37,6 +40,7 @@ function ProductDetailsSettings({
|
|
|
37
40
|
icon: buyButtonIconName = Icon.props.name,
|
|
38
41
|
alt: buyButtonIconAlt = Icon.props['aria-label'],
|
|
39
42
|
},
|
|
43
|
+
notAvailableButtonTitle,
|
|
40
44
|
}: ProductDetailsSettingsProps) {
|
|
41
45
|
const {
|
|
42
46
|
id,
|
|
@@ -54,8 +58,6 @@ function ProductDetailsSettings({
|
|
|
54
58
|
},
|
|
55
59
|
} = product
|
|
56
60
|
|
|
57
|
-
const buyDisabled = availability !== 'https://schema.org/InStock'
|
|
58
|
-
|
|
59
61
|
const buyProps = useBuyButton({
|
|
60
62
|
id,
|
|
61
63
|
price,
|
|
@@ -73,43 +75,94 @@ function ProductDetailsSettings({
|
|
|
73
75
|
},
|
|
74
76
|
})
|
|
75
77
|
|
|
78
|
+
const outOfStock = useMemo(
|
|
79
|
+
() => availability === 'https://schema.org/OutOfStock',
|
|
80
|
+
[availability]
|
|
81
|
+
)
|
|
82
|
+
const shouldShowDiscountedPrice = useMemo(
|
|
83
|
+
() => lowPrice !== listPrice,
|
|
84
|
+
[lowPrice, listPrice]
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
const AddToCartButton = () => {
|
|
88
|
+
return outOfStock ? (
|
|
89
|
+
// TODO: Adds <OutOfStock /> when component is ready to use
|
|
90
|
+
<NotAvailableButton.Component>
|
|
91
|
+
{notAvailableButtonTitle}
|
|
92
|
+
</NotAvailableButton.Component>
|
|
93
|
+
) : (
|
|
94
|
+
<BuyButton.Component
|
|
95
|
+
{...BuyButton.props}
|
|
96
|
+
icon={
|
|
97
|
+
<Icon.Component
|
|
98
|
+
{...Icon.props}
|
|
99
|
+
name={buyButtonIconName}
|
|
100
|
+
aria-label={buyButtonIconAlt}
|
|
101
|
+
/>
|
|
102
|
+
}
|
|
103
|
+
{...buyProps}
|
|
104
|
+
>
|
|
105
|
+
{buyButtonTitle || 'Add to Cart'}
|
|
106
|
+
</BuyButton.Component>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
76
110
|
return (
|
|
77
111
|
<>
|
|
78
|
-
|
|
79
|
-
<
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
112
|
+
{!outOfStock && (
|
|
113
|
+
<section data-fs-product-details-values>
|
|
114
|
+
<div data-fs-product-details-prices>
|
|
115
|
+
{shouldShowDiscountedPrice ? (
|
|
116
|
+
<>
|
|
117
|
+
<Price.Component
|
|
118
|
+
formatter={useFormattedPrice}
|
|
119
|
+
testId="list-price"
|
|
120
|
+
variant="listing"
|
|
121
|
+
SRText="Original price:"
|
|
122
|
+
{...Price.props}
|
|
123
|
+
// Dynamic props shouldn't be overridable
|
|
124
|
+
// This decision can be reviewed later if needed
|
|
125
|
+
value={listPrice}
|
|
126
|
+
data-value={listPrice}
|
|
127
|
+
/>
|
|
128
|
+
<Price.Component
|
|
129
|
+
formatter={useFormattedPrice}
|
|
130
|
+
testId="price"
|
|
131
|
+
variant="spot"
|
|
132
|
+
className="text__lead"
|
|
133
|
+
SRText="Sale Price:"
|
|
134
|
+
{...Price.props}
|
|
135
|
+
// Dynamic props shouldn't be overridable
|
|
136
|
+
// This decision can be reviewed later if needed
|
|
137
|
+
value={lowPrice}
|
|
138
|
+
data-value={lowPrice}
|
|
139
|
+
/>
|
|
140
|
+
</>
|
|
141
|
+
) : (
|
|
142
|
+
<Price.Component
|
|
143
|
+
formatter={useFormattedPrice}
|
|
144
|
+
testId="list-price"
|
|
145
|
+
variant="spot"
|
|
146
|
+
className="text__lead"
|
|
147
|
+
SRText="Original price:"
|
|
148
|
+
{...Price.props}
|
|
149
|
+
// Dynamic props shouldn't be overridable
|
|
150
|
+
// This decision can be reviewed later if needed
|
|
151
|
+
value={lowPrice}
|
|
152
|
+
data-value={lowPrice}
|
|
153
|
+
/>
|
|
154
|
+
)}
|
|
155
|
+
</div>
|
|
156
|
+
<QuantitySelector.Component
|
|
157
|
+
min={1}
|
|
158
|
+
max={10}
|
|
159
|
+
{...QuantitySelector.props}
|
|
98
160
|
// Dynamic props shouldn't be overridable
|
|
99
161
|
// This decision can be reviewed later if needed
|
|
100
|
-
|
|
101
|
-
data-value={lowPrice}
|
|
162
|
+
onChange={setQuantity}
|
|
102
163
|
/>
|
|
103
|
-
</
|
|
104
|
-
|
|
105
|
-
min={1}
|
|
106
|
-
max={10}
|
|
107
|
-
{...QuantitySelector.props}
|
|
108
|
-
// Dynamic props shouldn't be overridable
|
|
109
|
-
// This decision can be reviewed later if needed
|
|
110
|
-
onChange={setQuantity}
|
|
111
|
-
/>
|
|
112
|
-
</section>
|
|
164
|
+
</section>
|
|
165
|
+
)}
|
|
113
166
|
{skuVariants && (
|
|
114
167
|
<Selectors
|
|
115
168
|
slugsMap={skuVariants.slugsMap}
|
|
@@ -118,30 +171,16 @@ function ProductDetailsSettings({
|
|
|
118
171
|
data-fs-product-details-selectors
|
|
119
172
|
/>
|
|
120
173
|
)}
|
|
121
|
-
{
|
|
122
|
-
/* NOTE:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
icon={
|
|
132
|
-
<Icon.Component
|
|
133
|
-
{...Icon.props}
|
|
134
|
-
aria-label={buyButtonIconAlt}
|
|
135
|
-
name={buyButtonIconName}
|
|
136
|
-
/>
|
|
137
|
-
}
|
|
138
|
-
disabled={buyDisabled}
|
|
139
|
-
{...buyProps}
|
|
140
|
-
>
|
|
141
|
-
{buyButtonTitle || 'Add to Cart'}
|
|
142
|
-
</BuyButton.Component>
|
|
143
|
-
)
|
|
144
|
-
}
|
|
174
|
+
{isValidating ? (
|
|
175
|
+
/* NOTE:
|
|
176
|
+
A loading skeleton had to be used to avoid a Lighthouse's
|
|
177
|
+
non-composited animation violation due to the button transitioning its
|
|
178
|
+
background color when changing from its initial disabled to active state.
|
|
179
|
+
See full explanation on commit https://git.io/JyXV5. */
|
|
180
|
+
<AddToCartLoadingSkeleton />
|
|
181
|
+
) : (
|
|
182
|
+
<AddToCartButton />
|
|
183
|
+
)}
|
|
145
184
|
</>
|
|
146
185
|
)
|
|
147
186
|
}
|
|
@@ -22,8 +22,8 @@ import {
|
|
|
22
22
|
ResultsCountSkeleton,
|
|
23
23
|
SortSkeleton,
|
|
24
24
|
} from 'src/components/sections/ProductGallery/Overrides'
|
|
25
|
-
import { useDelayedFacets } from '
|
|
26
|
-
import { useDelayedPagination } from '
|
|
25
|
+
import { useDelayedFacets } from 'src/sdk/search/useDelayedFacets'
|
|
26
|
+
import { useDelayedPagination } from 'src/sdk/search/useDelayedPagination'
|
|
27
27
|
import {
|
|
28
28
|
PLPContext,
|
|
29
29
|
SearchPageContext,
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { ShippingSimulationProps as UIShippingSimulationProps } from '@faststore/ui'
|
|
2
2
|
|
|
3
|
-
import { getShippingSimulation } from 'src/sdk/shipping'
|
|
4
|
-
import { ShippingSla } from '@generated/graphql'
|
|
5
3
|
import { useSession } from 'src/sdk/session'
|
|
6
|
-
import {
|
|
7
|
-
import { useShippingSimulation } from './useShippingSimulation'
|
|
4
|
+
import { useShippingSimulation } from 'src/sdk/shipping/useShippingSimulation'
|
|
8
5
|
|
|
9
6
|
import { ShippingSimulation as ShippingSimulationWrapper } from 'src/components/sections/ProductDetails/Overrides'
|
|
10
7
|
|
|
@@ -26,27 +23,6 @@ interface ShippingSimulationProps
|
|
|
26
23
|
}
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
const fetchShippingSimulation = async (
|
|
30
|
-
shippingItem: IShippingItem,
|
|
31
|
-
country: string,
|
|
32
|
-
postalCode: string
|
|
33
|
-
): Promise<[string, ShippingSla[]]> => {
|
|
34
|
-
const shipping = await getShippingSimulation({
|
|
35
|
-
country,
|
|
36
|
-
postalCode: postalCode,
|
|
37
|
-
items: [shippingItem],
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const location =
|
|
41
|
-
[shipping?.address?.neighborhood, shipping?.address?.city]
|
|
42
|
-
.filter(Boolean)
|
|
43
|
-
.join(' / ') ?? ''
|
|
44
|
-
|
|
45
|
-
const options = shipping?.logisticsInfo?.[0]?.slas ?? []
|
|
46
|
-
|
|
47
|
-
return [location, options as ShippingSla[]]
|
|
48
|
-
}
|
|
49
|
-
|
|
50
26
|
export default function ShippingSimulation({
|
|
51
27
|
productShippingInfo,
|
|
52
28
|
formatter,
|
|
@@ -55,24 +31,25 @@ export default function ShippingSimulation({
|
|
|
55
31
|
idkPostalCodeLinkProps,
|
|
56
32
|
...otherProps
|
|
57
33
|
}: ShippingSimulationProps) {
|
|
58
|
-
const { country, postalCode: sessionPostalCode } = useSession()
|
|
59
|
-
|
|
60
34
|
const {
|
|
61
35
|
input,
|
|
62
36
|
shippingSimulation,
|
|
63
37
|
handleSubmit,
|
|
64
38
|
handleOnInput,
|
|
65
39
|
handleOnClear,
|
|
66
|
-
} = useShippingSimulation(
|
|
67
|
-
productShippingInfo,
|
|
68
|
-
fetchShippingSimulation,
|
|
69
|
-
sessionPostalCode,
|
|
70
|
-
country
|
|
71
|
-
)
|
|
40
|
+
} = useShippingSimulation(productShippingInfo)
|
|
72
41
|
|
|
73
42
|
const { postalCode, displayClearButton, errorMessage } = input
|
|
74
43
|
|
|
75
|
-
const
|
|
44
|
+
const location =
|
|
45
|
+
[
|
|
46
|
+
shippingSimulation?.address?.neighborhood,
|
|
47
|
+
shippingSimulation?.address?.city,
|
|
48
|
+
]
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.join(' / ') ?? ''
|
|
51
|
+
|
|
52
|
+
const options = shippingSimulation?.logisticsInfo?.[0]?.slas ?? []
|
|
76
53
|
|
|
77
54
|
return (
|
|
78
55
|
<ShippingSimulationWrapper.Component
|
|
@@ -82,6 +59,7 @@ export default function ShippingSimulation({
|
|
|
82
59
|
onClear={handleOnClear}
|
|
83
60
|
location={location}
|
|
84
61
|
options={options}
|
|
62
|
+
address={shippingSimulation?.address}
|
|
85
63
|
displayClearButton={displayClearButton}
|
|
86
64
|
errorMessage={errorMessage}
|
|
87
65
|
postalCode={postalCode}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SDK
|
|
2
|
+
export {
|
|
3
|
+
useSession as useSession_unstable,
|
|
4
|
+
sessionStore as sessionStore_unstable,
|
|
5
|
+
validateSession as validateSession_unstable,
|
|
6
|
+
} from '../../src/sdk/session'
|
|
7
|
+
export {
|
|
8
|
+
useCart as useCart_unstable,
|
|
9
|
+
cartStore as cartStore_unstable,
|
|
10
|
+
} from '../../src/sdk/cart'
|
|
11
|
+
export type { CartItem, Cart } from '../../src/sdk/cart'
|
|
12
|
+
export { useBuyButton as useBuyButton_unstable } from '../../src/sdk/cart/useBuyButton'
|
|
13
|
+
export { useCartToggleButton as useCartToggleButton_unstable } from '../../src/sdk/cart/useCartToggleButton'
|
|
14
|
+
export { useCheckoutButton as useCheckoutButton_unstable } from '../../src/sdk/cart/useCheckoutButton'
|
|
15
|
+
export { useRemoveButton as useRemoveButton_unstable } from '../../src/sdk/cart/useRemoveButton'
|
|
16
|
+
export { useQuery as useQuery_unstable } from '../../src/sdk/graphql/useQuery'
|
|
17
|
+
export { useLazyQuery as useLazyQuery_unstable } from '../../src/sdk/graphql/useLazyQuery'
|
|
18
|
+
export { useNewsletter as useNewsletter_unstable } from '../../src/sdk/newsletter/useNewsletter'
|
|
19
|
+
export { useDiscountPercent as useDiscountPercent_unstable } from '../../src/sdk/product/useDiscountPercent'
|
|
20
|
+
export { useFormattedPrice as useFormattedPrice_unstable } from '../../src/sdk/product/useFormattedPrice'
|
|
21
|
+
export { useLocalizedVariables as useLocalizedVariables_unstable } from '../../src/sdk/product/useLocalizedVariables'
|
|
22
|
+
export { useProductGalleryQuery as useProductGalleryQuery_unstable } from '../../src/sdk/product/useProductGalleryQuery'
|
|
23
|
+
export { useProductLink as useProductLink_unstable } from '../../src/sdk/product/useProductLink'
|
|
24
|
+
export { useProductQuery as useProductQuery_unstable } from '../../src/sdk/product/useProductQuery'
|
|
25
|
+
export { useProductsPrefetch as useProductsPrefetch_unstable } from '../../src/sdk/product/useProductsPrefetch'
|
|
26
|
+
export { default as useSearchHistory_unstable } from '../../src/sdk/search/useSearchHistory'
|
|
27
|
+
export { default as useSuggestions_unstable } from '../../src/sdk/search/useSuggestions'
|
|
28
|
+
export { default as useTopSearch_unstable } from '../../src/sdk/search/useTopSearch'
|
|
29
|
+
export { useFilter as useFilter_unstable } from '../../src/sdk/search/useFilter'
|
|
30
|
+
export { useDelayedFacets as useDelayedFacets_unstable } from '../../src/sdk/search/useDelayedFacets'
|
|
31
|
+
export { useDelayedPagination as useDelayedPagination_unstable } from '../../src/sdk/search/useDelayedPagination'
|
|
32
|
+
export { getShippingSimulation as getShippingSimulation_unstable } from '../../src/sdk/shipping'
|
|
33
|
+
export { useShippingSimulation as useShippingSimulation_unstable } from '../../src/sdk/shipping/useShippingSimulation'
|
|
34
|
+
|
|
35
|
+
// Components
|
|
36
|
+
export { Image as Image_unstable } from '../../src/components/ui/Image'
|
package/src/pages/[...slug].tsx
CHANGED
|
@@ -81,8 +81,10 @@ export const getStaticProps: GetStaticProps<
|
|
|
81
81
|
{ slug: string[] },
|
|
82
82
|
Locator
|
|
83
83
|
> = async ({ params, previewData }) => {
|
|
84
|
+
const slug = params?.slug.join('/') ?? ''
|
|
85
|
+
|
|
84
86
|
const [landingPagePromise, globalSectionsPromise] = [
|
|
85
|
-
getLandingPageBySlug(
|
|
87
|
+
getLandingPageBySlug(slug, previewData),
|
|
86
88
|
getGlobalSectionsData(previewData),
|
|
87
89
|
]
|
|
88
90
|
|
|
@@ -101,7 +103,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
101
103
|
ServerCollectionPageQueryQueryVariables,
|
|
102
104
|
ServerCollectionPageQueryQuery
|
|
103
105
|
>({
|
|
104
|
-
variables: { slug
|
|
106
|
+
variables: { slug },
|
|
105
107
|
operationName: query,
|
|
106
108
|
}),
|
|
107
109
|
getPage<PLPContentType>({
|
|
@@ -129,6 +131,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
129
131
|
page,
|
|
130
132
|
globalSections: await globalSectionsPromise,
|
|
131
133
|
type: 'plp',
|
|
134
|
+
key: slug,
|
|
132
135
|
},
|
|
133
136
|
}
|
|
134
137
|
}
|
package/src/pages/[slug]/p.tsx
CHANGED
|
@@ -7,9 +7,8 @@ import type { ComponentType } from 'react'
|
|
|
7
7
|
import deepmerge from 'deepmerge'
|
|
8
8
|
|
|
9
9
|
import type {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
ServerProductPageQueryQueryVariables,
|
|
10
|
+
ServerProductQueryQuery,
|
|
11
|
+
ServerProductQueryQueryVariables,
|
|
13
12
|
} from '@generated/graphql'
|
|
14
13
|
import RenderSections from 'src/components/cms/RenderSections'
|
|
15
14
|
import BannerNewsletter from 'src/components/sections/BannerNewsletter/BannerNewsletter'
|
|
@@ -44,7 +43,7 @@ const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
type Props = PDPContentType & {
|
|
47
|
-
data:
|
|
46
|
+
data: ServerProductQueryQuery
|
|
48
47
|
globalSections: GlobalSectionsData
|
|
49
48
|
meta: {
|
|
50
49
|
title: string
|
|
@@ -134,8 +133,8 @@ function Page({ data: server, sections, globalSections, offers, meta }: Props) {
|
|
|
134
133
|
}
|
|
135
134
|
|
|
136
135
|
const query = gql`
|
|
137
|
-
query
|
|
138
|
-
...
|
|
136
|
+
query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {
|
|
137
|
+
...ServerProduct
|
|
139
138
|
product(locator: $locator) {
|
|
140
139
|
id: productID
|
|
141
140
|
|
|
@@ -200,7 +199,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
200
199
|
> = async ({ params, previewData }) => {
|
|
201
200
|
const slug = params?.slug ?? ''
|
|
202
201
|
const [searchResult, cmsPage, globalSections] = await Promise.all([
|
|
203
|
-
execute<
|
|
202
|
+
execute<ServerProductQueryQueryVariables, ServerProductQueryQuery>({
|
|
204
203
|
variables: { locator: [{ key: 'slug', value: slug }] },
|
|
205
204
|
operationName: query,
|
|
206
205
|
}),
|
|
@@ -253,6 +252,7 @@ export const getStaticProps: GetStaticProps<
|
|
|
253
252
|
meta,
|
|
254
253
|
offers,
|
|
255
254
|
globalSections,
|
|
255
|
+
key: slug,
|
|
256
256
|
},
|
|
257
257
|
}
|
|
258
258
|
}
|
|
@@ -11,7 +11,7 @@ if (typeof window !== 'undefined') {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
const AnalyticsHandler = () => {
|
|
15
15
|
useAnalyticsEvent((event: AnalyticsEvent) => {
|
|
16
16
|
// Cleans the ecommerce object before pushing a new one
|
|
17
17
|
// This prevents the new data from getting merged with the previous one
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* More info at: https://www.notion.so/vtexhandbook/Event-API-Documentation-48eee26730cf4d7f80f8fd7262231f84
|
|
3
3
|
*/
|
|
4
4
|
import type { AnalyticsEvent } from '@faststore/sdk'
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
IntelligentSearchQueryEvent,
|
|
7
|
+
SearchSelectItemEvent,
|
|
8
|
+
} from '../../types'
|
|
6
9
|
|
|
7
10
|
import config from '../../../../../faststore.config'
|
|
8
11
|
import { getCookie } from '../../../../utils/getCookie'
|
|
@@ -52,6 +55,15 @@ type SearchEvent =
|
|
|
52
55
|
url: string
|
|
53
56
|
type: 'search.click'
|
|
54
57
|
}
|
|
58
|
+
| {
|
|
59
|
+
text: string
|
|
60
|
+
misspelled: boolean
|
|
61
|
+
match: number
|
|
62
|
+
operator: string
|
|
63
|
+
locale: string
|
|
64
|
+
url: string
|
|
65
|
+
type: 'search.query'
|
|
66
|
+
}
|
|
55
67
|
|
|
56
68
|
const sendEvent = (options: SearchEvent & { url?: string }) =>
|
|
57
69
|
fetch(`https://sp.vtex.com/event-api/v1/${config.api.storeId}/event`, {
|
|
@@ -71,30 +83,50 @@ const isFullTextSearch = (url: URL) =>
|
|
|
71
83
|
typeof url.searchParams.get('q') === 'string' &&
|
|
72
84
|
/^\/s(\/)?$/g.test(url.pathname)
|
|
73
85
|
|
|
74
|
-
const handleEvent = (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const handleEvent = (
|
|
87
|
+
event: AnalyticsEvent | SearchSelectItemEvent | IntelligentSearchQueryEvent
|
|
88
|
+
) => {
|
|
89
|
+
switch (event.name) {
|
|
90
|
+
case 'search_select_item': {
|
|
91
|
+
const url = new URL(event.params.url)
|
|
92
|
+
|
|
93
|
+
if (!isFullTextSearch(url)) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
for (const item of event.params.items ?? []) {
|
|
98
|
+
const productId = item.item_id ?? item.item_variant
|
|
99
|
+
const position = item.index
|
|
100
|
+
|
|
101
|
+
if (productId && position) {
|
|
102
|
+
sendEvent({
|
|
103
|
+
type: 'search.click',
|
|
104
|
+
productId,
|
|
105
|
+
position,
|
|
106
|
+
url: url.href,
|
|
107
|
+
text: url.searchParams.get('q') ?? '<empty>',
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
break
|
|
113
|
+
}
|
|
88
114
|
|
|
89
|
-
|
|
115
|
+
case 'intelligent_search_query': {
|
|
90
116
|
sendEvent({
|
|
91
|
-
type: 'search.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
117
|
+
type: 'search.query',
|
|
118
|
+
url: event.params.url,
|
|
119
|
+
text: event.params.term,
|
|
120
|
+
misspelled: event.params.isTermMisspelled,
|
|
121
|
+
match: event.params.totalCount,
|
|
122
|
+
operator: event.params.logicalOperator,
|
|
123
|
+
locale: event.params.locale,
|
|
96
124
|
})
|
|
125
|
+
|
|
126
|
+
break
|
|
97
127
|
}
|
|
128
|
+
|
|
129
|
+
default:
|
|
98
130
|
}
|
|
99
131
|
}
|
|
100
132
|
|
|
@@ -20,3 +20,17 @@ export interface SearchSelectItemEvent {
|
|
|
20
20
|
name: 'search_select_item'
|
|
21
21
|
params: SearchSelectItemParams
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
export interface IntelligentSearchQueryParams {
|
|
25
|
+
url: string
|
|
26
|
+
locale: string
|
|
27
|
+
term: string
|
|
28
|
+
logicalOperator: string
|
|
29
|
+
isTermMisspelled: boolean
|
|
30
|
+
totalCount: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface IntelligentSearchQueryEvent {
|
|
34
|
+
name: 'intelligent_search_query'
|
|
35
|
+
params: IntelligentSearchQueryParams
|
|
36
|
+
}
|
|
@@ -1,27 +1,31 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ClientProductGalleryQueryQuery,
|
|
3
3
|
ClientProductQueryQuery,
|
|
4
|
-
|
|
4
|
+
ClientManyProductsQueryQuery,
|
|
5
5
|
ServerCollectionPageQueryQuery,
|
|
6
|
-
|
|
6
|
+
ServerProductQueryQuery,
|
|
7
7
|
} from '@generated/graphql'
|
|
8
8
|
import type { PropsWithChildren } from 'react'
|
|
9
9
|
import { createContext, useContext, useMemo } from 'react'
|
|
10
10
|
import { SearchPageContextType } from 'src/pages/s'
|
|
11
11
|
|
|
12
12
|
export interface PDPContext {
|
|
13
|
-
data?:
|
|
13
|
+
data?: ServerProductQueryQuery &
|
|
14
14
|
ClientProductQueryQuery['product'] & { isValidating?: boolean }
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export interface PLPContext {
|
|
18
18
|
data?: ServerCollectionPageQueryQuery &
|
|
19
|
-
ClientProductGalleryQueryQuery & {
|
|
19
|
+
ClientProductGalleryQueryQuery & {
|
|
20
|
+
pages: ClientManyProductsQueryQuery[]
|
|
21
|
+
}
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
export interface SearchPageContext {
|
|
23
25
|
data?: SearchPageContextType &
|
|
24
|
-
ClientProductGalleryQueryQuery & {
|
|
26
|
+
ClientProductGalleryQueryQuery & {
|
|
27
|
+
pages: ClientManyProductsQueryQuery[]
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
export const isPDP = (x: any): x is PDPContext =>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useMemo } from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { ClientManyProductsQueryQueryVariables } from '@generated/graphql'
|
|
3
3
|
import { useSession } from '../session'
|
|
4
4
|
import { ITEMS_PER_SECTION } from 'src/constants'
|
|
5
5
|
|
|
@@ -12,7 +12,7 @@ export const useLocalizedVariables = ({
|
|
|
12
12
|
sort,
|
|
13
13
|
term,
|
|
14
14
|
selectedFacets,
|
|
15
|
-
}: Partial<
|
|
15
|
+
}: Partial<ClientManyProductsQueryQueryVariables>) => {
|
|
16
16
|
const { channel, locale } = useSession()
|
|
17
17
|
|
|
18
18
|
return useMemo(() => {
|