@jetshop/template-trend 5.12.3 → 5.13.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/.linaria-cache/packages/template-trend/src/components/Layout/Header/Logo.linaria.css +1 -1
- package/.linaria-cache/packages/ui/Pagination/usePagination.linaria.css +1 -0
- package/.vscode/launch.json +11 -0
- package/package.json +5 -5
- package/schema.graphql +76 -0
- package/src/components/Cart/CartFlyout.js +5 -1
- package/src/components/CategoryPage/ProductGrid.js +2 -0
- package/src/components/Forms/Success.js +1 -1
- package/src/components/Layout/Header/Logo.js +17 -3
- package/src/components/Layout/Header/NorceLogo.svg +1 -0
- package/src/components/MyPages/ChangePasswordPage.js +1 -0
- package/src/components/ProductList/Product.js +5 -1
- package/src/components/ProductPage/AddToCart/AddToCartForm.js +2 -4
- package/src/components/ProductPage/AddToCart/ProductToast.js +7 -6
- package/src/components/ProductPage/AddToCart/useProductToast.js +26 -0
- package/src/components/ProductPage/ProductPage.js +6 -2
- package/src/shop.config.js +2 -1
package/.linaria-cache/packages/template-trend/src/components/Layout/Header/Logo.linaria.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.StoreName_sgyktyw{font-size:30px;font-weight:bold;line-height:normal;text-align:center;-webkit-text-decoration:none;text-decoration:none;color:inherit;}.StoreName_sgyktyw a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-text-decoration:none;text-decoration:none;color:inherit;}
|
|
1
|
+
.StoreName_sgyktyw{font-size:30px;font-weight:bold;line-height:normal;text-align:center;-webkit-text-decoration:none;text-decoration:none;color:inherit;}.StoreName_sgyktyw a{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;-webkit-text-decoration:none;text-decoration:none;color:inherit;}.StoreName_sgyktyw a svg{width:100px;}@media (max-width:49.99rem){.StoreName_sgyktyw a svg{width:85px;}}.StoreName_sgyktyw a span{font-size:12px;text-transform:uppercase;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.PaginationWrapper_p1arddu{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetshop/template-trend",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.13.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "react-scripts build",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
]
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@jetshop/core": "^5.
|
|
48
|
+
"@jetshop/core": "^5.13.1",
|
|
49
49
|
"@jetshop/flight-shortcodes": "^2.0.10",
|
|
50
|
-
"@jetshop/intl": "^5.
|
|
51
|
-
"@jetshop/react-scripts": "^5.
|
|
52
|
-
"@jetshop/ui": "^5.
|
|
50
|
+
"@jetshop/intl": "^5.13.1",
|
|
51
|
+
"@jetshop/react-scripts": "^5.13.1",
|
|
52
|
+
"@jetshop/ui": "^5.13.1",
|
|
53
53
|
"@react-google-maps/api": "~1.7.0",
|
|
54
54
|
"prop-types": "^15.6.2",
|
|
55
55
|
"react": "^16.9.0",
|
package/schema.graphql
CHANGED
|
@@ -213,6 +213,12 @@ type Category implements Document {
|
|
|
213
213
|
"""
|
|
214
214
|
isDynamic: Boolean!
|
|
215
215
|
|
|
216
|
+
"""
|
|
217
|
+
The category's dynamic filtersNB: Carries a performance cost, as asking for
|
|
218
|
+
this will result in a separate API call in the backend.
|
|
219
|
+
"""
|
|
220
|
+
dynamicFiltering: [CategoryDynamicFilter]
|
|
221
|
+
|
|
216
222
|
"""
|
|
217
223
|
Get content data set via the Content Editor.NB: Carries a performance cost, as
|
|
218
224
|
asking for this will result in a separate API call in the backend.
|
|
@@ -229,6 +235,13 @@ type CategoryAutoCompleteResult {
|
|
|
229
235
|
result: [Category]
|
|
230
236
|
}
|
|
231
237
|
|
|
238
|
+
type CategoryDynamicFilter {
|
|
239
|
+
type: String
|
|
240
|
+
value: CategoryDynamicFilterValue
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
union CategoryDynamicFilterValue = StringValue | ListStringValue | BoolValue
|
|
244
|
+
|
|
232
245
|
type CategoryImage {
|
|
233
246
|
width: Int
|
|
234
247
|
height: Int
|
|
@@ -624,6 +637,11 @@ input CustomerUpdateDeliveryAddressInput {
|
|
|
624
637
|
addressName: String
|
|
625
638
|
}
|
|
626
639
|
|
|
640
|
+
input CustomerUpdateExternalAttribute {
|
|
641
|
+
name: String!
|
|
642
|
+
value: String!
|
|
643
|
+
}
|
|
644
|
+
|
|
627
645
|
input CustomerUpdateInput {
|
|
628
646
|
pid: String
|
|
629
647
|
organizationNumber: String
|
|
@@ -631,6 +649,7 @@ input CustomerUpdateInput {
|
|
|
631
649
|
deliveryAddresses: [CustomerUpdateDeliveryAddressInput]
|
|
632
650
|
preferences: CustomerUpdatePreferenceInput
|
|
633
651
|
consents: [CustomerUpdateConsentInput]
|
|
652
|
+
externalAttributes: [CustomerUpdateExternalAttribute]
|
|
634
653
|
dynamicContent: String
|
|
635
654
|
}
|
|
636
655
|
|
|
@@ -853,6 +872,10 @@ type ListFilterItem {
|
|
|
853
872
|
resultCount: Int
|
|
854
873
|
}
|
|
855
874
|
|
|
875
|
+
type ListStringValue {
|
|
876
|
+
value: [String]
|
|
877
|
+
}
|
|
878
|
+
|
|
856
879
|
input LoginExternalCustomerInput {
|
|
857
880
|
externalCustomerToken: String!
|
|
858
881
|
}
|
|
@@ -1051,6 +1074,24 @@ type Mutation {
|
|
|
1051
1074
|
"""
|
|
1052
1075
|
signUp(input: SignUpInput!): SignUpResponse
|
|
1053
1076
|
|
|
1077
|
+
"""
|
|
1078
|
+
## Description
|
|
1079
|
+
This mutation's purpose is to update a existing customer's group using an
|
|
1080
|
+
access code. An authorization token is needed in the request, in order to be
|
|
1081
|
+
able to update the customer.
|
|
1082
|
+
## Error Codes
|
|
1083
|
+
### Unauthorized
|
|
1084
|
+
Unauthorized
|
|
1085
|
+
### UnableToUpdateCustomer
|
|
1086
|
+
Error in underlying API call, more info may be contained in the error message.
|
|
1087
|
+
### CustomerAlreadyUpdated
|
|
1088
|
+
Customer already in the customer group
|
|
1089
|
+
### CustomerNotFound
|
|
1090
|
+
No match on customer with access code
|
|
1091
|
+
|
|
1092
|
+
"""
|
|
1093
|
+
updateCustomerGroup(customerGroupAccessCode: String!): UpdateCustomerGroupResult
|
|
1094
|
+
|
|
1054
1095
|
"""
|
|
1055
1096
|
This mutation's purpose is to update a existing customer's information. An
|
|
1056
1097
|
authorization token is needed in the request, in order to be able to update the customer.
|
|
@@ -1400,6 +1441,11 @@ type Price {
|
|
|
1400
1441
|
vat: Decimal!
|
|
1401
1442
|
}
|
|
1402
1443
|
|
|
1444
|
+
type PriceHistory {
|
|
1445
|
+
timestamp: DateTime
|
|
1446
|
+
price: Price
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1403
1449
|
type PrivateCustomer implements Customer {
|
|
1404
1450
|
pid: String
|
|
1405
1451
|
id: ID!
|
|
@@ -1610,6 +1656,12 @@ type Product implements Document {
|
|
|
1610
1656
|
performance cost, as asking for this will result in a separate API call in the backend.
|
|
1611
1657
|
"""
|
|
1612
1658
|
familyMembers: [Product!]
|
|
1659
|
+
|
|
1660
|
+
"""Get Product History within the set number of days"""
|
|
1661
|
+
history(
|
|
1662
|
+
"""number of days, default is 30"""
|
|
1663
|
+
days: Int = 30
|
|
1664
|
+
): ProductHistory
|
|
1613
1665
|
}
|
|
1614
1666
|
|
|
1615
1667
|
type ProductAutoCompleteResult {
|
|
@@ -1698,6 +1750,10 @@ enum ProductCustomFieldType {
|
|
|
1698
1750
|
MULTI_LEVEL_LIST
|
|
1699
1751
|
}
|
|
1700
1752
|
|
|
1753
|
+
type ProductHistory {
|
|
1754
|
+
previousPrice: [PriceHistory]
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1701
1757
|
type ProductImage {
|
|
1702
1758
|
"""
|
|
1703
1759
|
Alternate text for the image, commonly used for the alt attribute of img-tags.
|
|
@@ -1798,6 +1854,16 @@ type ProductVariant {
|
|
|
1798
1854
|
warehouseStock(includeInactive: Boolean = false): [Warehouse]
|
|
1799
1855
|
images: [ProductImage]
|
|
1800
1856
|
barcode: String
|
|
1857
|
+
|
|
1858
|
+
"""Get Product History within the set number of days"""
|
|
1859
|
+
history(
|
|
1860
|
+
"""number of days, default is 30"""
|
|
1861
|
+
days: Int = 30
|
|
1862
|
+
): ProductVariantHistory
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
type ProductVariantHistory {
|
|
1866
|
+
previousPrice: [PriceHistory]
|
|
1801
1867
|
}
|
|
1802
1868
|
|
|
1803
1869
|
type ProductVariantOption {
|
|
@@ -2061,6 +2127,11 @@ input SignUpDeliveryAddressInput {
|
|
|
2061
2127
|
addressName: String
|
|
2062
2128
|
}
|
|
2063
2129
|
|
|
2130
|
+
input SignUpExternalAttribute {
|
|
2131
|
+
name: String!
|
|
2132
|
+
value: String!
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2064
2135
|
input SignUpInput {
|
|
2065
2136
|
type: CustomerType!
|
|
2066
2137
|
pid: String
|
|
@@ -2074,6 +2145,7 @@ input SignUpInput {
|
|
|
2074
2145
|
deliveryAddresses: [SignUpDeliveryAddressInput]
|
|
2075
2146
|
preferences: SignUpPreferencesInput
|
|
2076
2147
|
consents: [SignUpConsentInput]
|
|
2148
|
+
externalAttributes: [SignUpExternalAttribute]
|
|
2077
2149
|
dynamicContent: String
|
|
2078
2150
|
priceListAccessCode: String
|
|
2079
2151
|
}
|
|
@@ -2208,6 +2280,10 @@ type UpdateCartMutation {
|
|
|
2208
2280
|
cart: Cart
|
|
2209
2281
|
}
|
|
2210
2282
|
|
|
2283
|
+
type UpdateCustomerGroupResult {
|
|
2284
|
+
success: Boolean!
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2211
2287
|
type UpdateCustomerPriceListResult {
|
|
2212
2288
|
success: Boolean!
|
|
2213
2289
|
}
|
|
@@ -198,7 +198,11 @@ const CartFlyoutView = ({ result, modal, ...rest }) => {
|
|
|
198
198
|
return (
|
|
199
199
|
<Flex key={discount.name} style={{ marginTop: '1em' }}>
|
|
200
200
|
<label>{discount.name}</label>
|
|
201
|
-
<Price
|
|
201
|
+
<Price
|
|
202
|
+
price={discount.value}
|
|
203
|
+
style={{ display: 'inline' }}
|
|
204
|
+
negative
|
|
205
|
+
/>
|
|
202
206
|
</Flex>
|
|
203
207
|
);
|
|
204
208
|
})}
|
|
@@ -61,6 +61,7 @@ export function ProductGrid({
|
|
|
61
61
|
category = '',
|
|
62
62
|
loading,
|
|
63
63
|
className,
|
|
64
|
+
categoryPath,
|
|
64
65
|
...rest
|
|
65
66
|
}) {
|
|
66
67
|
const track = useTracker();
|
|
@@ -86,6 +87,7 @@ export function ProductGrid({
|
|
|
86
87
|
product={product}
|
|
87
88
|
style={{ opacity: loading ? 0.5 : 1 }}
|
|
88
89
|
list={listName}
|
|
90
|
+
categoryPath={categoryPath}
|
|
89
91
|
loadImageEagerly={isAboveFold(index)}
|
|
90
92
|
{...rest}
|
|
91
93
|
>
|
|
@@ -2,7 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { Link } from 'react-router-dom';
|
|
3
3
|
import { Below } from '@jetshop/ui/Breakpoints';
|
|
4
4
|
import { styled } from 'linaria/react';
|
|
5
|
-
import
|
|
5
|
+
import { ReactComponent as NorceLogo } from './NorceLogo.svg';
|
|
6
|
+
import { theme } from '../../Theme';
|
|
6
7
|
|
|
7
8
|
const StoreName = styled('h2')`
|
|
8
9
|
font-size: 30px;
|
|
@@ -14,8 +15,19 @@ const StoreName = styled('h2')`
|
|
|
14
15
|
a {
|
|
15
16
|
display: flex;
|
|
16
17
|
align-items: center;
|
|
18
|
+
flex-direction: column;
|
|
17
19
|
text-decoration: none;
|
|
18
20
|
color: inherit;
|
|
21
|
+
svg {
|
|
22
|
+
width: 100px;
|
|
23
|
+
${theme.below.md} {
|
|
24
|
+
width: 85px;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
span {
|
|
28
|
+
font-size: 12px;
|
|
29
|
+
text-transform: uppercase;
|
|
30
|
+
}
|
|
19
31
|
}
|
|
20
32
|
`;
|
|
21
33
|
|
|
@@ -27,7 +39,8 @@ const Logo = ({ searchOpen }) => (
|
|
|
27
39
|
{!searchOpen && (
|
|
28
40
|
<StoreName>
|
|
29
41
|
<Link to="/">
|
|
30
|
-
<
|
|
42
|
+
<NorceLogo />
|
|
43
|
+
<span>Storefront</span>
|
|
31
44
|
</Link>
|
|
32
45
|
</StoreName>
|
|
33
46
|
)}
|
|
@@ -35,7 +48,8 @@ const Logo = ({ searchOpen }) => (
|
|
|
35
48
|
) : (
|
|
36
49
|
<StoreName>
|
|
37
50
|
<Link to="/">
|
|
38
|
-
<
|
|
51
|
+
<NorceLogo />
|
|
52
|
+
<span>Storefront</span>
|
|
39
53
|
</Link>
|
|
40
54
|
</StoreName>
|
|
41
55
|
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 515.3 102.8"><defs><style>.a{fill:#10141d;}</style></defs><path class="a" d="M466.13,100.83a28.63,28.63,0,0,0,28.3,22.9c10.2,0,18.4-3.2,22.7-9.6h26.3c-6.8,18.2-26.3,30.5-48.9,30.5A50.94,50.94,0,0,1,443,93.33c0-28.4,22.3-51.4,50.8-51.4s50.9,22.9,50.9,51.3a46.8,46.8,0,0,1-.6,7.6Zm1-19.6h53.3c-3.2-10.4-14-18.8-26.7-18.8S470.33,70.73,467.13,81.23Z" transform="translate(-29.43 -41.83)"/><path class="a" d="M126.43,140.63h-22V90.33a26.5,26.5,0,1,0-53,0v50.3h-22V90.33a48.5,48.5,0,1,1,97,0Z" transform="translate(-29.43 -41.83)"/><path class="a" d="M286.63,140.53h-22V91.63a48.61,48.61,0,0,1,48.5-48.5v22a26.55,26.55,0,0,0-26.5,26.5Z" transform="translate(-29.43 -41.83)"/><path class="a" d="M409,100.83c-2.9,13.8-13.8,22.8-28.3,22.8-17.2,0-28.8-12.4-28.8-30.5s11.6-30.5,28.8-30.5a26.77,26.77,0,0,1,20.4,9L417.33,57c-9.2-9.4-21-15.2-36.7-15.2-29.5,0-51.3,21.8-51.3,51.3s21.8,51.3,51.3,51.3c26.5,0,47.1-18.3,50.6-43.6Z" transform="translate(-29.43 -41.83)"/><path class="a" d="M242.43,140.63h-94.2v-95h94.2Zm-73.2-21h52.2v-53h-52.2v53Z" transform="translate(-29.43 -41.83)"/></svg>
|
|
@@ -10,7 +10,11 @@ import { useProductList } from '@jetshop/core/hooks/ProductList';
|
|
|
10
10
|
export function Product({ product, loading, children, listId }) {
|
|
11
11
|
// Use the variant's image for display
|
|
12
12
|
const productForDisplay = { ...product };
|
|
13
|
-
if (
|
|
13
|
+
if (
|
|
14
|
+
product.isVariant &&
|
|
15
|
+
product.variant.images &&
|
|
16
|
+
product.variant.images.length > 0
|
|
17
|
+
) {
|
|
14
18
|
productForDisplay.images = product.variant.images;
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -75,13 +75,12 @@ function AddToCartForm({
|
|
|
75
75
|
});
|
|
76
76
|
const [trigger, dismiss] = useNotification();
|
|
77
77
|
|
|
78
|
-
const onAddToCartInit = ({ mutationId, quantity
|
|
78
|
+
const onAddToCartInit = ({ mutationId, quantity }) => {
|
|
79
79
|
trigger(
|
|
80
80
|
<ProductToastWrapper
|
|
81
81
|
selectedVariation={variant}
|
|
82
82
|
product={product}
|
|
83
83
|
quantity={quantity}
|
|
84
|
-
price={price}
|
|
85
84
|
/>,
|
|
86
85
|
{
|
|
87
86
|
id: mutationId,
|
|
@@ -90,7 +89,7 @@ function AddToCartForm({
|
|
|
90
89
|
);
|
|
91
90
|
};
|
|
92
91
|
const onAddToCartError = () => {
|
|
93
|
-
return ({ mutationId, quantity,
|
|
92
|
+
return ({ mutationId, quantity, error }) => {
|
|
94
93
|
dismiss(mutationId);
|
|
95
94
|
|
|
96
95
|
trigger(
|
|
@@ -98,7 +97,6 @@ function AddToCartForm({
|
|
|
98
97
|
selectedVariation={variant}
|
|
99
98
|
product={product}
|
|
100
99
|
quantity={quantity}
|
|
101
|
-
price={price}
|
|
102
100
|
error={error}
|
|
103
101
|
/>,
|
|
104
102
|
{
|
|
@@ -8,6 +8,7 @@ import CartProvider from '@jetshop/core/components/Query/CartProvider';
|
|
|
8
8
|
import t from '@jetshop/intl';
|
|
9
9
|
import Image from '@jetshop/ui/Image/Image';
|
|
10
10
|
import { Price } from '@jetshop/ui/Price';
|
|
11
|
+
import useProductToast from './useProductToast';
|
|
11
12
|
|
|
12
13
|
import { baseStyles } from '../../ui/Button';
|
|
13
14
|
import { theme } from '../../Theme';
|
|
@@ -86,14 +87,16 @@ const Error = styled('p')`
|
|
|
86
87
|
const ProductToast = ({
|
|
87
88
|
product,
|
|
88
89
|
cart,
|
|
89
|
-
closeToast,
|
|
90
90
|
selectedVariation,
|
|
91
91
|
quantity,
|
|
92
|
-
price,
|
|
93
92
|
error
|
|
94
93
|
}) => {
|
|
94
|
+
const { price, previousPrice, image } = useProductToast({
|
|
95
|
+
product,
|
|
96
|
+
selectedVariation,
|
|
97
|
+
quantity
|
|
98
|
+
});
|
|
95
99
|
const track = useTracker();
|
|
96
|
-
const image = selectedVariation?.images[0] || product.images[0];
|
|
97
100
|
return (
|
|
98
101
|
<Container data-testid="product-toast">
|
|
99
102
|
<ProductCheckoutContainer>
|
|
@@ -120,9 +123,7 @@ const ProductToast = ({
|
|
|
120
123
|
</Header>
|
|
121
124
|
)}
|
|
122
125
|
<ProductName>{product.name}</ProductName>
|
|
123
|
-
{!error &&
|
|
124
|
-
<Price price={price.price} previousPrice={price.previousPrice} />
|
|
125
|
-
)}
|
|
126
|
+
{!error && <Price price={price} previousPrice={previousPrice} />}
|
|
126
127
|
{error && (
|
|
127
128
|
<Error>
|
|
128
129
|
{t('An error occurred. Details:')}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
function useProductToast({ product, selectedVariation, quantity }) {
|
|
2
|
+
let image, price, previousPrice;
|
|
3
|
+
|
|
4
|
+
const toastProduct = selectedVariation || product;
|
|
5
|
+
|
|
6
|
+
// Calculating the price by mutliplying with quantity
|
|
7
|
+
price = calculatePrice(toastProduct.price, quantity);
|
|
8
|
+
previousPrice = calculatePrice(toastProduct.previousPrice, quantity);
|
|
9
|
+
|
|
10
|
+
image = selectedVariation?.images[0] || product.images[0];
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
price,
|
|
14
|
+
previousPrice,
|
|
15
|
+
image
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function calculatePrice(price, quantity) {
|
|
20
|
+
const incVat = price.incVat * quantity;
|
|
21
|
+
const exVat = price.exVat * quantity;
|
|
22
|
+
const vat = price.vat * quantity;
|
|
23
|
+
return { incVat, exVat, vat };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default useProductToast;
|
|
@@ -120,7 +120,7 @@ const ProductContainer = styled('div')`
|
|
|
120
120
|
}
|
|
121
121
|
`;
|
|
122
122
|
|
|
123
|
-
const Product = ({ result: { data, loading }, product }) => {
|
|
123
|
+
const Product = ({ result: { data, loading }, product, partialProduct }) => {
|
|
124
124
|
const initialVariant = useVariantFromUrl();
|
|
125
125
|
const t = useIntl();
|
|
126
126
|
|
|
@@ -132,13 +132,17 @@ const Product = ({ result: { data, loading }, product }) => {
|
|
|
132
132
|
const { selectedVariant: selectedVariation, getMissingOptions } =
|
|
133
133
|
variantHandler;
|
|
134
134
|
|
|
135
|
+
if (!product) {
|
|
136
|
+
product = partialProduct;
|
|
137
|
+
}
|
|
135
138
|
// Return early if there is no product
|
|
136
|
-
if (!product)
|
|
139
|
+
if (!product) {
|
|
137
140
|
return (
|
|
138
141
|
<ProductContainer>
|
|
139
142
|
<ProductPageLoadingState />
|
|
140
143
|
</ProductContainer>
|
|
141
144
|
);
|
|
145
|
+
}
|
|
142
146
|
|
|
143
147
|
const images = product.images ?? [];
|
|
144
148
|
const parents = getParentOrCanonicalRoute(data?.route?.parents, product);
|