@graphcommerce/magento-cart-shipping-method 3.0.25 → 3.1.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 CHANGED
@@ -1,5 +1,55 @@
1
1
  # Change Log
2
2
 
3
+ ## 3.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1503](https://github.com/graphcommerce-org/graphcommerce/pull/1503) [`a9213f1f5`](https://github.com/graphcommerce-org/graphcommerce/commit/a9213f1f5a410d217768386ccb6d9b5ce7bd5782) Thanks [@mikekeehnen](https://github.com/mikekeehnen)! - Bug fixes for shipping methods in /checkout
8
+
9
+ ### Patch Changes
10
+
11
+ - [#1490](https://github.com/graphcommerce-org/graphcommerce/pull/1490) [`d311ef48b`](https://github.com/graphcommerce-org/graphcommerce/commit/d311ef48bb3e97806d992af5516d6b7f183ec9cb) Thanks [@paales](https://github.com/paales)! - upgraded packages
12
+
13
+ - Updated dependencies [[`a9213f1f5`](https://github.com/graphcommerce-org/graphcommerce/commit/a9213f1f5a410d217768386ccb6d9b5ce7bd5782), [`ddb6d6329`](https://github.com/graphcommerce-org/graphcommerce/commit/ddb6d6329bfad361b2fbe96402ca2bfc0ab3d98c), [`d311ef48b`](https://github.com/graphcommerce-org/graphcommerce/commit/d311ef48bb3e97806d992af5516d6b7f183ec9cb)]:
14
+ - @graphcommerce/magento-cart-shipping-address@3.1.0
15
+ - @graphcommerce/next-ui@4.9.0
16
+ - @graphcommerce/framer-scroller@2.1.16
17
+ - @graphcommerce/graphql@3.2.1
18
+ - @graphcommerce/image@3.1.7
19
+ - @graphcommerce/magento-cart@4.4.3
20
+ - @graphcommerce/magento-store@4.2.10
21
+ - @graphcommerce/react-hook-form@3.2.2
22
+
23
+ ## 3.0.28
24
+
25
+ ### Patch Changes
26
+
27
+ - Updated dependencies [[`0ab7c5465`](https://github.com/graphcommerce-org/graphcommerce/commit/0ab7c5465441cba9bf8cd185a6790ce2f443f4ed)]:
28
+ - @graphcommerce/framer-scroller@2.1.15
29
+ - @graphcommerce/next-ui@4.8.4
30
+ - @graphcommerce/magento-cart@4.4.2
31
+ - @graphcommerce/magento-cart-shipping-address@3.0.27
32
+ - @graphcommerce/magento-store@4.2.9
33
+
34
+ ## 3.0.27
35
+
36
+ ### Patch Changes
37
+
38
+ - Updated dependencies [[`d205b037f`](https://github.com/graphcommerce-org/graphcommerce/commit/d205b037fee82b8c03993f2c586f477e826093bf)]:
39
+ - @graphcommerce/magento-cart@4.4.1
40
+ - @graphcommerce/magento-cart-shipping-address@3.0.26
41
+
42
+ ## 3.0.26
43
+
44
+ ### Patch Changes
45
+
46
+ - Updated dependencies [[`ffec8800a`](https://github.com/graphcommerce-org/graphcommerce/commit/ffec8800a50ff2fe9b9fc5feeb5a0a878b573f0e), [`bed806ddd`](https://github.com/graphcommerce-org/graphcommerce/commit/bed806dddd7e025806a69798ef9587aa165d392f)]:
47
+ - @graphcommerce/react-hook-form@3.2.1
48
+ - @graphcommerce/graphql@3.2.0
49
+ - @graphcommerce/magento-cart@4.4.0
50
+ - @graphcommerce/magento-cart-shipping-address@3.0.25
51
+ - @graphcommerce/magento-store@4.2.8
52
+
3
53
  ## 3.0.25
4
54
 
5
55
  ### Patch Changes
@@ -0,0 +1,133 @@
1
+ import {
2
+ ApolloCartErrorAlert,
3
+ useCartQuery,
4
+ useFormGqlMutationCart,
5
+ } from '@graphcommerce/magento-cart'
6
+ import { Money, MoneyProps } from '@graphcommerce/magento-store'
7
+ import { ActionCard, Button, Form } from '@graphcommerce/next-ui'
8
+ import { ActionCardListForm } from '@graphcommerce/next-ui/ActionCard/ActionCardListForm'
9
+ import {
10
+ useFormCompose,
11
+ UseFormComposeOptions,
12
+ useFormPersist,
13
+ } from '@graphcommerce/react-hook-form'
14
+ import { Trans } from '@lingui/react'
15
+ import { Typography } from '@mui/material'
16
+ import { GetShippingMethodsDocument } from './GetShippingMethods.gql'
17
+ import {
18
+ ShippingMethodFormDocument,
19
+ ShippingMethodFormMutation,
20
+ ShippingMethodFormMutationVariables,
21
+ } from './ShippingMethodForm.gql'
22
+
23
+ export type ShippingMethodFormProps = Pick<UseFormComposeOptions, 'step'>
24
+
25
+ function ShippingMethodDetails(props: {
26
+ available: boolean | null | undefined
27
+ price: MoneyProps | null | undefined
28
+ errorMessage: string | null | undefined
29
+ }) {
30
+ const { available, price, errorMessage } = props
31
+ const isFree = price && price.value === 0
32
+ const amount = !isFree ? <Money {...price} /> : 'Free'
33
+ const amountColor = !isFree ? 'text.primary' : '#05C642'
34
+ return (
35
+ <Typography
36
+ variant={available ? 'h5' : 'body1'}
37
+ sx={{ display: 'flex', justifyContent: available ? 'flex-end' : 'flex-start' }}
38
+ color={!available ? undefined : amountColor}
39
+ >
40
+ {available ? amount : errorMessage}
41
+ </Typography>
42
+ )
43
+ }
44
+
45
+ export function ShippingMethodForm(props: ShippingMethodFormProps) {
46
+ const { step } = props
47
+ const { data: cartQuery } = useCartQuery(GetShippingMethodsDocument)
48
+ const currentAddress = cartQuery?.cart?.shipping_addresses?.[0]
49
+ const available = currentAddress?.available_shipping_methods
50
+ const selected = currentAddress?.selected_shipping_method
51
+ const carrier = selected?.carrier_code ?? available?.[0]?.carrier_code
52
+ const method = selected?.method_code ?? available?.[0]?.method_code ?? undefined
53
+ const carrierMethod = `${carrier}-${method}`
54
+
55
+ const sortedAvailableShippingMethods = [
56
+ ...(currentAddress?.available_shipping_methods ?? []),
57
+ // eslint-disable-next-line no-nested-ternary
58
+ ].sort((a, b) => (a === b ? 0 : a ? -1 : 1))
59
+
60
+ const form = useFormGqlMutationCart<
61
+ ShippingMethodFormMutation,
62
+ ShippingMethodFormMutationVariables & { carrierMethod?: string }
63
+ >(ShippingMethodFormDocument, {
64
+ defaultValues: { carrierMethod, carrier, method },
65
+ onBeforeSubmit: (variables) => {
66
+ const splitCarrierMethod = variables?.carrierMethod?.split('-')
67
+ return {
68
+ ...variables,
69
+ carrier: splitCarrierMethod?.[0] ?? available?.[0]?.carrier_code ?? '',
70
+ method: splitCarrierMethod?.[1] ?? available?.[0]?.method_code ?? '',
71
+ }
72
+ },
73
+ })
74
+
75
+ const { handleSubmit, control, error } = form
76
+ const submit = handleSubmit(() => {})
77
+
78
+ useFormPersist({ form, name: 'ShippingMethodForm' })
79
+ useFormCompose({ form, step, submit, key: 'ShippingMethodForm' })
80
+
81
+ return (
82
+ <Form onSubmit={submit} noValidate>
83
+ <ActionCardListForm
84
+ control={control}
85
+ name='carrierMethod'
86
+ errorMessage='Please select a shipping address'
87
+ items={[
88
+ ...(sortedAvailableShippingMethods ?? []).filter(Boolean).map((sortedMethod) => ({
89
+ ...sortedMethod,
90
+ title: sortedMethod?.carrier_title,
91
+ disabled: !sortedMethod?.available,
92
+ details: (
93
+ <ShippingMethodDetails
94
+ available={sortedMethod?.available}
95
+ price={sortedMethod?.amount}
96
+ errorMessage={sortedMethod?.error_message}
97
+ />
98
+ ),
99
+ value: `${sortedMethod?.carrier_code}-${sortedMethod?.method_code}`,
100
+ })),
101
+ ]}
102
+ render={(actionCardProps) => (
103
+ <ActionCard
104
+ {...actionCardProps}
105
+ sx={{ background: 'primary.disabled' }}
106
+ hidden={false}
107
+ action={
108
+ <Button
109
+ disableRipple
110
+ variant='text'
111
+ color='secondary'
112
+ sx={{ display: actionCardProps.available ? 'contents' : 'none' }}
113
+ >
114
+ <Trans id='Select' />
115
+ </Button>
116
+ }
117
+ reset={
118
+ <Button
119
+ disableRipple
120
+ variant='text'
121
+ color='secondary'
122
+ onClick={actionCardProps.onReset}
123
+ >
124
+ <Trans id='Change' />
125
+ </Button>
126
+ }
127
+ />
128
+ )}
129
+ />
130
+ <ApolloCartErrorAlert error={error} />
131
+ </Form>
132
+ )
133
+ }
package/index.ts CHANGED
@@ -1,4 +1,3 @@
1
1
  export * from './Api/AvailableShippingMethods.gql'
2
2
  export * from './Api/ShippingMethodSelected.gql'
3
-
4
- export * from './ShippingMethodForm/ShippingMethodForm'
3
+ export * from './components/ShippingMethodForm/ShippingMethodForm'
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-cart-shipping-method",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "3.0.25",
5
+ "version": "3.1.0",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -12,29 +12,29 @@
12
12
  }
13
13
  },
14
14
  "devDependencies": {
15
- "@graphcommerce/eslint-config-pwa": "^4.1.7",
15
+ "@graphcommerce/eslint-config-pwa": "^4.1.8",
16
16
  "@graphcommerce/prettier-config-pwa": "^4.0.6",
17
17
  "@graphcommerce/typescript-config-pwa": "^4.0.3",
18
18
  "@playwright/test": "^1.21.1",
19
19
  "type-fest": "^2.12.2"
20
20
  },
21
21
  "dependencies": {
22
- "@graphcommerce/framer-scroller": "2.1.14",
23
- "@graphcommerce/graphql": "3.1.3",
24
- "@graphcommerce/image": "3.1.6",
25
- "@graphcommerce/magento-cart": "4.3.4",
26
- "@graphcommerce/magento-cart-shipping-address": "3.0.24",
27
- "@graphcommerce/magento-store": "4.2.7",
28
- "@graphcommerce/next-ui": "4.8.3",
29
- "@graphcommerce/react-hook-form": "3.2.0"
22
+ "@graphcommerce/framer-scroller": "2.1.16",
23
+ "@graphcommerce/graphql": "3.2.1",
24
+ "@graphcommerce/image": "3.1.7",
25
+ "@graphcommerce/magento-cart": "4.4.3",
26
+ "@graphcommerce/magento-cart-shipping-address": "3.1.0",
27
+ "@graphcommerce/magento-store": "4.2.10",
28
+ "@graphcommerce/next-ui": "4.9.0",
29
+ "@graphcommerce/react-hook-form": "3.2.2"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "@lingui/react": "^3.13.2",
33
33
  "@lingui/core": "^3.13.2",
34
34
  "@mui/material": "5.5.3",
35
35
  "framer-motion": "^6.2.4",
36
- "next": "12.1.2",
37
- "react": "^17.0.2",
38
- "react-dom": "^17.0.2"
36
+ "next": "^12.1.2",
37
+ "react": "^18.0.0",
38
+ "react-dom": "^18.0.0"
39
39
  }
40
40
  }
@@ -1,244 +0,0 @@
1
- import { Scroller, ScrollerButton, ScrollerProvider } from '@graphcommerce/framer-scroller'
2
- import {
3
- ApolloCartErrorAlert,
4
- useCartQuery,
5
- useFormGqlMutationCart,
6
- } from '@graphcommerce/magento-cart'
7
- import {
8
- Form,
9
- FormRow,
10
- iconChevronLeft,
11
- iconChevronRight,
12
- IconSvg,
13
- extendableComponent,
14
- } from '@graphcommerce/next-ui'
15
- import { Controller, useFormCompose, UseFormComposeOptions } from '@graphcommerce/react-hook-form'
16
- import { i18n } from '@lingui/core'
17
- import { Trans } from '@lingui/react'
18
- import { FormControl, Alert, Box } from '@mui/material'
19
- import { AvailableShippingMethod } from '../AvailableShippingMethod/AvailableShippingMethod'
20
- import { GetShippingMethodsDocument } from './GetShippingMethods.gql'
21
- import {
22
- ShippingMethodFormDocument,
23
- ShippingMethodFormMutation,
24
- ShippingMethodFormMutationVariables,
25
- } from './ShippingMethodForm.gql'
26
-
27
- export type ShippingMethodFormProps = Pick<UseFormComposeOptions, 'step'>
28
-
29
- type OwnerProps = {
30
- itemCount?: number
31
- }
32
-
33
- const name = 'ShippingMethodForm' as const
34
- const parts = ['root', 'alert', 'buttonRoot', 'buttonContainer', 'scrollerRoot'] as const
35
- const { withState } = extendableComponent<OwnerProps, typeof name, typeof parts>(name, parts)
36
-
37
- export function ShippingMethodForm(props: ShippingMethodFormProps) {
38
- const { step } = props
39
- const { data: cartQuery } = useCartQuery(GetShippingMethodsDocument)
40
-
41
- const currentAddress = cartQuery?.cart?.shipping_addresses?.[0]
42
- const available = currentAddress?.available_shipping_methods
43
- const selected = currentAddress?.selected_shipping_method
44
- const carrier = selected?.carrier_code ?? available?.[0]?.carrier_code
45
- const method = selected?.method_code ?? available?.[0]?.method_code ?? undefined
46
- const carrierMethod = carrier && method ? `${carrier}-${method}` : undefined
47
-
48
- const sortedAvailableShippingMethods = [
49
- ...(currentAddress?.available_shipping_methods ?? []),
50
- // eslint-disable-next-line no-nested-ternary
51
- ].sort((a, b) => (a === b ? 0 : a ? -1 : 1))
52
-
53
- const form = useFormGqlMutationCart<
54
- ShippingMethodFormMutation,
55
- ShippingMethodFormMutationVariables & { carrierMethod?: string }
56
- >(ShippingMethodFormDocument, {
57
- defaultValues: { carrierMethod, carrier, method },
58
- })
59
-
60
- const { handleSubmit, control, setValue, register, required, error } = form
61
- const submit = handleSubmit(() => {})
62
- useFormCompose({ form, step, submit, key: 'ShippingMethodForm' })
63
-
64
- const classes = withState({ itemCount: sortedAvailableShippingMethods.length })
65
- return (
66
- <Form onSubmit={submit} noValidate>
67
- <input type='hidden' {...register('carrier', { required: required.carrier })} />
68
- <input type='hidden' {...register('method', { required: required.method })} />
69
-
70
- <FormRow
71
- className={classes.root}
72
- sx={(theme) => ({
73
- marginTop: theme.spacings.xs,
74
- position: 'relative',
75
- padding: 0,
76
- })}
77
- >
78
- <ScrollerProvider scrollSnapAlign='center'>
79
- <Box
80
- className={classes.buttonContainer}
81
- sx={{
82
- position: 'absolute',
83
- left: 0,
84
- zIndex: 2,
85
- height: '100%',
86
- '& > div': { height: '100%' },
87
- }}
88
- >
89
- <ScrollerButton
90
- direction='left'
91
- className={classes.buttonRoot}
92
- sx={{
93
- bgcolor: 'background.default',
94
- borderRadius: 0,
95
- width: '30px',
96
- height: '100%',
97
- boxShadow: 'none',
98
- borderWidth: 1,
99
- borderColor: 'divider',
100
- '&:focus': {
101
- boxShadow: 'none',
102
- },
103
- borderTopLeftRadius: 4,
104
- borderBottomLeftRadius: 4,
105
- '&.itemCount1, &.itemCount2': {
106
- display: 'none',
107
- },
108
- }}
109
- >
110
- <IconSvg
111
- src={iconChevronLeft}
112
- size='small'
113
- aria-label={i18n._(/* i18n */ `Scroll Left`)}
114
- />
115
- </ScrollerButton>
116
- </Box>
117
-
118
- <FormControl>
119
- <Controller
120
- defaultValue={carrierMethod}
121
- control={control}
122
- name='carrierMethod'
123
- rules={{ required: 'Please select a shipping method' }}
124
- render={({ field: { onChange, value, onBlur }, fieldState: { invalid } }) => (
125
- <>
126
- <Scroller
127
- className={classes.scrollerRoot}
128
- sx={[
129
- {
130
- gridTemplateRows: `100%`,
131
- gridTemplateColumns: `repeat(2, calc(50% - 20px))`,
132
- gap: `6px`,
133
- borderRadius: 0,
134
- padding: '1px 1px',
135
- '&:focus': {
136
- outline: 'unset',
137
- },
138
- },
139
- sortedAvailableShippingMethods.length === 2 && {
140
- gridTemplateColumns: `repeat(2, calc(50% - 4px))`,
141
- },
142
- sortedAvailableShippingMethods.length === 1 && {
143
- gridTemplateColumns: `repeat(2, calc(100% - 8px))`,
144
- },
145
- ]}
146
- hideScrollbar
147
- tabIndex={0}
148
- >
149
- {sortedAvailableShippingMethods.map((shippingMethod) => {
150
- if (!shippingMethod) return null
151
- const code = `${shippingMethod?.carrier_code}-${shippingMethod?.method_code}`
152
- return (
153
- <AvailableShippingMethod
154
- key={code}
155
- value={code}
156
- onChange={(_, val: string) => {
157
- onChange(val)
158
- setValue('carrier', val.split('-')?.[0])
159
- setValue('method', val.split('-')?.[1])
160
-
161
- // todo(paales): what if there are additional options to submit, shouldn't we wait for that or will those always come back from this mutation?
162
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
163
- submit()
164
- }}
165
- onBlur={onBlur}
166
- selected={value === code}
167
- {...shippingMethod}
168
- >
169
- Delivery from: Mon - Sat
170
- </AvailableShippingMethod>
171
- )
172
- })}
173
- {!currentAddress?.available_shipping_methods && (
174
- <AvailableShippingMethod
175
- available={false}
176
- carrier_code='none'
177
- carrier_title={i18n._(/* i18n */ `No shipping methods available`)}
178
- >
179
- <Trans id='Please fill in your address to see shipping methods' />
180
- </AvailableShippingMethod>
181
- )}
182
- </Scroller>
183
-
184
- {invalid && currentAddress?.available_shipping_methods && (
185
- <Alert
186
- className={classes.alert}
187
- severity='error'
188
- sx={(theme) => ({
189
- marginTop: theme.spacings.xxs,
190
- })}
191
- >
192
- Please select a shipping method
193
- </Alert>
194
- )}
195
- </>
196
- )}
197
- />
198
- </FormControl>
199
-
200
- <Box
201
- sx={{
202
- position: 'absolute',
203
- right: 0,
204
- zIndex: 2,
205
- height: '100%',
206
- '& > div': { height: '100%' },
207
- }}
208
- className={classes.buttonContainer}
209
- >
210
- <ScrollerButton
211
- direction='right'
212
- sx={{
213
- bgcolor: 'background.default',
214
- borderRadius: 0,
215
- width: '30px',
216
- height: '100%',
217
- boxShadow: 'none',
218
- borderWidth: 1,
219
- borderColor: 'divider',
220
- '&:focus': {
221
- boxShadow: 'none',
222
- },
223
- borderTopRightRadius: 4,
224
- borderBottomRightRadius: 4,
225
- '&.itemCount1, &.itemCount2': {
226
- display: 'none',
227
- },
228
- }}
229
- className={classes.buttonRoot}
230
- >
231
- <IconSvg
232
- src={iconChevronRight}
233
- size='small'
234
- aria-label={i18n._(/* i18n */ `Scroll Right`)}
235
- />
236
- </ScrollerButton>
237
- </Box>
238
- </ScrollerProvider>
239
- </FormRow>
240
-
241
- <ApolloCartErrorAlert error={error} />
242
- </Form>
243
- )
244
- }