@graphcommerce/magento-product 4.5.10 → 4.6.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.
- package/CHANGELOG.md +31 -0
- package/components/AddProductsToCart/AddProductsToCart.graphql +13 -0
- package/components/AddProductsToCart/AddProductsToCartButton.tsx +48 -0
- package/components/AddProductsToCart/AddProductsToCartError.tsx +22 -0
- package/components/AddProductsToCart/AddProductsToCartForm.tsx +69 -0
- package/components/AddProductsToCart/AddProductsToCartIndex.tsx +3 -0
- package/components/AddProductsToCart/AddProductsToCartQuantity.tsx +25 -0
- package/components/AddProductsToCart/AddProductsToCartSnackbar.tsx +67 -0
- package/components/AddProductsToCart/index.ts +6 -0
- package/components/ProductAddToCart/ProductAddToCart.graphql +1 -1
- package/components/ProductAddToCart/index.ts +2 -0
- package/components/ProductCustomizable/ProductCustomizable.tsx +93 -0
- package/components/ProductCustomizable/index.ts +1 -0
- package/components/ProductPage/ProductPageQueryFragment.graphql +1 -0
- package/components/ProductPageGallery/ProductPageGallery.tsx +2 -2
- package/components/ProductPagePrice/index.ts +1 -0
- package/components/ProductShortDescription/ProductShortDescription.tsx +7 -1
- package/components/ProductSidebarDelivery/ProductSidebarDelivery.tsx +0 -1
- package/components/ProductStaticPaths/getProductStaticPaths.ts +2 -2
- package/components/index.ts +5 -3
- package/hooks/useProductLink.ts +14 -8
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 4.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#1660](https://github.com/graphcommerce-org/graphcommerce/pull/1660) [`48e6522bb`](https://github.com/graphcommerce-org/graphcommerce/commit/48e6522bb9424d4bd77fd77c68065f5625f3ec8d) Thanks [@paales](https://github.com/paales)! - Forward onChange handler for AddProductsToCartButton
|
|
8
|
+
|
|
9
|
+
* [#1660](https://github.com/graphcommerce-org/graphcommerce/pull/1660) [`37b1980a0`](https://github.com/graphcommerce-org/graphcommerce/commit/37b1980a04a4a3d77663b404ae83539620cf65b9) Thanks [@paales](https://github.com/paales)! - Do not static build old product pages when the new product page is used an vice versa
|
|
10
|
+
|
|
11
|
+
* Updated dependencies [[`e5048c5ec`](https://github.com/graphcommerce-org/graphcommerce/commit/e5048c5ec52b83dbe70a246ffdcea65b55a884c6)]:
|
|
12
|
+
- @graphcommerce/ecommerce-ui@1.5.1
|
|
13
|
+
- @graphcommerce/magento-cart@4.8.5
|
|
14
|
+
|
|
15
|
+
## 4.6.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- [#1642](https://github.com/graphcommerce-org/graphcommerce/pull/1642) [`ad63ebf4e`](https://github.com/graphcommerce-org/graphcommerce/commit/ad63ebf4e33bfb0e5c9e5e68ab69b14775f3f8a8) Thanks [@paales](https://github.com/paales)! - Introduced `<AddProductsToCartForm/>`, which is allows for adding all product types to the cart with a single react-hook-form form.
|
|
20
|
+
|
|
21
|
+
Which allows you to fully compose the form on the product page without having to modify the page.
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- [#1642](https://github.com/graphcommerce-org/graphcommerce/pull/1642) [`b6bf2c941`](https://github.com/graphcommerce-org/graphcommerce/commit/b6bf2c94197ddacbf8f1fc0d352cd0d46e096f30) Thanks [@paales](https://github.com/paales)! - Remove unused ProductCustomizable on the old product pages
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`ad63ebf4e`](https://github.com/graphcommerce-org/graphcommerce/commit/ad63ebf4e33bfb0e5c9e5e68ab69b14775f3f8a8), [`9e6fd498e`](https://github.com/graphcommerce-org/graphcommerce/commit/9e6fd498e3242ab30602767ae77a8e22f80d9fd3)]:
|
|
28
|
+
- @graphcommerce/ecommerce-ui@1.5.0
|
|
29
|
+
- @graphcommerce/magento-store@4.3.0
|
|
30
|
+
- @graphcommerce/next-ui@4.27.0
|
|
31
|
+
- @graphcommerce/magento-cart@4.8.4
|
|
32
|
+
- @graphcommerce/framer-scroller@2.1.39
|
|
33
|
+
|
|
3
34
|
## 4.5.10
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Button, ButtonProps } from '@graphcommerce/next-ui'
|
|
2
|
+
import { Trans } from '@lingui/react'
|
|
3
|
+
import { SxProps, Theme, useEventCallback } from '@mui/material'
|
|
4
|
+
import { useFormAddProductsToCart } from './AddProductsToCartForm'
|
|
5
|
+
|
|
6
|
+
export type AddProductsToCartButtonProps = {
|
|
7
|
+
sx?: SxProps<Theme>
|
|
8
|
+
sku: string
|
|
9
|
+
index?: number
|
|
10
|
+
} & Pick<
|
|
11
|
+
ButtonProps<'button'>,
|
|
12
|
+
| 'variant'
|
|
13
|
+
| 'color'
|
|
14
|
+
| 'size'
|
|
15
|
+
| 'disabled'
|
|
16
|
+
| 'fullWidth'
|
|
17
|
+
| 'startIcon'
|
|
18
|
+
| 'endIcon'
|
|
19
|
+
| 'onClick'
|
|
20
|
+
| 'loading'
|
|
21
|
+
>
|
|
22
|
+
|
|
23
|
+
export function AddProductsToCartButton(props: AddProductsToCartButtonProps) {
|
|
24
|
+
const { formState, setValue } = useFormAddProductsToCart()
|
|
25
|
+
const { loading, sku, index = 0, disabled, onClick } = props
|
|
26
|
+
|
|
27
|
+
const clickHandler: NonNullable<AddProductsToCartButtonProps['onClick']> = useEventCallback(
|
|
28
|
+
(e) => {
|
|
29
|
+
setValue(`cartItems.${index}.sku`, sku)
|
|
30
|
+
onClick?.(e)
|
|
31
|
+
},
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Button
|
|
36
|
+
type='submit'
|
|
37
|
+
color='primary'
|
|
38
|
+
variant='pill'
|
|
39
|
+
size='large'
|
|
40
|
+
{...props}
|
|
41
|
+
disabled={Boolean(formState.errors.cartItems?.[index].sku?.message) || disabled}
|
|
42
|
+
loading={formState.isSubmitting || loading}
|
|
43
|
+
onClick={clickHandler}
|
|
44
|
+
>
|
|
45
|
+
<Trans id='Add to Cart' />
|
|
46
|
+
</Button>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { FormHelperText } from '@mui/material'
|
|
2
|
+
import { useFormAddProductsToCart } from './AddProductsToCartForm'
|
|
3
|
+
|
|
4
|
+
type AddProductsToCartErrorProps = {
|
|
5
|
+
children?: React.ReactNode
|
|
6
|
+
index?: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function AddProductsToCartError(props: AddProductsToCartErrorProps) {
|
|
10
|
+
const { children, index = 0 } = props
|
|
11
|
+
const { formState } = useFormAddProductsToCart()
|
|
12
|
+
const errorMsg = formState.errors.cartItems?.[index].sku?.message
|
|
13
|
+
|
|
14
|
+
if (errorMsg)
|
|
15
|
+
return (
|
|
16
|
+
<FormHelperText error sx={{ mt: 0, lineHeight: '1.3' }}>
|
|
17
|
+
{errorMsg}
|
|
18
|
+
</FormHelperText>
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return <>{children}</>
|
|
22
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { UseFormGqlMutationReturn, UseFormGraphQlOptions } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { useFormGqlMutationCart } from '@graphcommerce/magento-cart'
|
|
3
|
+
import { Box, SxProps, Theme } from '@mui/material'
|
|
4
|
+
import { createContext, useContext, useMemo } from 'react'
|
|
5
|
+
import {
|
|
6
|
+
AddProductsToCartDocument,
|
|
7
|
+
AddProductsToCartMutation,
|
|
8
|
+
AddProductsToCartMutationVariables,
|
|
9
|
+
} from './AddProductsToCart.gql'
|
|
10
|
+
|
|
11
|
+
type AddProductsToCartContextType = UseFormGqlMutationReturn<
|
|
12
|
+
AddProductsToCartMutation,
|
|
13
|
+
AddProductsToCartMutationVariables
|
|
14
|
+
>
|
|
15
|
+
|
|
16
|
+
export const addProductsToCartContext = createContext(
|
|
17
|
+
undefined as AddProductsToCartContextType | undefined,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
type AddProductsToCartFormProps = {
|
|
21
|
+
children: React.ReactNode
|
|
22
|
+
sx?: SxProps<Theme>
|
|
23
|
+
} & Omit<
|
|
24
|
+
UseFormGraphQlOptions<AddProductsToCartMutation, AddProductsToCartMutationVariables>,
|
|
25
|
+
'onBeforeSubmit'
|
|
26
|
+
>
|
|
27
|
+
|
|
28
|
+
export function AddProductsToCartForm(props: AddProductsToCartFormProps) {
|
|
29
|
+
const { children, defaultValues, sx, ...formProps } = props
|
|
30
|
+
const form = useFormGqlMutationCart(AddProductsToCartDocument, {
|
|
31
|
+
defaultValues,
|
|
32
|
+
|
|
33
|
+
// We're stripping out incomplete entered options.
|
|
34
|
+
onBeforeSubmit: ({ cartId, cartItems }) => ({
|
|
35
|
+
cartId,
|
|
36
|
+
cartItems: cartItems
|
|
37
|
+
.filter((cartItem) => cartItem.sku)
|
|
38
|
+
.map((cartItem) => ({
|
|
39
|
+
...cartItem,
|
|
40
|
+
selected_options: cartItem.selected_options?.filter(Boolean),
|
|
41
|
+
entered_options: cartItem.entered_options?.filter((option) => option?.value),
|
|
42
|
+
})),
|
|
43
|
+
}),
|
|
44
|
+
...formProps,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
const submit = form.handleSubmit(() => {})
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<addProductsToCartContext.Provider value={form}>
|
|
51
|
+
<Box component='form' onSubmit={submit} noValidate sx={sx}>
|
|
52
|
+
{children}
|
|
53
|
+
</Box>
|
|
54
|
+
</addProductsToCartContext.Provider>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function useFormAddProductsToCart(optional: true): AddProductsToCartContextType | undefined
|
|
59
|
+
export function useFormAddProductsToCart(optional?: false): AddProductsToCartContextType
|
|
60
|
+
export function useFormAddProductsToCart(optional = false) {
|
|
61
|
+
const context = useContext(addProductsToCartContext)
|
|
62
|
+
|
|
63
|
+
if (!optional && typeof context === 'undefined') {
|
|
64
|
+
throw Error(
|
|
65
|
+
'useFormAddProductsToCart must be used within a AddProductsToCartForm or provide the optional=true argument',
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
return context
|
|
69
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { NumberFieldElement, NumberFieldElementProps } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { useFormAddProductsToCart } from './AddProductsToCartForm'
|
|
3
|
+
|
|
4
|
+
type AddToCartQuantityProps = Omit<
|
|
5
|
+
NumberFieldElementProps,
|
|
6
|
+
'error' | 'required' | 'inputProps' | 'helperText' | 'name' | 'control' | 'name'
|
|
7
|
+
> & { index?: number }
|
|
8
|
+
|
|
9
|
+
export function AddProductsToCartQuantity(props: AddToCartQuantityProps) {
|
|
10
|
+
const { index = 0 } = props
|
|
11
|
+
const { control } = useFormAddProductsToCart()
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<NumberFieldElement
|
|
15
|
+
variant='outlined'
|
|
16
|
+
size='small'
|
|
17
|
+
{...props}
|
|
18
|
+
required
|
|
19
|
+
inputProps={{ min: 1 }}
|
|
20
|
+
defaultValue={1}
|
|
21
|
+
control={control}
|
|
22
|
+
name={`cartItems.${index}.quantity`}
|
|
23
|
+
/>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ApolloCartErrorSnackbar } from '@graphcommerce/magento-cart'
|
|
2
|
+
import {
|
|
3
|
+
Button,
|
|
4
|
+
iconChevronRight,
|
|
5
|
+
IconSvg,
|
|
6
|
+
MessageSnackbar,
|
|
7
|
+
ErrorSnackbar,
|
|
8
|
+
} from '@graphcommerce/next-ui'
|
|
9
|
+
import { Trans } from '@lingui/react'
|
|
10
|
+
import PageLink from 'next/link'
|
|
11
|
+
import { useFormAddProductsToCart } from './AddProductsToCartForm'
|
|
12
|
+
|
|
13
|
+
type AddToCartMessageProps = { name?: string | null }
|
|
14
|
+
|
|
15
|
+
export function AddProductsToCartSnackbar(props: AddToCartMessageProps) {
|
|
16
|
+
const { name } = props
|
|
17
|
+
const { formState, error, data } = useFormAddProductsToCart()
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<ApolloCartErrorSnackbar error={error} />
|
|
22
|
+
|
|
23
|
+
<ErrorSnackbar
|
|
24
|
+
variant='pill'
|
|
25
|
+
severity='error'
|
|
26
|
+
open={(data?.addProductsToCart?.user_errors?.length ?? 0) > 0}
|
|
27
|
+
action={
|
|
28
|
+
<Button size='medium' variant='pill' color='secondary'>
|
|
29
|
+
<Trans id='Ok' />
|
|
30
|
+
</Button>
|
|
31
|
+
}
|
|
32
|
+
>
|
|
33
|
+
<>{data?.addProductsToCart?.user_errors?.map((e) => e?.message).join(', ')}</>
|
|
34
|
+
</ErrorSnackbar>
|
|
35
|
+
|
|
36
|
+
<MessageSnackbar
|
|
37
|
+
open={
|
|
38
|
+
!formState.isSubmitting &&
|
|
39
|
+
formState.isSubmitSuccessful &&
|
|
40
|
+
!error?.message &&
|
|
41
|
+
!data?.addProductsToCart?.user_errors?.length
|
|
42
|
+
}
|
|
43
|
+
variant='pill'
|
|
44
|
+
action={
|
|
45
|
+
<PageLink href='/cart' passHref>
|
|
46
|
+
<Button
|
|
47
|
+
id='view-shopping-cart-button'
|
|
48
|
+
size='medium'
|
|
49
|
+
variant='pill'
|
|
50
|
+
color='secondary'
|
|
51
|
+
endIcon={<IconSvg src={iconChevronRight} />}
|
|
52
|
+
sx={{ display: 'flex' }}
|
|
53
|
+
>
|
|
54
|
+
<Trans id='View shopping cart' />
|
|
55
|
+
</Button>
|
|
56
|
+
</PageLink>
|
|
57
|
+
}
|
|
58
|
+
>
|
|
59
|
+
<Trans
|
|
60
|
+
id='<0>{name}</0> has been added to your shopping cart!'
|
|
61
|
+
components={{ 0: <strong /> }}
|
|
62
|
+
values={{ name }}
|
|
63
|
+
/>
|
|
64
|
+
</MessageSnackbar>
|
|
65
|
+
</>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { SelectElement, TextFieldElement } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { filterNonNullableKeys, RenderType, TypeRenderer } from '@graphcommerce/next-ui'
|
|
3
|
+
import { useFormAddProductsToCart } from '../AddProductsToCart'
|
|
4
|
+
import { ProductCustomizableFragment } from './ProductCustomizable.gql'
|
|
5
|
+
|
|
6
|
+
type OptionTypeRenderer = TypeRenderer<
|
|
7
|
+
NonNullable<NonNullable<ProductCustomizableFragment['options']>[number]> & {
|
|
8
|
+
optionIndex: number
|
|
9
|
+
index: number
|
|
10
|
+
}
|
|
11
|
+
>
|
|
12
|
+
|
|
13
|
+
const CustomizableAreaOption: OptionTypeRenderer['CustomizableAreaOption'] = (props) => {
|
|
14
|
+
const { uid, areaValue, required, optionIndex, index, title } = props
|
|
15
|
+
const maxLength = areaValue?.max_characters ?? undefined
|
|
16
|
+
const { control, register } = useFormAddProductsToCart()
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<>
|
|
20
|
+
<input
|
|
21
|
+
type='hidden'
|
|
22
|
+
{...register(`cartItems.${index}.entered_options.${optionIndex}.uid`)}
|
|
23
|
+
value={uid}
|
|
24
|
+
/>
|
|
25
|
+
<TextFieldElement
|
|
26
|
+
multiline
|
|
27
|
+
minRows={3}
|
|
28
|
+
control={control}
|
|
29
|
+
name={`cartItems.${index}.entered_options.${optionIndex}.value`}
|
|
30
|
+
label={title}
|
|
31
|
+
required={Boolean(required)}
|
|
32
|
+
validation={{ maxLength }}
|
|
33
|
+
helperText={(maxLength ?? 0) > 0 && `A maximum of ${maxLength}`}
|
|
34
|
+
/>
|
|
35
|
+
</>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const CustomizableDropDownOption: OptionTypeRenderer['CustomizableDropDownOption'] = (props) => {
|
|
40
|
+
const { uid, required, optionIndex, index, title, dropdownValue } = props
|
|
41
|
+
const { control, register } = useFormAddProductsToCart()
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<input
|
|
46
|
+
type='hidden'
|
|
47
|
+
{...register(`cartItems.${index}.entered_options.${optionIndex}.uid`)}
|
|
48
|
+
value={uid}
|
|
49
|
+
/>
|
|
50
|
+
<SelectElement
|
|
51
|
+
control={control}
|
|
52
|
+
name={`cartItems.${index}.entered_options.${optionIndex}.value`}
|
|
53
|
+
label={title}
|
|
54
|
+
required={Boolean(required)}
|
|
55
|
+
options={filterNonNullableKeys(dropdownValue, ['title']).map((option) => ({
|
|
56
|
+
id: option.uid,
|
|
57
|
+
label: option.title,
|
|
58
|
+
}))}
|
|
59
|
+
/>
|
|
60
|
+
</>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const renderer: OptionTypeRenderer = {
|
|
65
|
+
CustomizableAreaOption,
|
|
66
|
+
CustomizableCheckboxOption: () => <div>checkbox not implemented</div>,
|
|
67
|
+
CustomizableDateOption: () => <div>date not implemented</div>,
|
|
68
|
+
CustomizableDropDownOption,
|
|
69
|
+
CustomizableFieldOption: () => <div>field not implemented</div>,
|
|
70
|
+
CustomizableFileOption: () => <div>file not implemented</div>,
|
|
71
|
+
CustomizableMultipleOption: () => <div>multi not implemented</div>,
|
|
72
|
+
CustomizableRadioOption: () => <div>radios not implemented</div>,
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
type ProductCustomizableProps = { product: ProductCustomizableFragment; index?: number }
|
|
76
|
+
|
|
77
|
+
export function ProductCustomizable(props: ProductCustomizableProps) {
|
|
78
|
+
const { product, index = 0 } = props
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<>
|
|
82
|
+
{filterNonNullableKeys(product.options, ['sort_order']).map((option) => (
|
|
83
|
+
<RenderType
|
|
84
|
+
key={option.uid}
|
|
85
|
+
renderer={renderer}
|
|
86
|
+
{...option}
|
|
87
|
+
optionIndex={option.sort_order - 1}
|
|
88
|
+
index={index}
|
|
89
|
+
/>
|
|
90
|
+
))}
|
|
91
|
+
</>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ProductCustomizable'
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { SidebarGallery, SidebarGalleryProps, TypeRenderer } from '@graphcommerce/next-ui'
|
|
2
|
-
import
|
|
2
|
+
import { PropsWithChildren } from 'react'
|
|
3
3
|
import { ProductPageGalleryFragment } from './ProductPageGallery.gql'
|
|
4
4
|
|
|
5
5
|
export type ProductPageGalleryRenderers = TypeRenderer<
|
|
6
6
|
NonNullable<NonNullable<ProductPageGalleryFragment['media_gallery']>[0]>
|
|
7
7
|
>
|
|
8
8
|
|
|
9
|
-
type ProductPageGalleryProps = PropsWithChildren<ProductPageGalleryFragment> &
|
|
9
|
+
export type ProductPageGalleryProps = PropsWithChildren<ProductPageGalleryFragment> &
|
|
10
10
|
Omit<SidebarGalleryProps, 'sidebar' | 'images'>
|
|
11
11
|
|
|
12
12
|
export function ProductPageGallery(props: ProductPageGalleryProps) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './ProductPagePrice.gql'
|
|
@@ -15,7 +15,13 @@ export function ProductShortDescription(props: ProductShortDescriptionProps) {
|
|
|
15
15
|
component='div'
|
|
16
16
|
className={classes.description}
|
|
17
17
|
dangerouslySetInnerHTML={{ __html: short_description?.html ?? '' }}
|
|
18
|
-
sx={[
|
|
18
|
+
sx={[
|
|
19
|
+
{
|
|
20
|
+
'& > p:first-of-type': { marginTop: 0 },
|
|
21
|
+
'& > p:last-of-type': { marginBottom: 0 },
|
|
22
|
+
},
|
|
23
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
24
|
+
]}
|
|
19
25
|
/>
|
|
20
26
|
)
|
|
21
27
|
}
|
|
@@ -11,7 +11,7 @@ export type ProductTypenames = NonNullable<
|
|
|
11
11
|
export async function getProductStaticPaths(
|
|
12
12
|
client: ApolloClient<NormalizedCacheObject>,
|
|
13
13
|
locale: string,
|
|
14
|
-
typename
|
|
14
|
+
typename?: ProductTypenames,
|
|
15
15
|
) {
|
|
16
16
|
const query = client.query({
|
|
17
17
|
query: ProductStaticPathsDocument,
|
|
@@ -25,7 +25,7 @@ export async function getProductStaticPaths(
|
|
|
25
25
|
const paths: Return['paths'] = (await Promise.all(pages))
|
|
26
26
|
.map((q) => q.data.products?.items)
|
|
27
27
|
.flat(1)
|
|
28
|
-
.filter((item) => item?.__typename === typename)
|
|
28
|
+
.filter((item) => (typename ? item?.__typename === typename : true))
|
|
29
29
|
.map((p) => ({ params: { url: `${p?.url_key}` }, locale }))
|
|
30
30
|
|
|
31
31
|
return process.env.VERCEL_ENV !== 'production' ? paths.slice(0, 1) : paths
|
package/components/index.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
+
export * from './AddProductsToCart'
|
|
1
2
|
export * from './JsonLdProduct/jsonLdProduct'
|
|
2
|
-
export * from './ProductAddToCart
|
|
3
|
-
export * from './ProductAddToCart/ProductAddToCart.gql'
|
|
3
|
+
export * from './ProductAddToCart'
|
|
4
4
|
export * from './ProductList/ProductList.gql'
|
|
5
5
|
export * from './ProductListCount/ProductListCount'
|
|
6
6
|
export * from './ProductListFilters/ProductFilters.gql'
|
|
7
7
|
export * from './ProductListFilters/ProductListFilters'
|
|
8
8
|
export * from './ProductListFiltersContainer/ProductListFiltersContainer'
|
|
9
9
|
export * from './ProductListItem/ProductListItem'
|
|
10
|
-
export * from './ProductListItems/ProductListItems'
|
|
11
10
|
export * from './ProductListItems/filteredProductList'
|
|
12
11
|
export * from './ProductListItems/filterTypes'
|
|
13
12
|
export * from './ProductListItems/getFilterTypes'
|
|
13
|
+
export * from './ProductListItems/ProductListItems'
|
|
14
14
|
export * from './ProductListItems/ProductListItems.gql'
|
|
15
15
|
export * from './ProductListItems/ProductListItemsBase'
|
|
16
16
|
export * from './ProductListItems/ProductListParamsProvider'
|
|
@@ -22,6 +22,7 @@ export * from './ProductPageCategory/productPageCategory'
|
|
|
22
22
|
export * from './ProductPageDescription/ProductPageDescription'
|
|
23
23
|
export * from './ProductPageGallery/ProductPageGallery'
|
|
24
24
|
export * from './ProductPageMeta/ProductPageMeta'
|
|
25
|
+
export * from './ProductPagePrice'
|
|
25
26
|
export * from './ProductRelated/RelatedProducts.gql'
|
|
26
27
|
export * from './ProductShortDescription/ProductShortDescription'
|
|
27
28
|
export * from './ProductShortDescription/ProductShortDescription.gql'
|
|
@@ -30,3 +31,4 @@ export * from './ProductSpecs/ProductSpecs'
|
|
|
30
31
|
export * from './ProductStaticPaths/getProductStaticPaths'
|
|
31
32
|
export * from './ProductUpsells/UpsellProducts.gql'
|
|
32
33
|
export * from './ProductWeight/ProductWeight'
|
|
34
|
+
export * from './ProductCustomizable'
|
package/hooks/useProductLink.ts
CHANGED
|
@@ -3,16 +3,22 @@ import { ProductLinkFragment } from './ProductLink.gql'
|
|
|
3
3
|
export type ProductLinkProps = Omit<ProductLinkFragment, 'uid'>
|
|
4
4
|
|
|
5
5
|
export function productLink(link: ProductLinkProps) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
.split(/(?=[A-Z])/)
|
|
9
|
-
.map((s) => s.toLowerCase())
|
|
10
|
-
.reverse()
|
|
6
|
+
if (process.env.NEXT_PUBLIC_SINGLE_PRODUCT_PAGE !== '1') {
|
|
7
|
+
const { __typename, url_key } = link
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const productRoute = __typename
|
|
10
|
+
.split(/(?=[A-Z])/)
|
|
11
|
+
.map((s) => s.toLowerCase())
|
|
12
|
+
.reverse()
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
if (__typename === 'SimpleProduct')
|
|
15
|
+
// For Simple and Virtual products we're not navigating to a type specific page
|
|
16
|
+
productRoute.splice(1, 1)
|
|
17
|
+
|
|
18
|
+
return `/${productRoute.join('/')}/${url_key}`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return `/p/${link.url_key}`
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
export function useProductLink(props: ProductLinkProps) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/magento-product",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.6.1",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -19,13 +19,14 @@
|
|
|
19
19
|
"type-fest": "^2.12.2"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@graphcommerce/
|
|
22
|
+
"@graphcommerce/ecommerce-ui": "1.5.1",
|
|
23
|
+
"@graphcommerce/framer-scroller": "2.1.39",
|
|
23
24
|
"@graphcommerce/graphql": "3.4.8",
|
|
24
25
|
"@graphcommerce/graphql-mesh": "4.2.0",
|
|
25
26
|
"@graphcommerce/image": "3.1.9",
|
|
26
|
-
"@graphcommerce/magento-cart": "4.8.
|
|
27
|
-
"@graphcommerce/magento-store": "4.
|
|
28
|
-
"@graphcommerce/next-ui": "4.
|
|
27
|
+
"@graphcommerce/magento-cart": "4.8.5",
|
|
28
|
+
"@graphcommerce/magento-store": "4.3.0",
|
|
29
|
+
"@graphcommerce/next-ui": "4.27.0",
|
|
29
30
|
"schema-dts": "^1.1.0"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|