@graphcommerce/magento-product-configurable 9.1.0-canary.18 → 9.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.
Files changed (20) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/components/ConfigurableCartItemOptions/ConfigurableCartItemOptions.tsx +1 -0
  3. package/components/ConfigurableOptionValueImage/ConfigurableOptionValueImage.tsx +0 -5
  4. package/components/ConfigurableProductOptions/ConfigurableProductOption.tsx +1 -1
  5. package/components/ConfigurableProductOptions/ConfigurableProductOptions.tsx +1 -1
  6. package/graphql/index.ts +4 -2
  7. package/hooks/useConfigurableOptionsSelection.ts +2 -2
  8. package/package.json +18 -18
  9. package/plugins/ConfigurableCartItemActionCard.tsx +19 -9
  10. package/plugins/ConfigurableProductPage/ConfigurableProductPageDescription.tsx +4 -0
  11. package/plugins/ConfigurableProductPage/ConfigurableProductPageGallery.tsx +4 -1
  12. package/plugins/ConfigurableProductPage/ConfigurableProductPageJsonLd.tsx +4 -0
  13. package/plugins/ConfigurableProductPage/ConfigurableProductPageMeta.tsx +6 -0
  14. package/plugins/Configurable_cartItemToCartItemInput.ts +30 -0
  15. package/utils/defaultConfigurableOptionsSelection.ts +7 -46
  16. package/graphql/ConfigurableProductAddToCart.graphql +0 -27
  17. /package/graphql/{ConfigurableOptions.graphql → fragments/ConfigurableOptions.graphql} +0 -0
  18. /package/graphql/{ConfigurableOptionsSelection.graphql → fragments/ConfigurableOptionsSelection.graphql} +0 -0
  19. /package/graphql/{UseConfigurableOptions.graphql → fragments/UseConfigurableOptions.graphql} +0 -0
  20. /package/graphql/{GetConfigurableOptionsSelection.graphql → queries/GetConfigurableOptionsSelection.graphql} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Change Log
2
2
 
3
+ ## 9.1.0-canary.20
4
+
5
+ ## 9.1.0-canary.19
6
+
7
+ ### Patch Changes
8
+
9
+ - [#2499](https://github.com/graphcommerce-org/graphcommerce/pull/2499) [`d859dd8`](https://github.com/graphcommerce-org/graphcommerce/commit/d859dd8e5e89e4f22cd6e89e3ae8d03067de6c51) - Do not directly update the cache of the defaultConfigurableOptionsSelection, but query the backend. ([@paales](https://github.com/paales))
10
+
11
+ - [#2499](https://github.com/graphcommerce-org/graphcommerce/pull/2499) [`6b2b44c`](https://github.com/graphcommerce-org/graphcommerce/commit/6b2b44ca853279144d7768067f3462d4d4bf0af1) - Move the cartItemEdit functionality to a plugin for configurable products ([@paales](https://github.com/paales))
12
+
13
+ - [#2499](https://github.com/graphcommerce-org/graphcommerce/pull/2499) [`6b2b44c`](https://github.com/graphcommerce-org/graphcommerce/commit/6b2b44ca853279144d7768067f3462d4d4bf0af1) - Implement the Cart options as priceModifiers so the logic can be somewhat re-used for multiple locations ([@paales](https://github.com/paales))
14
+
3
15
  ## 9.1.0-canary.18
4
16
 
5
17
  ## 9.1.0-canary.17
@@ -5,6 +5,7 @@ import type { ConfigurableCartItemFragment } from '../../ConfigurableCartItem/Co
5
5
 
6
6
  export type ConfigurableActionCartItemProps = ConfigurableCartItemFragment & CartItemFragment
7
7
 
8
+ /** @deprecated Replaced by PriceModifiers on the CartItemActionCard */
8
9
  export function ConfigurableCartItemOptions(props: ConfigurableActionCartItemProps) {
9
10
  const { configurable_options } = props
10
11
  return (
@@ -64,11 +64,6 @@ export function ConfigurableOptionValueImage(props: ConfigurableOptionValueImage
64
64
  }
65
65
  })
66
66
  }
67
- reset={
68
- <Button variant='inline' color='secondary' onClick={onReset} disableRipple>
69
- <Trans id='Change' />
70
- </Button>
71
- }
72
67
  size={size}
73
68
  />
74
69
  )
@@ -7,7 +7,7 @@ import { useWatch } from '@graphcommerce/react-hook-form'
7
7
  import { i18n } from '@lingui/core'
8
8
  import type { SxProps, Theme } from '@mui/material'
9
9
  import { Box } from '@mui/material'
10
- import type { ConfigurableOptionsFragment } from '../../graphql/ConfigurableOptions.gql'
10
+ import type { ConfigurableOptionsFragment } from '../../graphql'
11
11
  import type { UseConfigurableOptionsSelection } from '../../hooks'
12
12
  import { useConfigurableOptionsForSelection } from '../../hooks'
13
13
  import type {
@@ -7,7 +7,7 @@ import { i18n } from '@lingui/core'
7
7
  import type { SxProps, Theme } from '@mui/material'
8
8
  import { Box } from '@mui/material'
9
9
  import React, { useEffect, useMemo } from 'react'
10
- import type { ConfigurableOptionsFragment } from '../../graphql/ConfigurableOptions.gql'
10
+ import type { ConfigurableOptionsFragment } from '../../graphql'
11
11
  import { useConfigurableOptionsSelection } from '../../hooks'
12
12
  import { ConfigurableOptionValue } from '../ConfigurableOptionValue/ConfigurableOptionValue'
13
13
  import { ConfigurableProductOption } from './ConfigurableProductOption'
package/graphql/index.ts CHANGED
@@ -1,2 +1,4 @@
1
- export * from './ConfigurableOptionsSelection.gql'
2
- export * from './GetConfigurableOptionsSelection.gql'
1
+ export * from './queries/GetConfigurableOptionsSelection.gql'
2
+ export * from './fragments/ConfigurableOptions.gql'
3
+ export * from './fragments/ConfigurableOptionsSelection.gql'
4
+ export * from './fragments/UseConfigurableOptions.gql'
@@ -3,8 +3,8 @@ import type { AddToCartItemSelector } from '@graphcommerce/magento-product'
3
3
  import { useFormAddProductsToCart } from '@graphcommerce/magento-product'
4
4
  import { findByTypename, nonNullable } from '@graphcommerce/next-ui'
5
5
  import { useWatch } from '@graphcommerce/react-hook-form'
6
- import { GetConfigurableOptionsSelectionDocument } from '../graphql/GetConfigurableOptionsSelection.gql'
7
- import type { UseConfigurableOptionsFragment } from '../graphql/UseConfigurableOptions.gql'
6
+ import type { UseConfigurableOptionsFragment } from '../graphql'
7
+ import { GetConfigurableOptionsSelectionDocument } from '../graphql'
8
8
 
9
9
  type UseConfigurableOptionsForSelection = {
10
10
  selectedOptions: string[]
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-product-configurable",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "9.1.0-canary.18",
5
+ "version": "9.1.0-canary.20",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -12,23 +12,23 @@
12
12
  }
13
13
  },
14
14
  "peerDependencies": {
15
- "@graphcommerce/ecommerce-ui": "^9.1.0-canary.18",
16
- "@graphcommerce/eslint-config-pwa": "^9.1.0-canary.18",
17
- "@graphcommerce/graphql": "^9.1.0-canary.18",
18
- "@graphcommerce/graphql-mesh": "^9.1.0-canary.18",
19
- "@graphcommerce/image": "^9.1.0-canary.18",
20
- "@graphcommerce/lingui-next": "9.1.0-canary.18",
21
- "@graphcommerce/magento-cart": "^9.1.0-canary.18",
22
- "@graphcommerce/magento-cart-items": "^9.1.0-canary.18",
23
- "@graphcommerce/magento-category": "^9.1.0-canary.18",
24
- "@graphcommerce/magento-customer": "^9.1.0-canary.18",
25
- "@graphcommerce/magento-product": "^9.1.0-canary.18",
26
- "@graphcommerce/magento-product-simple": "^9.1.0-canary.18",
27
- "@graphcommerce/magento-store": "^9.1.0-canary.18",
28
- "@graphcommerce/next-ui": "^9.1.0-canary.18",
29
- "@graphcommerce/prettier-config-pwa": "^9.1.0-canary.18",
30
- "@graphcommerce/react-hook-form": "^9.1.0-canary.18",
31
- "@graphcommerce/typescript-config-pwa": "^9.1.0-canary.18",
15
+ "@graphcommerce/ecommerce-ui": "^9.1.0-canary.20",
16
+ "@graphcommerce/eslint-config-pwa": "^9.1.0-canary.20",
17
+ "@graphcommerce/graphql": "^9.1.0-canary.20",
18
+ "@graphcommerce/graphql-mesh": "^9.1.0-canary.20",
19
+ "@graphcommerce/image": "^9.1.0-canary.20",
20
+ "@graphcommerce/lingui-next": "9.1.0-canary.20",
21
+ "@graphcommerce/magento-cart": "^9.1.0-canary.20",
22
+ "@graphcommerce/magento-cart-items": "^9.1.0-canary.20",
23
+ "@graphcommerce/magento-category": "^9.1.0-canary.20",
24
+ "@graphcommerce/magento-customer": "^9.1.0-canary.20",
25
+ "@graphcommerce/magento-product": "^9.1.0-canary.20",
26
+ "@graphcommerce/magento-product-simple": "^9.1.0-canary.20",
27
+ "@graphcommerce/magento-store": "^9.1.0-canary.20",
28
+ "@graphcommerce/next-ui": "^9.1.0-canary.20",
29
+ "@graphcommerce/prettier-config-pwa": "^9.1.0-canary.20",
30
+ "@graphcommerce/react-hook-form": "^9.1.0-canary.20",
31
+ "@graphcommerce/typescript-config-pwa": "^9.1.0-canary.20",
32
32
  "@lingui/core": "^4.2.1",
33
33
  "@lingui/macro": "^4.2.1",
34
34
  "@lingui/react": "^4.2.1",
@@ -1,7 +1,10 @@
1
- import type { CartItemActionCardProps } from '@graphcommerce/magento-cart-items'
1
+ import {
2
+ selectedCustomizableOptionsModifiers,
3
+ type CartItemActionCardProps,
4
+ } from '@graphcommerce/magento-cart-items'
5
+ import type { PriceModifier } from '@graphcommerce/magento-store'
2
6
  import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
3
- import { isTypename } from '@graphcommerce/next-ui'
4
- import { ConfigurableCartItemOptions } from '../components'
7
+ import { filterNonNullableKeys, isTypename } from '@graphcommerce/next-ui'
5
8
 
6
9
  export const config: PluginConfig = {
7
10
  type: 'component',
@@ -13,6 +16,14 @@ export function CartItemActionCard(props: PluginProps<CartItemActionCardProps>)
13
16
 
14
17
  if (!isTypename(rest.cartItem, ['ConfigurableCartItem'])) return <Prev {...rest} />
15
18
 
19
+ const configurableModifiers: PriceModifier[] = filterNonNullableKeys(
20
+ rest.cartItem.configurable_options,
21
+ ).map((option) => ({
22
+ key: option.configurable_product_option_uid,
23
+ label: option.option_label,
24
+ items: [{ key: option.configurable_product_option_value_uid, label: option.value_label }],
25
+ }))
26
+
16
27
  return (
17
28
  <Prev
18
29
  {...rest}
@@ -29,12 +40,11 @@ export function CartItemActionCard(props: PluginProps<CartItemActionCardProps>)
29
40
  // : rest.cartItem.product.url_key,
30
41
  },
31
42
  }}
32
- details={
33
- <>
34
- {rest.details}
35
- <ConfigurableCartItemOptions {...rest.cartItem} />
36
- </>
37
- }
43
+ priceModifiers={[
44
+ ...(rest.priceModifiers ?? []),
45
+ ...configurableModifiers,
46
+ ...selectedCustomizableOptionsModifiers(rest.cartItem),
47
+ ]}
38
48
  />
39
49
  )
40
50
  }
@@ -17,6 +17,10 @@ export function ProductPageDescription(
17
17
  const { Prev, product, index, ...rest } = props
18
18
  const variant = useConfigurableSelectedVariant({ ...product, index })
19
19
 
20
+ if (product.__typename !== 'ConfigurableProduct') {
21
+ return <Prev product={product} index={index} {...rest} />
22
+ }
23
+
20
24
  return (
21
25
  <Prev
22
26
  product={{
@@ -1,6 +1,5 @@
1
1
  import type { AddToCartItemSelector, ProductPageGalleryProps } from '@graphcommerce/magento-product'
2
2
  import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
3
- import { isTypename } from '@graphcommerce/next-ui'
4
3
  import { useConfigurableOptionsSelection } from '../../hooks'
5
4
 
6
5
  export const config: PluginConfig = {
@@ -21,5 +20,9 @@ export function ProductPageGallery(
21
20
  ? configured?.configurable_product_options_selection?.media_gallery
22
21
  : product.media_gallery
23
22
 
23
+ if (product.__typename !== 'ConfigurableProduct') {
24
+ return <Prev product={product} {...rest} />
25
+ }
26
+
24
27
  return <Prev product={{ ...product, media_gallery }} {...rest} />
25
28
  }
@@ -5,6 +5,7 @@ import type {
5
5
  } from '@graphcommerce/magento-product'
6
6
  import type { PluginConfig, PluginProps } from '@graphcommerce/next-config'
7
7
  import { useConfigurableSelectedVariant } from '../../hooks'
8
+ import { isTypename } from '@graphcommerce/next-ui'
8
9
 
9
10
  export const config: PluginConfig = {
10
11
  type: 'component',
@@ -17,5 +18,8 @@ export function ProductPageJsonLd<T extends { '@type': string }, P extends JsonL
17
18
  ) {
18
19
  const { Prev, product, index, ...rest } = props
19
20
  const variant = useConfigurableSelectedVariant({ ...product, index })
21
+
22
+ if (product.__typename !== 'ConfigurableProduct') return <Prev product={product} {...rest} />
23
+
20
24
  return <Prev product={(variant ?? product) as P} {...rest} />
21
25
  }
@@ -21,7 +21,9 @@ export function ProductPageMeta(props: PluginProps<ProductPageMetaProps> & AddTo
21
21
  const isValidVariant = (variant?.url_rewrites ?? []).length > 0 && variant?.url_key
22
22
  const targetUrl = isValidVariant ? productLink(variant) : productLink(product)
23
23
 
24
+
24
25
  useEffect(() => {
26
+ if (product.__typename !== 'ConfigurableProduct') return
25
27
  // Filter asPath with #, for zoomed gallery
26
28
  // Note for future use: This might be a dangerous way to
27
29
  // navigate to simple products, since it will trigger on every
@@ -32,5 +34,9 @@ export function ProductPageMeta(props: PluginProps<ProductPageMetaProps> & AddTo
32
34
  }
33
35
  }, [asPath, replace, targetUrl])
34
36
 
37
+ if (product.__typename !== 'ConfigurableProduct') {
38
+ return <Prev product={product} {...rest} />
39
+ }
40
+
35
41
  return <Prev product={variant ? mergeDeep(product, variant) : product} {...rest} />
36
42
  }
@@ -0,0 +1,30 @@
1
+ import { type cartItemToCartItemInput as cartItemToCartItemInputType } from '@graphcommerce/magento-cart-items'
2
+ import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config'
3
+ import { filterNonNullableKeys } from '@graphcommerce/next-ui'
4
+
5
+ export const config: PluginConfig = {
6
+ type: 'function',
7
+ module: '@graphcommerce/magento-cart-items',
8
+ }
9
+
10
+ export const cartItemToCartItemInput: FunctionPlugin<typeof cartItemToCartItemInputType> = (
11
+ prev,
12
+ props,
13
+ ) => {
14
+ const result = prev(props)
15
+ const { product, cartItem } = props
16
+
17
+ if (!result) return result
18
+ if (product.__typename !== 'ConfigurableProduct') return result
19
+ if (cartItem.__typename !== 'ConfigurableCartItem') return result
20
+
21
+ return {
22
+ ...result,
23
+ selected_options: [
24
+ ...filterNonNullableKeys(cartItem.configurable_options).map(
25
+ (option) => option.configurable_product_option_value_uid,
26
+ ),
27
+ ...(result?.selected_options ?? []),
28
+ ],
29
+ }
30
+ }
@@ -22,11 +22,11 @@ type BaseQuery =
22
22
  * selected by filling in `selectedOptions` and passing it as `defaultValues `. We also
23
23
  * prepopulating the result of `GetConfigurableOptionsSelection` query.
24
24
  */
25
- export function defaultConfigurableOptionsSelection<Q extends BaseQuery = BaseQuery>(
25
+ export async function defaultConfigurableOptionsSelection<Q extends BaseQuery = BaseQuery>(
26
26
  urlKey: string,
27
27
  client: ApolloClient<object>,
28
28
  query: Q,
29
- ): Q & Pick<AddProductsToCartFormProps, 'defaultValues'> {
29
+ ): Promise<Q & Pick<AddProductsToCartFormProps, 'defaultValues'>> {
30
30
  const simple = query?.products?.items?.find((p) => p?.url_key === urlKey)
31
31
  const configurable = findByTypename(query?.products?.items, 'ConfigurableProduct')
32
32
 
@@ -65,56 +65,17 @@ export function defaultConfigurableOptionsSelection<Q extends BaseQuery = BaseQu
65
65
  * })
66
66
  * ```
67
67
  */
68
- const optionsAvailableForSelection =
69
- configurable.configurable_product_options_selection?.options_available_for_selection?.filter(
70
- nonNullable,
71
- )
72
-
73
- client.cache.writeQuery({
68
+ await client.query({
74
69
  query: GetConfigurableOptionsSelectionDocument,
75
70
  variables: { urlKey: configurable.url_key, selectedOptions },
76
- data: {
77
- products: {
78
- ...query?.products,
79
- __typename: 'Products',
80
- items: [
81
- {
82
- __typename: 'ConfigurableProduct',
83
- uid: configurable.uid,
84
- configurable_product_options_selection: {
85
- __typename: 'ConfigurableProductOptionsSelection',
86
- configurable_options: filterNonNullableKeys(configurable.configurable_options, [
87
- 'attribute_code',
88
- 'label',
89
- 'values',
90
- ]).map((option) => ({
91
- __typename: 'ConfigurableProductOption' as const,
92
- uid: option.uid,
93
- attribute_code: option.attribute_code,
94
- label: option.label,
95
- values: filterNonNullableKeys(option.values, ['store_label', 'uid']).map(
96
- ({ store_label, uid }) => ({ label: store_label, uid }),
97
- ),
98
- })),
99
- options_available_for_selection: optionsAvailableForSelection?.map(
100
- ({ attribute_code, option_value_uids }) => ({
101
- __typename: 'ConfigurableOptionAvailableForSelection' as const,
102
- attribute_code,
103
- option_value_uids,
104
- }),
105
- ),
106
- media_gallery: simple?.media_gallery ?? configurable.media_gallery,
107
- variant: simple?.__typename === 'SimpleProduct' ? simple : null,
108
- },
109
- },
110
- ],
111
- },
112
- },
113
71
  })
114
72
 
115
73
  return {
116
74
  ...query,
117
- products: { ...query?.products, items: [configurable] },
75
+ products: {
76
+ ...query?.products,
77
+ items: [{ ...configurable, url_key: simple?.url_key }],
78
+ },
118
79
  defaultValues: { cartItems: [{ selected_options: selectedOptions }] },
119
80
  }
120
81
  }
@@ -1,27 +0,0 @@
1
- mutation ConfigurableProductAddToCart(
2
- $cartId: String!
3
- $sku: String!
4
- $quantity: Float = 1
5
- $enteredOptions: [EnteredOptionInput] = []
6
- $selectedOptions: [ID]!
7
- ) {
8
- addProductsToCart(
9
- cartId: $cartId
10
- cartItems: [
11
- {
12
- sku: $sku
13
- quantity: $quantity
14
- entered_options: $enteredOptions
15
- selected_options: $selectedOptions
16
- }
17
- ]
18
- ) {
19
- cart {
20
- ...CartItemCountChanged
21
- }
22
- user_errors {
23
- code
24
- message
25
- }
26
- }
27
- }