@graphcommerce/magento-cart 10.0.0-canary.67 → 10.0.0-canary.72
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 +20 -0
- package/components/CartAgreementsForm/CartAgreementsForm.tsx +2 -6
- package/components/CartFab/CartFab.tsx +6 -8
- package/components/CartItemSummary/CartItemSummary.tsx +5 -4
- package/components/CartStartCheckout/CartStartCheckout.tsx +4 -4
- package/components/CartSummary/CartSummary.tsx +9 -9
- package/components/CartTotals/CartTotals.tsx +9 -8
- package/components/EditBillingAddressForm/EditBillingAddressForm.tsx +0 -4
- package/components/EmptyCart/EmptyCart.tsx +1 -5
- package/components/InlineAccount/InlineAccount.tsx +9 -7
- package/hooks/useAssignCurrentCartId.ts +3 -3
- package/hooks/useCartQuery.ts +32 -17
- package/hooks/useCurrentCartId.ts +2 -3
- package/hooks/useFormGqlMutationCart.ts +9 -5
- package/link/cartLink.ts +42 -36
- package/package.json +16 -16
- package/plugins/useSignInFormMergeCart.ts +6 -6
- package/test/fillCartAgreementsForm.ts +1 -4
- package/typePolicies.ts +2 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 10.0.0-canary.72
|
|
4
|
+
|
|
5
|
+
## 10.0.0-canary.71
|
|
6
|
+
|
|
7
|
+
## 10.0.0-canary.70
|
|
8
|
+
|
|
9
|
+
### Major Changes
|
|
10
|
+
|
|
11
|
+
- [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`c96dfcd`](https://github.com/graphcommerce-org/graphcommerce/commit/c96dfcdca981baca387c270ad9e2b9515cdd00cc) - Updated to Apollo Client 4 ([@paales](https://github.com/paales))
|
|
12
|
+
|
|
13
|
+
## 10.0.0-canary.69
|
|
14
|
+
|
|
15
|
+
## 10.0.0-canary.68
|
|
16
|
+
|
|
17
|
+
### Major Changes
|
|
18
|
+
|
|
19
|
+
- [#2557](https://github.com/graphcommerce-org/graphcommerce/pull/2557) [`ceaadd8`](https://github.com/graphcommerce-org/graphcommerce/commit/ceaadd87f0648982a068a3b07b1fa149c9127f49) - ## Material UI v5 → v7 Migration
|
|
20
|
+
|
|
21
|
+
This release upgrades Material UI from v5 to v7 with full CSS variables support. ([@paales](https://github.com/paales))
|
|
22
|
+
|
|
3
23
|
## 10.0.0-canary.67
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CheckboxElement } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
|
-
import { extendableComponent, FormDiv } from '@graphcommerce/next-ui'
|
|
3
|
+
import { extendableComponent, FormDiv, sxx } from '@graphcommerce/next-ui'
|
|
4
4
|
import type { UseFormComposeOptions } from '@graphcommerce/react-hook-form'
|
|
5
5
|
import { FormPersist, useForm, useFormCompose } from '@graphcommerce/react-hook-form'
|
|
6
6
|
import { t } from '@lingui/core/macro'
|
|
@@ -50,10 +50,7 @@ export function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
|
50
50
|
if (data?.checkoutAgreements?.length === 0) return null
|
|
51
51
|
|
|
52
52
|
return (
|
|
53
|
-
<FormDiv
|
|
54
|
-
className={classes.form}
|
|
55
|
-
sx={[(theme) => ({ pt: theme.spacings.md }), ...(Array.isArray(sx) ? sx : [sx])]}
|
|
56
|
-
>
|
|
53
|
+
<FormDiv className={classes.form} sx={sxx((theme) => ({ pt: theme.spacings.md }), sx)}>
|
|
57
54
|
<form noValidate onSubmit={submit} name='cartAgreements'>
|
|
58
55
|
<Box className={classes.formInner} sx={{ typography: 'body1', display: 'inline-block' }}>
|
|
59
56
|
{data?.checkoutAgreements &&
|
|
@@ -64,7 +61,6 @@ export function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
|
64
61
|
// check if the agreement text contains an anchor tag
|
|
65
62
|
const containsLink = containsAnchorTag(agreement.checkbox_text)
|
|
66
63
|
let labelContent: React.ReactNode
|
|
67
|
-
|
|
68
64
|
if (containsLink) {
|
|
69
65
|
labelContent = (
|
|
70
66
|
<Typography
|
|
@@ -3,12 +3,13 @@ import {
|
|
|
3
3
|
extendableComponent,
|
|
4
4
|
iconShoppingBag,
|
|
5
5
|
IconSvg,
|
|
6
|
+
sxx,
|
|
6
7
|
useFabSize,
|
|
7
8
|
useScrollY,
|
|
8
9
|
} from '@graphcommerce/next-ui'
|
|
9
10
|
import { t } from '@lingui/core/macro'
|
|
10
11
|
import type { BadgeProps, FabProps, SxProps, Theme } from '@mui/material'
|
|
11
|
-
import {
|
|
12
|
+
import { Box, Fab, styled, useTheme } from '@mui/material'
|
|
12
13
|
import { m, useTransform } from 'framer-motion'
|
|
13
14
|
import React from 'react'
|
|
14
15
|
import { useCartEnabled, useCartShouldLoginToContinue } from '../../hooks'
|
|
@@ -42,8 +43,8 @@ function CartFabContent(props: CartFabContentProps) {
|
|
|
42
43
|
const scrollY = useScrollY()
|
|
43
44
|
const opacity = useTransform(scrollY, [50, 60], [0, 1])
|
|
44
45
|
|
|
45
|
-
const paper0 = alpha(theme2.palette.background.paper, 0)
|
|
46
|
-
const paper1 = alpha(theme2.palette.background.paper, 1)
|
|
46
|
+
const paper0 = theme2.alpha(theme2.palette.background.paper, 0)
|
|
47
|
+
const paper1 = theme2.alpha(theme2.palette.background.paper, 1)
|
|
47
48
|
const backgroundColor = useTransform(scrollY, [0, 10], [paper0, paper1])
|
|
48
49
|
|
|
49
50
|
const cartIcon = icon ?? <IconSvg src={iconShoppingBag} size='large' />
|
|
@@ -52,10 +53,7 @@ function CartFabContent(props: CartFabContentProps) {
|
|
|
52
53
|
return (
|
|
53
54
|
<Box
|
|
54
55
|
className={classes.root}
|
|
55
|
-
sx={
|
|
56
|
-
{ position: 'relative', width: fabIconSize, height: fabIconSize },
|
|
57
|
-
...(Array.isArray(sx) ? sx : [sx]),
|
|
58
|
-
]}
|
|
56
|
+
sx={sxx({ position: 'relative', width: fabIconSize, height: fabIconSize }, sx)}
|
|
59
57
|
>
|
|
60
58
|
<MotionFab
|
|
61
59
|
href='/cart'
|
|
@@ -66,7 +64,7 @@ function CartFabContent(props: CartFabContentProps) {
|
|
|
66
64
|
style={{ backgroundColor }}
|
|
67
65
|
sx={(theme) => ({
|
|
68
66
|
[theme.breakpoints.down('md')]: {
|
|
69
|
-
backgroundColor: `${theme.palette.background.paper} !important`,
|
|
67
|
+
backgroundColor: `${theme.vars.palette.background.paper} !important`,
|
|
70
68
|
},
|
|
71
69
|
})}
|
|
72
70
|
{...fabProps}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
extendableComponent,
|
|
8
8
|
nonNullable,
|
|
9
9
|
SectionContainer,
|
|
10
|
+
sxx,
|
|
10
11
|
} from '@graphcommerce/next-ui'
|
|
11
12
|
import { Trans } from '@lingui/react/macro'
|
|
12
13
|
import type { SxProps, Theme } from '@mui/material'
|
|
@@ -38,10 +39,10 @@ export function CartItemSummary(props: OrderSummaryProps) {
|
|
|
38
39
|
return (
|
|
39
40
|
<Box
|
|
40
41
|
className={classes.root}
|
|
41
|
-
sx={
|
|
42
|
+
sx={sxx(
|
|
42
43
|
(theme) => ({
|
|
43
44
|
padding: `${theme.spacings.sm} ${theme.spacings.sm}`,
|
|
44
|
-
border: `1px ${theme.palette.divider} solid`,
|
|
45
|
+
border: `1px ${theme.vars.palette.divider} solid`,
|
|
45
46
|
...breakpointVal(
|
|
46
47
|
'borderRadius',
|
|
47
48
|
theme.shape.borderRadius * 2,
|
|
@@ -49,8 +50,8 @@ export function CartItemSummary(props: OrderSummaryProps) {
|
|
|
49
50
|
theme.breakpoints.values,
|
|
50
51
|
),
|
|
51
52
|
}),
|
|
52
|
-
|
|
53
|
-
|
|
53
|
+
sx,
|
|
54
|
+
)}
|
|
54
55
|
>
|
|
55
56
|
<SectionContainer
|
|
56
57
|
sx={{ '& .SectionHeader-root': { mt: 0 } }}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Money } from '@graphcommerce/magento-store'
|
|
2
2
|
import type { ButtonProps } from '@graphcommerce/next-ui'
|
|
3
|
-
import { Button, extendableComponent, iconChevronRight, IconSvg } from '@graphcommerce/next-ui'
|
|
3
|
+
import { Button, extendableComponent, iconChevronRight, IconSvg, sxx } from '@graphcommerce/next-ui'
|
|
4
4
|
import { Trans } from '@lingui/react/macro'
|
|
5
5
|
import type { SxProps, Theme } from '@mui/material'
|
|
6
6
|
import { Box, Link } from '@mui/material'
|
|
@@ -49,13 +49,13 @@ export function CartStartCheckout(props: CartStartCheckoutProps) {
|
|
|
49
49
|
return (
|
|
50
50
|
<Box
|
|
51
51
|
className={classes.checkoutButtonContainer}
|
|
52
|
-
sx={
|
|
52
|
+
sx={sxx(
|
|
53
53
|
(theme) => ({
|
|
54
54
|
textAlign: 'center',
|
|
55
55
|
my: theme.spacings.md,
|
|
56
56
|
}),
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
sx,
|
|
58
|
+
)}
|
|
59
59
|
>
|
|
60
60
|
{shouldLoginToContinue && (
|
|
61
61
|
<Box sx={{ mb: 1 }} className={classes.loginContainer}>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { useHistoryLink } from '@graphcommerce/framer-next-pages'
|
|
2
2
|
import { useBillingAddressPermission } from '@graphcommerce/magento-customer'
|
|
3
|
-
import { breakpointVal, extendableComponent, SectionContainer } from '@graphcommerce/next-ui'
|
|
3
|
+
import { breakpointVal, extendableComponent, SectionContainer, sxx } from '@graphcommerce/next-ui'
|
|
4
4
|
import { Trans } from '@lingui/react/macro'
|
|
5
5
|
import type { SxProps, Theme } from '@mui/material'
|
|
6
|
-
import { Box,
|
|
6
|
+
import { Box, Link, Typography } from '@mui/material'
|
|
7
7
|
import React from 'react'
|
|
8
8
|
import { useCartQuery } from '../../hooks'
|
|
9
9
|
import { CartAddressMultiLine } from '../CartAddressMultiLine/CartAddressMultiLine'
|
|
@@ -37,7 +37,7 @@ export function CartSummary(props: CartSummaryProps) {
|
|
|
37
37
|
return (
|
|
38
38
|
<Box
|
|
39
39
|
className={classes.root}
|
|
40
|
-
sx={
|
|
40
|
+
sx={sxx(
|
|
41
41
|
(theme) => ({
|
|
42
42
|
margin: `${theme.spacings.sm} 0`,
|
|
43
43
|
'& > div:last-of-type': {
|
|
@@ -56,8 +56,8 @@ export function CartSummary(props: CartSummaryProps) {
|
|
|
56
56
|
),
|
|
57
57
|
},
|
|
58
58
|
}),
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
sx,
|
|
60
|
+
)}
|
|
61
61
|
>
|
|
62
62
|
<Box
|
|
63
63
|
className={classes.detailsContainer}
|
|
@@ -74,10 +74,7 @@ export function CartSummary(props: CartSummaryProps) {
|
|
|
74
74
|
theme.shape.borderRadius * 3,
|
|
75
75
|
theme.breakpoints.values,
|
|
76
76
|
),
|
|
77
|
-
background:
|
|
78
|
-
theme.palette.mode === 'light'
|
|
79
|
-
? theme.palette.background.default
|
|
80
|
-
: lighten(theme.palette.background.default, 0.15),
|
|
77
|
+
background: theme.lighten(theme.vars.palette.background.default, 0.15),
|
|
81
78
|
padding: theme.spacings.sm,
|
|
82
79
|
gridColumnGap: theme.spacings.xxl,
|
|
83
80
|
gridRowGap: theme.spacings.sm,
|
|
@@ -86,6 +83,9 @@ export function CartSummary(props: CartSummaryProps) {
|
|
|
86
83
|
gridTemplateColumns: '1fr 1fr',
|
|
87
84
|
marginTop: theme.spacings.xxs,
|
|
88
85
|
},
|
|
86
|
+
...theme.applyStyles('light', {
|
|
87
|
+
background: theme.vars.palette.background.default,
|
|
88
|
+
}),
|
|
89
89
|
})}
|
|
90
90
|
>
|
|
91
91
|
<Box>
|
|
@@ -3,7 +3,7 @@ import { magentoVersion } from '@graphcommerce/next-config/config'
|
|
|
3
3
|
import { breakpointVal, extendableComponent, sxx } from '@graphcommerce/next-ui'
|
|
4
4
|
import { Trans } from '@lingui/react/macro'
|
|
5
5
|
import type { SxProps, Theme } from '@mui/material'
|
|
6
|
-
import { Box, Divider
|
|
6
|
+
import { Box, Divider } from '@mui/material'
|
|
7
7
|
import { useCartQuery, useDisplayInclTax } from '../../hooks'
|
|
8
8
|
import { GetCartTotalsDocument } from './GetCartTotals.gql'
|
|
9
9
|
|
|
@@ -71,12 +71,11 @@ export function CartTotals(props: CartTotalsProps) {
|
|
|
71
71
|
theme.shape.borderRadius * 5,
|
|
72
72
|
theme.breakpoints.values,
|
|
73
73
|
),
|
|
74
|
-
background:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
background: theme.vars.palette.background.default,
|
|
75
|
+
...theme.applyStyles('dark', {
|
|
76
|
+
background: theme.lighten(theme.vars.palette.background.default, 0.15),
|
|
77
|
+
}),
|
|
78
78
|
padding: `${theme.spacings.xs} ${theme.spacings.sm}`,
|
|
79
|
-
|
|
80
79
|
'&.containerMargin': {
|
|
81
80
|
marginTop: theme.spacings.md,
|
|
82
81
|
px: theme.spacings.xs,
|
|
@@ -132,7 +131,9 @@ export function CartTotals(props: CartTotalsProps) {
|
|
|
132
131
|
sx={{ display: 'flex', justifyContent: 'space-between' }}
|
|
133
132
|
>
|
|
134
133
|
<Box>
|
|
135
|
-
<Trans>
|
|
134
|
+
<Trans>
|
|
135
|
+
Shipping ({shippingMethod.carrier_title} {shippingMethod.method_title})
|
|
136
|
+
</Trans>
|
|
136
137
|
</Box>
|
|
137
138
|
<Box className={classes.money} sx={{ whiteSpace: 'nowrap' }}>
|
|
138
139
|
<Money
|
|
@@ -171,7 +172,7 @@ export function CartTotals(props: CartTotalsProps) {
|
|
|
171
172
|
sx={(theme) => ({
|
|
172
173
|
display: 'flex',
|
|
173
174
|
justifyContent: 'space-between',
|
|
174
|
-
color: theme.palette.primary.main,
|
|
175
|
+
color: theme.vars.palette.primary.main,
|
|
175
176
|
})}
|
|
176
177
|
>
|
|
177
178
|
<Box>
|
|
@@ -74,7 +74,6 @@ export function EditBillingAddressForm(props: EditBillingAddressFormProps) {
|
|
|
74
74
|
<CompanyFields<SetBillingAddressMutationVariables> form={form} />
|
|
75
75
|
<NameFields form={form} prefix />
|
|
76
76
|
<AddressFields<SetBillingAddressMutationVariables> form={form} />
|
|
77
|
-
|
|
78
77
|
<FormRow>
|
|
79
78
|
<TelephoneElement
|
|
80
79
|
variant='outlined'
|
|
@@ -85,9 +84,7 @@ export function EditBillingAddressForm(props: EditBillingAddressFormProps) {
|
|
|
85
84
|
showValid
|
|
86
85
|
/>
|
|
87
86
|
</FormRow>
|
|
88
|
-
|
|
89
87
|
<FormDivider />
|
|
90
|
-
|
|
91
88
|
<FormActions sx={{ paddingBottom: 0 }}>
|
|
92
89
|
<Button
|
|
93
90
|
type='submit'
|
|
@@ -100,7 +97,6 @@ export function EditBillingAddressForm(props: EditBillingAddressFormProps) {
|
|
|
100
97
|
</Button>
|
|
101
98
|
</FormActions>
|
|
102
99
|
</Form>
|
|
103
|
-
|
|
104
100
|
<ApolloCustomerErrorAlert error={error} />
|
|
105
101
|
</>
|
|
106
102
|
)
|
|
@@ -30,11 +30,7 @@ export function EmptyCart(props: EmptyCartProps) {
|
|
|
30
30
|
}
|
|
31
31
|
{...rest}
|
|
32
32
|
>
|
|
33
|
-
{children ??
|
|
34
|
-
<Trans>
|
|
35
|
-
Discover our collection and add items to your cart!
|
|
36
|
-
</Trans>
|
|
37
|
-
)}
|
|
33
|
+
{children ?? <Trans>Discover our collection and add items to your cart!</Trans>}
|
|
38
34
|
</FullPageMessage>
|
|
39
35
|
)
|
|
40
36
|
}
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
useCustomerSession,
|
|
6
6
|
useGuestQuery,
|
|
7
7
|
} from '@graphcommerce/magento-customer'
|
|
8
|
-
import { Button, extendableComponent, FormRow } from '@graphcommerce/next-ui'
|
|
8
|
+
import { Button, extendableComponent, FormRow, sxx } from '@graphcommerce/next-ui'
|
|
9
9
|
import { Trans } from '@lingui/react/macro'
|
|
10
10
|
import type { SxProps, Theme } from '@mui/material'
|
|
11
11
|
import { Box, TextField, Typography } from '@mui/material'
|
|
@@ -48,15 +48,15 @@ export function InlineAccount(props: InlineAccountProps) {
|
|
|
48
48
|
<div>
|
|
49
49
|
<Box
|
|
50
50
|
className={classes.root}
|
|
51
|
-
sx={
|
|
51
|
+
sx={sxx(
|
|
52
52
|
(theme) => ({
|
|
53
53
|
borderRadius: '4px',
|
|
54
|
-
border: `1px solid ${theme.palette.divider}`,
|
|
54
|
+
border: `1px solid ${theme.vars.palette.divider}`,
|
|
55
55
|
padding: theme.spacings.md,
|
|
56
56
|
marginTop: theme.spacings.sm,
|
|
57
57
|
}),
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
sx,
|
|
59
|
+
)}
|
|
60
60
|
>
|
|
61
61
|
<Box
|
|
62
62
|
className={classes.innerContainer}
|
|
@@ -101,8 +101,10 @@ export function InlineAccount(props: InlineAccountProps) {
|
|
|
101
101
|
variant='outlined'
|
|
102
102
|
label={<Trans>Email address</Trans>}
|
|
103
103
|
value={cart?.email}
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
slotProps={{
|
|
105
|
+
input: {
|
|
106
|
+
readOnly: true,
|
|
107
|
+
},
|
|
106
108
|
}}
|
|
107
109
|
/>
|
|
108
110
|
</FormRow>
|
|
@@ -6,7 +6,7 @@ import { CurrentCartIdDocument } from './CurrentCartId.gql'
|
|
|
6
6
|
|
|
7
7
|
export const CART_ID_COOKIE = 'cart'
|
|
8
8
|
|
|
9
|
-
export function writeCartId(cache: ApolloCache
|
|
9
|
+
export function writeCartId(cache: ApolloCache, id: string | null = null) {
|
|
10
10
|
cache.writeQuery({
|
|
11
11
|
query: CurrentCartIdDocument,
|
|
12
12
|
data: { currentCartId: { __typename: 'CurrentCartId', locked: false, id } },
|
|
@@ -14,11 +14,11 @@ export function writeCartId(cache: ApolloCache<object>, id: string | null = null
|
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function readCartId(cache: ApolloCache
|
|
17
|
+
export function readCartId(cache: ApolloCache) {
|
|
18
18
|
return cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export function cartLock(cache: ApolloCache
|
|
21
|
+
export function cartLock(cache: ApolloCache, locked: boolean) {
|
|
22
22
|
const currentCartId = cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId
|
|
23
23
|
if (currentCartId?.id && currentCartId.locked !== locked) {
|
|
24
24
|
cache.writeQuery({
|
package/hooks/useCartQuery.ts
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
OperationVariables,
|
|
3
|
+
TypedDocumentNode,
|
|
4
|
+
WatchQueryFetchPolicy,
|
|
5
|
+
} from '@graphcommerce/graphql'
|
|
6
|
+
import { useQuery } from '@graphcommerce/graphql'
|
|
7
|
+
import { CombinedGraphQLErrors } from '@apollo/client/errors'
|
|
8
|
+
import type { useQuery as useQueryType } from '@apollo/client/react'
|
|
3
9
|
import { GraphQLError } from 'graphql'
|
|
4
10
|
import { useRouter } from 'next/router'
|
|
5
11
|
import { useCartShouldLoginToContinue } from './useCartPermissions'
|
|
6
12
|
import { useCurrentCartId } from './useCurrentCartId'
|
|
7
13
|
|
|
14
|
+
type CartQueryOptions<Q, V extends OperationVariables> = Omit<
|
|
15
|
+
useQueryType.Options<Q, V>,
|
|
16
|
+
'variables'
|
|
17
|
+
> & {
|
|
18
|
+
variables?: Omit<V, 'cartId'>
|
|
19
|
+
}
|
|
20
|
+
|
|
8
21
|
/**
|
|
9
22
|
* Requires the query to have a `$cartId: String!` argument. It will automatically inject the
|
|
10
23
|
* currently active cart_id.
|
|
@@ -15,12 +28,10 @@ import { useCurrentCartId } from './useCurrentCartId'
|
|
|
15
28
|
* const { data } = useCartQuery(CartFabQueryDocument)
|
|
16
29
|
* ```
|
|
17
30
|
*/
|
|
18
|
-
export function useCartQuery<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
) {
|
|
22
|
-
const { ...queryOptions } = options
|
|
23
|
-
|
|
31
|
+
export function useCartQuery<
|
|
32
|
+
Q,
|
|
33
|
+
V extends OperationVariables & { cartId: string; [index: string]: unknown },
|
|
34
|
+
>(document: TypedDocumentNode<Q, V>, options?: CartQueryOptions<Q, V>) {
|
|
24
35
|
const router = useRouter()
|
|
25
36
|
const { currentCartId, locked } = useCurrentCartId()
|
|
26
37
|
|
|
@@ -29,23 +40,27 @@ export function useCartQuery<Q, V extends { cartId: string; [index: string]: unk
|
|
|
29
40
|
const cartId = usingUrl ? urlCartId : currentCartId
|
|
30
41
|
const shouldLoginToContinue = useCartShouldLoginToContinue()
|
|
31
42
|
|
|
32
|
-
|
|
43
|
+
let fetchPolicy: WatchQueryFetchPolicy | undefined = options?.fetchPolicy
|
|
44
|
+
let returnPartialData: boolean | undefined = options?.returnPartialData
|
|
33
45
|
|
|
34
|
-
if (usingUrl
|
|
35
|
-
|
|
46
|
+
if (usingUrl || locked) fetchPolicy = 'cache-only'
|
|
47
|
+
if (usingUrl && typeof returnPartialData === 'undefined') returnPartialData = true
|
|
36
48
|
|
|
37
|
-
|
|
49
|
+
const variables = { cartId, ...options?.variables } as V
|
|
38
50
|
|
|
39
51
|
const query = useQuery(document, {
|
|
40
|
-
...
|
|
41
|
-
|
|
52
|
+
...options,
|
|
53
|
+
fetchPolicy,
|
|
54
|
+
returnPartialData,
|
|
55
|
+
variables,
|
|
56
|
+
skip: options?.skip || !cartId || shouldLoginToContinue,
|
|
42
57
|
})
|
|
43
58
|
|
|
44
|
-
if (shouldLoginToContinue && !
|
|
59
|
+
if (shouldLoginToContinue && !options?.skip) {
|
|
45
60
|
return {
|
|
46
61
|
...query,
|
|
47
|
-
error: new
|
|
48
|
-
|
|
62
|
+
error: new CombinedGraphQLErrors({
|
|
63
|
+
errors: [
|
|
49
64
|
new GraphQLError('Action can not be performed by the current user', {
|
|
50
65
|
extensions: { category: 'graphql-authorization' },
|
|
51
66
|
}),
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { QueryHookOptions } from '@graphcommerce/graphql'
|
|
2
1
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
2
|
import type { CurrentCartIdQuery, CurrentCartIdQueryVariables } from './CurrentCartId.gql'
|
|
4
3
|
import { CurrentCartIdDocument } from './CurrentCartId.gql'
|
|
@@ -6,8 +5,8 @@ import { CurrentCartIdDocument } from './CurrentCartId.gql'
|
|
|
6
5
|
export function useCurrentCartId<
|
|
7
6
|
Q extends CurrentCartIdQuery,
|
|
8
7
|
V extends CurrentCartIdQueryVariables,
|
|
9
|
-
>(options:
|
|
10
|
-
const queryResults = useQuery<Q, V>(CurrentCartIdDocument, options)
|
|
8
|
+
>(options: Partial<useQuery.Options<Q, V>> = {}) {
|
|
9
|
+
const queryResults = useQuery<Q, V>(CurrentCartIdDocument, options as useQuery.Options<Q, V>)
|
|
11
10
|
|
|
12
11
|
return {
|
|
13
12
|
currentCartId: queryResults.data?.currentCartId?.id || '',
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
CombinedGraphQLErrors,
|
|
3
|
+
TypedDocumentNode,
|
|
4
|
+
useApolloClient,
|
|
5
|
+
useMutation,
|
|
6
|
+
} from '@graphcommerce/graphql'
|
|
3
7
|
import type {
|
|
4
8
|
UseFormGqlMutationReturn,
|
|
5
9
|
UseFormGraphQlOptions,
|
|
@@ -18,7 +22,7 @@ export function useFormGqlMutationCart<
|
|
|
18
22
|
>(
|
|
19
23
|
document: TypedDocumentNode<Q, V>,
|
|
20
24
|
options: UseFormGraphQlOptions<Q, V> & { submitWhileLocked?: boolean } = {},
|
|
21
|
-
operationOptions?:
|
|
25
|
+
operationOptions?: useMutation.Options<NoInfer<Q>, NoInfer<V>>,
|
|
22
26
|
): UseFormGqlMutationReturn<Q, V> {
|
|
23
27
|
const cartIdCreate = useCartIdCreate()
|
|
24
28
|
const cartIdFromContext = useCartIdContext()
|
|
@@ -63,8 +67,8 @@ export function useFormGqlMutationCart<
|
|
|
63
67
|
if (shouldLoginToContinue && result.formState.isSubmitted && shouldBlockOperation) {
|
|
64
68
|
return {
|
|
65
69
|
...result,
|
|
66
|
-
error: new
|
|
67
|
-
|
|
70
|
+
error: new CombinedGraphQLErrors({
|
|
71
|
+
errors: [
|
|
68
72
|
new GraphQLError('Action can not be performed by the current user', {
|
|
69
73
|
extensions: { category: 'graphql-authorization' },
|
|
70
74
|
}),
|
package/link/cartLink.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { globalApolloClient } from '@graphcommerce/graphql'
|
|
2
|
+
import { ApolloLink, CombinedGraphQLErrors, ErrorLink } from '@graphcommerce/graphql/apollo'
|
|
3
|
+
import { filter, from, of, switchMap } from '@graphcommerce/graphql/rxjs'
|
|
4
4
|
import { CustomerTokenDocument, getCustomerAccountCanSignIn } from '@graphcommerce/magento-customer'
|
|
5
5
|
import type { PushRouter } from '@graphcommerce/magento-customer/link/customerLink'
|
|
6
6
|
import { pushWithPromise } from '@graphcommerce/magento-customer/link/customerLink'
|
|
@@ -14,8 +14,8 @@ import { CreateEmptyCartDocument } from '../hooks/CreateEmptyCart.gql'
|
|
|
14
14
|
import { getCartEnabledForUser } from '../utils'
|
|
15
15
|
import { isProtectedCartOperation } from './isProtectedCartOperation'
|
|
16
16
|
|
|
17
|
-
type CartOperation = Operation & { variables: { cartId: string } }
|
|
18
|
-
function isCartOperation(operation: Operation): operation is CartOperation {
|
|
17
|
+
type CartOperation = ApolloLink.Operation & { variables: { cartId: string } }
|
|
18
|
+
function isCartOperation(operation: ApolloLink.Operation): operation is CartOperation {
|
|
19
19
|
return typeof operation.variables.cartId === 'string'
|
|
20
20
|
}
|
|
21
21
|
|
|
@@ -24,13 +24,16 @@ function errorIsIncluded(errorPath: readonly (string | number)[] | undefined, ke
|
|
|
24
24
|
return keys.some((value) => value === error)
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
const cartErrorLink =
|
|
27
|
+
const cartErrorLink = new ErrorLink(({ error, operation, forward }) => {
|
|
28
28
|
if (!globalApolloClient.current) return undefined
|
|
29
29
|
|
|
30
30
|
const client = globalApolloClient.current
|
|
31
31
|
const { cache } = client
|
|
32
32
|
|
|
33
|
-
if
|
|
33
|
+
// Check if this is a GraphQL error
|
|
34
|
+
if (!CombinedGraphQLErrors.is(error)) return undefined
|
|
35
|
+
|
|
36
|
+
if (!isCartOperation(operation)) return undefined
|
|
34
37
|
|
|
35
38
|
const isErrorCategory = (err: GraphQLFormattedError, category: ErrorCategory) =>
|
|
36
39
|
err.extensions?.category === category
|
|
@@ -54,7 +57,7 @@ const cartErrorLink = onError(({ graphQLErrors, operation, forward }) => {
|
|
|
54
57
|
// 'applyCouponToCart',
|
|
55
58
|
// 'removeCouponFromCart'
|
|
56
59
|
])
|
|
57
|
-
const cartErr =
|
|
60
|
+
const cartErr = error.errors.find((err) => isNoSuchEntityError(err))
|
|
58
61
|
|
|
59
62
|
if (!cartErr) return undefined
|
|
60
63
|
|
|
@@ -63,9 +66,9 @@ const cartErrorLink = onError(({ graphQLErrors, operation, forward }) => {
|
|
|
63
66
|
if (urlParams.get('cart_id')) return forward(operation)
|
|
64
67
|
}
|
|
65
68
|
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
|
|
69
|
+
return from(client?.mutate({ mutation: CreateEmptyCartDocument })).pipe(
|
|
70
|
+
filter((value) => Boolean(value)),
|
|
71
|
+
switchMap((cartData) => {
|
|
69
72
|
const cartId = cartData.data?.createEmptyCart
|
|
70
73
|
if (!cartId) return forward(operation)
|
|
71
74
|
|
|
@@ -74,7 +77,8 @@ const cartErrorLink = onError(({ graphQLErrors, operation, forward }) => {
|
|
|
74
77
|
|
|
75
78
|
// retry the request, returning the new observable
|
|
76
79
|
return forward(operation)
|
|
77
|
-
})
|
|
80
|
+
}),
|
|
81
|
+
)
|
|
78
82
|
})
|
|
79
83
|
|
|
80
84
|
const cartPermissionLink = (router: PushRouter) =>
|
|
@@ -82,7 +86,7 @@ const cartPermissionLink = (router: PushRouter) =>
|
|
|
82
86
|
const { locale } = router
|
|
83
87
|
const { cache } = operation.getContext()
|
|
84
88
|
|
|
85
|
-
if (!isProtectedCartOperation(operation.operationName)) return forward(operation)
|
|
89
|
+
if (!isProtectedCartOperation(operation.operationName ?? '')) return forward(operation)
|
|
86
90
|
|
|
87
91
|
const check = () => Boolean(cache?.readQuery({ query: CustomerTokenDocument }))
|
|
88
92
|
if (getCartEnabledForUser(locale, check)) return forward(operation)
|
|
@@ -95,33 +99,35 @@ const cartPermissionLink = (router: PushRouter) =>
|
|
|
95
99
|
const oldHeaders = operation.getContext().headers
|
|
96
100
|
const signInAgainPromise = pushWithPromise(router, '/account/signin')
|
|
97
101
|
|
|
98
|
-
return
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
102
|
+
return from(signInAgainPromise).pipe(
|
|
103
|
+
switchMap(() => {
|
|
104
|
+
const tokenQuery = cache?.readQuery({ query: CustomerTokenDocument })
|
|
105
|
+
|
|
106
|
+
if (tokenQuery?.customerToken?.valid) {
|
|
107
|
+
// Customer is authenticated, retrying request.
|
|
108
|
+
operation.setContext({
|
|
109
|
+
headers: {
|
|
110
|
+
...oldHeaders,
|
|
111
|
+
authorization: `Bearer ${tokenQuery?.customerToken?.token}`,
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
return forward(operation)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return of({
|
|
118
|
+
data: null,
|
|
119
|
+
errors: [
|
|
120
|
+
new GraphQLError(t`Please login to add products to your cart`, {
|
|
121
|
+
extensions: { category: 'graphql-authorization' },
|
|
122
|
+
}),
|
|
123
|
+
],
|
|
108
124
|
})
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return Observable.of({
|
|
113
|
-
data: null,
|
|
114
|
-
errors: [
|
|
115
|
-
new GraphQLError(t`Please login to add products to your cart`, {
|
|
116
|
-
extensions: { category: 'graphql-authorization' },
|
|
117
|
-
}),
|
|
118
|
-
],
|
|
119
|
-
})
|
|
120
|
-
})
|
|
125
|
+
}),
|
|
126
|
+
)
|
|
121
127
|
})
|
|
122
128
|
|
|
123
129
|
export const cartLink = (router: PushRouter) => {
|
|
124
|
-
const links = [cartErrorLink]
|
|
130
|
+
const links: ApolloLink[] = [cartErrorLink]
|
|
125
131
|
|
|
126
132
|
if (!(permissions?.cart === 'ENABLED')) {
|
|
127
133
|
links.push(cartPermissionLink(router))
|
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": "10.0.0-canary.
|
|
5
|
+
"version": "10.0.0-canary.72",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -20,24 +20,24 @@
|
|
|
20
20
|
"./plugins/useSignInFormMergeCart": "./plugins/useSignInFormMergeCart.ts"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
|
-
"@graphcommerce/ecommerce-ui": "^10.0.0-canary.
|
|
24
|
-
"@graphcommerce/eslint-config-pwa": "^10.0.0-canary.
|
|
25
|
-
"@graphcommerce/framer-next-pages": "^10.0.0-canary.
|
|
26
|
-
"@graphcommerce/framer-scroller": "^10.0.0-canary.
|
|
27
|
-
"@graphcommerce/framer-utils": "^10.0.0-canary.
|
|
28
|
-
"@graphcommerce/graphql": "^10.0.0-canary.
|
|
29
|
-
"@graphcommerce/image": "^10.0.0-canary.
|
|
30
|
-
"@graphcommerce/magento-customer": "^10.0.0-canary.
|
|
31
|
-
"@graphcommerce/magento-graphql": "^10.0.0-canary.
|
|
32
|
-
"@graphcommerce/magento-store": "^10.0.0-canary.
|
|
33
|
-
"@graphcommerce/next-ui": "^10.0.0-canary.
|
|
34
|
-
"@graphcommerce/prettier-config-pwa": "^10.0.0-canary.
|
|
35
|
-
"@graphcommerce/react-hook-form": "^10.0.0-canary.
|
|
36
|
-
"@graphcommerce/typescript-config-pwa": "^10.0.0-canary.
|
|
23
|
+
"@graphcommerce/ecommerce-ui": "^10.0.0-canary.72",
|
|
24
|
+
"@graphcommerce/eslint-config-pwa": "^10.0.0-canary.72",
|
|
25
|
+
"@graphcommerce/framer-next-pages": "^10.0.0-canary.72",
|
|
26
|
+
"@graphcommerce/framer-scroller": "^10.0.0-canary.72",
|
|
27
|
+
"@graphcommerce/framer-utils": "^10.0.0-canary.72",
|
|
28
|
+
"@graphcommerce/graphql": "^10.0.0-canary.72",
|
|
29
|
+
"@graphcommerce/image": "^10.0.0-canary.72",
|
|
30
|
+
"@graphcommerce/magento-customer": "^10.0.0-canary.72",
|
|
31
|
+
"@graphcommerce/magento-graphql": "^10.0.0-canary.72",
|
|
32
|
+
"@graphcommerce/magento-store": "^10.0.0-canary.72",
|
|
33
|
+
"@graphcommerce/next-ui": "^10.0.0-canary.72",
|
|
34
|
+
"@graphcommerce/prettier-config-pwa": "^10.0.0-canary.72",
|
|
35
|
+
"@graphcommerce/react-hook-form": "^10.0.0-canary.72",
|
|
36
|
+
"@graphcommerce/typescript-config-pwa": "^10.0.0-canary.72",
|
|
37
37
|
"@lingui/core": "^5",
|
|
38
38
|
"@lingui/macro": "^5",
|
|
39
39
|
"@lingui/react": "^5",
|
|
40
|
-
"@mui/material": "^
|
|
40
|
+
"@mui/material": "^7.0.0",
|
|
41
41
|
"framer-motion": "^11.0.0",
|
|
42
42
|
"graphql": "^16.0.0",
|
|
43
43
|
"next": "*",
|
|
@@ -22,12 +22,12 @@ export const useSignInForm: FunctionPlugin<typeof useSignInFormType> = (useSignI
|
|
|
22
22
|
|
|
23
23
|
cartLock(client.cache, true)
|
|
24
24
|
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
25
|
+
const customerCartResult = await client.query({
|
|
26
|
+
query: CustomerCartDocument,
|
|
27
|
+
fetchPolicy: 'network-only',
|
|
28
|
+
})
|
|
29
|
+
const destinationCartId = customerCartResult.data?.customerCart?.id
|
|
30
|
+
if (!destinationCartId) return
|
|
31
31
|
|
|
32
32
|
try {
|
|
33
33
|
const sourceCartId = readCartId(client.cache)?.id
|
|
@@ -3,10 +3,7 @@ import type { ApolloClient, NormalizedCacheObject } from '@graphcommerce/graphql
|
|
|
3
3
|
import type { Page } from '@playwright/test'
|
|
4
4
|
import { CartAgreementsDocument } from '../components/CartAgreementsForm/CartAgreements.gql'
|
|
5
5
|
|
|
6
|
-
export async function fillCartAgreementsForm(
|
|
7
|
-
page: Page,
|
|
8
|
-
client: ApolloClient<NormalizedCacheObject>,
|
|
9
|
-
) {
|
|
6
|
+
export async function fillCartAgreementsForm(page: Page, client: ApolloClient) {
|
|
10
7
|
const res = (await client.query({ query: CartAgreementsDocument })).data
|
|
11
8
|
|
|
12
9
|
for await (const agreement of res.checkoutAgreements ?? []) {
|
package/typePolicies.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ApolloCache,
|
|
3
|
-
NormalizedCacheObject,
|
|
4
|
-
StrictTypedTypePolicies,
|
|
5
|
-
} from '@graphcommerce/graphql'
|
|
1
|
+
import type { ApolloCache, StrictTypedTypePolicies } from '@graphcommerce/graphql'
|
|
6
2
|
import type { CartPrices, QuerycartArgs, ShippingCartAddress } from '@graphcommerce/graphql-mesh'
|
|
7
3
|
import { CartFabDocument } from './components/CartFab/CartFab.gql'
|
|
8
4
|
import { readCartId, writeCartId } from './hooks'
|
|
@@ -57,10 +53,7 @@ export const cartTypePolicies: StrictTypedTypePolicies = {
|
|
|
57
53
|
},
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
export const migrateCart = (
|
|
61
|
-
oldCache: ApolloCache<NormalizedCacheObject>,
|
|
62
|
-
newCache: ApolloCache<NormalizedCacheObject>,
|
|
63
|
-
) => {
|
|
56
|
+
export const migrateCart = (oldCache: ApolloCache, newCache: ApolloCache) => {
|
|
64
57
|
const cartId = readCartId(oldCache)?.id
|
|
65
58
|
|
|
66
59
|
if (cartId) {
|