@graphcommerce/magento-customer 7.0.0-canary.21 → 7.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 +211 -1
- package/components/AccountSignInUpForm/AccountSignInUpForm.tsx +4 -1
- package/components/AddressFields/AddressFields.tsx +1 -1
- package/components/ApolloCustomerError/ApolloCustomerErrorAlert.tsx +0 -1
- package/components/ChangePasswordForm/ChangePasswordForm.tsx +44 -30
- package/components/CreateCustomerAddressForm/CreateCustomerAddress.graphql +2 -2
- package/components/CreateCustomerAddressForm/CreateCustomerAddressForm.tsx +2 -1
- package/components/CreateCustomerAddressForm/CustomerAddress.graphql +1 -0
- package/components/CustomerFab/CustomerFab.tsx +3 -0
- package/components/EditAddressForm/EditAddressForm.tsx +2 -0
- package/components/ForgotPasswordForm/ForgotPasswordForm.tsx +1 -0
- package/components/NameFields/NameFields.tsx +2 -1
- package/components/OrderCard/OrderCard.tsx +1 -1
- package/components/ResetPasswordForm/ResetPasswordForm.tsx +5 -9
- package/components/SessionDebugger/SessionDebugger.tsx +2 -1
- package/components/SignInForm/SignInForm.tsx +9 -10
- package/components/SignInForm/SignInFormInline.tsx +17 -17
- package/components/SignUpForm/SignUpForm.tsx +14 -27
- package/components/SignUpForm/SignUpFormInline.tsx +39 -52
- package/components/UpdateCustomerEmailForm/UpdateCustomerEmailForm.tsx +28 -21
- package/components/UpdateDefaultAddressForm/UpdateDefaultAddressForm.tsx +1 -0
- package/components/ValidatedPasswordElement/ValidatedPasswordElement.tsx +47 -0
- package/hooks/CustomerInfo.graphql +1 -0
- package/hooks/UseCustomerValidateToken.graphql +5 -0
- package/hooks/useCustomerValidateToken.ts +23 -0
- package/link/createCustomerTokenLink.ts +2 -7
- package/package.json +16 -15
- package/test/authentication.playwright.ts +1 -0
- package/link/onAuthenticationError.ts +0 -39
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,216 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
## 7.0.0
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1962](https://github.com/graphcommerce-org/graphcommerce/pull/1962) [`518b6ca24`](https://github.com/graphcommerce-org/graphcommerce/commit/518b6ca248fc94624dc06eb02de5b3eac0fc9483) - Created a new `<ValidatedPasswordElement/>` which validates according to Magento's validation groups and implement on all locations. Move remaining password fields to `<PasswordElement />` ([@carlocarels90](https://github.com/carlocarels90))
|
|
8
|
+
|
|
9
|
+
- [#1926](https://github.com/graphcommerce-org/graphcommerce/pull/1926) [`ab8877fdb`](https://github.com/graphcommerce-org/graphcommerce/commit/ab8877fdb6147960ce656d28306d719e92f6de68) - Made the follow order link in the order card & order details a working `<Link />` if provided from magento backend. ([@JoshuaS98](https://github.com/JoshuaS98))
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [#1916](https://github.com/graphcommerce-org/graphcommerce/pull/1916) [`97ebc19af`](https://github.com/graphcommerce-org/graphcommerce/commit/97ebc19aff093bf57d24d009e96661ad43926fd6) - The customer's token would be invalidated if any authorization error occured. Now only scoped to customer queries and mutations, potentially reducing the amount of random logouts. ([@paales](https://github.com/paales))
|
|
14
|
+
|
|
15
|
+
- [#1952](https://github.com/graphcommerce-org/graphcommerce/pull/1952) [`f1fe4f598`](https://github.com/graphcommerce-org/graphcommerce/commit/f1fe4f5986cee1f7c8313152e43691ed939c8f21) - Enable password fields when there is an error and user input correction is required. ([@carlocarels90](https://github.com/carlocarels90))
|
|
16
|
+
|
|
17
|
+
- [#1914](https://github.com/graphcommerce-org/graphcommerce/pull/1914) [`38d6c4888`](https://github.com/graphcommerce-org/graphcommerce/commit/38d6c488850013b36cae9f388996039219c1327e) - Errors in the cart didn't allow for recovery from the faulty state ([@paales](https://github.com/paales))
|
|
18
|
+
|
|
19
|
+
- [#1930](https://github.com/graphcommerce-org/graphcommerce/pull/1930) [`c8d023e9e`](https://github.com/graphcommerce-org/graphcommerce/commit/c8d023e9e874131cd9f8fe192b1fca5fe1a26ee3) - Fix the 'close menu' on search and add the option to secondary menu items ([@StefanAngenent](https://github.com/StefanAngenent))
|
|
20
|
+
|
|
21
|
+
- [#2006](https://github.com/graphcommerce-org/graphcommerce/pull/2006) [`80b60cb40`](https://github.com/graphcommerce-org/graphcommerce/commit/80b60cb404882260bd0e8184f3e54f4720925c96) - The Billing address was set to the shipping address when a default billing address was available and made prefix optional when creating an address ([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
22
|
+
|
|
23
|
+
- [#1942](https://github.com/graphcommerce-org/graphcommerce/pull/1942) [`21b0d0c48`](https://github.com/graphcommerce-org/graphcommerce/commit/21b0d0c48603343c09f287978bf051140e9be912) - Customer's session is now revalidated when a previous session is detected on pageload, making sure the customer is still logged in. ([@paales](https://github.com/paales))
|
|
24
|
+
|
|
25
|
+
- [#1972](https://github.com/graphcommerce-org/graphcommerce/pull/1972) [`cda89820d`](https://github.com/graphcommerce-org/graphcommerce/commit/cda89820dc50e2019a26239b7450863d8c862bfb) - Ensure correct width for CircularProgress and fix misalignment in rotate animation ([@carlocarels90](https://github.com/carlocarels90))
|
|
26
|
+
|
|
27
|
+
- [#2016](https://github.com/graphcommerce-org/graphcommerce/pull/2016) [`227ddcee8`](https://github.com/graphcommerce-org/graphcommerce/commit/227ddcee8808715928371c1f3a4c7925032df0ef) - Made cardProps on CustomerAddressActionCards overridable. ([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
28
|
+
|
|
29
|
+
- [#1969](https://github.com/graphcommerce-org/graphcommerce/pull/1969) [`838322a97`](https://github.com/graphcommerce-org/graphcommerce/commit/838322a97c7ef1b8aa919196e756da381904bf04) - Fixing the Internal Server Error if the third address line is empty. ([@action-simon](https://github.com/action-simon))
|
|
30
|
+
|
|
31
|
+
## 6.2.0-canary.98
|
|
32
|
+
|
|
33
|
+
## 6.2.0-canary.97
|
|
34
|
+
|
|
35
|
+
## 6.2.0-canary.96
|
|
36
|
+
|
|
37
|
+
## 6.2.0-canary.95
|
|
38
|
+
|
|
39
|
+
## 6.2.0-canary.94
|
|
40
|
+
|
|
41
|
+
## 6.2.0-canary.93
|
|
42
|
+
|
|
43
|
+
## 6.2.0-canary.92
|
|
44
|
+
|
|
45
|
+
## 6.2.0-canary.91
|
|
46
|
+
|
|
47
|
+
## 6.2.0-canary.90
|
|
48
|
+
|
|
49
|
+
## 6.2.0-canary.89
|
|
50
|
+
|
|
51
|
+
## 6.2.0-canary.88
|
|
52
|
+
|
|
53
|
+
## 6.2.0-canary.87
|
|
54
|
+
|
|
55
|
+
## 6.2.0-canary.86
|
|
56
|
+
|
|
57
|
+
## 6.2.0-canary.85
|
|
58
|
+
|
|
59
|
+
## 6.2.0-canary.84
|
|
60
|
+
|
|
61
|
+
## 6.2.0-canary.83
|
|
62
|
+
|
|
63
|
+
## 6.2.0-canary.82
|
|
64
|
+
|
|
65
|
+
## 6.2.0-canary.81
|
|
66
|
+
|
|
67
|
+
## 6.2.0-canary.80
|
|
68
|
+
|
|
69
|
+
## 6.2.0-canary.79
|
|
70
|
+
|
|
71
|
+
## 6.2.0-canary.78
|
|
72
|
+
|
|
73
|
+
## 6.2.0-canary.77
|
|
74
|
+
|
|
75
|
+
## 6.2.0-canary.76
|
|
76
|
+
|
|
77
|
+
## 6.2.0-canary.75
|
|
78
|
+
|
|
79
|
+
### Patch Changes
|
|
80
|
+
|
|
81
|
+
- [#2016](https://github.com/graphcommerce-org/graphcommerce/pull/2016) [`227ddcee8`](https://github.com/graphcommerce-org/graphcommerce/commit/227ddcee8808715928371c1f3a4c7925032df0ef) - Made cardProps on CustomerAddressActionCards overridable. ([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
82
|
+
|
|
83
|
+
## 6.2.0-canary.74
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- [#2006](https://github.com/graphcommerce-org/graphcommerce/pull/2006) [`80b60cb40`](https://github.com/graphcommerce-org/graphcommerce/commit/80b60cb404882260bd0e8184f3e54f4720925c96) - Bugfix for unintentionally overriding the billing address even if a default address was set. Also made prefix optional when creating an address ([@Jessevdpoel](https://github.com/Jessevdpoel))
|
|
88
|
+
|
|
89
|
+
## 6.2.0-canary.73
|
|
90
|
+
|
|
91
|
+
## 6.2.0-canary.72
|
|
92
|
+
|
|
93
|
+
## 6.2.0-canary.71
|
|
94
|
+
|
|
95
|
+
## 6.2.0-canary.70
|
|
96
|
+
|
|
97
|
+
## 6.2.0-canary.69
|
|
98
|
+
|
|
99
|
+
## 6.2.0-canary.68
|
|
100
|
+
|
|
101
|
+
## 6.2.0-canary.67
|
|
102
|
+
|
|
103
|
+
## 6.2.0-canary.66
|
|
104
|
+
|
|
105
|
+
## 6.2.0-canary.65
|
|
106
|
+
|
|
107
|
+
## 6.2.0-canary.64
|
|
108
|
+
|
|
109
|
+
## 6.2.0-canary.63
|
|
110
|
+
|
|
111
|
+
## 6.2.0-canary.62
|
|
112
|
+
|
|
113
|
+
## 6.2.0-canary.61
|
|
114
|
+
|
|
115
|
+
## 6.2.0-canary.60
|
|
116
|
+
|
|
117
|
+
## 6.2.0-canary.59
|
|
118
|
+
|
|
119
|
+
## 6.2.0-canary.58
|
|
120
|
+
|
|
121
|
+
## 6.2.0-canary.57
|
|
122
|
+
|
|
123
|
+
## 6.2.0-canary.56
|
|
124
|
+
|
|
125
|
+
## 6.2.0-canary.55
|
|
126
|
+
|
|
127
|
+
## 6.2.0-canary.54
|
|
128
|
+
|
|
129
|
+
## 6.2.0-canary.53
|
|
130
|
+
|
|
131
|
+
## 6.2.0-canary.52
|
|
132
|
+
|
|
133
|
+
### Patch Changes
|
|
134
|
+
|
|
135
|
+
- [#1972](https://github.com/graphcommerce-org/graphcommerce/pull/1972) [`cda89820d`](https://github.com/graphcommerce-org/graphcommerce/commit/cda89820dc50e2019a26239b7450863d8c862bfb) - Ensure correct width for CircularProgress and fix misalignment in rotate animation ([@carlocarels90](https://github.com/carlocarels90))
|
|
136
|
+
|
|
137
|
+
## 6.2.0-canary.51
|
|
138
|
+
|
|
139
|
+
## 6.2.0-canary.50
|
|
140
|
+
|
|
141
|
+
## 6.2.0-canary.49
|
|
142
|
+
|
|
143
|
+
## 6.2.0-canary.48
|
|
144
|
+
|
|
145
|
+
## 6.2.0-canary.47
|
|
146
|
+
|
|
147
|
+
### Patch Changes
|
|
148
|
+
|
|
149
|
+
- [#1969](https://github.com/graphcommerce-org/graphcommerce/pull/1969) [`838322a97`](https://github.com/graphcommerce-org/graphcommerce/commit/838322a97c7ef1b8aa919196e756da381904bf04) - Fixing the Internal Server Error if the third address line is empty. ([@action-simon](https://github.com/action-simon))
|
|
150
|
+
|
|
151
|
+
## 6.2.0-canary.46
|
|
152
|
+
|
|
153
|
+
## 6.2.0-canary.45
|
|
154
|
+
|
|
155
|
+
### Minor Changes
|
|
156
|
+
|
|
157
|
+
- [#1962](https://github.com/graphcommerce-org/graphcommerce/pull/1962) [`518b6ca24`](https://github.com/graphcommerce-org/graphcommerce/commit/518b6ca248fc94624dc06eb02de5b3eac0fc9483) - Created a new `<ValidatedPasswordElement/>` which validates according to Magento's validation groups and implement on all locations. Move remaining password fields to `<PasswordElement />` ([@carlocarels90](https://github.com/carlocarels90))
|
|
158
|
+
|
|
159
|
+
## 6.2.0-canary.44
|
|
160
|
+
|
|
161
|
+
## 6.2.0-canary.43
|
|
162
|
+
|
|
163
|
+
## 6.2.0-canary.42
|
|
164
|
+
|
|
165
|
+
## 6.2.0-canary.41
|
|
166
|
+
|
|
167
|
+
## 6.2.0-canary.40
|
|
168
|
+
|
|
169
|
+
## 6.2.0-canary.39
|
|
170
|
+
|
|
171
|
+
## 6.2.0-canary.38
|
|
172
|
+
|
|
173
|
+
## 6.2.0-canary.37
|
|
174
|
+
|
|
175
|
+
### Patch Changes
|
|
176
|
+
|
|
177
|
+
- [#1952](https://github.com/graphcommerce-org/graphcommerce/pull/1952) [`f1fe4f598`](https://github.com/graphcommerce-org/graphcommerce/commit/f1fe4f5986cee1f7c8313152e43691ed939c8f21) - enable password fields when there is an error and user input correction is required. ([@carlocarels90](https://github.com/carlocarels90))
|
|
178
|
+
|
|
179
|
+
## 6.2.0-canary.36
|
|
180
|
+
|
|
181
|
+
## 6.2.0-canary.35
|
|
182
|
+
|
|
183
|
+
## 6.2.0-canary.34
|
|
184
|
+
|
|
185
|
+
## 6.2.0-canary.33
|
|
186
|
+
|
|
187
|
+
## 6.2.0-canary.32
|
|
188
|
+
|
|
189
|
+
## 6.2.0-canary.31
|
|
190
|
+
|
|
191
|
+
## 6.2.0-canary.30
|
|
192
|
+
|
|
193
|
+
### Patch Changes
|
|
194
|
+
|
|
195
|
+
- [#1942](https://github.com/graphcommerce-org/graphcommerce/pull/1942) [`21b0d0c48`](https://github.com/graphcommerce-org/graphcommerce/commit/21b0d0c48603343c09f287978bf051140e9be912) - Customer's session is now revalidated when a previous session is detected on pageload, making sure the customer is still logged in. ([@paales](https://github.com/paales))
|
|
196
|
+
|
|
197
|
+
## 6.2.0-canary.29
|
|
198
|
+
|
|
199
|
+
## 6.2.0-canary.28
|
|
200
|
+
|
|
201
|
+
## 6.2.0-canary.27
|
|
202
|
+
|
|
203
|
+
## 6.2.0-canary.26
|
|
204
|
+
|
|
205
|
+
## 6.2.0-canary.25
|
|
206
|
+
|
|
207
|
+
## 6.2.0-canary.24
|
|
208
|
+
|
|
209
|
+
## 6.2.0-canary.23
|
|
210
|
+
|
|
211
|
+
## 6.2.0-canary.22
|
|
212
|
+
|
|
213
|
+
## 6.2.0-canary.21
|
|
4
214
|
|
|
5
215
|
## 6.2.0-canary.20
|
|
6
216
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from '@graphcommerce/next-ui'
|
|
9
9
|
import { emailPattern } from '@graphcommerce/react-hook-form'
|
|
10
10
|
import { Trans } from '@lingui/react'
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
11
12
|
import { Box, CircularProgress, Link, SxProps, TextField, Theme, Typography } from '@mui/material'
|
|
12
13
|
import router from 'next/router'
|
|
13
14
|
import { CustomerDocument, useFormIsEmailAvailable } from '../../hooks'
|
|
@@ -118,7 +119,9 @@ export function AccountSignInUpForm(props: AccountSignInUpFormProps) {
|
|
|
118
119
|
pattern: { value: emailPattern, message: '' },
|
|
119
120
|
})}
|
|
120
121
|
InputProps={{
|
|
121
|
-
endAdornment: formState.isSubmitting &&
|
|
122
|
+
endAdornment: formState.isSubmitting && (
|
|
123
|
+
<CircularProgress sx={{ display: 'inline-flex' }} />
|
|
124
|
+
),
|
|
122
125
|
readOnly: !!customerQuery.data?.customer?.email,
|
|
123
126
|
}}
|
|
124
127
|
/>
|
|
@@ -21,8 +21,8 @@ export type AddressFieldValues = {
|
|
|
21
21
|
city?: string
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
24
|
export type AddressFieldsProps = {
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
26
|
form: UseFormReturn<any>
|
|
27
27
|
readOnly?: boolean
|
|
28
28
|
countryFirst?: boolean
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ApolloErrorAlert, ApolloErrorAlertProps } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { Button } from '@graphcommerce/next-ui'
|
|
3
3
|
import { Trans } from '@lingui/react'
|
|
4
|
-
import { Link } from '@mui/material'
|
|
5
4
|
import { useCustomerSession } from '../../hooks/useCustomerSession'
|
|
6
5
|
import { useAuthorizationErrorMasked } from './useAuthorizationErrorMasked'
|
|
7
6
|
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ApolloErrorSnackbar,
|
|
3
|
+
PasswordElement,
|
|
4
|
+
PasswordRepeatElement,
|
|
5
|
+
} from '@graphcommerce/ecommerce-ui'
|
|
6
|
+
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
1
7
|
import {
|
|
2
8
|
Form,
|
|
3
9
|
FormActions,
|
|
@@ -7,10 +13,8 @@ import {
|
|
|
7
13
|
Button,
|
|
8
14
|
} from '@graphcommerce/next-ui'
|
|
9
15
|
import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
10
|
-
import { i18n } from '@lingui/core'
|
|
11
16
|
import { Trans } from '@lingui/react'
|
|
12
|
-
import {
|
|
13
|
-
import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert'
|
|
17
|
+
import { ValidatedPasswordElement } from '../ValidatedPasswordElement/ValidatedPasswordElement'
|
|
14
18
|
import {
|
|
15
19
|
ChangePasswordDocument,
|
|
16
20
|
ChangePasswordMutation,
|
|
@@ -21,55 +25,61 @@ export function ChangePasswordForm() {
|
|
|
21
25
|
const form = useFormGqlMutation<
|
|
22
26
|
ChangePasswordMutation,
|
|
23
27
|
ChangePasswordMutationVariables & { confirmPassword?: string }
|
|
24
|
-
>(ChangePasswordDocument)
|
|
25
|
-
const {
|
|
28
|
+
>(ChangePasswordDocument, {}, { errorPolicy: 'all' })
|
|
29
|
+
const { handleSubmit, required, formState, error, control } = form
|
|
30
|
+
const [remainingError0, authenticationError] = graphqlErrorByCategory({
|
|
31
|
+
category: 'graphql-authentication',
|
|
32
|
+
error,
|
|
33
|
+
})
|
|
34
|
+
const [remainingError, inputError] = graphqlErrorByCategory({
|
|
35
|
+
category: 'graphql-input',
|
|
36
|
+
error: remainingError0,
|
|
37
|
+
})
|
|
38
|
+
|
|
26
39
|
const submitHandler = handleSubmit(() => {})
|
|
27
|
-
|
|
40
|
+
|
|
41
|
+
const showSuccess = !formState.isSubmitting && formState.isSubmitSuccessful && !error?.message
|
|
28
42
|
|
|
29
43
|
return (
|
|
30
44
|
<Form onSubmit={submitHandler} noValidate>
|
|
31
45
|
<FormRow>
|
|
32
|
-
<
|
|
46
|
+
<PasswordElement
|
|
47
|
+
control={control}
|
|
48
|
+
name='currentPassword'
|
|
33
49
|
variant='outlined'
|
|
34
|
-
|
|
35
|
-
error={!!formState.errors.currentPassword}
|
|
50
|
+
autoComplete='current-password'
|
|
36
51
|
label={<Trans id='Current Password' />}
|
|
37
52
|
required={required.currentPassword}
|
|
38
|
-
{...muiRegister('currentPassword', { required: required.currentPassword })}
|
|
39
|
-
helperText={formState.errors.currentPassword?.message}
|
|
40
53
|
disabled={formState.isSubmitting}
|
|
54
|
+
error={Boolean(authenticationError)}
|
|
55
|
+
helperText={authenticationError?.message}
|
|
41
56
|
/>
|
|
42
57
|
</FormRow>
|
|
43
58
|
|
|
44
59
|
<FormRow>
|
|
45
|
-
<
|
|
60
|
+
<ValidatedPasswordElement
|
|
61
|
+
control={control}
|
|
62
|
+
name='newPassword'
|
|
46
63
|
variant='outlined'
|
|
47
|
-
|
|
48
|
-
error={!!formState.errors.newPassword}
|
|
64
|
+
autoComplete='new-password'
|
|
49
65
|
label={<Trans id='New password' />}
|
|
50
66
|
required={required.newPassword}
|
|
51
|
-
{...muiRegister('newPassword', { required: required.newPassword })}
|
|
52
|
-
helperText={formState.errors.newPassword?.message}
|
|
53
67
|
disabled={formState.isSubmitting}
|
|
68
|
+
error={Boolean(inputError)}
|
|
69
|
+
helperText={inputError?.message}
|
|
54
70
|
/>
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
<PasswordRepeatElement
|
|
72
|
+
control={control}
|
|
73
|
+
name='confirmPassword'
|
|
74
|
+
passwordFieldName='newPassword'
|
|
75
|
+
autoComplete='new-password'
|
|
57
76
|
variant='outlined'
|
|
58
|
-
type='password'
|
|
59
|
-
error={!!formState.errors.confirmPassword}
|
|
60
77
|
label={<Trans id='Confirm password' />}
|
|
61
78
|
required
|
|
62
|
-
{...muiRegister('confirmPassword', {
|
|
63
|
-
required: true,
|
|
64
|
-
validate: (value) => value === pass || i18n._(/* i18n */ "Passwords don't match"),
|
|
65
|
-
})}
|
|
66
|
-
helperText={formState.errors.confirmPassword?.message}
|
|
67
79
|
disabled={formState.isSubmitting}
|
|
68
80
|
/>
|
|
69
81
|
</FormRow>
|
|
70
82
|
|
|
71
|
-
<ApolloCustomerErrorAlert error={error} />
|
|
72
|
-
|
|
73
83
|
<FormDivider />
|
|
74
84
|
|
|
75
85
|
<FormActions>
|
|
@@ -84,9 +94,13 @@ export function ChangePasswordForm() {
|
|
|
84
94
|
</Button>
|
|
85
95
|
</FormActions>
|
|
86
96
|
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
97
|
+
<ApolloErrorSnackbar error={remainingError} />
|
|
98
|
+
|
|
99
|
+
{showSuccess && (
|
|
100
|
+
<MessageSnackbar open={showSuccess} sticky variant='pill'>
|
|
101
|
+
<Trans id='Successfully changed password' />
|
|
102
|
+
</MessageSnackbar>
|
|
103
|
+
)}
|
|
90
104
|
</Form>
|
|
91
105
|
)
|
|
92
106
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
mutation CreateCustomerAddress(
|
|
2
|
-
$prefix: String
|
|
2
|
+
$prefix: String
|
|
3
3
|
$firstname: String!
|
|
4
4
|
$middlename: String
|
|
5
5
|
$lastname: String!
|
|
@@ -7,7 +7,7 @@ mutation CreateCustomerAddress(
|
|
|
7
7
|
$telephone: String!
|
|
8
8
|
$street: String!
|
|
9
9
|
$houseNumber: String!
|
|
10
|
-
$addition: String
|
|
10
|
+
$addition: String = ""
|
|
11
11
|
$city: String!
|
|
12
12
|
$postcode: String!
|
|
13
13
|
$region: CustomerAddressRegionInput!
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
import { phonePattern, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
13
13
|
import { i18n } from '@lingui/core'
|
|
14
14
|
import { Trans } from '@lingui/react'
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
15
16
|
import { TextField } from '@mui/material'
|
|
16
17
|
import { useRouter } from 'next/router'
|
|
17
18
|
import { AddressFields } from '../AddressFields/AddressFields'
|
|
@@ -43,7 +44,7 @@ export function CreateCustomerAddressForm() {
|
|
|
43
44
|
{},
|
|
44
45
|
}
|
|
45
46
|
},
|
|
46
|
-
onComplete: (
|
|
47
|
+
onComplete: () => {
|
|
47
48
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
48
49
|
router.push(`/account/addresses`)
|
|
49
50
|
},
|
|
@@ -8,6 +8,7 @@ import { i18n } from '@lingui/core'
|
|
|
8
8
|
import { Fab, FabProps as FabPropsType, NoSsr, SxProps, Theme } from '@mui/material'
|
|
9
9
|
import React from 'react'
|
|
10
10
|
import { useCustomerSession, UseCustomerSessionReturn } from '../../hooks'
|
|
11
|
+
import { useCustomerValidateToken } from '../../hooks/useCustomerValidateToken'
|
|
11
12
|
|
|
12
13
|
type CustomerFabContentProps = {
|
|
13
14
|
icon?: React.ReactNode
|
|
@@ -53,6 +54,8 @@ export type CustomerFabProps = Omit<CustomerFabContentProps, 'session'>
|
|
|
53
54
|
export function CustomerFab(props: CustomerFabProps) {
|
|
54
55
|
const session = useCustomerSession()
|
|
55
56
|
|
|
57
|
+
useCustomerValidateToken()
|
|
58
|
+
|
|
56
59
|
return (
|
|
57
60
|
<NoSsr fallback={<CustomerFabContent {...props} />}>
|
|
58
61
|
<CustomerFabContent session={session} {...props} />
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
1
2
|
import { useGo, usePageContext } from '@graphcommerce/framer-next-pages'
|
|
2
3
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
4
|
import { CountryRegionsDocument } from '@graphcommerce/magento-store'
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
import { phonePattern, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
13
14
|
import { i18n } from '@lingui/core'
|
|
14
15
|
import { Trans } from '@lingui/react'
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
15
17
|
import { SxProps, TextField, Theme } from '@mui/material'
|
|
16
18
|
import { AccountAddressFragment } from '../AccountAddress/AccountAddress.gql'
|
|
17
19
|
import { AddressFields } from '../AddressFields/AddressFields'
|
|
@@ -2,6 +2,7 @@ import { Button, Form, FormActions, FormRow } from '@graphcommerce/next-ui'
|
|
|
2
2
|
import { emailPattern, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
3
3
|
import { i18n } from '@lingui/core'
|
|
4
4
|
import { Trans } from '@lingui/react'
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
5
6
|
import { TextField, Alert, SxProps, Theme } from '@mui/material'
|
|
6
7
|
import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert'
|
|
7
8
|
import {
|
|
@@ -3,6 +3,7 @@ import { FormRow, InputCheckmark } from '@graphcommerce/next-ui'
|
|
|
3
3
|
import { assertFormGqlOperation, Controller, UseFormReturn } from '@graphcommerce/react-hook-form'
|
|
4
4
|
import { i18n } from '@lingui/core'
|
|
5
5
|
import { Trans } from '@lingui/react'
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
6
7
|
import { MenuItem, TextField } from '@mui/material'
|
|
7
8
|
import React from 'react'
|
|
8
9
|
|
|
@@ -28,7 +29,7 @@ export function NameFields(props: NameFieldProps) {
|
|
|
28
29
|
const { prefix, form, readOnly, prefixes = [mr, mrs, other] } = props
|
|
29
30
|
assertFormGqlOperation<NameFieldValues>(form)
|
|
30
31
|
|
|
31
|
-
const { control,
|
|
32
|
+
const { control, required, valid } = form
|
|
32
33
|
|
|
33
34
|
return (
|
|
34
35
|
<>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { Money } from '@graphcommerce/magento-store'
|
|
2
2
|
import { extendableComponent, NextLink, useDateTimeFormat } from '@graphcommerce/next-ui'
|
|
3
|
+
import { Trans } from '@lingui/react'
|
|
3
4
|
import { Box, styled, SxProps, Theme, Skeleton, ListItemButton } from '@mui/material'
|
|
4
5
|
import { UseOrderCardItemImages } from '../../hooks/useOrderCardItemImages'
|
|
5
6
|
import { OrderCardItemImage } from '../OrderCardItemImage/OrderCardItemImage'
|
|
6
7
|
import { OrderStateLabel } from '../OrderStateLabel/OrderStateLabel'
|
|
7
8
|
import { TrackingLink } from '../TrackingLink/TrackingLink'
|
|
8
9
|
import { OrderCardFragment } from './OrderCard.gql'
|
|
9
|
-
import { Trans } from '@lingui/react'
|
|
10
10
|
|
|
11
11
|
type OrderCardProps = Partial<OrderCardFragment> & {
|
|
12
12
|
loading?: boolean
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
PasswordElement,
|
|
3
|
-
PasswordRepeatElement,
|
|
4
|
-
TextFieldElement,
|
|
5
|
-
} from '@graphcommerce/ecommerce-ui'
|
|
1
|
+
import { PasswordRepeatElement, TextFieldElement } from '@graphcommerce/ecommerce-ui'
|
|
6
2
|
import { Button, Form, FormActions, FormRow } from '@graphcommerce/next-ui'
|
|
7
3
|
import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
8
4
|
import { Trans } from '@lingui/react'
|
|
9
|
-
import { TextField } from '@mui/material'
|
|
10
5
|
import { useRouter } from 'next/router'
|
|
11
6
|
import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert'
|
|
7
|
+
import { ValidatedPasswordElement } from '../ValidatedPasswordElement/ValidatedPasswordElement'
|
|
12
8
|
import {
|
|
13
9
|
ResetPasswordDocument,
|
|
14
10
|
ResetPasswordMutation,
|
|
@@ -59,11 +55,11 @@ export function ResetPasswordForm(props: ResetPasswordFormProps) {
|
|
|
59
55
|
/>
|
|
60
56
|
</FormRow>
|
|
61
57
|
<FormRow>
|
|
62
|
-
<
|
|
58
|
+
<ValidatedPasswordElement
|
|
63
59
|
control={control}
|
|
64
60
|
name='newPassword'
|
|
61
|
+
autoComplete='new-password'
|
|
65
62
|
variant='outlined'
|
|
66
|
-
type='password'
|
|
67
63
|
label={<Trans id='New password' />}
|
|
68
64
|
required
|
|
69
65
|
disabled={formState.isSubmitting}
|
|
@@ -71,9 +67,9 @@ export function ResetPasswordForm(props: ResetPasswordFormProps) {
|
|
|
71
67
|
<PasswordRepeatElement
|
|
72
68
|
control={control}
|
|
73
69
|
name='confirmPassword'
|
|
70
|
+
autoComplete='new-password'
|
|
74
71
|
passwordFieldName='newPassword'
|
|
75
72
|
variant='outlined'
|
|
76
|
-
type='password'
|
|
77
73
|
label={<Trans id='Confirm password' />}
|
|
78
74
|
required
|
|
79
75
|
disabled={formState.isSubmitting}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
import { useApolloClient } from '@graphcommerce/graphql'
|
|
2
|
-
import { CustomerTokenDocument } from '@graphcommerce/magento-customer'
|
|
3
3
|
import { Button } from '@mui/material'
|
|
4
|
+
import { CustomerTokenDocument } from '../../hooks/CustomerToken.gql'
|
|
4
5
|
|
|
5
6
|
export function SessionDebugger() {
|
|
6
7
|
const client = useApolloClient()
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { PasswordElement } from '@graphcommerce/ecommerce-ui'
|
|
1
2
|
import { useApolloClient } from '@graphcommerce/graphql'
|
|
2
3
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
3
4
|
import { Button, FormRow, FormActions } from '@graphcommerce/next-ui'
|
|
4
5
|
import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
5
6
|
import { Trans } from '@lingui/react'
|
|
6
|
-
import { Box, FormControl, Link, SxProps,
|
|
7
|
+
import { Box, FormControl, Link, SxProps, Theme } from '@mui/material'
|
|
7
8
|
import { CustomerDocument } from '../../hooks'
|
|
8
9
|
import { ApolloCustomerErrorAlert } from '../ApolloCustomerError/ApolloCustomerErrorAlert'
|
|
9
10
|
import { SignInDocument } from './SignIn.gql'
|
|
@@ -12,7 +13,6 @@ type SignInFormProps = { email: string; sx?: SxProps<Theme> }
|
|
|
12
13
|
|
|
13
14
|
export function SignInForm(props: SignInFormProps) {
|
|
14
15
|
const { email, sx } = props
|
|
15
|
-
|
|
16
16
|
const client = useApolloClient()
|
|
17
17
|
const form = useFormGqlMutation(
|
|
18
18
|
SignInDocument,
|
|
@@ -32,7 +32,7 @@ export function SignInForm(props: SignInFormProps) {
|
|
|
32
32
|
{ errorPolicy: 'all' },
|
|
33
33
|
)
|
|
34
34
|
|
|
35
|
-
const {
|
|
35
|
+
const { handleSubmit, required, formState, error, control } = form
|
|
36
36
|
const [remainingError, authError] = graphqlErrorByCategory({
|
|
37
37
|
category: 'graphql-authentication',
|
|
38
38
|
error,
|
|
@@ -41,18 +41,19 @@ export function SignInForm(props: SignInFormProps) {
|
|
|
41
41
|
|
|
42
42
|
return (
|
|
43
43
|
<Box component='form' onSubmit={submitHandler} noValidate sx={sx}>
|
|
44
|
-
<FormRow>
|
|
45
|
-
<
|
|
46
|
-
key='password'
|
|
44
|
+
<FormRow sx={{ gridTemplateColumns: 'none' }}>
|
|
45
|
+
<PasswordElement
|
|
47
46
|
variant='outlined'
|
|
48
|
-
type='password'
|
|
49
47
|
error={!!formState.errors.password || !!authError}
|
|
48
|
+
control={control}
|
|
49
|
+
name='password'
|
|
50
50
|
label={<Trans id='Password' />}
|
|
51
51
|
autoFocus
|
|
52
52
|
autoComplete='current-password'
|
|
53
53
|
id='current-password'
|
|
54
54
|
required={required.password}
|
|
55
|
-
{
|
|
55
|
+
disabled={formState.isSubmitting}
|
|
56
|
+
helperText={!!formState.errors.password || authError?.message}
|
|
56
57
|
InputProps={{
|
|
57
58
|
endAdornment: (
|
|
58
59
|
<Link href='/account/forgot-password' underline='hover' sx={{ whiteSpace: 'nowrap' }}>
|
|
@@ -60,8 +61,6 @@ export function SignInForm(props: SignInFormProps) {
|
|
|
60
61
|
</Link>
|
|
61
62
|
),
|
|
62
63
|
}}
|
|
63
|
-
helperText={formState.errors.password?.message || authError?.message}
|
|
64
|
-
disabled={formState.isSubmitting}
|
|
65
64
|
/>
|
|
66
65
|
</FormRow>
|
|
67
66
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { PasswordElement } from '@graphcommerce/ecommerce-ui'
|
|
1
2
|
import { Button, extendableComponent } from '@graphcommerce/next-ui'
|
|
2
3
|
import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
3
4
|
import { Trans } from '@lingui/react'
|
|
4
|
-
import { Box,
|
|
5
|
+
import { Box, Link, SxProps, Theme } from '@mui/material'
|
|
5
6
|
import { SignInDocument, SignInMutationVariables } from './SignIn.gql'
|
|
6
7
|
|
|
7
8
|
type InlineSignInFormProps = Omit<SignInMutationVariables, 'password'> & {
|
|
@@ -12,13 +13,13 @@ type InlineSignInFormProps = Omit<SignInMutationVariables, 'password'> & {
|
|
|
12
13
|
const { classes } = extendableComponent('SignInFormInline', ['form', 'button'] as const)
|
|
13
14
|
|
|
14
15
|
export function SignInFormInline(props: InlineSignInFormProps) {
|
|
15
|
-
const { email, sx = [] } = props
|
|
16
|
+
const { email, children, sx = [] } = props
|
|
16
17
|
const form = useFormGqlMutation(
|
|
17
18
|
SignInDocument,
|
|
18
19
|
{ defaultValues: { email }, onBeforeSubmit: (values) => ({ ...values, email }) },
|
|
19
20
|
{ errorPolicy: 'all' },
|
|
20
21
|
)
|
|
21
|
-
const {
|
|
22
|
+
const { handleSubmit, required, formState, control } = form
|
|
22
23
|
const submitHandler = handleSubmit(() => {})
|
|
23
24
|
|
|
24
25
|
return (
|
|
@@ -41,35 +42,34 @@ export function SignInFormInline(props: InlineSignInFormProps) {
|
|
|
41
42
|
...(Array.isArray(sx) ? sx : [sx]),
|
|
42
43
|
]}
|
|
43
44
|
>
|
|
44
|
-
<
|
|
45
|
+
<PasswordElement
|
|
46
|
+
control={control}
|
|
45
47
|
variant='outlined'
|
|
46
|
-
|
|
47
|
-
error={!!formState.errors.password || !!error?.message}
|
|
48
|
+
name='password'
|
|
48
49
|
label={<Trans id='Password' />}
|
|
49
50
|
autoFocus
|
|
50
51
|
autoComplete='current-password'
|
|
51
52
|
id='current-password'
|
|
52
53
|
required={required.password}
|
|
53
|
-
{...muiRegister('password', { required: required.password })}
|
|
54
|
-
helperText={error?.message}
|
|
55
54
|
disabled={formState.isSubmitting}
|
|
56
55
|
InputProps={{
|
|
57
56
|
endAdornment: (
|
|
58
|
-
<
|
|
59
|
-
href='/account/forgot-password'
|
|
60
|
-
color='secondary'
|
|
61
|
-
variant='text'
|
|
62
|
-
className={classes.button}
|
|
63
|
-
sx={{ minWidth: 'max-content' }}
|
|
64
|
-
>
|
|
57
|
+
<Link href='/account/forgot-password' underline='hover' sx={{ whiteSpace: 'nowrap' }}>
|
|
65
58
|
<Trans id='Forgot password?' />
|
|
66
|
-
</
|
|
59
|
+
</Link>
|
|
67
60
|
),
|
|
68
61
|
}}
|
|
69
62
|
/>
|
|
70
|
-
<Button
|
|
63
|
+
<Button
|
|
64
|
+
type='submit'
|
|
65
|
+
loading={formState.isSubmitting}
|
|
66
|
+
color='secondary'
|
|
67
|
+
variant='pill'
|
|
68
|
+
sx={{ alignSelf: 'start', marginTop: (theme) => `calc(${theme.spacings.xxs} * .33)` }}
|
|
69
|
+
>
|
|
71
70
|
<Trans id='Sign in' />
|
|
72
71
|
</Button>
|
|
72
|
+
{children}
|
|
73
73
|
</Box>
|
|
74
74
|
)
|
|
75
75
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PasswordRepeatElement } from '@graphcommerce/ecommerce-ui'
|
|
2
2
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
3
|
-
import { StoreConfigDocument } from '@graphcommerce/magento-store'
|
|
4
3
|
import { Button, FormActions, FormRow } from '@graphcommerce/next-ui'
|
|
5
4
|
import { useFormGqlMutation, useFormPersist } from '@graphcommerce/react-hook-form'
|
|
6
|
-
import { i18n } from '@lingui/core'
|
|
7
5
|
import { Trans } from '@lingui/react'
|
|
8
|
-
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
7
|
+
import { Alert, FormControlLabel, Switch } from '@mui/material'
|
|
9
8
|
import { ApolloCustomerErrorSnackbar } from '../ApolloCustomerError/ApolloCustomerErrorSnackbar'
|
|
10
9
|
import { NameFields } from '../NameFields/NameFields'
|
|
10
|
+
import { ValidatedPasswordElement } from '../ValidatedPasswordElement/ValidatedPasswordElement'
|
|
11
11
|
import { SignUpDocument, SignUpMutation, SignUpMutationVariables } from './SignUp.gql'
|
|
12
12
|
import { SignUpConfirmDocument } from './SignUpConfirm.gql'
|
|
13
13
|
|
|
@@ -18,8 +18,6 @@ const requireEmailValidation = import.meta.graphCommerce.customerRequireEmailCon
|
|
|
18
18
|
export function SignUpForm(props: SignUpFormProps) {
|
|
19
19
|
const { email } = props
|
|
20
20
|
|
|
21
|
-
const storeConfig = useQuery(StoreConfigDocument).data?.storeConfig
|
|
22
|
-
|
|
23
21
|
const Mutation = requireEmailValidation ? SignUpConfirmDocument : SignUpDocument
|
|
24
22
|
|
|
25
23
|
const form = useFormGqlMutation<
|
|
@@ -31,11 +29,10 @@ export function SignUpForm(props: SignUpFormProps) {
|
|
|
31
29
|
{ errorPolicy: 'all' },
|
|
32
30
|
)
|
|
33
31
|
|
|
34
|
-
const { muiRegister, handleSubmit, required,
|
|
32
|
+
const { muiRegister, handleSubmit, required, formState, error, control } = form
|
|
35
33
|
const [remainingError, inputError] = graphqlErrorByCategory({ category: 'graphql-input', error })
|
|
36
34
|
|
|
37
35
|
const submitHandler = handleSubmit(() => {})
|
|
38
|
-
const watchPassword = watch('password')
|
|
39
36
|
|
|
40
37
|
useFormPersist({ form, name: 'SignUp', exclude: ['password', 'confirmPassword'] })
|
|
41
38
|
|
|
@@ -50,37 +47,27 @@ export function SignUpForm(props: SignUpFormProps) {
|
|
|
50
47
|
return (
|
|
51
48
|
<form onSubmit={submitHandler} noValidate>
|
|
52
49
|
<FormRow>
|
|
53
|
-
<
|
|
50
|
+
<ValidatedPasswordElement
|
|
51
|
+
control={control}
|
|
52
|
+
name='password'
|
|
54
53
|
variant='outlined'
|
|
55
|
-
type='password'
|
|
56
54
|
error={!!formState.errors.password || !!inputError}
|
|
57
55
|
label={<Trans id='Password' />}
|
|
58
56
|
autoFocus
|
|
59
57
|
autoComplete='new-password'
|
|
60
58
|
required={required.password}
|
|
61
|
-
{...muiRegister('password', {
|
|
62
|
-
required: required.password,
|
|
63
|
-
minLength: {
|
|
64
|
-
value: Number(storeConfig?.minimum_password_length ?? 8),
|
|
65
|
-
message: i18n._(/* i18n */ 'Password must have at least 8 characters'),
|
|
66
|
-
},
|
|
67
|
-
})}
|
|
68
|
-
helperText={formState.errors.password?.message || inputError?.message}
|
|
69
59
|
disabled={formState.isSubmitting}
|
|
60
|
+
helperText={inputError?.message}
|
|
70
61
|
/>
|
|
71
|
-
<
|
|
62
|
+
<PasswordRepeatElement
|
|
63
|
+
control={control}
|
|
64
|
+
name='confirmPassword'
|
|
65
|
+
passwordFieldName='password'
|
|
72
66
|
variant='outlined'
|
|
73
|
-
|
|
74
|
-
error={!!formState.errors.confirmPassword}
|
|
67
|
+
error={!!formState.errors.confirmPassword || !!inputError}
|
|
75
68
|
label={<Trans id='Confirm password' />}
|
|
76
69
|
autoComplete='new-password'
|
|
77
70
|
required
|
|
78
|
-
{...muiRegister('confirmPassword', {
|
|
79
|
-
required: true,
|
|
80
|
-
validate: (value) =>
|
|
81
|
-
value === watchPassword || i18n._(/* i18n */ "Passwords don't match"),
|
|
82
|
-
})}
|
|
83
|
-
helperText={formState.errors.confirmPassword?.message}
|
|
84
71
|
disabled={formState.isSubmitting}
|
|
85
72
|
/>
|
|
86
73
|
</FormRow>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { ApolloErrorAlert, PasswordRepeatElement } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
3
3
|
import { Button, extendableComponent, Form, FormRow } from '@graphcommerce/next-ui'
|
|
4
4
|
import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
5
|
-
import { i18n } from '@lingui/core'
|
|
6
5
|
import { Trans } from '@lingui/react'
|
|
7
|
-
import { Alert, Box
|
|
6
|
+
import { Alert, Box } from '@mui/material'
|
|
8
7
|
import React from 'react'
|
|
8
|
+
import { ValidatedPasswordElement } from '../ValidatedPasswordElement/ValidatedPasswordElement'
|
|
9
9
|
import { SignUpMutationVariables, SignUpMutation, SignUpDocument } from './SignUp.gql'
|
|
10
10
|
import { SignUpConfirmDocument } from './SignUpConfirm.gql'
|
|
11
11
|
|
|
@@ -25,37 +25,35 @@ const { classes } = extendableComponent('SignUpFormInline', [
|
|
|
25
25
|
|
|
26
26
|
const requireEmailValidation = import.meta.graphCommerce.customerRequireEmailConfirmation ?? false
|
|
27
27
|
|
|
28
|
-
export function SignUpFormInline({
|
|
29
|
-
email,
|
|
30
|
-
children,
|
|
31
|
-
firstname,
|
|
32
|
-
lastname,
|
|
33
|
-
onSubmitted = () => {},
|
|
34
|
-
}: SignUpFormInlineProps) {
|
|
28
|
+
export function SignUpFormInline(props: SignUpFormInlineProps) {
|
|
29
|
+
const { email, children, firstname, lastname, onSubmitted = () => {} } = props
|
|
35
30
|
const Mutation = requireEmailValidation ? SignUpConfirmDocument : SignUpDocument
|
|
36
31
|
|
|
37
32
|
const form = useFormGqlMutation<
|
|
38
33
|
SignUpMutation,
|
|
39
34
|
SignUpMutationVariables & { confirmPassword?: string }
|
|
40
|
-
>(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
>(
|
|
36
|
+
Mutation,
|
|
37
|
+
{
|
|
38
|
+
// todo(paales): This causes dirty data to be send to the backend.
|
|
39
|
+
defaultValues: {
|
|
40
|
+
email,
|
|
41
|
+
prefix: '-',
|
|
42
|
+
firstname: firstname ?? '-',
|
|
43
|
+
lastname: lastname ?? '-',
|
|
44
|
+
},
|
|
45
|
+
onBeforeSubmit: (values) => ({ ...values, email }),
|
|
46
|
+
onComplete: (result) => {
|
|
47
|
+
if (!result.errors) onSubmitted()
|
|
48
|
+
},
|
|
47
49
|
},
|
|
48
|
-
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const { muiRegister, watch, handleSubmit, required, formState, error } = form
|
|
52
|
-
const submitHandler = handleSubmit(onSubmitted)
|
|
53
|
-
const watchPassword = watch('password')
|
|
54
|
-
|
|
55
|
-
const minPasswordLength = Number(
|
|
56
|
-
useQuery(StoreConfigDocument).data?.storeConfig?.minimum_password_length ?? 8,
|
|
50
|
+
{ errorPolicy: 'all' },
|
|
57
51
|
)
|
|
58
52
|
|
|
53
|
+
const { handleSubmit, formState, control, error, required } = form
|
|
54
|
+
const [remainingError, inputError] = graphqlErrorByCategory({ category: 'graphql-input', error })
|
|
55
|
+
const submitHandler = handleSubmit(() => {})
|
|
56
|
+
|
|
59
57
|
if (requireEmailValidation && form.formState.isSubmitSuccessful) {
|
|
60
58
|
return (
|
|
61
59
|
<Alert>
|
|
@@ -66,43 +64,31 @@ export function SignUpFormInline({
|
|
|
66
64
|
|
|
67
65
|
return (
|
|
68
66
|
<Form onSubmit={submitHandler} noValidate className={classes.form} sx={{ padding: 0 }}>
|
|
69
|
-
<FormRow
|
|
70
|
-
<
|
|
67
|
+
<FormRow className={classes.row} sx={{ padding: 0 }}>
|
|
68
|
+
<ValidatedPasswordElement
|
|
69
|
+
control={control}
|
|
70
|
+
name='password'
|
|
71
|
+
autoComplete='new-password'
|
|
71
72
|
variant='outlined'
|
|
72
|
-
type='password'
|
|
73
|
-
error={!!formState.errors.password || !!error?.message}
|
|
74
73
|
label={<Trans id='Password' />}
|
|
75
|
-
autoFocus
|
|
76
|
-
autoComplete='new-password'
|
|
77
|
-
id='new-password'
|
|
78
74
|
required={required.password}
|
|
79
|
-
{...muiRegister('password', {
|
|
80
|
-
required: required.password,
|
|
81
|
-
minLength: {
|
|
82
|
-
value: minPasswordLength,
|
|
83
|
-
message: i18n._(/* i18n */ 'Password must have at least 8 characters'),
|
|
84
|
-
},
|
|
85
|
-
})}
|
|
86
|
-
helperText={error?.message}
|
|
87
75
|
disabled={formState.isSubmitting}
|
|
76
|
+
error={!!inputError}
|
|
77
|
+
helperText={inputError?.message}
|
|
88
78
|
/>
|
|
89
|
-
<
|
|
79
|
+
<PasswordRepeatElement
|
|
80
|
+
control={control}
|
|
81
|
+
name='confirmPassword'
|
|
82
|
+
passwordFieldName='password'
|
|
83
|
+
autoComplete='new-password'
|
|
90
84
|
variant='outlined'
|
|
91
|
-
type='password'
|
|
92
|
-
error={!!formState.errors.confirmPassword || !!error?.message}
|
|
93
85
|
label={<Trans id='Confirm password' />}
|
|
94
|
-
autoComplete='new-password'
|
|
95
86
|
required
|
|
96
|
-
{...muiRegister('confirmPassword', {
|
|
97
|
-
required: true,
|
|
98
|
-
validate: (value) => value === watchPassword,
|
|
99
|
-
})}
|
|
100
|
-
helperText={!!formState.errors.confirmPassword && <Trans id='Passwords should match' />}
|
|
101
87
|
disabled={formState.isSubmitting}
|
|
102
88
|
/>
|
|
103
89
|
</FormRow>
|
|
104
90
|
|
|
105
|
-
<FormRow
|
|
91
|
+
<FormRow>
|
|
106
92
|
<FormRow
|
|
107
93
|
className={classes.buttonFormRow}
|
|
108
94
|
sx={(theme) => ({
|
|
@@ -126,6 +112,7 @@ export function SignUpFormInline({
|
|
|
126
112
|
</Box>
|
|
127
113
|
</FormRow>
|
|
128
114
|
</FormRow>
|
|
115
|
+
<ApolloErrorAlert error={remainingError} />
|
|
129
116
|
</Form>
|
|
130
117
|
)
|
|
131
118
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PasswordElement } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
1
3
|
import {
|
|
2
4
|
Button,
|
|
3
5
|
Form,
|
|
@@ -9,8 +11,9 @@ import {
|
|
|
9
11
|
import { emailPattern, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
10
12
|
import { i18n } from '@lingui/core'
|
|
11
13
|
import { Trans } from '@lingui/react'
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
12
15
|
import { TextField } from '@mui/material'
|
|
13
|
-
import {
|
|
16
|
+
import { ApolloCustomerErrorSnackbar } from '../ApolloCustomerError'
|
|
14
17
|
import {
|
|
15
18
|
UpdateCustomerEmailDocument,
|
|
16
19
|
UpdateCustomerEmailMutation,
|
|
@@ -26,13 +29,20 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
26
29
|
|
|
27
30
|
const form = useFormGqlMutation<
|
|
28
31
|
UpdateCustomerEmailMutation,
|
|
29
|
-
UpdateCustomerEmailMutationVariables & {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
32
|
+
UpdateCustomerEmailMutationVariables & { currentEmail?: string; confirmEmail?: string }
|
|
33
|
+
>(
|
|
34
|
+
UpdateCustomerEmailDocument,
|
|
35
|
+
{},
|
|
36
|
+
{
|
|
37
|
+
errorPolicy: 'all',
|
|
38
|
+
},
|
|
39
|
+
)
|
|
34
40
|
|
|
35
|
-
const { handleSubmit, error, required, formState, watch, muiRegister, reset } = form
|
|
41
|
+
const { handleSubmit, error, required, formState, watch, muiRegister, reset, control } = form
|
|
42
|
+
const [remainingError, authenticationError] = graphqlErrorByCategory({
|
|
43
|
+
category: 'graphql-authentication',
|
|
44
|
+
error,
|
|
45
|
+
})
|
|
36
46
|
const submit = handleSubmit(() => {
|
|
37
47
|
reset()
|
|
38
48
|
})
|
|
@@ -45,7 +55,7 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
45
55
|
key='current-email'
|
|
46
56
|
variant='outlined'
|
|
47
57
|
type='text'
|
|
48
|
-
autoComplete='
|
|
58
|
+
autoComplete='email'
|
|
49
59
|
autoFocus
|
|
50
60
|
error={formState.isSubmitted && !!formState.errors.currentEmail}
|
|
51
61
|
helperText={formState.isSubmitted && formState.errors.currentEmail?.message}
|
|
@@ -67,8 +77,7 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
67
77
|
key='email'
|
|
68
78
|
variant='outlined'
|
|
69
79
|
type='text'
|
|
70
|
-
autoComplete='
|
|
71
|
-
autoFocus
|
|
80
|
+
autoComplete='off'
|
|
72
81
|
error={formState.isSubmitted && !!formState.errors.email}
|
|
73
82
|
helperText={formState.isSubmitted && formState.errors.email?.message}
|
|
74
83
|
label={<Trans id='New email' />}
|
|
@@ -82,8 +91,7 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
82
91
|
key='confirm-email'
|
|
83
92
|
variant='outlined'
|
|
84
93
|
type='text'
|
|
85
|
-
autoComplete='
|
|
86
|
-
autoFocus
|
|
94
|
+
autoComplete='off'
|
|
87
95
|
error={formState.isSubmitted && !!formState.errors.confirmEmail}
|
|
88
96
|
helperText={formState.isSubmitted && formState.errors.confirmEmail?.message}
|
|
89
97
|
label={<Trans id='Confirm new email' />}
|
|
@@ -96,21 +104,21 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
96
104
|
</FormRow>
|
|
97
105
|
|
|
98
106
|
<FormRow>
|
|
99
|
-
<
|
|
107
|
+
<PasswordElement
|
|
108
|
+
control={control}
|
|
100
109
|
variant='outlined'
|
|
101
|
-
|
|
102
|
-
error={!!formState.errors.password}
|
|
110
|
+
name='password'
|
|
103
111
|
label={<Trans id='Password' />}
|
|
104
|
-
autoComplete='password'
|
|
112
|
+
autoComplete='current-password'
|
|
105
113
|
required={required.password}
|
|
106
|
-
{...muiRegister('password', {
|
|
107
|
-
required: required.password,
|
|
108
|
-
})}
|
|
109
|
-
helperText={formState.errors.password?.message}
|
|
110
114
|
disabled={formState.isSubmitting}
|
|
115
|
+
error={Boolean(authenticationError)}
|
|
116
|
+
helperText={authenticationError?.message}
|
|
111
117
|
/>
|
|
112
118
|
</FormRow>
|
|
113
119
|
|
|
120
|
+
<ApolloCustomerErrorSnackbar error={remainingError} />
|
|
121
|
+
|
|
114
122
|
<FormDivider />
|
|
115
123
|
<FormActions>
|
|
116
124
|
<Button
|
|
@@ -123,7 +131,6 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
123
131
|
<Trans id='Save changes' />
|
|
124
132
|
</Button>
|
|
125
133
|
</FormActions>
|
|
126
|
-
<ApolloCustomerErrorAlert error={error} />
|
|
127
134
|
|
|
128
135
|
<MessageSnackbar sticky open={formState.isSubmitSuccessful && !error}>
|
|
129
136
|
<Trans id='Successfully updated email' />
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Controller, useFormAutoSubmit, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
2
2
|
import { Trans } from '@lingui/react'
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
|
3
4
|
import { FormControl, FormControlLabel, FormHelperText, Switch } from '@mui/material'
|
|
4
5
|
import React, { useEffect, useMemo } from 'react'
|
|
5
6
|
import { AccountAddressFragment } from '../AccountAddress/AccountAddress.gql'
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PasswordElement, PasswordElementProps } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { useQuery } from '@graphcommerce/graphql'
|
|
3
|
+
import { StoreConfigDocument } from '@graphcommerce/magento-store'
|
|
4
|
+
import { FieldValues } from '@graphcommerce/react-hook-form'
|
|
5
|
+
import { i18n } from '@lingui/core'
|
|
6
|
+
|
|
7
|
+
export type ValidatedPasswordElementProps<T extends FieldValues> = PasswordElementProps<T>
|
|
8
|
+
|
|
9
|
+
export function ValidatedPasswordElement<TFieldValues extends FieldValues>(
|
|
10
|
+
props: PasswordElementProps<TFieldValues>,
|
|
11
|
+
): JSX.Element {
|
|
12
|
+
const { ...textFieldProps } = props
|
|
13
|
+
|
|
14
|
+
const storeConfig = useQuery(StoreConfigDocument).data?.storeConfig
|
|
15
|
+
const minPasswordLength = Number(storeConfig?.minimum_password_length) ?? 0
|
|
16
|
+
const passwordMinCharacterSets = Number(storeConfig?.required_character_classes_number) ?? 0
|
|
17
|
+
|
|
18
|
+
const validation: NonNullable<PasswordElementProps<TFieldValues>['validation']> = {}
|
|
19
|
+
|
|
20
|
+
validation.minLength = {
|
|
21
|
+
value: minPasswordLength,
|
|
22
|
+
message: i18n._(/* i18n */ 'Password must have at least {minPasswordLength} characters', {
|
|
23
|
+
minPasswordLength,
|
|
24
|
+
}),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
validation.validate = (value: string) => {
|
|
28
|
+
const pass = value.trim()
|
|
29
|
+
let counter = 0
|
|
30
|
+
|
|
31
|
+
if (pass.match(/\d+/)) counter++
|
|
32
|
+
if (pass.match(/[a-z]+/)) counter++
|
|
33
|
+
if (pass.match(/[A-Z]+/)) counter++
|
|
34
|
+
if (pass.match(/[^a-zA-Z0-9]+/)) counter++
|
|
35
|
+
|
|
36
|
+
if (counter < passwordMinCharacterSets) {
|
|
37
|
+
return i18n._(
|
|
38
|
+
/* i18n */ 'Minimum of different classes of characters in password is {passwordMinCharacterSets}. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.',
|
|
39
|
+
{ passwordMinCharacterSets },
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return <PasswordElement {...textFieldProps} validation={validation} />
|
|
47
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useApolloClient } from '@graphcommerce/graphql'
|
|
2
|
+
import { ErrorCategory } from '@graphcommerce/magento-graphql'
|
|
3
|
+
import { useRouter } from 'next/router'
|
|
4
|
+
import { UseCustomerValidateTokenDocument } from './UseCustomerValidateToken.gql'
|
|
5
|
+
import { useCustomerQuery } from './useCustomerQuery'
|
|
6
|
+
|
|
7
|
+
/** Validates the current customer token. This hook is supposed to be called only once. */
|
|
8
|
+
export function useCustomerValidateToken() {
|
|
9
|
+
const client = useApolloClient()
|
|
10
|
+
const router = useRouter()
|
|
11
|
+
|
|
12
|
+
useCustomerQuery(UseCustomerValidateTokenDocument, {
|
|
13
|
+
initialFetchPolicy: 'network-only',
|
|
14
|
+
onError: async ({ graphQLErrors }) => {
|
|
15
|
+
const category: ErrorCategory = 'graphql-authorization'
|
|
16
|
+
// If there is no authorization error, do nothing.
|
|
17
|
+
if (!graphQLErrors.some((e) => e.extensions?.category === category)) return
|
|
18
|
+
|
|
19
|
+
await client.clearStore()
|
|
20
|
+
router.reload()
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ApolloLink, ApolloCache, setContext } from '@graphcommerce/graphql/apollo'
|
|
1
|
+
import { setContext } from '@graphcommerce/graphql/apollo'
|
|
3
2
|
import { CustomerTokenDocument } from '../hooks'
|
|
4
|
-
import { onAuthorizationError } from './onAuthenticationError'
|
|
5
3
|
|
|
6
4
|
export const addTokenHeader = setContext((_, context) => {
|
|
7
5
|
if (!context.headers) context.headers = {}
|
|
@@ -17,7 +15,4 @@ export const addTokenHeader = setContext((_, context) => {
|
|
|
17
15
|
}
|
|
18
16
|
})
|
|
19
17
|
|
|
20
|
-
export const customerTokenLink =
|
|
21
|
-
|
|
22
|
-
/** Not really required anymore, you can use customerTokenLink directly */
|
|
23
|
-
export const createCustomerTokenLink = (_: ApolloCache<NormalizedCacheObject>) => customerTokenLink
|
|
18
|
+
export const customerTokenLink = addTokenHeader
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/magento-customer",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "7.0.0
|
|
5
|
+
"version": "7.0.0",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -12,24 +12,25 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@graphcommerce/eslint-config-pwa": "7.0.0
|
|
16
|
-
"@graphcommerce/prettier-config-pwa": "7.0.0
|
|
17
|
-
"@graphcommerce/typescript-config-pwa": "7.0.0
|
|
15
|
+
"@graphcommerce/eslint-config-pwa": "7.0.0",
|
|
16
|
+
"@graphcommerce/prettier-config-pwa": "7.0.0",
|
|
17
|
+
"@graphcommerce/typescript-config-pwa": "7.0.0"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@graphcommerce/ecommerce-ui": "7.0.0
|
|
21
|
-
"@graphcommerce/framer-utils": "7.0.0
|
|
22
|
-
"@graphcommerce/graphql": "7.0.0
|
|
23
|
-
"@graphcommerce/graphql-mesh": "7.0.0
|
|
24
|
-
"@graphcommerce/image": "7.0.0
|
|
25
|
-
"@graphcommerce/magento-graphql": "7.0.0
|
|
26
|
-
"@graphcommerce/magento-store": "7.0.0
|
|
27
|
-
"@graphcommerce/next-ui": "7.0.0
|
|
28
|
-
"@graphcommerce/react-hook-form": "7.0.0
|
|
20
|
+
"@graphcommerce/ecommerce-ui": "7.0.0",
|
|
21
|
+
"@graphcommerce/framer-utils": "7.0.0",
|
|
22
|
+
"@graphcommerce/graphql": "7.0.0",
|
|
23
|
+
"@graphcommerce/graphql-mesh": "7.0.0",
|
|
24
|
+
"@graphcommerce/image": "7.0.0",
|
|
25
|
+
"@graphcommerce/magento-graphql": "7.0.0",
|
|
26
|
+
"@graphcommerce/magento-store": "7.0.0",
|
|
27
|
+
"@graphcommerce/next-ui": "7.0.0",
|
|
28
|
+
"@graphcommerce/react-hook-form": "7.0.0"
|
|
29
29
|
},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@lingui/react": "^
|
|
32
|
-
"@lingui/core": "^
|
|
31
|
+
"@lingui/react": "^4.2.1",
|
|
32
|
+
"@lingui/core": "^4.2.1",
|
|
33
|
+
"@lingui/macro": "^4.2.1",
|
|
33
34
|
"@mui/material": "^5.10.16",
|
|
34
35
|
"framer-motion": "^10.0.0",
|
|
35
36
|
"graphql": "^16.0.0",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies */
|
|
1
2
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
2
3
|
import { waitForGraphQlResponse } from '@graphcommerce/graphql/test/apolloClient.fixture'
|
|
3
4
|
import { SignUpDocument, SignUpMutation } from '@graphcommerce/magento-customer/components'
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { InMemoryCache } from '@graphcommerce/graphql'
|
|
2
|
-
import { onError } from '@graphcommerce/graphql/apollo'
|
|
3
|
-
import { CustomerTokenDocument } from '../hooks/CustomerToken.gql'
|
|
4
|
-
|
|
5
|
-
function invalidateToken(cache: InMemoryCache) {
|
|
6
|
-
const res = cache.readQuery({
|
|
7
|
-
query: CustomerTokenDocument,
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
if (res?.customerToken?.valid) {
|
|
11
|
-
// Write arbitrary old token to document
|
|
12
|
-
cache.writeQuery({
|
|
13
|
-
query: CustomerTokenDocument,
|
|
14
|
-
data: {
|
|
15
|
-
customerToken: {
|
|
16
|
-
...res.customerToken,
|
|
17
|
-
token: null,
|
|
18
|
-
createdAt: new Date('2000').toUTCString(),
|
|
19
|
-
valid: false,
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
broadcast: true,
|
|
23
|
-
})
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const onAuthorizationError = onError(({ graphQLErrors, operation }) => {
|
|
28
|
-
const { cache } = operation.getContext()
|
|
29
|
-
if (graphQLErrors) {
|
|
30
|
-
for (const err of graphQLErrors) {
|
|
31
|
-
const isCustomerError = err.path?.join('.').toLowerCase().includes('customer')
|
|
32
|
-
if (err.extensions?.category === 'graphql-authorization' && isCustomerError) {
|
|
33
|
-
// Modify the operation context with a new token
|
|
34
|
-
invalidateToken(cache as InMemoryCache)
|
|
35
|
-
break
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
})
|