@graphcommerce/magento-customer 3.0.1

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.
Files changed (78) hide show
  1. package/CHANGELOG.md +294 -0
  2. package/components/AccountAddress/AccountAddress.gql.ts +4 -0
  3. package/components/AccountAddress/AccountAddress.graphql +6 -0
  4. package/components/AccountAddress/index.tsx +59 -0
  5. package/components/AccountAddresses/AccountAddresses.gql.ts +4 -0
  6. package/components/AccountAddresses/AccountAddresses.graphql +5 -0
  7. package/components/AccountAddresses/UpdateDefaultAddress.gql.ts +14 -0
  8. package/components/AccountAddresses/UpdateDefaultAddress.graphql +14 -0
  9. package/components/AccountAddresses/index.tsx +101 -0
  10. package/components/AddressFields/index.tsx +189 -0
  11. package/components/AddressMultiLine/index.tsx +68 -0
  12. package/components/AddressSingleLine/index.tsx +34 -0
  13. package/components/ApolloCustomerError/ApolloCustomerErrorAlert.tsx +21 -0
  14. package/components/ApolloCustomerError/ApolloCustomerErrorFullPage.tsx +46 -0
  15. package/components/ChangeNameForm/UpdateCustomerName.gql.ts +14 -0
  16. package/components/ChangeNameForm/UpdateCustomerName.graphql +9 -0
  17. package/components/ChangeNameForm/index.tsx +66 -0
  18. package/components/ChangePasswordForm/ChangePassword.gql.ts +13 -0
  19. package/components/ChangePasswordForm/ChangePassword.graphql +5 -0
  20. package/components/ChangePasswordForm/ChangePasswordForm.tsx +93 -0
  21. package/components/CreateCustomerAddressForm/CreateCustomerAddress.gql.ts +28 -0
  22. package/components/CreateCustomerAddressForm/CreateCustomerAddress.graphql +41 -0
  23. package/components/CreateCustomerAddressForm/CustomerAddress.gql.ts +4 -0
  24. package/components/CreateCustomerAddressForm/CustomerAddress.graphql +22 -0
  25. package/components/CreateCustomerAddressForm/CustomerAddressEdit.gql.ts +4 -0
  26. package/components/CreateCustomerAddressForm/CustomerAddressEdit.graphql +4 -0
  27. package/components/CreateCustomerAddressForm/index.tsx +98 -0
  28. package/components/CustomerFab/index.tsx +55 -0
  29. package/components/CustomerMenuFabItem/index.tsx +68 -0
  30. package/components/DeleteCustomerAddressForm/DeleteCustomerAddressForm.gql.ts +12 -0
  31. package/components/DeleteCustomerAddressForm/DeleteCustomerAddressForm.graphql +3 -0
  32. package/components/DeleteCustomerAddressForm/index.tsx +46 -0
  33. package/components/EditAddressForm/UpdateCustomerAddress.gql.ts +29 -0
  34. package/components/EditAddressForm/UpdateCustomerAddress.graphql +43 -0
  35. package/components/EditAddressForm/index.tsx +127 -0
  36. package/components/ForgotPasswordForm/ForgotPassword.gql.ts +12 -0
  37. package/components/ForgotPasswordForm/ForgotPassword.graphql +3 -0
  38. package/components/ForgotPasswordForm/ForgotPasswordForm.tsx +73 -0
  39. package/components/InlineAccount/InlineAccount.gql.ts +12 -0
  40. package/components/InlineAccount/InlineAccount.graphql +10 -0
  41. package/components/InlineAccount/index.tsx +149 -0
  42. package/components/NameFields/index.tsx +89 -0
  43. package/components/ResetPasswordForm/ResetPassword.gql.ts +14 -0
  44. package/components/ResetPasswordForm/ResetPassword.graphql +3 -0
  45. package/components/ResetPasswordForm/index.tsx +98 -0
  46. package/components/SignInForm/SignIn.gql.ts +13 -0
  47. package/components/SignInForm/SignIn.graphql +5 -0
  48. package/components/SignInForm/SignInForm.tsx +96 -0
  49. package/components/SignInForm/SignInFormInline.tsx +68 -0
  50. package/components/SignOutForm/SignOutForm.gql.ts +10 -0
  51. package/components/SignOutForm/SignOutForm.graphql +5 -0
  52. package/components/SignOutForm/index.tsx +30 -0
  53. package/components/SignUpForm/SignUp.gql.ts +22 -0
  54. package/components/SignUpForm/SignUp.graphql +36 -0
  55. package/components/SignUpForm/SignUpForm.tsx +90 -0
  56. package/components/SignUpForm/SignUpFormInline.tsx +113 -0
  57. package/components/UpdateCustomerEmailForm/UpdateCustomerEmail.gql.ts +13 -0
  58. package/components/UpdateCustomerEmailForm/UpdateCustomerEmail.graphql +7 -0
  59. package/components/UpdateCustomerEmailForm/index.tsx +133 -0
  60. package/components/UpdateDefaultAddressForm/index.tsx +91 -0
  61. package/components/index.ts +29 -0
  62. package/hooks/Customer.gql.ts +10 -0
  63. package/hooks/Customer.graphql +5 -0
  64. package/hooks/CustomerInfo.gql.ts +4 -0
  65. package/hooks/CustomerInfo.graphql +20 -0
  66. package/hooks/CustomerToken.gql.ts +10 -0
  67. package/hooks/CustomerToken.graphql +8 -0
  68. package/hooks/CustomerToken.graphqls +8 -0
  69. package/hooks/IsEmailAvailable.gql.ts +12 -0
  70. package/hooks/IsEmailAvailable.graphql +5 -0
  71. package/hooks/index.ts +7 -0
  72. package/hooks/useExtractCustomerErrors.tsx +42 -0
  73. package/hooks/useFormIsEmailAvailable.tsx +69 -0
  74. package/index.ts +4 -0
  75. package/next-env.d.ts +4 -0
  76. package/package.json +41 -0
  77. package/tsconfig.json +5 -0
  78. package/typePolicies.ts +91 -0
@@ -0,0 +1,30 @@
1
+ import { FormState, useFormGqlMutation } from '@graphcommerce/react-hook-form'
2
+ import { useRouter } from 'next/router'
3
+ import React from 'react'
4
+ import ApolloCustomerErrorAlert from '../ApolloCustomerError/ApolloCustomerErrorAlert'
5
+ import { SignOutFormDocument } from './SignOutForm.gql'
6
+
7
+ type SignOutFormProps = { button: (props: { formState: FormState<unknown> }) => React.ReactNode }
8
+
9
+ export default function SignOutForm(props: SignOutFormProps) {
10
+ const { button } = props
11
+ const router = useRouter()
12
+ const { handleSubmit, formState, error } = useFormGqlMutation(
13
+ SignOutFormDocument,
14
+ {
15
+ onComplete: () => {
16
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
17
+ router.push('/')
18
+ },
19
+ },
20
+ { errorPolicy: 'all' },
21
+ )
22
+ const submitHandler = handleSubmit(() => {})
23
+
24
+ return (
25
+ <form onSubmit={submitHandler} noValidate>
26
+ {button({ formState })}
27
+ <ApolloCustomerErrorAlert error={error} />
28
+ </form>
29
+ )
30
+ }
@@ -0,0 +1,22 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const SignUpDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SignUp"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"prefix"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"firstname"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"middlename"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"lastname"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"suffix"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"taxvat"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"gender"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"isSubscribed"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"Boolean"}},"defaultValue":{"kind":"BooleanValue","value":false}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"dateOfBirth"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createCustomer"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"prefix"},"value":{"kind":"Variable","name":{"kind":"Name","value":"prefix"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"firstname"},"value":{"kind":"Variable","name":{"kind":"Name","value":"firstname"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"middlename"},"value":{"kind":"Variable","name":{"kind":"Name","value":"middlename"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"lastname"},"value":{"kind":"Variable","name":{"kind":"Name","value":"lastname"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"suffix"},"value":{"kind":"Variable","name":{"kind":"Name","value":"suffix"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"taxvat"},"value":{"kind":"Variable","name":{"kind":"Name","value":"taxvat"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"gender"},"value":{"kind":"Variable","name":{"kind":"Name","value":"gender"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"is_subscribed"},"value":{"kind":"Variable","name":{"kind":"Name","value":"isSubscribed"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"date_of_birth"},"value":{"kind":"Variable","name":{"kind":"Name","value":"dateOfBirth"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"default_billing"}},{"kind":"Field","name":{"kind":"Name","value":"default_shipping"}},{"kind":"Field","name":{"kind":"Name","value":"addresses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"prefix"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"middlename"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"suffix"}},{"kind":"Field","name":{"kind":"Name","value":"city"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"country_code"}},{"kind":"Field","name":{"kind":"Name","value":"postcode"}},{"kind":"Field","name":{"kind":"Name","value":"region"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"region"}},{"kind":"Field","name":{"kind":"Name","value":"region_code"}},{"kind":"Field","name":{"kind":"Name","value":"region_id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"street"}},{"kind":"Field","name":{"kind":"Name","value":"telephone"}},{"kind":"Field","name":{"kind":"Name","value":"vat_id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"prefix"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"middlename"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"suffix"}},{"kind":"Field","name":{"kind":"Name","value":"gender"}},{"kind":"Field","name":{"kind":"Name","value":"is_subscribed"}},{"kind":"Field","name":{"kind":"Name","value":"date_of_birth"}},{"kind":"Field","name":{"kind":"Name","value":"taxvat"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"generateCustomerToken"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"Argument","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"token"}}]}}]}}]} as unknown as DocumentNode<SignUpMutation, SignUpMutationVariables>;
7
+ export type SignUpMutationVariables = Types.Exact<{
8
+ email: Types.Scalars['String'];
9
+ password: Types.Scalars['String'];
10
+ prefix: Types.Scalars['String'];
11
+ firstname: Types.Scalars['String'];
12
+ middlename?: Types.Maybe<Types.Scalars['String']>;
13
+ lastname: Types.Scalars['String'];
14
+ suffix?: Types.Maybe<Types.Scalars['String']>;
15
+ taxvat?: Types.Maybe<Types.Scalars['String']>;
16
+ gender?: Types.Maybe<Types.Scalars['Int']>;
17
+ isSubscribed?: Types.Maybe<Types.Scalars['Boolean']>;
18
+ dateOfBirth?: Types.Maybe<Types.Scalars['String']>;
19
+ }>;
20
+
21
+
22
+ export type SignUpMutation = { createCustomer?: Types.Maybe<{ customer: { default_billing?: Types.Maybe<string>, default_shipping?: Types.Maybe<string>, email?: Types.Maybe<string>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, gender?: Types.Maybe<number>, is_subscribed?: Types.Maybe<boolean>, date_of_birth?: Types.Maybe<string>, taxvat?: Types.Maybe<string>, addresses?: Types.Maybe<Array<Types.Maybe<{ id?: Types.Maybe<number>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, city?: Types.Maybe<string>, company?: Types.Maybe<string>, country_code?: Types.Maybe<Types.CountryCodeEnum>, postcode?: Types.Maybe<string>, street?: Types.Maybe<Array<Types.Maybe<string>>>, telephone?: Types.Maybe<string>, vat_id?: Types.Maybe<string>, region?: Types.Maybe<{ region?: Types.Maybe<string>, region_code?: Types.Maybe<string>, region_id?: Types.Maybe<number> }> }>>> } }>, generateCustomerToken?: Types.Maybe<{ token?: Types.Maybe<string> }> };
@@ -0,0 +1,36 @@
1
+ mutation SignUp(
2
+ $email: String!
3
+ $password: String!
4
+ $prefix: String!
5
+ $firstname: String!
6
+ $middlename: String
7
+ $lastname: String!
8
+ $suffix: String
9
+ $taxvat: String
10
+ $gender: Int
11
+ $isSubscribed: Boolean = false
12
+ $dateOfBirth: String
13
+ ) {
14
+ createCustomer(
15
+ input: {
16
+ email: $email
17
+ password: $password
18
+ prefix: $prefix
19
+ firstname: $firstname
20
+ middlename: $middlename
21
+ lastname: $lastname
22
+ suffix: $suffix
23
+ taxvat: $taxvat
24
+ gender: $gender
25
+ is_subscribed: $isSubscribed
26
+ date_of_birth: $dateOfBirth
27
+ }
28
+ ) {
29
+ customer {
30
+ ...CustomerInfo
31
+ }
32
+ }
33
+ generateCustomerToken(email: $email, password: $password) {
34
+ token
35
+ }
36
+ }
@@ -0,0 +1,90 @@
1
+ import { FormControlLabel, Switch, TextField } from '@material-ui/core'
2
+ import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
3
+ import { Button, FormActions, FormRow } from '@graphcommerce/next-ui'
4
+ import { useFormGqlMutation, useFormPersist } from '@graphcommerce/react-hook-form'
5
+ import React from 'react'
6
+ import ApolloCustomerErrorAlert from '../ApolloCustomerError/ApolloCustomerErrorAlert'
7
+ import NameFields from '../NameFields'
8
+ import { SignUpDocument, SignUpMutation, SignUpMutationVariables } from './SignUp.gql'
9
+
10
+ type SignUpFormProps = {
11
+ email?: string
12
+ }
13
+
14
+ export default function SignUpForm(props: SignUpFormProps) {
15
+ const { email } = props
16
+ const form = useFormGqlMutation<
17
+ SignUpMutation,
18
+ SignUpMutationVariables & { confirmPassword?: string }
19
+ >(SignUpDocument, { defaultValues: { email } })
20
+
21
+ useFormPersist({ form, name: 'SignUp', exclude: ['password', 'confirmPassword'] })
22
+ const { muiRegister, handleSubmit, required, watch, formState, error } = form
23
+ const [remainingError, inputError] = graphqlErrorByCategory({ category: 'graphql-input', error })
24
+
25
+ const submitHandler = handleSubmit(() => {})
26
+ const watchPassword = watch('password')
27
+
28
+ return (
29
+ <form onSubmit={submitHandler} noValidate>
30
+ <FormRow>
31
+ <TextField
32
+ variant='outlined'
33
+ type='password'
34
+ error={!!formState.errors.password || !!inputError}
35
+ label='Password'
36
+ autoFocus
37
+ autoComplete='new-password'
38
+ required={required.password}
39
+ {...muiRegister('password', {
40
+ required: required.password,
41
+ minLength: { value: 8, message: 'Password must have at least 8 characters' },
42
+ })}
43
+ helperText={
44
+ formState.errors.password?.message ||
45
+ inputError?.message ||
46
+ 'At least 8 characters long, must contain a symbol'
47
+ }
48
+ disabled={formState.isSubmitting}
49
+ />
50
+ <TextField
51
+ variant='outlined'
52
+ type='password'
53
+ error={!!formState.errors.confirmPassword}
54
+ label='Confirm Password'
55
+ autoComplete='new-password'
56
+ required
57
+ {...muiRegister('confirmPassword', {
58
+ required: true,
59
+ validate: (value) => value === watchPassword || "Passwords don't match",
60
+ })}
61
+ helperText={formState.errors.confirmPassword?.message}
62
+ disabled={formState.isSubmitting}
63
+ />
64
+ </FormRow>
65
+
66
+ <NameFields form={form} prefix />
67
+
68
+ <FormControlLabel
69
+ control={<Switch color='primary' />}
70
+ {...muiRegister('isSubscribed', { required: required.isSubscribed })}
71
+ disabled={formState.isSubmitting}
72
+ label='Subscribe to newsletter'
73
+ />
74
+
75
+ <ApolloCustomerErrorAlert error={remainingError} />
76
+
77
+ <FormActions>
78
+ <Button
79
+ type='submit'
80
+ variant='contained'
81
+ color='primary'
82
+ size='large'
83
+ loading={formState.isSubmitting}
84
+ >
85
+ Create Account
86
+ </Button>
87
+ </FormActions>
88
+ </form>
89
+ )
90
+ }
@@ -0,0 +1,113 @@
1
+ import { makeStyles, TextField, Theme } from '@material-ui/core'
2
+ import { Button, Form, FormRow } from '@graphcommerce/next-ui'
3
+ import { useFormGqlMutation } from '@graphcommerce/react-hook-form'
4
+ import React, { PropsWithChildren } from 'react'
5
+ import { SignUpMutationVariables, SignUpMutation, SignUpDocument } from './SignUp.gql'
6
+
7
+ const useStyles = makeStyles(
8
+ (theme: Theme) => ({
9
+ buttonFormRow: {
10
+ padding: 0,
11
+ [theme.breakpoints.up('sm')]: {
12
+ gridTemplateColumns: 'minmax(200px, 3.5fr) 1fr',
13
+ },
14
+ },
15
+ form: {
16
+ padding: 0,
17
+ },
18
+ row: {
19
+ padding: 0,
20
+ },
21
+ button: {
22
+ minWidth: 'max-content',
23
+ },
24
+ buttonContainer: {
25
+ alignSelf: 'center',
26
+ },
27
+ }),
28
+ { name: 'SignUpFormInline' },
29
+ )
30
+
31
+ type SignUpFormInlineProps = Pick<SignUpMutationVariables, 'email'> & {
32
+ helperList?: React.ReactNode
33
+ firstname?: string
34
+ lastname?: string
35
+ onSubmitted?: () => void
36
+ }
37
+
38
+ export default function SignUpFormInline({
39
+ email,
40
+ helperList,
41
+ firstname,
42
+ lastname,
43
+ onSubmitted = () => {},
44
+ }: PropsWithChildren<SignUpFormInlineProps>) {
45
+ const classes = useStyles()
46
+ const form = useFormGqlMutation<
47
+ SignUpMutation,
48
+ SignUpMutationVariables & { confirmPassword?: string }
49
+ >(SignUpDocument, {
50
+ // todo(paales): This causes dirty data to be send to the backend.
51
+ defaultValues: {
52
+ email,
53
+ prefix: '-',
54
+ firstname: firstname ?? '-',
55
+ lastname: lastname ?? '-',
56
+ },
57
+ })
58
+ const { muiRegister, watch, handleSubmit, required, formState, error } = form
59
+ const submitHandler = handleSubmit(onSubmitted)
60
+ const watchPassword = watch('password')
61
+
62
+ return (
63
+ <Form onSubmit={submitHandler} noValidate classes={{ root: classes.form }}>
64
+ <FormRow key='inline-signup' classes={{ root: classes.row }}>
65
+ <TextField
66
+ variant='outlined'
67
+ type='password'
68
+ error={!!formState.errors.password || !!error?.message}
69
+ label='Password'
70
+ autoFocus
71
+ autoComplete='new-password'
72
+ id='new-password'
73
+ required={required.password}
74
+ {...muiRegister('password', { required: required.password })}
75
+ helperText={error?.message}
76
+ disabled={formState.isSubmitting}
77
+ />
78
+ <TextField
79
+ variant='outlined'
80
+ type='password'
81
+ error={!!formState.errors.confirmPassword || !!error?.message}
82
+ label='Confirm password'
83
+ autoComplete='new-password'
84
+ required
85
+ {...muiRegister('confirmPassword', {
86
+ required: true,
87
+ validate: (value) => value === watchPassword,
88
+ })}
89
+ helperText={!!formState.errors.confirmPassword && 'Passwords should match'}
90
+ disabled={formState.isSubmitting}
91
+ />
92
+ </FormRow>
93
+
94
+ <FormRow key='signup-submit'>
95
+ <FormRow classes={{ root: classes.buttonFormRow }}>
96
+ <div>{helperList}</div>
97
+ <div className={classes.buttonContainer}>
98
+ <Button
99
+ fullWidth
100
+ type='submit'
101
+ loading={formState.isSubmitting}
102
+ color='secondary'
103
+ variant='pill'
104
+ text='bold'
105
+ >
106
+ Sign up
107
+ </Button>
108
+ </div>
109
+ </FormRow>
110
+ </FormRow>
111
+ </Form>
112
+ )
113
+ }
@@ -0,0 +1,13 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const UpdateCustomerEmailDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateCustomerEmail"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"email"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"password"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateCustomerEmail"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"email"},"value":{"kind":"Variable","name":{"kind":"Name","value":"email"}}},{"kind":"Argument","name":{"kind":"Name","value":"password"},"value":{"kind":"Variable","name":{"kind":"Name","value":"password"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"email"}}]}}]}}]}}]} as unknown as DocumentNode<UpdateCustomerEmailMutation, UpdateCustomerEmailMutationVariables>;
7
+ export type UpdateCustomerEmailMutationVariables = Types.Exact<{
8
+ email: Types.Scalars['String'];
9
+ password: Types.Scalars['String'];
10
+ }>;
11
+
12
+
13
+ export type UpdateCustomerEmailMutation = { updateCustomerEmail?: Types.Maybe<{ customer: { email?: Types.Maybe<string> } }> };
@@ -0,0 +1,7 @@
1
+ mutation UpdateCustomerEmail($email: String!, $password: String!) {
2
+ updateCustomerEmail(email: $email, password: $password) {
3
+ customer {
4
+ email
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,133 @@
1
+ import { TextField } from '@material-ui/core'
2
+ import {
3
+ Button,
4
+ Form,
5
+ FormActions,
6
+ FormDivider,
7
+ FormRow,
8
+ MessageSnackbar,
9
+ } from '@graphcommerce/next-ui'
10
+ import { emailPattern, useFormGqlMutation } from '@graphcommerce/react-hook-form'
11
+ import React from 'react'
12
+ import ApolloCustomerErrorAlert from '../ApolloCustomerError/ApolloCustomerErrorAlert'
13
+ import {
14
+ UpdateCustomerEmailDocument,
15
+ UpdateCustomerEmailMutation,
16
+ UpdateCustomerEmailMutationVariables,
17
+ } from './UpdateCustomerEmail.gql'
18
+
19
+ type UpdateCustomerEmailFormProps = {
20
+ email: string
21
+ }
22
+
23
+ export default function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
24
+ const { email } = props
25
+
26
+ const form = useFormGqlMutation<
27
+ UpdateCustomerEmailMutation,
28
+ UpdateCustomerEmailMutationVariables & {
29
+ currentEmail?: string
30
+ confirmEmail?: string
31
+ }
32
+ >(UpdateCustomerEmailDocument)
33
+
34
+ const { handleSubmit, error, required, formState, watch, muiRegister, reset } = form
35
+ const submit = handleSubmit(() => {
36
+ reset()
37
+ })
38
+ const watchNewEmail = watch('email')
39
+
40
+ return (
41
+ <Form onSubmit={submit} noValidate>
42
+ <FormRow>
43
+ <TextField
44
+ key='current-email'
45
+ variant='outlined'
46
+ type='text'
47
+ autoComplete='currentEmail'
48
+ autoFocus
49
+ error={formState.isSubmitted && !!formState.errors.currentEmail}
50
+ helperText={formState.isSubmitted && formState.errors.currentEmail?.message}
51
+ label='Current email'
52
+ required
53
+ value={email}
54
+ {...muiRegister('currentEmail', {
55
+ required: true,
56
+ pattern: { value: emailPattern, message: '' },
57
+ })}
58
+ InputProps={{
59
+ readOnly: true,
60
+ }}
61
+ />
62
+ </FormRow>
63
+
64
+ <FormRow>
65
+ <TextField
66
+ key='email'
67
+ variant='outlined'
68
+ type='text'
69
+ autoComplete='email'
70
+ autoFocus
71
+ error={formState.isSubmitted && !!formState.errors.email}
72
+ helperText={formState.isSubmitted && formState.errors.email?.message}
73
+ label='New email'
74
+ required={required.email}
75
+ {...muiRegister('email', {
76
+ required: true,
77
+ pattern: { value: emailPattern, message: '' },
78
+ })}
79
+ />
80
+ <TextField
81
+ key='confirm-email'
82
+ variant='outlined'
83
+ type='text'
84
+ autoComplete='confirmEmail'
85
+ autoFocus
86
+ error={formState.isSubmitted && !!formState.errors.confirmEmail}
87
+ helperText={formState.isSubmitted && formState.errors.confirmEmail?.message}
88
+ label='Confirm new email'
89
+ required
90
+ {...muiRegister('confirmEmail', {
91
+ required: true,
92
+ validate: (value) => value === watchNewEmail || "Emails don't match",
93
+ })}
94
+ />
95
+ </FormRow>
96
+
97
+ <FormRow>
98
+ <TextField
99
+ variant='outlined'
100
+ type='password'
101
+ error={!!formState.errors.password}
102
+ label='Password'
103
+ autoComplete='password'
104
+ required={required.password}
105
+ {...muiRegister('password', {
106
+ required: required.password,
107
+ })}
108
+ helperText={formState.errors.password?.message}
109
+ disabled={formState.isSubmitting}
110
+ />
111
+ </FormRow>
112
+
113
+ <FormDivider />
114
+ <FormActions>
115
+ <Button
116
+ type='submit'
117
+ text='bold'
118
+ color='primary'
119
+ variant='contained'
120
+ size='large'
121
+ loading={formState.isSubmitting}
122
+ >
123
+ Save changes
124
+ </Button>
125
+ </FormActions>
126
+ <ApolloCustomerErrorAlert error={error} />
127
+
128
+ <MessageSnackbar sticky open={formState.isSubmitSuccessful && !error}>
129
+ <>Successfully updated email</>
130
+ </MessageSnackbar>
131
+ </Form>
132
+ )
133
+ }
@@ -0,0 +1,91 @@
1
+ import { FormControl, FormControlLabel, FormHelperText, Switch } from '@material-ui/core'
2
+ import { Controller, useFormAutoSubmit, useFormGqlMutation } from '@graphcommerce/react-hook-form'
3
+ import React, { useEffect, useMemo } from 'react'
4
+ import { AccountAddressFragment } from '../AccountAddress/AccountAddress.gql'
5
+ import { UpdateDefaultAddressDocument } from '../AccountAddresses/UpdateDefaultAddress.gql'
6
+ import ApolloCustomerErrorAlert from '../ApolloCustomerError/ApolloCustomerErrorAlert'
7
+
8
+ export type AccountAddressProps = Pick<
9
+ AccountAddressFragment,
10
+ 'id' | 'default_shipping' | 'default_billing'
11
+ >
12
+
13
+ export default function UpdateDefaultAddressForm(props: AccountAddressProps) {
14
+ const { id, default_shipping, default_billing } = props
15
+ const defaultValues = useMemo(
16
+ () => ({
17
+ addressId: id ?? undefined,
18
+ defaultBilling: !!default_billing,
19
+ defaultShipping: !!default_shipping,
20
+ }),
21
+ [default_billing, default_shipping, id],
22
+ )
23
+
24
+ const form = useFormGqlMutation(
25
+ UpdateDefaultAddressDocument,
26
+ {
27
+ mode: 'onChange',
28
+ defaultValues,
29
+ },
30
+ { errorPolicy: 'all' },
31
+ )
32
+
33
+ const { handleSubmit, control, error, reset, formState } = form
34
+
35
+ const submit = handleSubmit(() => {
36
+ //
37
+ })
38
+ useFormAutoSubmit({ form, submit })
39
+
40
+ useEffect(() => {
41
+ reset(defaultValues)
42
+ }, [defaultValues, reset])
43
+
44
+ return (
45
+ <form onSubmit={() => {}} noValidate>
46
+ <Controller
47
+ name='defaultShipping'
48
+ control={control}
49
+ render={({ field: { onChange, value, name, ref, onBlur } }) => (
50
+ <FormControl error={!!formState.errors.defaultShipping}>
51
+ <FormControlLabel
52
+ control={<Switch color='primary' />}
53
+ label='Shipping address'
54
+ checked={value}
55
+ inputRef={ref}
56
+ onBlur={onBlur}
57
+ name={name}
58
+ onChange={(e) => onChange((e as React.ChangeEvent<HTMLInputElement>).target.checked)}
59
+ />
60
+
61
+ {formState.errors.defaultShipping?.message && (
62
+ <FormHelperText>{formState.errors.defaultShipping?.message}</FormHelperText>
63
+ )}
64
+ </FormControl>
65
+ )}
66
+ />
67
+ <Controller
68
+ name='defaultBilling'
69
+ control={control}
70
+ render={({ field: { onChange, value, name, ref, onBlur } }) => (
71
+ <FormControl error={!!formState.errors.defaultBilling}>
72
+ <FormControlLabel
73
+ control={<Switch color='primary' />}
74
+ label='Billing address'
75
+ checked={value}
76
+ inputRef={ref}
77
+ onBlur={onBlur}
78
+ name={name}
79
+ onChange={(e) => onChange((e as React.ChangeEvent<HTMLInputElement>).target.checked)}
80
+ />
81
+
82
+ {formState.errors.defaultBilling?.message && (
83
+ <FormHelperText>{formState.errors.defaultBilling?.message}</FormHelperText>
84
+ )}
85
+ </FormControl>
86
+ )}
87
+ />
88
+ <ApolloCustomerErrorAlert error={error} />
89
+ </form>
90
+ )
91
+ }
@@ -0,0 +1,29 @@
1
+ export { default as AccountAddress } from './AccountAddress'
2
+ export { default as AccountAddresses } from './AccountAddresses'
3
+ export { default as CustomerFab } from './CustomerFab'
4
+ export { default as ChangePasswordForm } from './ChangePasswordForm/ChangePasswordForm'
5
+ export * from './ChangePasswordForm/ChangePassword.gql'
6
+ export { default as ForgotPasswordForm } from './ForgotPasswordForm/ForgotPasswordForm'
7
+ export * from './ForgotPasswordForm/ForgotPassword.gql'
8
+ export { default as SignOutForm } from './SignOutForm'
9
+ export { default as InlineAccount } from './InlineAccount'
10
+ export { default as CreateCustomerAddressForm } from './CreateCustomerAddressForm'
11
+ export { default as DeleteCustomerAddressForm } from './DeleteCustomerAddressForm'
12
+ export { default as EditAddressForm } from './EditAddressForm'
13
+ export { default as AddressMultiLine } from './AddressMultiLine'
14
+ export { default as AddressSingleLine } from './AddressSingleLine'
15
+ export { default as ResetPasswordForm } from './ResetPasswordForm'
16
+ export { default as AddressFields } from './AddressFields'
17
+ export { default as NameFields } from './NameFields'
18
+ export { default as CustomerMenuFabItem } from './CustomerMenuFabItem'
19
+ export { default as ChangeNameForm } from './ChangeNameForm'
20
+ export { default as UpdateCustomerEmailForm } from './UpdateCustomerEmailForm'
21
+ export { default as ApolloCustomerErrorAlert } from './ApolloCustomerError/ApolloCustomerErrorAlert'
22
+ export { default as ApolloCustomerErrorFullPage } from './ApolloCustomerError/ApolloCustomerErrorFullPage'
23
+ export { default as UpdateDefaultAddressForm } from './UpdateDefaultAddressForm'
24
+ export { default as SignInForm } from './SignInForm/SignInForm'
25
+ export { default as SignInFormInline } from './SignInForm/SignInFormInline'
26
+ export { default as SignUpForm } from './SignUpForm/SignUpForm'
27
+ export { default as SignUpFormInline } from './SignUpForm/SignUpFormInline'
28
+ export * from './SignInForm/SignIn.gql'
29
+ export * from './SignUpForm/SignUp.gql'
@@ -0,0 +1,10 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
5
+
6
+ export const CustomerDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Customer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"customer"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"default_billing"}},{"kind":"Field","name":{"kind":"Name","value":"default_shipping"}},{"kind":"Field","name":{"kind":"Name","value":"addresses"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"prefix"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"middlename"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"suffix"}},{"kind":"Field","name":{"kind":"Name","value":"city"}},{"kind":"Field","name":{"kind":"Name","value":"company"}},{"kind":"Field","name":{"kind":"Name","value":"country_code"}},{"kind":"Field","name":{"kind":"Name","value":"postcode"}},{"kind":"Field","name":{"kind":"Name","value":"region"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"region"}},{"kind":"Field","name":{"kind":"Name","value":"region_code"}},{"kind":"Field","name":{"kind":"Name","value":"region_id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"street"}},{"kind":"Field","name":{"kind":"Name","value":"telephone"}},{"kind":"Field","name":{"kind":"Name","value":"vat_id"}}]}},{"kind":"Field","name":{"kind":"Name","value":"email"}},{"kind":"Field","name":{"kind":"Name","value":"prefix"}},{"kind":"Field","name":{"kind":"Name","value":"firstname"}},{"kind":"Field","name":{"kind":"Name","value":"middlename"}},{"kind":"Field","name":{"kind":"Name","value":"lastname"}},{"kind":"Field","name":{"kind":"Name","value":"suffix"}},{"kind":"Field","name":{"kind":"Name","value":"gender"}},{"kind":"Field","name":{"kind":"Name","value":"is_subscribed"}},{"kind":"Field","name":{"kind":"Name","value":"date_of_birth"}},{"kind":"Field","name":{"kind":"Name","value":"taxvat"}}]}}]}}]} as unknown as DocumentNode<CustomerQuery, CustomerQueryVariables>;
7
+ export type CustomerQueryVariables = Types.Exact<{ [key: string]: never; }>;
8
+
9
+
10
+ export type CustomerQuery = { customer?: Types.Maybe<{ default_billing?: Types.Maybe<string>, default_shipping?: Types.Maybe<string>, email?: Types.Maybe<string>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, gender?: Types.Maybe<number>, is_subscribed?: Types.Maybe<boolean>, date_of_birth?: Types.Maybe<string>, taxvat?: Types.Maybe<string>, addresses?: Types.Maybe<Array<Types.Maybe<{ id?: Types.Maybe<number>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, city?: Types.Maybe<string>, company?: Types.Maybe<string>, country_code?: Types.Maybe<Types.CountryCodeEnum>, postcode?: Types.Maybe<string>, street?: Types.Maybe<Array<Types.Maybe<string>>>, telephone?: Types.Maybe<string>, vat_id?: Types.Maybe<string>, region?: Types.Maybe<{ region?: Types.Maybe<string>, region_code?: Types.Maybe<string>, region_id?: Types.Maybe<number> }> }>>> }> };
@@ -0,0 +1,5 @@
1
+ query Customer {
2
+ customer {
3
+ ...CustomerInfo
4
+ }
5
+ }
@@ -0,0 +1,4 @@
1
+ /* eslint-disable */
2
+ import * as Types from '@graphcommerce/graphql';
3
+
4
+ export type CustomerInfoFragment = { default_billing?: Types.Maybe<string>, default_shipping?: Types.Maybe<string>, email?: Types.Maybe<string>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, gender?: Types.Maybe<number>, is_subscribed?: Types.Maybe<boolean>, date_of_birth?: Types.Maybe<string>, taxvat?: Types.Maybe<string>, addresses?: Types.Maybe<Array<Types.Maybe<{ id?: Types.Maybe<number>, prefix?: Types.Maybe<string>, firstname?: Types.Maybe<string>, middlename?: Types.Maybe<string>, lastname?: Types.Maybe<string>, suffix?: Types.Maybe<string>, city?: Types.Maybe<string>, company?: Types.Maybe<string>, country_code?: Types.Maybe<Types.CountryCodeEnum>, postcode?: Types.Maybe<string>, street?: Types.Maybe<Array<Types.Maybe<string>>>, telephone?: Types.Maybe<string>, vat_id?: Types.Maybe<string>, region?: Types.Maybe<{ region?: Types.Maybe<string>, region_code?: Types.Maybe<string>, region_id?: Types.Maybe<number> }> }>>> };
@@ -0,0 +1,20 @@
1
+ fragment CustomerInfo on Customer {
2
+ default_billing
3
+ default_shipping
4
+ addresses {
5
+ ...CustomerAddress
6
+ }
7
+ email
8
+
9
+ prefix
10
+ firstname
11
+ middlename
12
+ lastname
13
+ suffix
14
+ gender
15
+
16
+ is_subscribed
17
+
18
+ date_of_birth
19
+ taxvat
20
+ }