@graphcommerce/magento-cart 9.1.0-canary.54 → 9.1.0-canary.55

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 CHANGED
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ ## 9.1.0-canary.55
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`cf44b1f`](https://github.com/graphcommerce-org/graphcommerce/commit/cf44b1f723b7f2073a21abd6821768427cb95315) - Added hideTotals to MultiCartStartCheckout ([@paales](https://github.com/paales))
8
+
9
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`af4463d`](https://github.com/graphcommerce-org/graphcommerce/commit/af4463dcbc6903241c8804ffba2f43b2b8e1a00b) - When running a cart mutation and the cartId is already passed to the form we use that value instead of retrieving the current cart again. ([@paales](https://github.com/paales))
10
+
11
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`415f9fb`](https://github.com/graphcommerce-org/graphcommerce/commit/415f9fb50454fb20cb533235969dd9ab4ffc134b) - Allow setting the cartId in the form for useFormGqlMutationCart by setting the cartId in the form AND allow setting the cartId for a whole context by wrapping with CartIdProvider ([@paales](https://github.com/paales))
12
+
13
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`4e3f3f2`](https://github.com/graphcommerce-org/graphcommerce/commit/4e3f3f2df58638ba8ffc68ee9f274cdd6c45d6d4) - Allow setting the redirect value in the AddProductsToCartForm as a form value. ([@paales](https://github.com/paales))
14
+
15
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`af4463d`](https://github.com/graphcommerce-org/graphcommerce/commit/af4463dcbc6903241c8804ffba2f43b2b8e1a00b) - Solve issue where if the onBeforeSubmit would return false, it would still error if submitted while the cart is locked. ([@paales](https://github.com/paales))
16
+
17
+ - [#2539](https://github.com/graphcommerce-org/graphcommerce/pull/2539) [`1a06135`](https://github.com/graphcommerce-org/graphcommerce/commit/1a061357f4ccb430dd13194f755815474e140520) - Allow awaitable async requests for onStart on checkout button ([@paales](https://github.com/paales))
18
+
3
19
  ## 9.1.0-canary.54
4
20
 
5
21
  ## 9.1.0-canary.53
@@ -0,0 +1,20 @@
1
+ import { createContext, useContext } from 'react'
2
+
3
+ export const CartIdContext = createContext<string | null>(null)
4
+
5
+ /**
6
+ * By default we use the currently selected cartId.
7
+ *
8
+ * However in a MultiCart scenario we need to be able to switch the cartId in certain contexts.
9
+ */
10
+ export function CartIdProvider(props: {
11
+ children: React.ReactNode
12
+ cartId: string | null | undefined
13
+ }) {
14
+ const { children, cartId } = props
15
+ return <CartIdContext.Provider value={cartId ?? null}>{children}</CartIdContext.Provider>
16
+ }
17
+
18
+ export function useCartIdContext() {
19
+ return useContext(CartIdContext)
20
+ }
@@ -1,8 +1,9 @@
1
1
  import { Money } from '@graphcommerce/magento-store'
2
- import { extendableComponent, iconChevronRight, IconSvg } from '@graphcommerce/next-ui'
2
+ import type { ButtonProps } from '@graphcommerce/next-ui'
3
+ import { Button, extendableComponent, iconChevronRight, IconSvg } from '@graphcommerce/next-ui'
3
4
  import { Trans } from '@lingui/macro'
4
- import type { ButtonProps, SxProps, Theme } from '@mui/material'
5
- import { Box, Button, Link } from '@mui/material'
5
+ import type { SxProps, Theme } from '@mui/material'
6
+ import { Box, Link } from '@mui/material'
6
7
  import React from 'react'
7
8
  import { useCheckoutShouldLoginToContinue } from '../../hooks'
8
9
  import type { CartStartCheckoutFragment } from './CartStartCheckout.gql'
@@ -12,11 +13,12 @@ export type CartStartCheckoutProps = {
12
13
  sx?: SxProps<Theme>
13
14
  buttonProps?: ButtonProps<'button'>
14
15
  disabled?: boolean
16
+ hideTotal?: boolean
15
17
  cart?: CartStartCheckoutFragment | null | undefined
16
18
  onStart?: (
17
- e: React.MouseEvent<HTMLButtonElement>,
19
+ e: React.MouseEvent<HTMLButtonElement, MouseEvent>,
18
20
  cart: CartStartCheckoutFragment | null | undefined,
19
- ) => void
21
+ ) => Promise<void>
20
22
  }
21
23
 
22
24
  const name = 'CartStartCheckout'
@@ -35,6 +37,7 @@ export function CartStartCheckout(props: CartStartCheckoutProps) {
35
37
  onStart,
36
38
  buttonProps: { onClick, ...buttonProps } = {},
37
39
  disabled,
40
+ hideTotal = false,
38
41
  sx = [],
39
42
  cart,
40
43
  } = props
@@ -70,10 +73,9 @@ export function CartStartCheckout(props: CartStartCheckoutProps) {
70
73
  size='large'
71
74
  className={classes.checkoutButton}
72
75
  endIcon={<IconSvg src={iconChevronRight} />}
73
- onClick={(e) => {
76
+ onClick={async (e) => {
74
77
  onClick?.(e)
75
- onStart?.(e, cart)
76
- return onClick?.(e)
78
+ await onStart?.(e, cart)
77
79
  }}
78
80
  disabled={disabled || !hasTotals || hasErrors || shouldLoginToContinue}
79
81
  {...buttonProps}
@@ -88,7 +90,7 @@ export function CartStartCheckout(props: CartStartCheckoutProps) {
88
90
  >
89
91
  <Trans>Start Checkout</Trans>
90
92
  </Box>{' '}
91
- {hasTotals && (
93
+ {hasTotals && !hideTotal && (
92
94
  <span className={classes.checkoutMoney}>
93
95
  <Money {...cart?.prices?.grand_total} />
94
96
  </span>
@@ -1,5 +1,5 @@
1
1
  import type { LinkOrButtonProps } from '@graphcommerce/next-ui'
2
- import { iconChevronRight, IconSvg, LinkOrButton } from '@graphcommerce/next-ui'
2
+ import { iconChevronRight, IconSvg, LinkOrButton, sxx } from '@graphcommerce/next-ui'
3
3
  import { Trans } from '@lingui/react'
4
4
  import type { SxProps, Theme } from '@mui/material'
5
5
  import React from 'react'
@@ -8,13 +8,12 @@ import type { CartStartCheckoutFragment } from './CartStartCheckout.gql'
8
8
 
9
9
  export type CartStartCheckoutLinkOrButtonProps = {
10
10
  children?: React.ReactNode
11
- sx?: SxProps<Theme>
12
11
  disabled?: boolean
13
12
  cart?: CartStartCheckoutFragment | null | undefined
14
13
  onStart?: (
15
14
  e: React.MouseEvent<HTMLButtonElement & HTMLAnchorElement & HTMLSpanElement>,
16
15
  cart: CartStartCheckoutFragment | null | undefined,
17
- ) => void
16
+ ) => Promise<void>
18
17
  linkOrButtonProps?: LinkOrButtonProps
19
18
  }
20
19
 
@@ -24,6 +23,7 @@ export function CartStartCheckoutLinkOrButton(props: CartStartCheckoutLinkOrButt
24
23
  disabled,
25
24
  linkOrButtonProps: { onClick, button, ...linkOrButtonProps } = {},
26
25
  cart,
26
+ children,
27
27
  } = props
28
28
 
29
29
  const shouldLoginToContinue = useCheckoutShouldLoginToContinue()
@@ -34,11 +34,11 @@ export function CartStartCheckoutLinkOrButton(props: CartStartCheckoutLinkOrButt
34
34
  return (
35
35
  <LinkOrButton
36
36
  href='/checkout'
37
- onClick={(
37
+ onClick={async (
38
38
  e: React.MouseEvent<HTMLButtonElement & HTMLAnchorElement & HTMLSpanElement, MouseEvent>,
39
39
  ) => {
40
40
  onClick?.(e)
41
- onStart?.(e, cart)
41
+ await onStart?.(e, cart)
42
42
  }}
43
43
  button={{ variant: 'pill', ...button }}
44
44
  disabled={disabled || !hasTotals || hasErrors || shouldLoginToContinue}
@@ -46,7 +46,7 @@ export function CartStartCheckoutLinkOrButton(props: CartStartCheckoutLinkOrButt
46
46
  endIcon={<IconSvg src={iconChevronRight} />}
47
47
  {...linkOrButtonProps}
48
48
  >
49
- <Trans id='Next' />
49
+ {children ?? <Trans id='Next' />}
50
50
  </LinkOrButton>
51
51
  )
52
52
  }
@@ -1,8 +1,12 @@
1
1
  import type { FullPageMessageProps } from '@graphcommerce/next-ui'
2
- import { FullPageMessage, iconShoppingBag, IconSvg } from '@graphcommerce/next-ui'
2
+ import {
3
+ FullPageMessage,
4
+ iconShoppingBag,
5
+ IconSvg,
6
+ OverlayCloseButton,
7
+ } from '@graphcommerce/next-ui'
3
8
  import { Trans } from '@lingui/react'
4
9
  import type { SxProps, Theme } from '@mui/material'
5
- import { Button } from '@mui/material'
6
10
  import React from 'react'
7
11
 
8
12
  export type EmptyCartProps = {
@@ -19,9 +23,9 @@ export function EmptyCart(props: EmptyCartProps) {
19
23
  icon={<IconSvg src={iconShoppingBag} size='xxl' />}
20
24
  button={
21
25
  button || (
22
- <Button href='/' variant='pill' color='secondary' size='large'>
23
- <Trans id='Continue shopping' />
24
- </Button>
26
+ <OverlayCloseButton variant='pill' color='secondary' size='large'>
27
+ <Trans id='Continue shopping'>Continue shopping</Trans>
28
+ </OverlayCloseButton>
25
29
  )
26
30
  }
27
31
  {...rest}
@@ -5,11 +5,12 @@ export * from './CartAddressSingleLine/CartAddressSingleLine'
5
5
  export * from './CartAgreementsForm/CartAgreements.gql'
6
6
  export * from './CartAgreementsForm/CartAgreementsForm'
7
7
  export * from './CartFab/CartFab'
8
+ export * from './CartIdContext'
8
9
  export * from './CartItemSummary/CartItemSummary'
9
10
  export * from './CartStartCheckout'
10
11
  export * from './CartSummary/CartSummary'
11
12
  export * from './CartSummary/CartSummary.gql'
12
13
  export * from './CartTotals/CartTotals'
14
+ export * from './EditBillingAddressForm/EditBillingAddressForm'
13
15
  export * from './EmptyCart/EmptyCart'
14
16
  export * from './InlineAccount/InlineAccount'
15
- export * from './EditBillingAddressForm/EditBillingAddressForm'
@@ -6,6 +6,7 @@ import type {
6
6
  } from '@graphcommerce/react-hook-form'
7
7
  import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
8
8
  import { GraphQLError, Kind } from 'graphql'
9
+ import { useCartIdContext } from '../components/CartIdContext'
9
10
  import { isProtectedCartOperation } from '../link/isProtectedCartOperation'
10
11
  import { CurrentCartIdDocument } from './CurrentCartId.gql'
11
12
  import { useCartIdCreate } from './useCartIdCreate'
@@ -19,7 +20,8 @@ export function useFormGqlMutationCart<
19
20
  options: UseFormGraphQlOptions<Q, V> & { submitWhileLocked?: boolean } = {},
20
21
  operationOptions?: MutationHookOptions<Q, V>,
21
22
  ): UseFormGqlMutationReturn<Q, V> {
22
- const cartId = useCartIdCreate()
23
+ const cartIdCreate = useCartIdCreate()
24
+ const cartIdFromContext = useCartIdContext()
23
25
  const client = useApolloClient()
24
26
  const shouldLoginToContinue = useCartShouldLoginToContinue()
25
27
 
@@ -34,20 +36,25 @@ export function useFormGqlMutationCart<
34
36
  document,
35
37
  {
36
38
  ...options,
37
- onBeforeSubmit: async (variables) => {
38
- if (shouldLoginToContinue && shouldBlockOperation) {
39
- return false
40
- }
41
- const vars = { ...variables, cartId: await cartId() }
39
+ onBeforeSubmit: async (incoming) => {
40
+ const variables = options.onBeforeSubmit ? await options.onBeforeSubmit(incoming) : incoming
41
+ if (variables === false) return false
42
+ if (shouldLoginToContinue && shouldBlockOperation) return false
42
43
 
43
44
  const res = client.cache.readQuery({ query: CurrentCartIdDocument })
44
- if (!options.submitWhileLocked && res?.currentCartId?.locked) {
45
- throw Error('Could not submit form, cart is locked')
46
- // console.log('Could not submit form, cart is locked', res.currentCartId.locked)
47
- // return false
45
+ const cartId = cartIdFromContext ?? incoming.cartId ?? (await cartIdCreate())
46
+
47
+ if (
48
+ cartId === res?.currentCartId?.id &&
49
+ res?.currentCartId?.locked &&
50
+ !options.submitWhileLocked
51
+ ) {
52
+ throw Error(
53
+ 'Could not submit form, cart is locked. This is a bug. You may never submit a form while the cart is locked.',
54
+ )
48
55
  }
49
56
 
50
- return options.onBeforeSubmit ? options.onBeforeSubmit(vars) : vars
57
+ return { ...variables, cartId }
51
58
  },
52
59
  },
53
60
  { errorPolicy: 'all', ...operationOptions },
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-cart",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "9.1.0-canary.54",
5
+ "version": "9.1.0-canary.55",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -12,20 +12,20 @@
12
12
  }
13
13
  },
14
14
  "peerDependencies": {
15
- "@graphcommerce/ecommerce-ui": "^9.1.0-canary.54",
16
- "@graphcommerce/eslint-config-pwa": "^9.1.0-canary.54",
17
- "@graphcommerce/framer-next-pages": "^9.1.0-canary.54",
18
- "@graphcommerce/framer-scroller": "^9.1.0-canary.54",
19
- "@graphcommerce/framer-utils": "^9.1.0-canary.54",
20
- "@graphcommerce/graphql": "^9.1.0-canary.54",
21
- "@graphcommerce/image": "^9.1.0-canary.54",
22
- "@graphcommerce/magento-customer": "^9.1.0-canary.54",
23
- "@graphcommerce/magento-graphql": "^9.1.0-canary.54",
24
- "@graphcommerce/magento-store": "^9.1.0-canary.54",
25
- "@graphcommerce/next-ui": "^9.1.0-canary.54",
26
- "@graphcommerce/prettier-config-pwa": "^9.1.0-canary.54",
27
- "@graphcommerce/react-hook-form": "^9.1.0-canary.54",
28
- "@graphcommerce/typescript-config-pwa": "^9.1.0-canary.54",
15
+ "@graphcommerce/ecommerce-ui": "^9.1.0-canary.55",
16
+ "@graphcommerce/eslint-config-pwa": "^9.1.0-canary.55",
17
+ "@graphcommerce/framer-next-pages": "^9.1.0-canary.55",
18
+ "@graphcommerce/framer-scroller": "^9.1.0-canary.55",
19
+ "@graphcommerce/framer-utils": "^9.1.0-canary.55",
20
+ "@graphcommerce/graphql": "^9.1.0-canary.55",
21
+ "@graphcommerce/image": "^9.1.0-canary.55",
22
+ "@graphcommerce/magento-customer": "^9.1.0-canary.55",
23
+ "@graphcommerce/magento-graphql": "^9.1.0-canary.55",
24
+ "@graphcommerce/magento-store": "^9.1.0-canary.55",
25
+ "@graphcommerce/next-ui": "^9.1.0-canary.55",
26
+ "@graphcommerce/prettier-config-pwa": "^9.1.0-canary.55",
27
+ "@graphcommerce/react-hook-form": "^9.1.0-canary.55",
28
+ "@graphcommerce/typescript-config-pwa": "^9.1.0-canary.55",
29
29
  "@lingui/core": "^4.2.1",
30
30
  "@lingui/macro": "^4.2.1",
31
31
  "@lingui/react": "^4.2.1",