@graphcommerce/magento-cart 3.1.2 → 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,19 @@
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
+
6
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)
7
20
 
8
21
 
@@ -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
+ }
@@ -45,10 +45,7 @@ export default function CartSummary(props: CartSummaryProps) {
45
45
  const classes = useStyles(props)
46
46
  const { children, editable } = props
47
47
 
48
- const { data } = useCartQuery(GetCartSummaryDocument, {
49
- // allowUrl: true,
50
- fetchPolicy: 'network-only',
51
- })
48
+ const { data } = useCartQuery(GetCartSummaryDocument, { allowUrl: true })
52
49
 
53
50
  if (!data?.cart) return null
54
51
 
@@ -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.1.2",
3
+ "version": "3.1.3",
4
4
  "sideEffects": false,
5
5
  "prettier": "@graphcommerce/prettier-config-pwa",
6
6
  "browserslist": [
@@ -21,14 +21,14 @@
21
21
  },
22
22
  "dependencies": {
23
23
  "@apollo/client": "^3.4.16",
24
- "@graphcommerce/framer-scroller": "^0.2.6",
24
+ "@graphcommerce/framer-scroller": "^0.2.7",
25
25
  "@graphcommerce/graphql": "^2.103.5",
26
26
  "@graphcommerce/image": "^2.104.6",
27
- "@graphcommerce/magento-customer": "^3.0.15",
27
+ "@graphcommerce/magento-customer": "^3.0.16",
28
28
  "@graphcommerce/magento-graphql": "^2.103.5",
29
- "@graphcommerce/magento-store": "^3.0.13",
30
- "@graphcommerce/next-ui": "^3.1.5",
31
- "@graphcommerce/react-hook-form": "^2.102.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": "f1d0e488921787f39a260c410790ec13d32c8143"
41
+ "gitHead": "717bd3c1658e421c247c1f8b210935cdb7780197"
42
42
  }