@graphcommerce/magento-product 8.1.0-canary.19 → 8.1.0-canary.20
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/CHANGELOG.md +2 -0
- package/components/AddProductsToCart/AddProductsToCartButton.tsx +1 -0
- package/components/AddProductsToCart/AddProductsToCartForm.tsx +7 -2
- package/components/AddProductsToCart/useFormAddProductsToCart.ts +1 -2
- package/components/ProductCustomizable/index.ts +1 -0
- package/components/ProductCustomizable/productCustomizableSelectors.ts +59 -0
- package/components/ProductPagePrice/useCustomizableOptionPrice.ts +11 -53
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
@@ -5,7 +5,7 @@ import {
|
|
5
5
|
CrosssellsDocument,
|
6
6
|
CrosssellsQuery,
|
7
7
|
} from '@graphcommerce/magento-cart'
|
8
|
-
import { ExtendableComponent } from '@graphcommerce/next-ui'
|
8
|
+
import { ExtendableComponent, nonNullable } from '@graphcommerce/next-ui'
|
9
9
|
import { Box, SxProps, Theme, useThemeProps } from '@mui/material'
|
10
10
|
import { useRouter } from 'next/router'
|
11
11
|
import { useMemo, useRef } from 'react'
|
@@ -103,7 +103,12 @@ export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
|
|
103
103
|
...(cartItem.selected_options ?? []).filter(Boolean),
|
104
104
|
...options,
|
105
105
|
],
|
106
|
-
entered_options:
|
106
|
+
entered_options: [
|
107
|
+
...(cartItem.entered_options
|
108
|
+
?.filter((option) => option?.value)
|
109
|
+
.filter(nonNullable)
|
110
|
+
.map((option) => ({ uid: option.uid, value: `${option?.value}` })) ?? []),
|
111
|
+
],
|
107
112
|
}
|
108
113
|
}),
|
109
114
|
}
|
@@ -1,11 +1,10 @@
|
|
1
1
|
import { UseFormGqlMutationReturn } from '@graphcommerce/ecommerce-ui'
|
2
2
|
import { createContext, useContext } from 'react'
|
3
|
-
import type { LiteralUnion } from 'type-fest'
|
3
|
+
import type { Simplify, LiteralUnion } from 'type-fest'
|
4
4
|
import {
|
5
5
|
AddProductsToCartMutation,
|
6
6
|
AddProductsToCartMutationVariables,
|
7
7
|
} from './AddProductsToCart.gql'
|
8
|
-
import { Simplify } from 'type-fest'
|
9
8
|
|
10
9
|
export type RedirectType = LiteralUnion<'added' | undefined | false, `/${string}`>
|
11
10
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import type { PriceTypeEnum } from '@graphcommerce/graphql-mesh'
|
2
|
+
import type { Simplify } from 'type-fest'
|
3
|
+
import type { CustomizableAreaOptionFragment } from './CustomizableAreaOption.gql'
|
4
|
+
import type { CustomizableCheckboxOptionFragment } from './CustomizableCheckboxOption.gql'
|
5
|
+
import type { CustomizableDateOptionFragment } from './CustomizableDateOption.gql'
|
6
|
+
import type { CustomizableDropDownOptionFragment } from './CustomizableDropDownOption.gql'
|
7
|
+
import type { CustomizableFieldOptionFragment } from './CustomizableFieldOption.gql'
|
8
|
+
import type { CustomizableFileOptionFragment } from './CustomizableFileOption.gql'
|
9
|
+
import type { CustomizableMultipleOptionFragment } from './CustomizableMultipleOption.gql'
|
10
|
+
import type { CustomizableRadioOptionFragment } from './CustomizableRadioOption.gql'
|
11
|
+
import type { ProductCustomizable_SimpleProduct_Fragment } from './ProductCustomizable.gql'
|
12
|
+
|
13
|
+
export type CustomizableProductOptionBase =
|
14
|
+
| {
|
15
|
+
price?: number | null | undefined
|
16
|
+
price_type?: PriceTypeEnum | null | undefined
|
17
|
+
uid?: string | null | undefined
|
18
|
+
}
|
19
|
+
| undefined
|
20
|
+
| null
|
21
|
+
|
22
|
+
export type AnyOption = NonNullable<
|
23
|
+
NonNullable<ProductCustomizable_SimpleProduct_Fragment['options']>[number]
|
24
|
+
>
|
25
|
+
|
26
|
+
export type OptionValueSelector = {
|
27
|
+
[T in AnyOption as T['__typename']]: (
|
28
|
+
option: T,
|
29
|
+
) => CustomizableProductOptionBase | CustomizableProductOptionBase[]
|
30
|
+
}
|
31
|
+
|
32
|
+
type MissingOptionValueSelectors = Omit<
|
33
|
+
OptionValueSelector,
|
34
|
+
keyof typeof productCustomizableSelectors
|
35
|
+
>
|
36
|
+
type DefinedOptionValueSelectors = Partial<
|
37
|
+
Pick<OptionValueSelector, keyof typeof productCustomizableSelectors>
|
38
|
+
>
|
39
|
+
|
40
|
+
type Selectors = Simplify<
|
41
|
+
keyof MissingOptionValueSelectors extends never
|
42
|
+
? (MissingOptionValueSelectors & DefinedOptionValueSelectors) | undefined
|
43
|
+
: MissingOptionValueSelectors & DefinedOptionValueSelectors
|
44
|
+
>
|
45
|
+
|
46
|
+
export const productCustomizableSelectors = {
|
47
|
+
CustomizableAreaOption: (o: CustomizableAreaOptionFragment) => o.areaValue,
|
48
|
+
CustomizableCheckboxOption: (o: CustomizableCheckboxOptionFragment) => o.checkboxValue,
|
49
|
+
CustomizableFileOption: (o: CustomizableFileOptionFragment) => o.fileValue,
|
50
|
+
CustomizableDateOption: (o: CustomizableDateOptionFragment) => o.dateValue,
|
51
|
+
CustomizableDropDownOption: (o: CustomizableDropDownOptionFragment) => o.dropdownValue,
|
52
|
+
CustomizableFieldOption: (o: CustomizableFieldOptionFragment) => o.fieldValue,
|
53
|
+
CustomizableMultipleOption: (o: CustomizableMultipleOptionFragment) => o.multipleValue,
|
54
|
+
CustomizableRadioOption: (o: CustomizableRadioOptionFragment) => o.radioValue,
|
55
|
+
}
|
56
|
+
|
57
|
+
export type SelectorsProp = keyof MissingOptionValueSelectors extends never
|
58
|
+
? { selectors?: Selectors }
|
59
|
+
: { selectors: Selectors }
|
@@ -1,65 +1,23 @@
|
|
1
1
|
import { useWatch } from '@graphcommerce/ecommerce-ui'
|
2
|
-
import { PriceTypeEnum } from '@graphcommerce/graphql-mesh'
|
3
2
|
import { MoneyFragment } from '@graphcommerce/magento-store'
|
4
3
|
import { filterNonNullableKeys, isTypename, nonNullable } from '@graphcommerce/next-ui'
|
5
|
-
import type { Simplify } from 'type-fest'
|
6
4
|
import { AddToCartItemSelector, useFormAddProductsToCart } from '../AddProductsToCart'
|
7
|
-
import
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
import { CustomizableRadioOptionFragment } from '../ProductCustomizable/CustomizableRadioOption.gql'
|
15
|
-
import { ProductCustomizable_SimpleProduct_Fragment } from '../ProductCustomizable/ProductCustomizable.gql'
|
5
|
+
import {
|
6
|
+
productCustomizableSelectors,
|
7
|
+
CustomizableProductOptionBase,
|
8
|
+
OptionValueSelector,
|
9
|
+
AnyOption,
|
10
|
+
SelectorsProp,
|
11
|
+
} from '../ProductCustomizable/productCustomizableSelectors'
|
16
12
|
import { ProductPagePriceFragment } from './ProductPagePrice.gql'
|
17
13
|
import { getProductTierPrice } from './getProductTierPrice'
|
18
14
|
|
19
|
-
type AnyOption = NonNullable<
|
20
|
-
NonNullable<ProductCustomizable_SimpleProduct_Fragment['options']>[number]
|
21
|
-
>
|
22
|
-
type OptionValueSelector = {
|
23
|
-
[T in AnyOption as T['__typename']]: (option: T) => Option | Option[]
|
24
|
-
}
|
25
|
-
|
26
|
-
const defaultSelectors = {
|
27
|
-
CustomizableAreaOption: (o: CustomizableAreaOptionFragment) => o.areaValue,
|
28
|
-
CustomizableCheckboxOption: (o: CustomizableCheckboxOptionFragment) => o.checkboxValue,
|
29
|
-
CustomizableFileOption: (o: CustomizableFileOptionFragment) => o.fileValue,
|
30
|
-
CustomizableDateOption: (o: CustomizableDateOptionFragment) => o.dateValue,
|
31
|
-
CustomizableDropDownOption: (o: CustomizableDropDownOptionFragment) => o.dropdownValue,
|
32
|
-
CustomizableFieldOption: (o: CustomizableFieldOptionFragment) => o.fieldValue,
|
33
|
-
CustomizableMultipleOption: (o: CustomizableMultipleOptionFragment) => o.multipleValue,
|
34
|
-
CustomizableRadioOption: (o: CustomizableRadioOptionFragment) => o.radioValue,
|
35
|
-
}
|
36
|
-
|
37
|
-
type MissingOptionValueSelectors = Omit<OptionValueSelector, keyof typeof defaultSelectors>
|
38
|
-
type DefinedOptionValueSelectors = Partial<Pick<OptionValueSelector, keyof typeof defaultSelectors>>
|
39
|
-
|
40
|
-
type Selectors = Simplify<
|
41
|
-
keyof MissingOptionValueSelectors extends never
|
42
|
-
? (MissingOptionValueSelectors & DefinedOptionValueSelectors) | undefined
|
43
|
-
: MissingOptionValueSelectors & DefinedOptionValueSelectors
|
44
|
-
>
|
45
|
-
|
46
15
|
export type UseCustomizableOptionPriceProps = {
|
47
16
|
product: ProductPagePriceFragment
|
48
17
|
} & AddToCartItemSelector &
|
49
|
-
|
50
|
-
? { selectors?: Selectors }
|
51
|
-
: { selectors: Selectors })
|
52
|
-
|
53
|
-
type Option =
|
54
|
-
| {
|
55
|
-
price?: number | null | undefined
|
56
|
-
price_type?: PriceTypeEnum | null | undefined
|
57
|
-
uid?: string | null | undefined
|
58
|
-
}
|
59
|
-
| undefined
|
60
|
-
| null
|
18
|
+
SelectorsProp
|
61
19
|
|
62
|
-
function calcOptionPrice(option:
|
20
|
+
function calcOptionPrice(option: CustomizableProductOptionBase, product: MoneyFragment) {
|
63
21
|
if (!option?.price) return 0
|
64
22
|
switch (option.price_type) {
|
65
23
|
case 'DYNAMIC':
|
@@ -81,7 +39,7 @@ export function useCustomizableOptionPrice(props: UseCustomizableOptionPriceProp
|
|
81
39
|
getProductTierPrice(product, cartItem?.quantity) ??
|
82
40
|
product.price_range.minimum_price.final_price
|
83
41
|
|
84
|
-
const allSelectors: OptionValueSelector = { ...
|
42
|
+
const allSelectors: OptionValueSelector = { ...productCustomizableSelectors, ...selectors }
|
85
43
|
|
86
44
|
if (isTypename(product, ['GroupedProduct'])) return price.value
|
87
45
|
if (!product.options || product.options.length === 0) return price.value
|
@@ -95,7 +53,7 @@ export function useCustomizableOptionPrice(props: UseCustomizableOptionPriceProp
|
|
95
53
|
|
96
54
|
const selector = allSelectors[productOption.__typename] as
|
97
55
|
| undefined
|
98
|
-
| ((option: AnyOption) =>
|
56
|
+
| ((option: AnyOption) => CustomizableProductOptionBase | CustomizableProductOptionBase[])
|
99
57
|
const value = selector ? selector(productOption) : null
|
100
58
|
|
101
59
|
if (!value) return 0
|
package/package.json
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
"name": "@graphcommerce/magento-product",
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
5
|
-
"version": "8.1.0-canary.
|
5
|
+
"version": "8.1.0-canary.20",
|
6
6
|
"sideEffects": false,
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
8
8
|
"eslintConfig": {
|
@@ -18,18 +18,18 @@
|
|
18
18
|
"typescript": "5.3.3"
|
19
19
|
},
|
20
20
|
"peerDependencies": {
|
21
|
-
"@graphcommerce/ecommerce-ui": "^8.1.0-canary.
|
22
|
-
"@graphcommerce/eslint-config-pwa": "^8.1.0-canary.
|
23
|
-
"@graphcommerce/framer-next-pages": "^8.1.0-canary.
|
24
|
-
"@graphcommerce/framer-scroller": "^8.1.0-canary.
|
25
|
-
"@graphcommerce/graphql": "^8.1.0-canary.
|
26
|
-
"@graphcommerce/graphql-mesh": "^8.1.0-canary.
|
27
|
-
"@graphcommerce/image": "^8.1.0-canary.
|
28
|
-
"@graphcommerce/magento-cart": "^8.1.0-canary.
|
29
|
-
"@graphcommerce/magento-store": "^8.1.0-canary.
|
30
|
-
"@graphcommerce/next-ui": "^8.1.0-canary.
|
31
|
-
"@graphcommerce/prettier-config-pwa": "^8.1.0-canary.
|
32
|
-
"@graphcommerce/typescript-config-pwa": "^8.1.0-canary.
|
21
|
+
"@graphcommerce/ecommerce-ui": "^8.1.0-canary.20",
|
22
|
+
"@graphcommerce/eslint-config-pwa": "^8.1.0-canary.20",
|
23
|
+
"@graphcommerce/framer-next-pages": "^8.1.0-canary.20",
|
24
|
+
"@graphcommerce/framer-scroller": "^8.1.0-canary.20",
|
25
|
+
"@graphcommerce/graphql": "^8.1.0-canary.20",
|
26
|
+
"@graphcommerce/graphql-mesh": "^8.1.0-canary.20",
|
27
|
+
"@graphcommerce/image": "^8.1.0-canary.20",
|
28
|
+
"@graphcommerce/magento-cart": "^8.1.0-canary.20",
|
29
|
+
"@graphcommerce/magento-store": "^8.1.0-canary.20",
|
30
|
+
"@graphcommerce/next-ui": "^8.1.0-canary.20",
|
31
|
+
"@graphcommerce/prettier-config-pwa": "^8.1.0-canary.20",
|
32
|
+
"@graphcommerce/typescript-config-pwa": "^8.1.0-canary.20",
|
33
33
|
"@lingui/core": "^4.2.1",
|
34
34
|
"@lingui/macro": "^4.2.1",
|
35
35
|
"@lingui/react": "^4.2.1",
|