@faststore/core 3.0.73 → 3.0.75

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 (78) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +35 -35
  3. package/.next/cache/.tsbuildinfo +1 -1
  4. package/.next/cache/config.json +3 -3
  5. package/.next/cache/eslint/.cache_1gneedd +1 -1
  6. package/.next/cache/webpack/client-production/0.pack +0 -0
  7. package/.next/cache/webpack/client-production/index.pack +0 -0
  8. package/.next/cache/webpack/server-production/0.pack +0 -0
  9. package/.next/cache/webpack/server-production/index.pack +0 -0
  10. package/.next/next-server.js.nft.json +1 -1
  11. package/.next/prerender-manifest.js +1 -1
  12. package/.next/prerender-manifest.json +1 -1
  13. package/.next/react-loadable-manifest.json +3 -3
  14. package/.next/routes-manifest.json +1 -1
  15. package/.next/server/chunks/247.js +1 -1
  16. package/.next/server/chunks/350.js +1 -1
  17. package/.next/server/chunks/485.js +2 -2
  18. package/.next/server/chunks/646.js +9 -2
  19. package/.next/server/chunks/96.js +1 -1
  20. package/.next/server/middleware-build-manifest.js +1 -1
  21. package/.next/server/middleware-react-loadable-manifest.js +1 -1
  22. package/.next/server/pages/[...slug].js.nft.json +1 -1
  23. package/.next/server/pages/[slug]/p.js +1 -1
  24. package/.next/server/pages/[slug]/p.js.nft.json +1 -1
  25. package/.next/server/pages/api/graphql.js +1 -1
  26. package/.next/server/pages/api/graphql.js.nft.json +1 -1
  27. package/.next/server/pages/en-US/404.html +2 -2
  28. package/.next/server/pages/en-US/500.html +2 -2
  29. package/.next/server/pages/en-US/account.html +2 -2
  30. package/.next/server/pages/en-US/checkout.html +2 -2
  31. package/.next/server/pages/en-US/login.html +2 -2
  32. package/.next/server/pages/en-US/s.html +2 -2
  33. package/.next/server/pages/en-US.html +2 -2
  34. package/.next/server/pages-manifest.json +1 -1
  35. package/.next/static/{GB2C_IQhpGsuLLX0K-ny1 → 86oMoNlJHH0MqVuMHG536}/_buildManifest.js +1 -1
  36. package/.next/static/chunks/104-8bf09f16d6f3a4cd.js +1 -0
  37. package/.next/static/chunks/247.50945bfe8f760e62.js +1 -0
  38. package/.next/static/chunks/661-fc56d46a6f6ad0a8.js +1 -0
  39. package/.next/static/chunks/758.a411edd1cbd09134.js +1 -0
  40. package/.next/static/chunks/pages/[...slug]-c83d89b6d411553c.js +1 -0
  41. package/.next/static/chunks/pages/[slug]/p-e75ab6f3f36d8f19.js +1 -0
  42. package/.next/static/chunks/{webpack-fdd195abd12b3685.js → webpack-e9b95bf547123b36.js} +1 -1
  43. package/.next/static/css/{cff9aafa16fccc9c.css → 002309c74e696c85.css} +1 -1
  44. package/.next/static/css/{131e3773fcbf70e4.css → 0cbe11ce717a6c2c.css} +1 -1
  45. package/.next/static/css/30a88c3e4b758d2e.css +1 -0
  46. package/.next/static/css/{211c7542af66d8b4.css → 88c892db4c8964d5.css} +1 -1
  47. package/.next/trace +95 -95
  48. package/.turbo/turbo-build.log +12 -12
  49. package/.turbo/turbo-test.log +4 -4
  50. package/@generated/gql.ts +8 -8
  51. package/@generated/graphql.ts +37 -5
  52. package/@generated/persisted-documents.json +5 -5
  53. package/@generated/schema.graphql +6 -0
  54. package/cms/faststore/sections.json +96 -0
  55. package/package.json +5 -5
  56. package/src/components/cart/CartItem/CartItem.tsx +21 -3
  57. package/src/components/cart/CartSidebar/CartSidebar.tsx +28 -3
  58. package/src/components/cart/OrderSummary/OrderSummary.tsx +7 -2
  59. package/src/components/product/ProductCard/ProductCard.tsx +22 -2
  60. package/src/components/product/ProductGrid/ProductGrid.tsx +6 -2
  61. package/src/components/sections/CrossSellingShelf/CrossSellingShelf.tsx +6 -0
  62. package/src/components/sections/ProductDetails/ProductDetails.tsx +21 -3
  63. package/src/components/sections/ProductDetails/section.module.scss +11 -0
  64. package/src/components/sections/ProductTiles/ProductTiles.tsx +10 -1
  65. package/src/components/ui/ProductDetails/ProductDetailsSettings.tsx +42 -10
  66. package/src/components/ui/ProductGallery/ProductGallery.tsx +4 -1
  67. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +4 -1
  68. package/src/components/ui/ProductShelf/ProductShelf.tsx +6 -0
  69. package/src/pages/[slug]/p.tsx +1 -0
  70. package/src/sdk/cart/index.ts +48 -30
  71. package/.next/static/chunks/104-e89fd47aa32b199b.js +0 -1
  72. package/.next/static/chunks/247.6eb0f179401e9e2f.js +0 -1
  73. package/.next/static/chunks/661-0ff17cbc40856afe.js +0 -1
  74. package/.next/static/chunks/758.9ca1da3ac30b665d.js +0 -1
  75. package/.next/static/chunks/pages/[...slug]-484e64ab6c753be5.js +0 -1
  76. package/.next/static/chunks/pages/[slug]/p-a27af8a8168e7c73.js +0 -1
  77. package/.next/static/css/455d52db23e9236a.css +0 -1
  78. /package/.next/static/{GB2C_IQhpGsuLLX0K-ny1 → 86oMoNlJHH0MqVuMHG536}/_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 { items, gifts, totalItems, isValidating, subTotal, total } = useCart()
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={subTotal}
149
- total={total}
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 { OrderSummary as UIOrderSummary } from '@faststore/ui'
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
- interface OrderSummaryProps {
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: spotPrice,
74
- offers: [{ listPrice, availability }],
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<ProductCardProps, 'showDiscountBadge' | 'bordered'>
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={listPrice}
168
- spotPrice={lowPrice}
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 = ({ title, ...variables }: ProductTilesProps) => {
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: boolean
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: [{ availability, price, listPrice, seller }],
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
- <ProductPrice.Component
113
- data-fs-product-details-prices
114
- value={price}
115
- listPrice={listPrice}
116
- formatter={useFormattedPrice}
117
- {...ProductPrice.props}
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<ProductCardProps, 'showDiscountBadge' | 'bordered'>
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<ProductCardProps, 'showDiscountBadge' | 'bordered'>
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}`}
@@ -181,6 +181,7 @@ const query = gql(`
181
181
  offers {
182
182
  lowPrice
183
183
  highPrice
184
+ lowPriceWithTaxes
184
185
  priceCurrency
185
186
  offers {
186
187
  availability
@@ -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
- price,
120
- listPrice,
121
- seller,
122
- quantity,
123
- itemOffered: {
124
- sku: itemOffered.sku,
125
- image: itemOffered.image,
126
- name: itemOffered.name,
127
- additionalProperty: itemOffered.additionalProperty,
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
- totalItems: cart.items.reduce(
175
- (acc, curr) => acc + (isGift(curr) ? 0 : curr.quantity),
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
  }