@faststore/core 3.0.74 → 3.0.76
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 +35 -35
- package/.next/cache/.tsbuildinfo +1 -1
- package/.next/cache/config.json +3 -3
- package/.next/cache/eslint/.cache_1gneedd +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-minimal-server.js.nft.json +1 -1
- package/.next/next-server.js.nft.json +1 -1
- package/.next/prerender-manifest.js +1 -1
- package/.next/prerender-manifest.json +1 -1
- package/.next/react-loadable-manifest.json +3 -3
- package/.next/routes-manifest.json +1 -1
- package/.next/server/chunks/247.js +1 -1
- package/.next/server/chunks/350.js +1 -1
- package/.next/server/chunks/485.js +2 -2
- package/.next/server/chunks/640.js +1 -1
- package/.next/server/chunks/646.js +10 -3
- package/.next/server/chunks/96.js +1 -1
- 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 +1 -1
- package/.next/server/pages/500.js +1 -1
- package/.next/server/pages/[...slug].js +1 -1
- package/.next/server/pages/[...slug].js.nft.json +1 -1
- package/.next/server/pages/[slug]/p.js +1 -1
- package/.next/server/pages/[slug]/p.js.nft.json +1 -1
- package/.next/server/pages/account.js +1 -1
- package/.next/server/pages/api/graphql.js +1 -1
- package/.next/server/pages/api/graphql.js.nft.json +1 -1
- package/.next/server/pages/checkout.js +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 +2 -2
- package/.next/server/pages/index.js +1 -1
- package/.next/server/pages/login.js +1 -1
- package/.next/server/pages/s.js +1 -1
- package/.next/server/pages-manifest.json +1 -1
- package/.next/static/{nYzSKXE4KKqXVQ7J-XNJ4 → MicuvvXHUUVq_w--K0EDu}/_buildManifest.js +1 -1
- package/.next/static/chunks/104-8bf09f16d6f3a4cd.js +1 -0
- package/.next/static/chunks/247.50945bfe8f760e62.js +1 -0
- package/.next/static/chunks/661-fc56d46a6f6ad0a8.js +1 -0
- package/.next/static/chunks/758.a411edd1cbd09134.js +1 -0
- package/.next/static/chunks/pages/[...slug]-c83d89b6d411553c.js +1 -0
- package/.next/static/chunks/pages/[slug]/p-e75ab6f3f36d8f19.js +1 -0
- package/.next/static/chunks/{webpack-fdd195abd12b3685.js → webpack-f21bbd452a1f0b51.js} +1 -1
- package/.next/static/css/30a88c3e4b758d2e.css +1 -0
- package/.next/static/css/{211c7542af66d8b4.css → 88c892db4c8964d5.css} +1 -1
- package/.next/static/css/b7e9baf615efe7df.css +1 -0
- package/.next/static/css/d5ac0818cefcb033.css +1 -0
- package/.next/trace +95 -95
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-test.log +4 -4
- package/@generated/gql.ts +8 -8
- package/@generated/graphql.ts +37 -5
- package/@generated/persisted-documents.json +5 -5
- package/@generated/schema.graphql +6 -0
- package/cms/faststore/sections.json +96 -0
- package/package.json +5 -5
- package/src/components/cart/CartItem/CartItem.tsx +21 -3
- package/src/components/cart/CartSidebar/CartSidebar.tsx +28 -3
- package/src/components/cart/OrderSummary/OrderSummary.tsx +7 -2
- package/src/components/product/ProductCard/ProductCard.tsx +22 -2
- package/src/components/product/ProductGrid/ProductGrid.tsx +6 -2
- package/src/components/sections/CrossSellingShelf/CrossSellingShelf.tsx +6 -0
- package/src/components/sections/ProductDetails/ProductDetails.tsx +21 -3
- package/src/components/sections/ProductDetails/section.module.scss +11 -0
- package/src/components/sections/ProductTiles/ProductTiles.tsx +10 -1
- package/src/components/ui/ProductDetails/ProductDetailsSettings.tsx +42 -10
- package/src/components/ui/ProductGallery/ProductGallery.tsx +4 -1
- package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +4 -1
- package/src/components/ui/ProductShelf/ProductShelf.tsx +6 -0
- package/src/pages/[slug]/p.tsx +1 -0
- package/src/sdk/cart/index.ts +48 -30
- package/.next/static/chunks/104-e89fd47aa32b199b.js +0 -1
- package/.next/static/chunks/247.6eb0f179401e9e2f.js +0 -1
- package/.next/static/chunks/661-0ff17cbc40856afe.js +0 -1
- package/.next/static/chunks/758.9ca1da3ac30b665d.js +0 -1
- package/.next/static/chunks/pages/[...slug]-484e64ab6c753be5.js +0 -1
- package/.next/static/chunks/pages/[slug]/p-a27af8a8168e7c73.js +0 -1
- package/.next/static/css/131e3773fcbf70e4.css +0 -1
- package/.next/static/css/455d52db23e9236a.css +0 -1
- package/.next/static/css/cff9aafa16fccc9c.css +0 -1
- /package/.next/static/{nYzSKXE4KKqXVQ7J-XNJ4 → MicuvvXHUUVq_w--K0EDu}/_ssgManifest.js +0 -0
|
@@ -72,6 +72,10 @@ export interface CartSidebarProps {
|
|
|
72
72
|
quantitySelector: {
|
|
73
73
|
useUnitMultiplier?: boolean
|
|
74
74
|
}
|
|
75
|
+
taxesConfiguration?: {
|
|
76
|
+
usePriceWithTaxes?: boolean
|
|
77
|
+
taxesLabel?: string
|
|
78
|
+
}
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
function CartSidebar({
|
|
@@ -86,9 +90,19 @@ function CartSidebar({
|
|
|
86
90
|
icon: { icon: checkoutButtonIcon, alt: checkoutButtonIconAlt },
|
|
87
91
|
},
|
|
88
92
|
quantitySelector,
|
|
93
|
+
taxesConfiguration,
|
|
89
94
|
}: CartSidebarProps) {
|
|
90
95
|
const btnProps = useCheckoutButton()
|
|
91
|
-
const {
|
|
96
|
+
const {
|
|
97
|
+
items,
|
|
98
|
+
gifts,
|
|
99
|
+
totalItems,
|
|
100
|
+
isValidating,
|
|
101
|
+
subTotal,
|
|
102
|
+
total,
|
|
103
|
+
subTotalWithTaxes,
|
|
104
|
+
totalWithTaxes,
|
|
105
|
+
} = useCart({ useUnitMultiplier: quantitySelector?.useUnitMultiplier })
|
|
92
106
|
const { cart: displayCart, closeCart } = useUI()
|
|
93
107
|
const { fadeOut } = useFadeEffect()
|
|
94
108
|
const { sendViewCartEvent } = useViewCartEvent()
|
|
@@ -126,6 +140,7 @@ function CartSidebar({
|
|
|
126
140
|
<li key={item.id}>
|
|
127
141
|
<CartItem
|
|
128
142
|
item={item}
|
|
143
|
+
taxesConfiguration={taxesConfiguration}
|
|
129
144
|
useUnitMultiplier={
|
|
130
145
|
quantitySelector?.useUnitMultiplier ?? false
|
|
131
146
|
}
|
|
@@ -145,8 +160,18 @@ function CartSidebar({
|
|
|
145
160
|
|
|
146
161
|
<UICartSidebarFooter>
|
|
147
162
|
<OrderSummary
|
|
148
|
-
subTotal={
|
|
149
|
-
|
|
163
|
+
subTotal={
|
|
164
|
+
taxesConfiguration?.usePriceWithTaxes
|
|
165
|
+
? subTotalWithTaxes
|
|
166
|
+
: subTotal
|
|
167
|
+
}
|
|
168
|
+
total={
|
|
169
|
+
taxesConfiguration?.usePriceWithTaxes
|
|
170
|
+
? totalWithTaxes
|
|
171
|
+
: total
|
|
172
|
+
}
|
|
173
|
+
includeTaxes={taxesConfiguration?.usePriceWithTaxes}
|
|
174
|
+
includeTaxesLabel={taxesConfiguration?.taxesLabel}
|
|
150
175
|
numberOfItems={totalItems}
|
|
151
176
|
checkoutButton={
|
|
152
177
|
<UIButton
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
OrderSummary as UIOrderSummary,
|
|
3
|
+
OrderSummaryProps as UIOrderSummaryProps,
|
|
4
|
+
} from '@faststore/ui'
|
|
2
5
|
import type { ReactNode } from 'react'
|
|
3
6
|
|
|
4
7
|
import { useFormattedPrice } from 'src/sdk/product/useFormattedPrice'
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
type OrderSummaryProps = UIOrderSummaryProps & {
|
|
7
10
|
subTotal: number
|
|
8
11
|
total: number
|
|
9
12
|
numberOfItems: number
|
|
@@ -15,6 +18,7 @@ function OrderSummary({
|
|
|
15
18
|
total,
|
|
16
19
|
numberOfItems,
|
|
17
20
|
checkoutButton,
|
|
21
|
+
...otherProps
|
|
18
22
|
}: OrderSummaryProps) {
|
|
19
23
|
const discount = subTotal - total
|
|
20
24
|
const formattedDiscount = useFormattedPrice(discount)
|
|
@@ -26,6 +30,7 @@ function OrderSummary({
|
|
|
26
30
|
subtotalValue={useFormattedPrice(subTotal)}
|
|
27
31
|
discountValue={discount > 0 ? `-${formattedDiscount}` : undefined}
|
|
28
32
|
totalValue={useFormattedPrice(total)}
|
|
33
|
+
{...otherProps}
|
|
29
34
|
/>
|
|
30
35
|
{checkoutButton}
|
|
31
36
|
</>
|
|
@@ -50,6 +50,13 @@ export interface ProductCardProps {
|
|
|
50
50
|
* Enables a DiscountBadge to the component.
|
|
51
51
|
*/
|
|
52
52
|
showDiscountBadge?: boolean
|
|
53
|
+
/**
|
|
54
|
+
* Define taxes configuration, if taxes should be considered
|
|
55
|
+
*/
|
|
56
|
+
taxesConfiguration?: {
|
|
57
|
+
usePriceWithTaxes?: boolean
|
|
58
|
+
taxesLabel?: string
|
|
59
|
+
}
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
function ProductCard({
|
|
@@ -63,6 +70,7 @@ function ProductCard({
|
|
|
63
70
|
buttonLabel = 'Add',
|
|
64
71
|
onButtonClick,
|
|
65
72
|
showDiscountBadge = true,
|
|
73
|
+
taxesConfiguration,
|
|
66
74
|
...otherProps
|
|
67
75
|
}: ProductCardProps) {
|
|
68
76
|
const {
|
|
@@ -70,8 +78,9 @@ function ProductCard({
|
|
|
70
78
|
isVariantOf: { name },
|
|
71
79
|
image: [img],
|
|
72
80
|
offers: {
|
|
73
|
-
lowPrice
|
|
74
|
-
|
|
81
|
+
lowPrice,
|
|
82
|
+
lowPriceWithTaxes,
|
|
83
|
+
offers: [{ listPrice: listPriceBase, availability, listPriceWithTaxes }],
|
|
75
84
|
},
|
|
76
85
|
} = product
|
|
77
86
|
|
|
@@ -88,6 +97,13 @@ function ProductCard({
|
|
|
88
97
|
[availability]
|
|
89
98
|
)
|
|
90
99
|
|
|
100
|
+
const spotPrice = taxesConfiguration?.usePriceWithTaxes
|
|
101
|
+
? lowPriceWithTaxes
|
|
102
|
+
: lowPrice
|
|
103
|
+
const listPrice = taxesConfiguration?.usePriceWithTaxes
|
|
104
|
+
? listPriceWithTaxes
|
|
105
|
+
: listPriceBase
|
|
106
|
+
|
|
91
107
|
const hasDiscount = spotPrice <= listPrice
|
|
92
108
|
|
|
93
109
|
return (
|
|
@@ -120,6 +136,8 @@ function ProductCard({
|
|
|
120
136
|
onButtonClick={onButtonClick}
|
|
121
137
|
linkProps={linkProps}
|
|
122
138
|
showDiscountBadge={hasDiscount && showDiscountBadge}
|
|
139
|
+
includeTaxes={taxesConfiguration?.usePriceWithTaxes}
|
|
140
|
+
includeTaxesLabel={taxesConfiguration?.taxesLabel}
|
|
123
141
|
/>
|
|
124
142
|
</UIProductCard>
|
|
125
143
|
)
|
|
@@ -152,10 +170,12 @@ export const fragment = gql(`
|
|
|
152
170
|
|
|
153
171
|
offers {
|
|
154
172
|
lowPrice
|
|
173
|
+
lowPriceWithTaxes
|
|
155
174
|
offers {
|
|
156
175
|
availability
|
|
157
176
|
price
|
|
158
177
|
listPrice
|
|
178
|
+
listPriceWithTaxes
|
|
159
179
|
quantity
|
|
160
180
|
seller {
|
|
161
181
|
identifier
|
|
@@ -22,14 +22,17 @@ interface Props {
|
|
|
22
22
|
/**
|
|
23
23
|
* CMS defined data to be used in ProductCard component.
|
|
24
24
|
*/
|
|
25
|
-
productCard?: Pick<
|
|
25
|
+
productCard?: Pick<
|
|
26
|
+
ProductCardProps,
|
|
27
|
+
'showDiscountBadge' | 'bordered' | 'taxesConfiguration'
|
|
28
|
+
>
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
function ProductGrid({
|
|
29
32
|
products,
|
|
30
33
|
page,
|
|
31
34
|
pageSize,
|
|
32
|
-
productCard: { showDiscountBadge, bordered } = {},
|
|
35
|
+
productCard: { showDiscountBadge, bordered, taxesConfiguration } = {},
|
|
33
36
|
}: Props) {
|
|
34
37
|
const { __experimentalProductCard: ProductCard } =
|
|
35
38
|
useOverrideComponents<'ProductGallery'>()
|
|
@@ -58,6 +61,7 @@ function ProductGrid({
|
|
|
58
61
|
}
|
|
59
62
|
product={product}
|
|
60
63
|
index={pageSize * page + idx + 1}
|
|
64
|
+
taxesConfiguration={taxesConfiguration}
|
|
61
65
|
/>
|
|
62
66
|
</UIProductGridItem>
|
|
63
67
|
))}
|
|
@@ -13,12 +13,17 @@ interface Props {
|
|
|
13
13
|
itemsPerPage?: number
|
|
14
14
|
title: string
|
|
15
15
|
kind: 'buy' | 'view'
|
|
16
|
+
taxesConfiguration?: {
|
|
17
|
+
usePriceWithTaxes?: boolean
|
|
18
|
+
taxesLabel?: string
|
|
19
|
+
}
|
|
16
20
|
}
|
|
17
21
|
const CrossSellingShelf = ({
|
|
18
22
|
numberOfItems,
|
|
19
23
|
itemsPerPage,
|
|
20
24
|
title,
|
|
21
25
|
kind,
|
|
26
|
+
taxesConfiguration,
|
|
22
27
|
}: Props) => {
|
|
23
28
|
const { ref, inView } = useInView()
|
|
24
29
|
const context = usePDP()
|
|
@@ -40,6 +45,7 @@ const CrossSellingShelf = ({
|
|
|
40
45
|
itemsPerPage={itemsPerPage}
|
|
41
46
|
title={title}
|
|
42
47
|
selectedFacets={selectedFacets}
|
|
48
|
+
taxesConfiguration={taxesConfiguration}
|
|
43
49
|
/>
|
|
44
50
|
</Section>
|
|
45
51
|
)
|
|
@@ -52,6 +52,10 @@ export interface ProductDetailsProps {
|
|
|
52
52
|
quantitySelector: {
|
|
53
53
|
useUnitMultiplier?: boolean
|
|
54
54
|
}
|
|
55
|
+
taxesConfiguration?: {
|
|
56
|
+
usePriceWithTaxes?: boolean
|
|
57
|
+
taxesLabel?: string
|
|
58
|
+
}
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
function ProductDetails({
|
|
@@ -73,6 +77,7 @@ function ProductDetails({
|
|
|
73
77
|
},
|
|
74
78
|
notAvailableButton: { title: notAvailableButtonTitle },
|
|
75
79
|
quantitySelector,
|
|
80
|
+
taxesConfiguration,
|
|
76
81
|
}: ProductDetailsProps) {
|
|
77
82
|
const {
|
|
78
83
|
DiscountBadge,
|
|
@@ -103,8 +108,9 @@ function ProductDetails({
|
|
|
103
108
|
isVariantOf: { name, productGroupID: productId },
|
|
104
109
|
image: productImages,
|
|
105
110
|
offers: {
|
|
106
|
-
offers: [{ availability, price, listPrice, seller }],
|
|
111
|
+
offers: [{ availability, price, listPrice, listPriceWithTaxes, seller }],
|
|
107
112
|
lowPrice,
|
|
113
|
+
lowPriceWithTaxes,
|
|
108
114
|
},
|
|
109
115
|
} = product
|
|
110
116
|
|
|
@@ -164,8 +170,16 @@ function ProductDetails({
|
|
|
164
170
|
size={discountBadgeSize ?? DiscountBadge.props.size}
|
|
165
171
|
// Dynamic props shouldn't be overridable
|
|
166
172
|
// This decision can be reviewed later if needed
|
|
167
|
-
listPrice={
|
|
168
|
-
|
|
173
|
+
listPrice={
|
|
174
|
+
taxesConfiguration?.usePriceWithTaxes
|
|
175
|
+
? listPriceWithTaxes
|
|
176
|
+
: listPrice
|
|
177
|
+
}
|
|
178
|
+
spotPrice={
|
|
179
|
+
taxesConfiguration?.usePriceWithTaxes
|
|
180
|
+
? lowPriceWithTaxes
|
|
181
|
+
: lowPrice
|
|
182
|
+
}
|
|
169
183
|
/>
|
|
170
184
|
)
|
|
171
185
|
}
|
|
@@ -196,6 +210,7 @@ function ProductDetails({
|
|
|
196
210
|
setQuantity={setQuantity}
|
|
197
211
|
product={product}
|
|
198
212
|
isValidating={isValidating}
|
|
213
|
+
taxesConfiguration={taxesConfiguration}
|
|
199
214
|
/>
|
|
200
215
|
</section>
|
|
201
216
|
|
|
@@ -279,10 +294,13 @@ export const fragment = gql(`
|
|
|
279
294
|
|
|
280
295
|
offers {
|
|
281
296
|
lowPrice
|
|
297
|
+
lowPriceWithTaxes
|
|
282
298
|
offers {
|
|
283
299
|
availability
|
|
284
300
|
price
|
|
301
|
+
priceWithTaxes
|
|
285
302
|
listPrice
|
|
303
|
+
listPriceWithTaxes
|
|
286
304
|
seller {
|
|
287
305
|
identifier
|
|
288
306
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
@layer components {
|
|
2
2
|
.section {
|
|
3
|
+
// Taxes label
|
|
4
|
+
--fs-product-details-taxes-label-color : var(--fs-color-info-text);
|
|
5
|
+
--fs-product-details-taxes-text-size : var(--fs-text-size-tiny);
|
|
6
|
+
--fs-product-details-taxes-text-weight : var(--fs-text-weight-regular);
|
|
7
|
+
|
|
3
8
|
margin-top: 0;
|
|
4
9
|
|
|
5
10
|
@import "@faststore/ui/src/components/atoms/Icon/styles.scss";
|
|
@@ -24,5 +29,11 @@
|
|
|
24
29
|
@import "@faststore/ui/src/components/organisms/ShippingSimulation/styles.scss";
|
|
25
30
|
@import "@faststore/ui/src/components/organisms/ImageGallery/styles.scss";
|
|
26
31
|
@import "@faststore/ui/src/components/organisms/ProductDetails/styles.scss";
|
|
32
|
+
|
|
33
|
+
[data-fs-product-details-taxes-label] {
|
|
34
|
+
font-size: var(--fs-product-details-taxes-text-size);
|
|
35
|
+
font-weight: var(--fs-product-details-taxes-text-weight);
|
|
36
|
+
color: var(--fs-product-details-taxes-label-color);
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
39
|
}
|
|
@@ -15,6 +15,10 @@ import styles from './section.module.scss'
|
|
|
15
15
|
interface ProductTilesProps
|
|
16
16
|
extends Partial<ClientManyProductsQueryQueryVariables> {
|
|
17
17
|
title: string
|
|
18
|
+
taxesConfiguration?: {
|
|
19
|
+
usePriceWithTaxes?: boolean
|
|
20
|
+
taxesLabel?: string
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
const NUMBER_ITEMS_TO_EXPAND_FIRST = 3
|
|
@@ -54,7 +58,11 @@ const getSizes = (products: number, idx: number) => {
|
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
|
|
57
|
-
const ProductTiles = ({
|
|
61
|
+
const ProductTiles = ({
|
|
62
|
+
title,
|
|
63
|
+
taxesConfiguration,
|
|
64
|
+
...variables
|
|
65
|
+
}: ProductTilesProps) => {
|
|
58
66
|
const viewedOnce = useRef(false)
|
|
59
67
|
const { ref, inView } = useInView()
|
|
60
68
|
const data = useProductsQuery(variables)
|
|
@@ -97,6 +105,7 @@ const ProductTiles = ({ title, ...variables }: ProductTilesProps) => {
|
|
|
97
105
|
variant="wide"
|
|
98
106
|
aspectRatio={getRatio(productEdges.length, idx)}
|
|
99
107
|
imgProps={getSizes(productEdges.length, idx)}
|
|
108
|
+
taxesConfiguration={taxesConfiguration}
|
|
100
109
|
/>
|
|
101
110
|
</Tile>
|
|
102
111
|
))}
|
|
@@ -10,6 +10,7 @@ import Selectors from 'src/components/ui/SkuSelector'
|
|
|
10
10
|
import AddToCartLoadingSkeleton from './AddToCartLoadingSkeleton'
|
|
11
11
|
|
|
12
12
|
import { useOverrideComponents } from 'src/sdk/overrides/OverrideContext'
|
|
13
|
+
import { Label as UILabel } from '@faststore/ui'
|
|
13
14
|
|
|
14
15
|
interface ProductDetailsSettingsProps {
|
|
15
16
|
product: ProductDetailsFragment_ProductFragment
|
|
@@ -22,7 +23,11 @@ interface ProductDetailsSettingsProps {
|
|
|
22
23
|
quantity: number
|
|
23
24
|
setQuantity: Dispatch<SetStateAction<number>>
|
|
24
25
|
notAvailableButtonTitle: string
|
|
25
|
-
useUnitMultiplier
|
|
26
|
+
useUnitMultiplier?: boolean
|
|
27
|
+
taxesConfiguration?: {
|
|
28
|
+
usePriceWithTaxes?: boolean
|
|
29
|
+
taxesLabel?: string
|
|
30
|
+
}
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
function ProductDetailsSettings({
|
|
@@ -33,7 +38,8 @@ function ProductDetailsSettings({
|
|
|
33
38
|
setQuantity,
|
|
34
39
|
buyButtonIcon: { icon: buyButtonIconName, alt: buyButtonIconAlt },
|
|
35
40
|
notAvailableButtonTitle,
|
|
36
|
-
useUnitMultiplier,
|
|
41
|
+
useUnitMultiplier = false,
|
|
42
|
+
taxesConfiguration,
|
|
37
43
|
}: ProductDetailsSettingsProps) {
|
|
38
44
|
const {
|
|
39
45
|
BuyButton,
|
|
@@ -55,14 +61,25 @@ function ProductDetailsSettings({
|
|
|
55
61
|
image: productImages,
|
|
56
62
|
additionalProperty,
|
|
57
63
|
offers: {
|
|
58
|
-
offers: [
|
|
64
|
+
offers: [
|
|
65
|
+
{
|
|
66
|
+
availability,
|
|
67
|
+
price,
|
|
68
|
+
priceWithTaxes,
|
|
69
|
+
listPrice,
|
|
70
|
+
seller,
|
|
71
|
+
listPriceWithTaxes,
|
|
72
|
+
},
|
|
73
|
+
],
|
|
59
74
|
},
|
|
60
75
|
} = product
|
|
61
76
|
|
|
62
77
|
const buyProps = useBuyButton({
|
|
63
78
|
id,
|
|
64
79
|
price,
|
|
80
|
+
priceWithTaxes,
|
|
65
81
|
listPrice,
|
|
82
|
+
listPriceWithTaxes,
|
|
66
83
|
seller,
|
|
67
84
|
quantity,
|
|
68
85
|
itemOffered: {
|
|
@@ -109,13 +126,28 @@ function ProductDetailsSettings({
|
|
|
109
126
|
<>
|
|
110
127
|
{!outOfStock && (
|
|
111
128
|
<section data-fs-product-details-values>
|
|
112
|
-
<
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
129
|
+
<div data-fs-product-details-values-wrapper>
|
|
130
|
+
<ProductPrice.Component
|
|
131
|
+
data-fs-product-details-prices
|
|
132
|
+
value={
|
|
133
|
+
(taxesConfiguration?.usePriceWithTaxes
|
|
134
|
+
? priceWithTaxes
|
|
135
|
+
: price) * (unitMultiplier ?? 1)
|
|
136
|
+
}
|
|
137
|
+
listPrice={
|
|
138
|
+
(taxesConfiguration?.usePriceWithTaxes
|
|
139
|
+
? listPriceWithTaxes
|
|
140
|
+
: listPrice) * (unitMultiplier ?? 1)
|
|
141
|
+
}
|
|
142
|
+
formatter={useFormattedPrice}
|
|
143
|
+
{...ProductPrice.props}
|
|
144
|
+
/>
|
|
145
|
+
{taxesConfiguration?.usePriceWithTaxes && (
|
|
146
|
+
<UILabel data-fs-product-details-taxes-label>
|
|
147
|
+
{taxesConfiguration?.taxesLabel}
|
|
148
|
+
</UILabel>
|
|
149
|
+
)}
|
|
150
|
+
</div>
|
|
119
151
|
<QuantitySelector.Component
|
|
120
152
|
min={1}
|
|
121
153
|
max={10}
|
|
@@ -57,7 +57,10 @@ export interface ProductGalleryProps {
|
|
|
57
57
|
label?: string
|
|
58
58
|
}
|
|
59
59
|
sortBySelector?: SortProps
|
|
60
|
-
productCard?: Pick<
|
|
60
|
+
productCard?: Pick<
|
|
61
|
+
ProductCardProps,
|
|
62
|
+
'showDiscountBadge' | 'bordered' | 'taxesConfiguration'
|
|
63
|
+
>
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
function ProductGallery({
|
|
@@ -8,7 +8,10 @@ import { useGalleryPage } from 'src/sdk/product/usePageProductsQuery'
|
|
|
8
8
|
interface Props {
|
|
9
9
|
page: number
|
|
10
10
|
title: string
|
|
11
|
-
productCard?: Pick<
|
|
11
|
+
productCard?: Pick<
|
|
12
|
+
ProductCardProps,
|
|
13
|
+
'showDiscountBadge' | 'bordered' | 'taxesConfiguration'
|
|
14
|
+
>
|
|
12
15
|
itemsPerPage: number
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -27,6 +27,10 @@ export type ProductShelfProps = {
|
|
|
27
27
|
key: string
|
|
28
28
|
value: string
|
|
29
29
|
}[]
|
|
30
|
+
taxesConfiguration?: {
|
|
31
|
+
usePriceWithTaxes?: boolean
|
|
32
|
+
taxesLabel?: string
|
|
33
|
+
}
|
|
30
34
|
productCardConfiguration?: {
|
|
31
35
|
showDiscountBadge?: boolean
|
|
32
36
|
bordered?: boolean
|
|
@@ -40,6 +44,7 @@ function ProductShelf({
|
|
|
40
44
|
productCardConfiguration: { bordered, showDiscountBadge } = {},
|
|
41
45
|
numberOfItems,
|
|
42
46
|
itemsPerPage = 5,
|
|
47
|
+
taxesConfiguration = {},
|
|
43
48
|
...otherProps
|
|
44
49
|
}: ProductShelfProps) {
|
|
45
50
|
const {
|
|
@@ -101,6 +106,7 @@ function ProductShelf({
|
|
|
101
106
|
showDiscountBadge={
|
|
102
107
|
showDiscountBadge ?? ProductCard.props.showDiscountBadge
|
|
103
108
|
}
|
|
109
|
+
taxesConfiguration={taxesConfiguration}
|
|
104
110
|
// Dynamic props shouldn't be overridable
|
|
105
111
|
// This decision can be reviewed later if needed
|
|
106
112
|
key={`${product.node.id}`}
|
package/src/pages/[slug]/p.tsx
CHANGED
package/src/sdk/cart/index.ts
CHANGED
|
@@ -49,7 +49,9 @@ export const ValidateCartMutation = gql(`
|
|
|
49
49
|
}
|
|
50
50
|
quantity
|
|
51
51
|
price
|
|
52
|
+
priceWithTaxes
|
|
52
53
|
listPrice
|
|
54
|
+
listPriceWithTaxes
|
|
53
55
|
itemOffered {
|
|
54
56
|
...CartProductItem
|
|
55
57
|
}
|
|
@@ -115,18 +117,20 @@ const validateCart = async (cart: Cart): Promise<Cart | null> => {
|
|
|
115
117
|
seller,
|
|
116
118
|
quantity,
|
|
117
119
|
itemOffered,
|
|
118
|
-
}): IStoreOffer =>
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
120
|
+
}): IStoreOffer => {
|
|
121
|
+
return {
|
|
122
|
+
price,
|
|
123
|
+
listPrice,
|
|
124
|
+
seller,
|
|
125
|
+
quantity,
|
|
126
|
+
itemOffered: {
|
|
127
|
+
sku: itemOffered.sku,
|
|
128
|
+
image: itemOffered.image,
|
|
129
|
+
name: itemOffered.name,
|
|
130
|
+
additionalProperty: itemOffered.additionalProperty,
|
|
131
|
+
},
|
|
132
|
+
}
|
|
133
|
+
}
|
|
130
134
|
),
|
|
131
135
|
},
|
|
132
136
|
},
|
|
@@ -159,31 +163,45 @@ export const cartStore = {
|
|
|
159
163
|
},
|
|
160
164
|
}
|
|
161
165
|
|
|
162
|
-
export const useCart = (
|
|
166
|
+
export const useCart = (
|
|
167
|
+
{ useUnitMultiplier } = { useUnitMultiplier: false }
|
|
168
|
+
) => {
|
|
163
169
|
const cart = useStore(cartStore)
|
|
164
170
|
const isValidating = useStore(validationStore)
|
|
165
171
|
|
|
166
|
-
return useMemo(
|
|
167
|
-
|
|
172
|
+
return useMemo(() => {
|
|
173
|
+
const cartTotals = cart.items.reduce(
|
|
174
|
+
(totals, curr) => {
|
|
175
|
+
totals.total += curr.price * curr.quantity
|
|
176
|
+
totals.totalWithTaxes += curr.priceWithTaxes * curr.quantity
|
|
177
|
+
|
|
178
|
+
const quantityMultiplier = useUnitMultiplier
|
|
179
|
+
? curr.quantity * (curr?.itemOffered?.unitMultiplier ?? 1)
|
|
180
|
+
: curr.quantity
|
|
181
|
+
|
|
182
|
+
totals.totalItems += isGift(curr) ? 0 : quantityMultiplier
|
|
183
|
+
totals.subTotal += curr.listPrice * quantityMultiplier
|
|
184
|
+
totals.subTotalWithTaxes += curr.listPriceWithTaxes * quantityMultiplier
|
|
185
|
+
|
|
186
|
+
return totals
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
totalItems: 0,
|
|
190
|
+
total: 0,
|
|
191
|
+
subTotal: 0,
|
|
192
|
+
totalWithTaxes: 0,
|
|
193
|
+
subTotalWithTaxes: 0,
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
return {
|
|
168
198
|
...cart,
|
|
199
|
+
...cartTotals,
|
|
169
200
|
isValidating,
|
|
170
201
|
messages: cart.messages,
|
|
171
202
|
gifts: cart.items.filter((item) => isGift(item)),
|
|
172
203
|
items: cart.items.filter((item) => !isGift(item)),
|
|
173
204
|
totalUniqueItems: cart.items.length,
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
0
|
|
177
|
-
),
|
|
178
|
-
total: cart.items.reduce(
|
|
179
|
-
(acc, curr) => acc + curr.price * curr.quantity,
|
|
180
|
-
0
|
|
181
|
-
),
|
|
182
|
-
subTotal: cart.items.reduce(
|
|
183
|
-
(acc, curr) => acc + curr.listPrice * curr.quantity,
|
|
184
|
-
0
|
|
185
|
-
),
|
|
186
|
-
}),
|
|
187
|
-
[cart, isValidating]
|
|
188
|
-
)
|
|
205
|
+
}
|
|
206
|
+
}, [cart, isValidating, useUnitMultiplier])
|
|
189
207
|
}
|