@graphcommerce/magento-cart 3.10.1 → 4.0.0
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 +399 -353
- package/components/ApolloCartError/ApolloCartErrorAlert.tsx +3 -2
- package/components/ApolloCartError/ApolloCartErrorFullPage.tsx +3 -4
- package/components/ApolloCartError/ApolloCartErrorSnackbar.tsx +2 -1
- package/components/CartAgreementsForm/CartAgreementsForm.tsx +23 -34
- package/components/CartFab/CartFab.tsx +49 -54
- package/components/CartItemSummary/index.tsx +92 -76
- package/components/CartStartCheckout/CartStartCheckout.tsx +34 -33
- package/components/CartSummary/index.tsx +55 -55
- package/components/CartTotals/CartTotals.tsx +92 -97
- package/components/EmptyCart/EmptyCart.tsx +3 -2
- package/components/InlineAccount/index.tsx +46 -51
- package/components/index.ts +1 -0
- package/hooks/useAssignCurrentCartId.ts +1 -1
- package/hooks/useCartIdCreate.ts +1 -1
- package/hooks/useCartQuery.ts +1 -1
- package/hooks/useClearCurrentCartId.ts +1 -1
- package/hooks/useCurrentCartId.ts +1 -1
- package/hooks/useFormGqlMutationCart.ts +1 -1
- package/hooks/useMergeCustomerCart.ts +1 -1
- package/package.json +19 -27
- package/typePolicies.ts +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { useQuery } from '@
|
|
1
|
+
import { useQuery } from '@graphcommerce/graphql'
|
|
2
2
|
import { CustomerTokenDocument } from '@graphcommerce/magento-customer'
|
|
3
3
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
4
|
-
import { ApolloErrorAlert, ApolloErrorAlertProps
|
|
4
|
+
import { ApolloErrorAlert, ApolloErrorAlertProps } from '@graphcommerce/next-ui'
|
|
5
5
|
import { t } from '@lingui/macro'
|
|
6
|
+
import { Button } from '@mui/material'
|
|
6
7
|
import Link from 'next/link'
|
|
7
8
|
import React from 'react'
|
|
8
9
|
import { useClearCurrentCartId } from '../../hooks/useClearCurrentCartId'
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
2
2
|
import {
|
|
3
3
|
ApolloErrorFullPage,
|
|
4
|
-
Button,
|
|
5
4
|
ApolloErrorFullPageProps,
|
|
6
5
|
iconSadFace,
|
|
7
|
-
|
|
6
|
+
SvgIcon,
|
|
8
7
|
} from '@graphcommerce/next-ui'
|
|
9
|
-
import
|
|
8
|
+
import { Button } from '@mui/material'
|
|
10
9
|
import { useClearCurrentCartId } from '../../hooks/useClearCurrentCartId'
|
|
11
10
|
|
|
12
11
|
export type ApolloCartErrorFullPageProps = Omit<ApolloErrorFullPageProps, 'icon'>
|
|
@@ -21,7 +20,7 @@ export function ApolloCartErrorFullPage(props: ApolloCartErrorFullPageProps) {
|
|
|
21
20
|
return (
|
|
22
21
|
<ApolloErrorFullPage
|
|
23
22
|
error={error}
|
|
24
|
-
icon={<
|
|
23
|
+
icon={<SvgIcon src={iconSadFace} size='xxl' />}
|
|
25
24
|
button={action}
|
|
26
25
|
{...passedProps}
|
|
27
26
|
/>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
2
|
-
import {
|
|
2
|
+
import { ApolloErrorSnackbarProps, ApolloErrorSnackbar } from '@graphcommerce/next-ui'
|
|
3
|
+
import { Button } from '@mui/material'
|
|
3
4
|
import React from 'react'
|
|
4
5
|
import { useClearCurrentCartId } from '../../hooks/useClearCurrentCartId'
|
|
5
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useQuery } from '@
|
|
2
|
-
import { FormDiv } from '@graphcommerce/next-ui'
|
|
1
|
+
import { useQuery } from '@graphcommerce/graphql'
|
|
2
|
+
import { extendableComponent, FormDiv } from '@graphcommerce/next-ui'
|
|
3
3
|
import {
|
|
4
4
|
Controller,
|
|
5
5
|
useForm,
|
|
@@ -9,49 +9,33 @@ import {
|
|
|
9
9
|
} from '@graphcommerce/react-hook-form'
|
|
10
10
|
import { t } from '@lingui/macro'
|
|
11
11
|
import {
|
|
12
|
+
Box,
|
|
12
13
|
Checkbox,
|
|
13
14
|
FormControl,
|
|
14
15
|
FormControlLabel,
|
|
15
16
|
FormHelperText,
|
|
16
17
|
Link,
|
|
17
|
-
|
|
18
|
+
SxProps,
|
|
18
19
|
Theme,
|
|
19
|
-
} from '@material
|
|
20
|
+
} from '@mui/material'
|
|
20
21
|
import PageLink from 'next/link'
|
|
21
22
|
import React from 'react'
|
|
22
23
|
import { CartAgreementsDocument } from './CartAgreements.gql'
|
|
23
24
|
|
|
24
|
-
export type CartAgreementsFormProps = Pick<UseFormComposeOptions, 'step'>
|
|
25
|
+
export type CartAgreementsFormProps = Pick<UseFormComposeOptions, 'step'> & { sx?: SxProps<Theme> }
|
|
25
26
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
paddingTop: theme.spacings.sm,
|
|
30
|
-
},
|
|
31
|
-
formInner: {
|
|
32
|
-
...theme.typography.body1,
|
|
33
|
-
display: 'inline-block',
|
|
34
|
-
},
|
|
35
|
-
formControlRoot: {
|
|
36
|
-
display: 'block',
|
|
37
|
-
},
|
|
38
|
-
manualCheck: {
|
|
39
|
-
padding: `9px 0`,
|
|
40
|
-
},
|
|
41
|
-
}),
|
|
42
|
-
{
|
|
43
|
-
name: 'CartAgreements',
|
|
44
|
-
},
|
|
45
|
-
)
|
|
27
|
+
const name = 'CartAgreementsForm' as const
|
|
28
|
+
const parts = ['form', 'formInner', 'formControlRoot', 'manualCheck'] as const
|
|
29
|
+
const { classes } = extendableComponent(name, parts)
|
|
46
30
|
|
|
47
31
|
export default function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
48
32
|
const { step } = props
|
|
49
33
|
const { data } = useQuery(CartAgreementsDocument)
|
|
50
|
-
const classes = useStyles()
|
|
51
34
|
|
|
52
35
|
// sort conditions so checkboxes will be placed first
|
|
53
36
|
const sortedAgreements = data?.checkoutAgreements
|
|
54
37
|
? [...data.checkoutAgreements].sort((a, b) =>
|
|
38
|
+
// eslint-disable-next-line no-nested-ternary
|
|
55
39
|
a?.mode === 'MANUAL' ? -1 : b?.mode === 'MANUAL' ? 1 : 0,
|
|
56
40
|
)
|
|
57
41
|
: []
|
|
@@ -67,9 +51,9 @@ export default function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
|
67
51
|
useFormCompose({ form, step, submit, key: 'PaymentAgreementsForm' })
|
|
68
52
|
|
|
69
53
|
return (
|
|
70
|
-
<FormDiv classes={{
|
|
54
|
+
<FormDiv className={classes.form} sx={(theme) => ({ pt: theme.spacings.md })}>
|
|
71
55
|
<form noValidate onSubmit={submit} name='cartAgreements'>
|
|
72
|
-
<
|
|
56
|
+
<Box className={classes.formInner} sx={{ typography: 'body1', display: 'inline-block' }}>
|
|
73
57
|
{data?.checkoutAgreements &&
|
|
74
58
|
sortedAgreements?.map((agreement) => {
|
|
75
59
|
if (!agreement) return null
|
|
@@ -88,13 +72,16 @@ export default function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
|
88
72
|
}) => (
|
|
89
73
|
<FormControl
|
|
90
74
|
error={!!formState.errors[String(agreement.agreement_id)]}
|
|
91
|
-
|
|
75
|
+
className={classes.formControlRoot}
|
|
76
|
+
sx={{ display: 'block' }}
|
|
92
77
|
>
|
|
93
78
|
<FormControlLabel
|
|
94
79
|
control={<Checkbox color='secondary' required />}
|
|
95
80
|
label={
|
|
96
81
|
<PageLink href={href} passHref>
|
|
97
|
-
<Link color='secondary'>
|
|
82
|
+
<Link color='secondary' underline='hover'>
|
|
83
|
+
{agreement.checkbox_text}
|
|
84
|
+
</Link>
|
|
98
85
|
</PageLink>
|
|
99
86
|
}
|
|
100
87
|
checked={!!value}
|
|
@@ -108,16 +95,18 @@ export default function CartAgreementsForm(props: CartAgreementsFormProps) {
|
|
|
108
95
|
)}
|
|
109
96
|
/>
|
|
110
97
|
) : (
|
|
111
|
-
<
|
|
98
|
+
<Box className={classes.manualCheck} sx={{ padding: `9px 0` }}>
|
|
112
99
|
<PageLink href={href} passHref>
|
|
113
|
-
<Link color='secondary'>
|
|
100
|
+
<Link color='secondary' underline='hover'>
|
|
101
|
+
{agreement.checkbox_text}
|
|
102
|
+
</Link>
|
|
114
103
|
</PageLink>
|
|
115
|
-
</
|
|
104
|
+
</Box>
|
|
116
105
|
)}
|
|
117
106
|
</React.Fragment>
|
|
118
107
|
)
|
|
119
108
|
})}
|
|
120
|
-
</
|
|
109
|
+
</Box>
|
|
121
110
|
</form>
|
|
122
111
|
</FormDiv>
|
|
123
112
|
)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
extendableComponent,
|
|
2
3
|
iconShoppingBag,
|
|
3
4
|
responsiveVal,
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
DesktopHeaderBadge,
|
|
6
|
+
SvgIcon,
|
|
6
7
|
useScrollY,
|
|
7
|
-
UseStyles,
|
|
8
8
|
} from '@graphcommerce/next-ui'
|
|
9
9
|
import { t } from '@lingui/macro'
|
|
10
|
-
import { alpha, Fab, FabProps,
|
|
10
|
+
import { alpha, Fab, FabProps, NoSsr, styled, useTheme, Box } from '@mui/material'
|
|
11
11
|
import { m, useTransform } from 'framer-motion'
|
|
12
12
|
import PageLink from 'next/link'
|
|
13
13
|
import React from 'react'
|
|
@@ -15,85 +15,83 @@ import { useCartQuery } from '../../hooks/useCartQuery'
|
|
|
15
15
|
import { CartFabDocument } from './CartFab.gql'
|
|
16
16
|
import { CartTotalQuantityFragment } from './CartTotalQuantity.gql'
|
|
17
17
|
|
|
18
|
-
const useStyles = makeStyles(
|
|
19
|
-
(theme: Theme) => ({
|
|
20
|
-
placeholderFab: {
|
|
21
|
-
width: responsiveVal(42, 56),
|
|
22
|
-
height: responsiveVal(42, 56),
|
|
23
|
-
[theme.breakpoints.down('sm')]: {
|
|
24
|
-
backgroundColor: `${theme.palette.background.paper} !important`,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
cartFab: {
|
|
28
|
-
boxShadow: 'none',
|
|
29
|
-
width: responsiveVal(42, 56),
|
|
30
|
-
height: responsiveVal(42, 56),
|
|
31
|
-
pointerEvents: 'all',
|
|
32
|
-
color: theme.palette.text.primary,
|
|
33
|
-
},
|
|
34
|
-
shadow: {
|
|
35
|
-
pointerEvents: 'none',
|
|
36
|
-
borderRadius: '99em',
|
|
37
|
-
position: 'absolute',
|
|
38
|
-
height: '100%',
|
|
39
|
-
width: '100%',
|
|
40
|
-
boxShadow: theme.shadows[6],
|
|
41
|
-
top: 0,
|
|
42
|
-
[theme.breakpoints.down('sm')]: {
|
|
43
|
-
opacity: '1 !important',
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
}),
|
|
47
|
-
{ name: 'CartFab' },
|
|
48
|
-
)
|
|
49
|
-
|
|
50
18
|
export type CartFabProps = {
|
|
51
19
|
icon?: React.ReactNode
|
|
52
|
-
}
|
|
20
|
+
}
|
|
53
21
|
|
|
54
22
|
type CartFabContentProps = CartFabProps & CartTotalQuantityFragment
|
|
55
23
|
|
|
24
|
+
const MotionDiv = styled(m.div)({})
|
|
25
|
+
|
|
56
26
|
const MotionFab = m(
|
|
57
27
|
React.forwardRef<any, Omit<FabProps, 'style' | 'onDrag'>>((props, ref) => (
|
|
58
28
|
<Fab {...props} ref={ref} />
|
|
59
29
|
)),
|
|
60
30
|
)
|
|
61
31
|
|
|
32
|
+
const { classes } = extendableComponent('CartFab', ['root', 'cart', 'shadow'] as const)
|
|
33
|
+
|
|
62
34
|
function CartFabContent(props: CartFabContentProps) {
|
|
63
35
|
const { total_quantity, icon, ...fabProps } = props
|
|
64
|
-
const classes = useStyles(props)
|
|
65
36
|
|
|
66
|
-
const
|
|
37
|
+
const theme2 = useTheme()
|
|
67
38
|
const scrollY = useScrollY()
|
|
68
39
|
const opacity = useTransform(scrollY, [50, 60], [0, 1])
|
|
69
40
|
|
|
70
|
-
const paper0 = alpha(
|
|
71
|
-
const paper1 = alpha(
|
|
41
|
+
const paper0 = alpha(theme2.palette.background.paper, 0)
|
|
42
|
+
const paper1 = alpha(theme2.palette.background.paper, 1)
|
|
72
43
|
const backgroundColor = useTransform(scrollY, [0, 10], [paper0, paper1])
|
|
73
44
|
|
|
74
|
-
const cartIcon = icon ?? <
|
|
45
|
+
const cartIcon = icon ?? <SvgIcon src={iconShoppingBag} size='large' />
|
|
46
|
+
const fabIconSize = responsiveVal(42, 56) // @todo generalize this
|
|
47
|
+
|
|
75
48
|
return (
|
|
76
|
-
|
|
49
|
+
<Box
|
|
50
|
+
className={classes.root}
|
|
51
|
+
sx={{ position: 'relative', width: fabIconSize, height: fabIconSize }}
|
|
52
|
+
>
|
|
77
53
|
<PageLink href='/cart' passHref>
|
|
78
54
|
<MotionFab
|
|
55
|
+
className={classes.cart}
|
|
79
56
|
{...fabProps}
|
|
80
57
|
aria-label={t`Cart`}
|
|
81
58
|
color='inherit'
|
|
82
59
|
size='large'
|
|
83
|
-
classes={{ root: classes.placeholderFab }}
|
|
84
60
|
style={{ backgroundColor }}
|
|
61
|
+
sx={(theme) => ({
|
|
62
|
+
width: fabIconSize,
|
|
63
|
+
height: fabIconSize,
|
|
64
|
+
[theme.breakpoints.down('md')]: {
|
|
65
|
+
backgroundColor: `${theme.palette.background.paper} !important`,
|
|
66
|
+
},
|
|
67
|
+
})}
|
|
85
68
|
>
|
|
86
69
|
{total_quantity > 0 ? (
|
|
87
|
-
<
|
|
70
|
+
<DesktopHeaderBadge color='primary' variant='dot' overlap='circular'>
|
|
88
71
|
{cartIcon}
|
|
89
|
-
</
|
|
72
|
+
</DesktopHeaderBadge>
|
|
90
73
|
) : (
|
|
91
74
|
cartIcon
|
|
92
75
|
)}
|
|
93
76
|
</MotionFab>
|
|
94
77
|
</PageLink>
|
|
95
|
-
<
|
|
96
|
-
|
|
78
|
+
<MotionDiv
|
|
79
|
+
className={classes.shadow}
|
|
80
|
+
sx={(theme) => ({
|
|
81
|
+
pointerEvents: 'none',
|
|
82
|
+
borderRadius: '99em',
|
|
83
|
+
position: 'absolute',
|
|
84
|
+
height: '100%',
|
|
85
|
+
width: '100%',
|
|
86
|
+
boxShadow: theme.shadows[6],
|
|
87
|
+
top: 0,
|
|
88
|
+
[theme.breakpoints.down('md')]: {
|
|
89
|
+
opacity: '1 !important',
|
|
90
|
+
},
|
|
91
|
+
})}
|
|
92
|
+
style={{ opacity }}
|
|
93
|
+
/>
|
|
94
|
+
</Box>
|
|
97
95
|
)
|
|
98
96
|
}
|
|
99
97
|
|
|
@@ -108,7 +106,6 @@ function CartFabContent(props: CartFabContentProps) {
|
|
|
108
106
|
* product to the cart. This would mean that it would immediately start executing this query.
|
|
109
107
|
*/
|
|
110
108
|
export default function CartFab(props: CartFabProps) {
|
|
111
|
-
const classes = useStyles(props)
|
|
112
109
|
const { data } = useCartQuery(CartFabDocument, {
|
|
113
110
|
fetchPolicy: 'cache-only',
|
|
114
111
|
nextFetchPolicy: 'cache-first',
|
|
@@ -116,10 +113,8 @@ export default function CartFab(props: CartFabProps) {
|
|
|
116
113
|
const qty = data?.cart?.total_quantity ?? 0
|
|
117
114
|
|
|
118
115
|
return (
|
|
119
|
-
<
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
</NoSsr>
|
|
123
|
-
</Fab>
|
|
116
|
+
<NoSsr fallback={<CartFabContent {...props} total_quantity={0} />}>
|
|
117
|
+
<CartFabContent total_quantity={qty} {...props} />
|
|
118
|
+
</NoSsr>
|
|
124
119
|
)
|
|
125
120
|
}
|
|
@@ -5,74 +5,35 @@ import {
|
|
|
5
5
|
iconChevronRight,
|
|
6
6
|
responsiveVal,
|
|
7
7
|
SectionContainer,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
SvgIcon,
|
|
9
|
+
extendableComponent,
|
|
10
10
|
} from '@graphcommerce/next-ui'
|
|
11
|
-
import {
|
|
12
|
-
import { Divider,
|
|
13
|
-
import clsx from 'clsx'
|
|
11
|
+
import { Trans } from '@lingui/macro'
|
|
12
|
+
import { Box, Divider, SxProps, Theme } from '@mui/material'
|
|
14
13
|
import React from 'react'
|
|
15
14
|
import { useCartQuery } from '../../hooks'
|
|
16
15
|
import CartTotals from '../CartTotals/CartTotals'
|
|
17
16
|
import { CartItemSummaryDocument } from './GetCartItemSummary.gql'
|
|
18
17
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
borderRadius: '50%',
|
|
34
|
-
marginRight: theme.spacings.xs,
|
|
35
|
-
border: `1px solid ${theme.palette.divider}`,
|
|
36
|
-
padding: responsiveVal(5, 10),
|
|
37
|
-
width: `${responsiveVal(48, 96)} !important`,
|
|
38
|
-
height: `${responsiveVal(48, 96)} !important`,
|
|
39
|
-
display: 'block',
|
|
40
|
-
},
|
|
41
|
-
scrollerContainer: {
|
|
42
|
-
padding: 1,
|
|
43
|
-
},
|
|
44
|
-
scroller: {},
|
|
45
|
-
prevNext: {
|
|
46
|
-
position: 'absolute',
|
|
47
|
-
top: '50%',
|
|
48
|
-
transform: 'translateY(-50%)',
|
|
49
|
-
zIndex: 2,
|
|
50
|
-
},
|
|
51
|
-
prev: {
|
|
52
|
-
left: 8,
|
|
53
|
-
},
|
|
54
|
-
next: {
|
|
55
|
-
right: 8,
|
|
56
|
-
},
|
|
57
|
-
costContainer: {
|
|
58
|
-
background: theme.palette.background.default,
|
|
59
|
-
padding: 0,
|
|
60
|
-
},
|
|
61
|
-
sectionHeaderWrapper: {
|
|
62
|
-
marginTop: 0,
|
|
63
|
-
},
|
|
64
|
-
divider: {
|
|
65
|
-
margin: `${theme.spacings.xs} 0 ${theme.spacings.xs} 0`,
|
|
66
|
-
},
|
|
67
|
-
}),
|
|
68
|
-
{ name: 'CartItemSummary' },
|
|
69
|
-
)
|
|
18
|
+
const name = 'CartItemSummary' as const
|
|
19
|
+
const parts = [
|
|
20
|
+
'root',
|
|
21
|
+
'imageScrollerContainer',
|
|
22
|
+
'image',
|
|
23
|
+
'scrollerContainer',
|
|
24
|
+
'scroller',
|
|
25
|
+
'prevNext',
|
|
26
|
+
'prev',
|
|
27
|
+
'next',
|
|
28
|
+
'sectionHeaderWrapper',
|
|
29
|
+
'divider',
|
|
30
|
+
] as const
|
|
31
|
+
const { classes } = extendableComponent(name, parts)
|
|
70
32
|
|
|
71
|
-
type OrderSummaryProps =
|
|
33
|
+
type OrderSummaryProps = { sx?: SxProps<Theme> }
|
|
72
34
|
|
|
73
35
|
export default function CartItemSummary(props: OrderSummaryProps) {
|
|
74
|
-
const
|
|
75
|
-
|
|
36
|
+
const { sx = [] } = props
|
|
76
37
|
const { data } = useCartQuery(CartItemSummaryDocument, { allowUrl: true })
|
|
77
38
|
|
|
78
39
|
if (!data?.cart) return null
|
|
@@ -80,12 +41,20 @@ export default function CartItemSummary(props: OrderSummaryProps) {
|
|
|
80
41
|
const items = data?.cart.items
|
|
81
42
|
|
|
82
43
|
return (
|
|
83
|
-
<
|
|
44
|
+
<Box
|
|
45
|
+
className={classes.root}
|
|
46
|
+
sx={[
|
|
47
|
+
(theme) => ({
|
|
48
|
+
padding: `${theme.spacings.sm} ${theme.spacings.sm}`,
|
|
49
|
+
border: `1px ${theme.palette.divider} solid`,
|
|
50
|
+
borderRadius: '4px',
|
|
51
|
+
}),
|
|
52
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
53
|
+
]}
|
|
54
|
+
>
|
|
84
55
|
<SectionContainer
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}}
|
|
88
|
-
labelLeft={t`Order summary`}
|
|
56
|
+
sx={{ '& .SectionHeader': { mt: 0 } }}
|
|
57
|
+
labelLeft={<Trans>Order summary</Trans>}
|
|
89
58
|
// labelRight={
|
|
90
59
|
// <PageLink href='/download' passHref>
|
|
91
60
|
// <Link color='secondary'>Download invoice</Link>
|
|
@@ -93,12 +62,30 @@ export default function CartItemSummary(props: OrderSummaryProps) {
|
|
|
93
62
|
// }
|
|
94
63
|
variantLeft='h6'
|
|
95
64
|
>
|
|
96
|
-
<
|
|
65
|
+
<Box
|
|
66
|
+
className={classes.imageScrollerContainer}
|
|
67
|
+
sx={(theme) => ({
|
|
68
|
+
display: 'flex',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
gap: theme.spacings.sm,
|
|
71
|
+
position: 'relative',
|
|
72
|
+
})}
|
|
73
|
+
>
|
|
97
74
|
<ScrollerProvider scrollSnapAlign='start'>
|
|
98
|
-
<ScrollerButton
|
|
99
|
-
|
|
75
|
+
<ScrollerButton
|
|
76
|
+
direction='left'
|
|
77
|
+
className={`${classes.prevNext} ${classes.prev}`}
|
|
78
|
+
sx={{
|
|
79
|
+
position: 'absolute',
|
|
80
|
+
top: '50%',
|
|
81
|
+
transform: 'translateY(-50%)',
|
|
82
|
+
zIndex: 2,
|
|
83
|
+
left: 8,
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<SvgIcon src={iconChevronLeft} />
|
|
100
87
|
</ScrollerButton>
|
|
101
|
-
<
|
|
88
|
+
<Box className={classes.scrollerContainer} sx={{ padding: '1px' }}>
|
|
102
89
|
<Scroller className={classes.scroller}>
|
|
103
90
|
{items?.map((item) => (
|
|
104
91
|
<React.Fragment key={item?.uid}>
|
|
@@ -110,22 +97,51 @@ export default function CartItemSummary(props: OrderSummaryProps) {
|
|
|
110
97
|
className={classes.image}
|
|
111
98
|
layout='fill'
|
|
112
99
|
sizes={responsiveVal(48, 96)}
|
|
100
|
+
sx={(theme) => ({
|
|
101
|
+
borderRadius: '50%',
|
|
102
|
+
marginRight: theme.spacings.xs,
|
|
103
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
104
|
+
padding: responsiveVal(5, 10),
|
|
105
|
+
width: `${responsiveVal(48, 96)} !important`,
|
|
106
|
+
height: `${responsiveVal(48, 96)} !important`,
|
|
107
|
+
display: 'block',
|
|
108
|
+
})}
|
|
113
109
|
/>
|
|
114
110
|
) : (
|
|
115
|
-
<
|
|
111
|
+
<Box />
|
|
116
112
|
)}
|
|
117
113
|
</React.Fragment>
|
|
118
114
|
))}
|
|
119
115
|
</Scroller>
|
|
120
|
-
</
|
|
121
|
-
<ScrollerButton
|
|
122
|
-
|
|
116
|
+
</Box>
|
|
117
|
+
<ScrollerButton
|
|
118
|
+
direction='right'
|
|
119
|
+
className={`${(classes.prevNext, classes.next)}`}
|
|
120
|
+
sx={{
|
|
121
|
+
position: 'absolute',
|
|
122
|
+
top: '50%',
|
|
123
|
+
transform: 'translateY(-50%)',
|
|
124
|
+
zIndex: 2,
|
|
125
|
+
right: 8,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
<SvgIcon src={iconChevronRight} />
|
|
123
129
|
</ScrollerButton>
|
|
124
130
|
</ScrollerProvider>
|
|
125
|
-
</
|
|
126
|
-
<Divider
|
|
127
|
-
|
|
131
|
+
</Box>
|
|
132
|
+
<Divider
|
|
133
|
+
classes={{ root: classes.divider }}
|
|
134
|
+
sx={(theme) => ({
|
|
135
|
+
margin: `${theme.spacings.xs} 0 ${theme.spacings.xs} 0`,
|
|
136
|
+
})}
|
|
137
|
+
/>
|
|
138
|
+
<CartTotals
|
|
139
|
+
sx={(theme) => ({
|
|
140
|
+
background: theme.palette.background.default,
|
|
141
|
+
padding: 0,
|
|
142
|
+
})}
|
|
143
|
+
/>
|
|
128
144
|
</SectionContainer>
|
|
129
|
-
</
|
|
145
|
+
</Box>
|
|
130
146
|
)
|
|
131
147
|
}
|
|
@@ -1,55 +1,56 @@
|
|
|
1
1
|
import { Money } from '@graphcommerce/magento-store'
|
|
2
|
-
import {
|
|
2
|
+
import { iconChevronRight, SvgIcon, extendableComponent } from '@graphcommerce/next-ui'
|
|
3
3
|
import { Trans } from '@lingui/macro'
|
|
4
|
-
import {
|
|
4
|
+
import { Box, Button, SxProps, Theme } from '@mui/material'
|
|
5
5
|
import PageLink from 'next/link'
|
|
6
|
-
import React, { PropsWithChildren } from 'react'
|
|
7
6
|
import { CartStartCheckoutFragment } from './CartStartCheckout.gql'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
},
|
|
14
|
-
checkoutButton: {
|
|
15
|
-
marginTop: theme.spacings.md,
|
|
16
|
-
marginBottom: theme.spacings.lg,
|
|
17
|
-
},
|
|
18
|
-
checkoutButtonIcon: {
|
|
19
|
-
marginLeft: 0,
|
|
20
|
-
},
|
|
21
|
-
checkoutButtonTotal: {
|
|
22
|
-
paddingRight: theme.spacings.xxs,
|
|
23
|
-
'& ~ span.MuiButton-endIcon': {
|
|
24
|
-
marginLeft: 6,
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
checkoutMoney: {},
|
|
28
|
-
}),
|
|
29
|
-
{ name: 'Cart' },
|
|
30
|
-
)
|
|
8
|
+
export type CartStartCheckoutProps = CartStartCheckoutFragment & {
|
|
9
|
+
children?: React.ReactNode
|
|
10
|
+
sx?: SxProps<Theme>
|
|
11
|
+
}
|
|
31
12
|
|
|
32
|
-
|
|
13
|
+
const name = 'CartStartCheckout' as const
|
|
14
|
+
const parts = [
|
|
15
|
+
'checkoutButtonContainer',
|
|
16
|
+
'checkoutButton',
|
|
17
|
+
'checkoutButtonTotal',
|
|
18
|
+
'checkoutMoney',
|
|
19
|
+
] as const
|
|
20
|
+
const { classes } = extendableComponent(name, parts)
|
|
33
21
|
|
|
34
22
|
export default function CartStartCheckout(props: CartStartCheckoutProps) {
|
|
35
|
-
const { prices, children } = props
|
|
23
|
+
const { prices, children, sx = [] } = props
|
|
36
24
|
|
|
37
25
|
const hasTotals = (prices?.grand_total?.value ?? 0) > 0
|
|
38
|
-
const classes = useStyles()
|
|
39
26
|
return (
|
|
40
|
-
<
|
|
27
|
+
<Box
|
|
28
|
+
className={classes.checkoutButtonContainer}
|
|
29
|
+
sx={[{ textAlign: 'center' }, ...(Array.isArray(sx) ? sx : [sx])]}
|
|
30
|
+
>
|
|
41
31
|
<PageLink href='/checkout' passHref>
|
|
42
32
|
<Button
|
|
43
33
|
variant='pill'
|
|
44
34
|
color='secondary'
|
|
45
35
|
size='large'
|
|
46
36
|
className={classes.checkoutButton}
|
|
47
|
-
endIcon={<
|
|
37
|
+
endIcon={<SvgIcon src={iconChevronRight} />}
|
|
48
38
|
disabled={!hasTotals}
|
|
39
|
+
sx={(theme) => ({
|
|
40
|
+
marginTop: theme.spacings.md,
|
|
41
|
+
marginBottom: theme.spacings.lg,
|
|
42
|
+
})}
|
|
49
43
|
>
|
|
50
|
-
<
|
|
44
|
+
<Box
|
|
45
|
+
component='span'
|
|
46
|
+
className={classes.checkoutButtonTotal}
|
|
47
|
+
sx={(theme) => ({
|
|
48
|
+
paddingRight: theme.spacings.xxs,
|
|
49
|
+
'& ~ span.MuiButton-endIcon': { marginLeft: '6px' },
|
|
50
|
+
})}
|
|
51
|
+
>
|
|
51
52
|
<Trans>Start Checkout</Trans>
|
|
52
|
-
</
|
|
53
|
+
</Box>{' '}
|
|
53
54
|
{hasTotals && (
|
|
54
55
|
<span className={classes.checkoutMoney}>
|
|
55
56
|
<Money {...prices?.grand_total} />
|
|
@@ -58,6 +59,6 @@ export default function CartStartCheckout(props: CartStartCheckoutProps) {
|
|
|
58
59
|
</Button>
|
|
59
60
|
</PageLink>
|
|
60
61
|
{children}
|
|
61
|
-
</
|
|
62
|
+
</Box>
|
|
62
63
|
)
|
|
63
64
|
}
|