@graphcommerce/magento-cart 3.0.13 → 3.1.3

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
@@ -3,6 +3,41 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.1.3](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-cart@3.1.2...@graphcommerce/magento-cart@3.1.3) (2021-10-07)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **cart:** agreements didn't handle state updates properly ([4401ff9](https://github.com/ho-nl/m2-pwa/commit/4401ff96a410379805d89bb2fa711df2d8a8fad0))
12
+ * make sure if no payment method is filled in we get an error shown ([a203e57](https://github.com/ho-nl/m2-pwa/commit/a203e570caad0732427a178e8e8b10b4a15d676b))
13
+ * make sure the CartAgreementsForm validates immediately ([eceacbb](https://github.com/ho-nl/m2-pwa/commit/eceacbb4803dd6e2701bf1835aa601c06ba4d6a3))
14
+
15
+
16
+
17
+
18
+
19
+ ## [3.1.1](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-cart@3.1.0...@graphcommerce/magento-cart@3.1.1) (2021-10-06)
20
+
21
+
22
+ ### Bug Fixes
23
+
24
+ * **cart-fab:** box shadow in safari ([4eb316d](https://github.com/ho-nl/m2-pwa/commit/4eb316dd0f2ab7ee2806a3acdb306af1eb72854b))
25
+
26
+
27
+
28
+
29
+
30
+ # [3.1.0](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-cart@3.0.13...@graphcommerce/magento-cart@3.1.0) (2021-10-05)
31
+
32
+
33
+ ### Features
34
+
35
+ * **checkout-shipping:** edit shipping address link ([b598008](https://github.com/ho-nl/m2-pwa/commit/b598008ffccb499fe0109ee557e08d557cf20d6e))
36
+
37
+
38
+
39
+
40
+
6
41
  ## [3.0.9](https://github.com/ho-nl/m2-pwa/compare/@graphcommerce/magento-cart@3.0.8...@graphcommerce/magento-cart@3.0.9) (2021-09-30)
7
42
 
8
43
 
@@ -0,0 +1,6 @@
1
+ import { Page } from '@playwright/test'
2
+
3
+ export async function fillCartAgreementsForm(page: Page) {
4
+ const inputs = await page.$$('form[name=cartAgreements] input')
5
+ await Promise.all(inputs.map((input) => input.check()))
6
+ }
@@ -16,13 +16,14 @@ export default function ApolloCartErrorAlert(props: ApolloCartErrorAlertProps) {
16
16
  let action: JSX.Element | undefined
17
17
 
18
18
  const [, noSuchEntity] = graphqlErrorByCategory({ category: 'graphql-no-such-entity', error })
19
- action = noSuchEntity && clear ? <Button onClick={clear}>Reset Cart</Button> : undefined
19
+ action = noSuchEntity ? <Button onClick={clear}>Reset Cart</Button> : undefined
20
20
 
21
21
  const [, authorizationError] = graphqlErrorByCategory({
22
22
  category: 'graphql-authorization',
23
23
  error,
24
24
  mask: token?.token ? 'Please reauthenticate and try again' : 'You must sign in to continue',
25
25
  })
26
+
26
27
  action =
27
28
  authorizationError && clear ? (
28
29
  <Link href='/account/signin' passHref>
@@ -1 +1,30 @@
1
- export {}
1
+ import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
2
+ import {
3
+ ApolloErrorFullPage,
4
+ Button,
5
+ SvgImage,
6
+ ApolloErrorFullPageProps,
7
+ iconLock,
8
+ iconSadShoppingBag,
9
+ } from '@graphcommerce/next-ui'
10
+ import React from 'react'
11
+ import { useClearCurrentCartId } from '../../hooks/useClearCurrentCartId'
12
+
13
+ export type ApolloCartErrorFullPageProps = Omit<ApolloErrorFullPageProps, 'icon'>
14
+
15
+ export default function ApolloCartErrorFullPage(props: ApolloCartErrorFullPageProps) {
16
+ const { error, ...passedProps } = props
17
+ const clear = useClearCurrentCartId()
18
+
19
+ const [, noSuchEntity] = graphqlErrorByCategory({ category: 'graphql-no-such-entity', error })
20
+ const action = noSuchEntity ? <Button onClick={clear}>Reset Cart</Button> : undefined
21
+
22
+ return (
23
+ <ApolloErrorFullPage
24
+ error={error}
25
+ icon={<SvgImage src={iconSadShoppingBag} size={148} alt='person' />}
26
+ button={action}
27
+ {...passedProps}
28
+ />
29
+ )
30
+ }
@@ -0,0 +1,11 @@
1
+ query CartAgreements {
2
+ checkoutAgreements {
3
+ agreement_id
4
+ checkbox_text
5
+ content
6
+ content_height
7
+ is_html
8
+ mode
9
+ name
10
+ }
11
+ }
@@ -0,0 +1,132 @@
1
+ import { useQuery } from '@apollo/client'
2
+ import { FormDiv } from '@graphcommerce/next-ui'
3
+ import {
4
+ Controller,
5
+ useForm,
6
+ useFormCompose,
7
+ UseFormComposeOptions,
8
+ useFormPersist,
9
+ } from '@graphcommerce/react-hook-form'
10
+ import {
11
+ Checkbox,
12
+ FormControl,
13
+ FormControlLabel,
14
+ FormHelperText,
15
+ Link,
16
+ makeStyles,
17
+ Theme,
18
+ } from '@material-ui/core'
19
+ import PageLink from 'next/link'
20
+ import React from 'react'
21
+ import { CartAgreementsDocument } from './CartAgreements.gql'
22
+
23
+ export type CartAgreementsFormProps = Pick<UseFormComposeOptions, 'step'>
24
+
25
+ const useStyles = makeStyles(
26
+ (theme: Theme) => ({
27
+ formDiv: {
28
+ paddingTop: theme.spacings.sm,
29
+ },
30
+ formInner: {
31
+ ...theme.typography.body1,
32
+ display: 'inline-block',
33
+ },
34
+ formControlRoot: {
35
+ display: 'block',
36
+ },
37
+ manualCheck: {
38
+ padding: `9px 0`,
39
+ },
40
+ }),
41
+ {
42
+ name: 'CartAgreements',
43
+ },
44
+ )
45
+
46
+ export default function CartAgreementsForm(props: CartAgreementsFormProps) {
47
+ const { step } = props
48
+ const { data } = useQuery(CartAgreementsDocument)
49
+ const classes = useStyles()
50
+
51
+ // sort conditions so checkboxes will be placed first
52
+ const sortedAgreements = data?.checkoutAgreements
53
+ ? [...data.checkoutAgreements].sort((a, b) => {
54
+ return a?.mode === 'MANUAL' ? -1 : b?.mode === 'MANUAL' ? 1 : 0
55
+ })
56
+ : []
57
+
58
+ const form = useForm({ mode: 'onChange' })
59
+
60
+ const { handleSubmit, formState, control } = form
61
+
62
+ const submit = handleSubmit(() => {})
63
+
64
+ useFormPersist({ form, name: 'PaymentAgreementsForm' })
65
+
66
+ useFormCompose({ form, step, submit, key: 'PaymentAgreementsForm' })
67
+
68
+ return (
69
+ <FormDiv classes={{ root: classes.formDiv }}>
70
+ <form noValidate onSubmit={submit} name='cartAgreements'>
71
+ <div className={classes.formInner}>
72
+ {data?.checkoutAgreements &&
73
+ sortedAgreements?.map(
74
+ (agreement) =>
75
+ agreement && (
76
+ <React.Fragment key={agreement.agreement_id}>
77
+ {agreement.mode === 'MANUAL' ? (
78
+ <>
79
+ <Controller
80
+ defaultValue={''}
81
+ name={String(agreement.agreement_id)}
82
+ control={control}
83
+ rules={{ required: 'You have to agree in order to proceed' }}
84
+ render={({
85
+ field: { onChange, value, name, ref, onBlur },
86
+ fieldState: { error },
87
+ }) => (
88
+ <FormControl
89
+ error={!!formState.errors[String(agreement.agreement_id)]}
90
+ classes={{ root: classes.formControlRoot }}
91
+ >
92
+ <FormControlLabel
93
+ control={<Checkbox color='secondary' required={true} />}
94
+ label={
95
+ <PageLink
96
+ href={`/legal/view/${agreement.name
97
+ ?.toLowerCase()
98
+ .replaceAll(' ', '-')}`}
99
+ passHref
100
+ >
101
+ <Link color='secondary'>{agreement.checkbox_text}</Link>
102
+ </PageLink>
103
+ }
104
+ checked={!!value}
105
+ inputRef={ref}
106
+ onBlur={onBlur}
107
+ name={name}
108
+ onChange={(e) => onChange(e as React.ChangeEvent<HTMLInputElement>)}
109
+ />
110
+ {error?.message && <FormHelperText>{error.message}</FormHelperText>}
111
+ </FormControl>
112
+ )}
113
+ />
114
+ </>
115
+ ) : (
116
+ <div className={classes.manualCheck}>
117
+ <PageLink
118
+ href={`/legal/view/${agreement.name?.toLowerCase().replaceAll(' ', '-')}`}
119
+ passHref
120
+ >
121
+ <Link color='secondary'>{agreement.checkbox_text}</Link>
122
+ </PageLink>
123
+ </div>
124
+ )}
125
+ </React.Fragment>
126
+ ),
127
+ )}
128
+ </div>
129
+ </form>
130
+ </FormDiv>
131
+ )
132
+ }
@@ -2,6 +2,7 @@ import {
2
2
  iconShoppingBag,
3
3
  StyledBadge,
4
4
  SvgImageSimple,
5
+ FixedFab,
5
6
  useFixedFabAnimation,
6
7
  } from '@graphcommerce/next-ui'
7
8
  import { Fab, FabProps, NoSsr } from '@material-ui/core'
@@ -23,12 +24,20 @@ function CartFabContent(props: CartFabContentProps) {
23
24
  const cartIcon = icon ?? (
24
25
  <SvgImageSimple src={iconShoppingBag} alt='Shopping Bag' loading='eager' size='large' />
25
26
  )
26
- const { filter } = useFixedFabAnimation()
27
+ const { boxShadow } = useFixedFabAnimation()
27
28
 
28
29
  return (
29
- <m.div style={{ filter }}>
30
+ <m.div style={{ boxShadow, width: 'inherit', borderRadius: 'inherit' }}>
30
31
  <PageLink href='/cart' passHref>
31
- <Fab aria-label='Cart' color='inherit' size='large' {...fabProps}>
32
+ <Fab
33
+ aria-label='Cart'
34
+ color='inherit'
35
+ size='large'
36
+ style={{
37
+ boxShadow: 'none',
38
+ }}
39
+ {...fabProps}
40
+ >
32
41
  {total_quantity > 0 ? (
33
42
  <StyledBadge color='primary' variant='dot'>
34
43
  {cartIcon}
@@ -60,8 +69,10 @@ export default function CartFab(props: CartFabProps) {
60
69
  const qty = data?.cart?.total_quantity ?? 0
61
70
 
62
71
  return (
63
- <NoSsr fallback={<CartFabContent {...props} total_quantity={0} />}>
64
- <CartFabContent total_quantity={qty} {...props} />
65
- </NoSsr>
72
+ <FixedFab>
73
+ <NoSsr fallback={<CartFabContent {...props} total_quantity={0} />}>
74
+ <CartFabContent total_quantity={qty} {...props} />
75
+ </NoSsr>
76
+ </FixedFab>
66
77
  )
67
78
  }
@@ -1,3 +1,4 @@
1
+ import { useHistoryLink } from '@graphcommerce/framer-next-pages'
1
2
  import { SectionContainer, UseStyles } from '@graphcommerce/next-ui'
2
3
  import { Link, makeStyles, Theme, Typography } from '@material-ui/core'
3
4
  import PageLink from 'next/link'
@@ -44,15 +45,16 @@ export default function CartSummary(props: CartSummaryProps) {
44
45
  const classes = useStyles(props)
45
46
  const { children, editable } = props
46
47
 
47
- const { data } = useCartQuery(GetCartSummaryDocument, {
48
- // allowUrl: true,
49
- fetchPolicy: 'network-only',
50
- })
48
+ const { data } = useCartQuery(GetCartSummaryDocument, { allowUrl: true })
51
49
 
52
50
  if (!data?.cart) return null
53
51
 
54
52
  const { email, shipping_addresses, billing_address } = data.cart
55
53
 
54
+ const { href: historyHref, onClick: historyOnClick } = useHistoryLink({
55
+ href: '/checkout',
56
+ })
57
+
56
58
  return (
57
59
  <div className={classes.root}>
58
60
  <div className={classes.detailsContainer}>
@@ -61,15 +63,6 @@ export default function CartSummary(props: CartSummaryProps) {
61
63
  variantLeft='h5'
62
64
  labelLeft='Confirmation + Track & trace'
63
65
  classes={{ sectionHeaderWrapper: classes.sectionHeaderWrapper }}
64
- // labelRight={
65
- // editable ? (
66
- // <PageLink href='/checkout/edit' passHref>
67
- // <Link color='secondary' variant='body2'>
68
- // Edit
69
- // </Link>
70
- // </PageLink>
71
- // ) : undefined
72
- // }
73
66
  />
74
67
  <Typography variant='body1'>{email || ''}</Typography>
75
68
  </div>
@@ -78,15 +71,6 @@ export default function CartSummary(props: CartSummaryProps) {
78
71
  variantLeft='h5'
79
72
  labelLeft='Shipping method'
80
73
  classes={{ sectionHeaderWrapper: classes.sectionHeaderWrapper }}
81
- // labelRight={
82
- // editable ? (
83
- // <PageLink href='/checkout/edit/shipping' passHref>
84
- // <Link color='secondary' variant='body2'>
85
- // Edit
86
- // </Link>
87
- // </PageLink>
88
- // ) : undefined
89
- // }
90
74
  />
91
75
  <Typography variant='body1'>
92
76
  {shipping_addresses?.[0]?.selected_shipping_method?.carrier_title}
@@ -100,15 +84,15 @@ export default function CartSummary(props: CartSummaryProps) {
100
84
  variantLeft='h5'
101
85
  labelLeft='Shipping address'
102
86
  classes={{ sectionHeaderWrapper: classes.sectionHeaderWrapper }}
103
- // labelRight={
104
- // editable ? (
105
- // <PageLink href='/checkout/edit/shipping_address' passHref>
106
- // <Link color='secondary' variant='body2'>
107
- // Edit
108
- // </Link>
109
- // </PageLink>
110
- // ) : undefined
111
- // }
87
+ labelRight={
88
+ editable ? (
89
+ <PageLink href={historyHref} passHref>
90
+ <Link color='secondary' variant='body2' onClick={historyOnClick}>
91
+ Edit
92
+ </Link>
93
+ </PageLink>
94
+ ) : undefined
95
+ }
112
96
  />
113
97
  <CartAddressMultiLine {...shipping_addresses[0]} />
114
98
  </div>
@@ -1,5 +1,11 @@
1
- import { responsiveVal, SvgImage, iconSadShoppingBag } from '@graphcommerce/next-ui'
2
- import { makeStyles, Theme, Typography } from '@material-ui/core'
1
+ import {
2
+ responsiveVal,
3
+ SvgImage,
4
+ iconSadShoppingBag,
5
+ FullPageMessage,
6
+ } from '@graphcommerce/next-ui'
7
+ import { Button, makeStyles, Theme, Typography } from '@material-ui/core'
8
+ import Link from 'next/link'
3
9
  import React from 'react'
4
10
 
5
11
  const useStyles = makeStyles(
@@ -31,6 +37,30 @@ export default function EmptyCart(props: EmptyCartProps) {
31
37
  const { children } = props
32
38
  const classes = useStyles()
33
39
 
40
+ return (
41
+ <FullPageMessage
42
+ title={'Your cart is empty'}
43
+ icon={
44
+ <SvgImage
45
+ src={iconSadShoppingBag}
46
+ alt='Empty Cart'
47
+ className={classes.img}
48
+ loading='eager'
49
+ size='large'
50
+ />
51
+ }
52
+ button={
53
+ <Link href='/' passHref>
54
+ <Button variant='contained' color='primary' size='large'>
55
+ Continue shopping
56
+ </Button>
57
+ </Link>
58
+ }
59
+ >
60
+ Discover our collection and add items to your basket!
61
+ </FullPageMessage>
62
+ )
63
+
34
64
  return (
35
65
  <div className={classes.root}>
36
66
  <div>
@@ -12,8 +12,8 @@ export { default as EmptyCart } from './EmptyCart/EmptyCart'
12
12
  export * from './ApolloCartError/ApolloCartErrorAlert'
13
13
  export { default as ApolloCartErrorAlert } from './ApolloCartError/ApolloCartErrorAlert'
14
14
 
15
- // export { default as ApolloCartErrorFullPage } from './ApolloCartError/ApolloCartErrorFullPage'
16
- // export * from './ApolloCartError/ApolloCartErrorFullPage'
15
+ export * from './ApolloCartError/ApolloCartErrorFullPage'
16
+ export { default as ApolloCartErrorFullPage } from './ApolloCartError/ApolloCartErrorFullPage'
17
17
 
18
18
  export * from './CartSummary'
19
19
  export { default as CartSummary } from './CartSummary'
@@ -28,3 +28,6 @@ export { default as CartAddressMultiLine } from './CartAddressMultiLine'
28
28
 
29
29
  export * from './CartAddressSingleLine'
30
30
  export { default as CartAddressSingleLine } from './CartAddressSingleLine'
31
+
32
+ export * from './CartAgreementsForm/CartAgreementsForm'
33
+ export { default as CartAgreementsForm } from './CartAgreementsForm/CartAgreementsForm'
@@ -1,14 +1,13 @@
1
1
  import { useApolloClient } from '@apollo/client'
2
2
  import { CurrentCartIdDocument } from './CurrentCartId.gql'
3
- import { useCurrentCartId } from './useCurrentCartId'
4
3
 
5
4
  export function useClearCurrentCartId() {
6
5
  const { cache } = useApolloClient()
7
- const currentCartId = useCurrentCartId()
8
-
9
- if (!currentCartId) return undefined
10
6
 
11
7
  return () => {
8
+ const id = cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId?.id
9
+ if (!id) return
10
+
12
11
  cache.writeQuery({
13
12
  query: CurrentCartIdDocument,
14
13
  data: { currentCartId: { __typename: 'CurrentCartId', id: null } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@graphcommerce/magento-cart",
3
- "version": "3.0.13",
3
+ "version": "3.1.3",
4
4
  "sideEffects": false,
5
5
  "prettier": "@graphcommerce/prettier-config-pwa",
6
6
  "browserslist": [
@@ -14,21 +14,21 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "@graphcommerce/browserslist-config-pwa": "^3.0.1",
17
- "@graphcommerce/eslint-config-pwa": "^3.0.4",
17
+ "@graphcommerce/eslint-config-pwa": "^3.0.5",
18
18
  "@graphcommerce/prettier-config-pwa": "^3.0.2",
19
19
  "@graphcommerce/typescript-config-pwa": "^3.1.0",
20
20
  "@playwright/test": "^1.15.0"
21
21
  },
22
22
  "dependencies": {
23
- "@apollo/client": "^3.3.21",
24
- "@graphcommerce/framer-scroller": "^0.2.5",
25
- "@graphcommerce/graphql": "^2.103.4",
26
- "@graphcommerce/image": "^2.104.5",
27
- "@graphcommerce/magento-customer": "^3.0.13",
28
- "@graphcommerce/magento-graphql": "^2.103.4",
29
- "@graphcommerce/magento-store": "^3.0.11",
30
- "@graphcommerce/next-ui": "^3.1.3",
31
- "@graphcommerce/react-hook-form": "^2.102.4",
23
+ "@apollo/client": "^3.4.16",
24
+ "@graphcommerce/framer-scroller": "^0.2.7",
25
+ "@graphcommerce/graphql": "^2.103.5",
26
+ "@graphcommerce/image": "^2.104.6",
27
+ "@graphcommerce/magento-customer": "^3.0.16",
28
+ "@graphcommerce/magento-graphql": "^2.103.5",
29
+ "@graphcommerce/magento-store": "^3.0.14",
30
+ "@graphcommerce/next-ui": "^3.1.6",
31
+ "@graphcommerce/react-hook-form": "^2.102.6",
32
32
  "@graphql-typed-document-node/core": "^3.1.0",
33
33
  "@material-ui/core": "^4.12.3",
34
34
  "@material-ui/lab": "^4.0.0-alpha.60",
@@ -38,5 +38,5 @@
38
38
  "react": "^17.0.2",
39
39
  "react-dom": "^17.0.2"
40
40
  },
41
- "gitHead": "148ed6eb34bf3b3da72c1791c4195d8d141bc6e6"
41
+ "gitHead": "717bd3c1658e421c247c1f8b210935cdb7780197"
42
42
  }