@akinon/projectzero 2.0.0-beta.20 → 2.0.0-beta.21
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 +8 -0
- package/app-template/CHANGELOG.md +138 -0
- package/app-template/next.config.mjs +0 -1
- package/app-template/package.json +31 -30
- package/app-template/src/app/[pz]/[...prettyurl]/page.tsx +2 -2
- package/app-template/src/app/[pz]/account/layout.tsx +2 -1
- package/app-template/src/app/{[commerce]/[locale]/[currency] → [pz]}/blog/[slug]/page.tsx +4 -2
- package/app-template/src/app/[pz]/category/[pk]/page.tsx +11 -1
- package/app-template/src/app/[pz]/group-product/[pk]/page.tsx +2 -2
- package/app-template/src/app/[pz]/layout.tsx +3 -1
- package/app-template/src/app/[pz]/list/page.tsx +11 -1
- package/app-template/src/app/[pz]/page.tsx +13 -35
- package/app-template/src/app/[pz]/pages/[slug]/page.tsx +19 -0
- package/app-template/src/app/[pz]/product/[pk]/page.tsx +2 -2
- package/app-template/src/app/api/barcode-search/route.ts +1 -1
- package/app-template/src/app/api/cache/route.ts +1 -1
- package/app-template/src/app/api/image-proxy/route.ts +1 -1
- package/app-template/src/app/api/logout/route.ts +1 -1
- package/app-template/src/app/api/product-categories/route.ts +1 -1
- package/app-template/src/app/api/similar-product-list/route.ts +1 -1
- package/app-template/src/app/api/similar-products/route.ts +1 -1
- package/app-template/src/app/api/virtual-try-on/route.ts +1 -1
- package/app-template/src/app/api/web-vitals/route.ts +1 -1
- package/app-template/src/components/quantity-selector.tsx +16 -4
- package/app-template/src/components/widget-content.tsx +3 -3
- package/app-template/src/routes/index.ts +6 -6
- package/app-template/src/utils/__tests__/theme-page-context.test.ts +145 -0
- package/app-template/src/utils/theme-page-context.ts +309 -0
- package/app-template/src/views/basket/basket-item.tsx +107 -691
- package/app-template/src/views/basket/index.ts +0 -2
- package/app-template/src/views/basket/summary.tsx +75 -496
- package/app-template/src/views/breadcrumb.tsx +38 -13
- package/app-template/src/views/category/category-header.tsx +66 -289
- package/app-template/src/views/category/category-info.tsx +24 -173
- package/app-template/src/views/category/filters/index.tsx +48 -208
- package/app-template/src/views/category/layout.tsx +5 -7
- package/app-template/src/views/checkout/index.tsx +0 -5
- package/app-template/src/views/checkout/steps/payment/index.tsx +2 -5
- package/app-template/src/views/checkout/steps/payment/options/credit-card/index.tsx +1 -72
- package/app-template/src/views/checkout/steps/payment/payment-option-buttons.tsx +40 -171
- package/app-template/src/views/checkout/steps/shipping/address-box.tsx +12 -74
- package/app-template/src/views/checkout/steps/shipping/addresses.tsx +45 -128
- package/app-template/src/views/checkout/steps/shipping/shipping-options.tsx +27 -232
- package/app-template/src/views/checkout/summary.tsx +29 -303
- package/app-template/src/views/footer.tsx +13 -415
- package/app-template/src/views/guest-login/index.tsx +1 -1
- package/app-template/src/views/header/action-menu.tsx +45 -277
- package/app-template/src/views/header/band.tsx +21 -6
- package/app-template/src/views/header/index.tsx +47 -109
- package/app-template/src/views/header/mini-basket.tsx +45 -820
- package/app-template/src/views/header/navbar.tsx +111 -178
- package/app-template/src/views/header/search/index.tsx +32 -71
- package/app-template/src/views/header/search/results.tsx +65 -127
- package/app-template/src/views/product/accordion-wrapper.tsx +43 -135
- package/app-template/src/views/product/index.ts +1 -1
- package/app-template/src/views/product/layout.tsx +7 -2
- package/app-template/src/views/product/misc-buttons.tsx +25 -339
- package/app-template/src/views/product/product-actions.tsx +8 -137
- package/app-template/src/views/product/product-info.tsx +31 -69
- package/app-template/src/views/product/product-share.tsx +8 -11
- package/app-template/src/views/product/slider.tsx +79 -117
- package/app-template/src/views/product-item/index.tsx +46 -119
- package/app-template/src/widgets/footer-social.tsx +16 -47
- package/app-template/src/widgets/footer-subscription/index.tsx +17 -183
- package/dist/commands/plugins.js +23 -2
- package/package.json +1 -1
- package/app-template/src/app/[commerce]/[locale]/[currency]/pages/[slug]/page.tsx +0 -15
- package/app-template/src/views/basket/basket-summary-context.tsx +0 -560
- package/app-template/src/views/basket/designer-context.tsx +0 -617
- package/app-template/src/views/breadcrumb/breadcrumb-client.tsx +0 -190
- package/app-template/src/views/breadcrumb/breadcrumb-registrar.tsx +0 -286
- package/app-template/src/views/breadcrumb/constants.ts +0 -15
- package/app-template/src/views/breadcrumb/index.tsx +0 -127
- package/app-template/src/views/category/native-widget-context.tsx +0 -257
- package/app-template/src/views/category/product-list-registrar.tsx +0 -665
- package/app-template/src/views/checkout/checkout-address-registrar.tsx +0 -254
- package/app-template/src/views/checkout/checkout-buttons-registrar.tsx +0 -183
- package/app-template/src/views/checkout/checkout-delivery-method-registrar.tsx +0 -259
- package/app-template/src/views/checkout/checkout-payment-options-registrar.tsx +0 -253
- package/app-template/src/views/checkout/checkout-summary-registrar.tsx +0 -183
- package/app-template/src/views/checkout/constants.ts +0 -5
- package/app-template/src/views/checkout/steps/payment/options/masterpass-rest.tsx +0 -15
- package/app-template/src/views/checkout/steps/payment/options/saved-card.tsx +0 -18
- package/app-template/src/views/footer/footer-app-banner-context.tsx +0 -326
- package/app-template/src/views/footer/footer-bottom-context.tsx +0 -215
- package/app-template/src/views/footer/footer-bottom-wrapper.tsx +0 -74
- package/app-template/src/views/footer/footer-layout-constants.ts +0 -35
- package/app-template/src/views/footer/footer-layout-registrar.tsx +0 -342
- package/app-template/src/views/footer/footer-layout-switcher.tsx +0 -110
- package/app-template/src/views/footer/footer-menu-context.tsx +0 -211
- package/app-template/src/views/footer/footer-native-widgets.tsx +0 -60
- package/app-template/src/views/footer/footer-social-context.tsx +0 -254
- package/app-template/src/views/footer/footer-subscription-context.tsx +0 -210
- package/app-template/src/views/footer/footer-utils.ts +0 -43
- package/app-template/src/views/footer/footer-value-props-context.tsx +0 -326
- package/app-template/src/views/footer/logo-settings.ts +0 -183
- package/app-template/src/views/footer/native-widget-config.ts +0 -262
- package/app-template/src/views/footer/subscription-settings.ts +0 -122
- package/app-template/src/views/footer/use-footer-logo.ts +0 -162
- package/app-template/src/views/header/designer-context.tsx +0 -261
- package/app-template/src/views/header/header-announcement-registrar.tsx +0 -267
- package/app-template/src/views/header/header-client-wrapper.tsx +0 -496
- package/app-template/src/views/header/header-content.tsx +0 -1026
- package/app-template/src/views/header/header-currency-registrar.tsx +0 -348
- package/app-template/src/views/header/header-icons-context.tsx +0 -262
- package/app-template/src/views/header/header-language-registrar.tsx +0 -348
- package/app-template/src/views/header/header-layout-context.tsx +0 -143
- package/app-template/src/views/header/header-layout-registrar.tsx +0 -658
- package/app-template/src/views/header/header-logo-context.tsx +0 -228
- package/app-template/src/views/header/header-logo.tsx +0 -118
- package/app-template/src/views/header/header-mini-basket-context.tsx +0 -524
- package/app-template/src/views/header/header-search-registrar.tsx +0 -511
- package/app-template/src/views/header/header-text-slider-registrar.tsx +0 -382
- package/app-template/src/views/header/inline-search.tsx +0 -262
- package/app-template/src/views/header/navbar-menu-context.tsx +0 -219
- package/app-template/src/views/header/search/search-input.tsx +0 -61
- package/app-template/src/views/header/server-settings-parser.ts +0 -1105
- package/app-template/src/views/header/use-header-icons.ts +0 -241
- package/app-template/src/views/header/use-header-logo.ts +0 -213
- package/app-template/src/views/header/use-navbar-menu.ts +0 -179
- package/app-template/src/views/product/accordion-section.tsx +0 -61
- package/app-template/src/views/product/custom-button-group.tsx +0 -69
- package/app-template/src/views/product/favorites-button-section.tsx +0 -69
- package/app-template/src/views/product/find-in-store-section.tsx +0 -60
- package/app-template/src/views/product/product-info-section.tsx +0 -140
- package/app-template/src/views/product/quantity-section.tsx +0 -73
- package/app-template/src/views/product/sale-tag.tsx +0 -10
- package/app-template/src/views/product/share-section.tsx +0 -357
- package/app-template/src/views/product/variants-section.tsx +0 -126
- package/app-template/src/views/product-detail/constants.ts +0 -272
- package/app-template/src/views/product-detail/index.ts +0 -10
- package/app-template/src/views/product-detail/product-detail-registrar.tsx +0 -616
- package/app-template/src/widgets/footer-app-banner.tsx +0 -444
- package/app-template/src/widgets/footer-bottom.tsx +0 -127
- package/app-template/src/widgets/footer-menu-compact.tsx +0 -238
- package/app-template/src/widgets/footer-menu-two.tsx +0 -298
- package/app-template/src/widgets/footer-social-client.tsx +0 -251
- package/app-template/src/widgets/footer-value-props.tsx +0 -201
|
@@ -4,15 +4,8 @@ import {
|
|
|
4
4
|
} from '@akinon/next/data/client/basket';
|
|
5
5
|
import { useAppDispatch } from '@akinon/next/redux/hooks';
|
|
6
6
|
import { BasketItem as BasketItemType } from '@akinon/next/types';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
Button,
|
|
10
|
-
Icon,
|
|
11
|
-
LoaderSpinner,
|
|
12
|
-
Modal,
|
|
13
|
-
Link
|
|
14
|
-
} from '@theme/components';
|
|
15
|
-
import { ComponentProps, useState } from 'react';
|
|
7
|
+
import { Price, Button, Icon, Modal, Select, Link } from '@theme/components';
|
|
8
|
+
import { useState } from 'react';
|
|
16
9
|
import { useAddFavoriteMutation } from '@akinon/next/data/client/wishlist';
|
|
17
10
|
import {
|
|
18
11
|
useCommonProductAttributes,
|
|
@@ -20,89 +13,14 @@ import {
|
|
|
20
13
|
} from '@akinon/next/hooks';
|
|
21
14
|
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
22
15
|
import { Image } from '@akinon/next/components/image';
|
|
16
|
+
import clsx from 'clsx';
|
|
23
17
|
import { pushRemoveFromCart } from '@theme/utils/gtm';
|
|
24
|
-
import { WithDesignerFeatures } from '@akinon/next/components/theme-editor/components/with-designer-features';
|
|
25
|
-
import {
|
|
26
|
-
BASKET_ITEM_BLOCKS,
|
|
27
|
-
BASKET_ITEMS_SECTION_ID,
|
|
28
|
-
BASKET_PLACEHOLDER_ID,
|
|
29
|
-
useBasketDesigner
|
|
30
|
-
} from './designer-context';
|
|
31
18
|
|
|
32
19
|
interface Props {
|
|
33
20
|
basketItem?: BasketItemType;
|
|
34
21
|
namespace?: string;
|
|
35
22
|
}
|
|
36
23
|
|
|
37
|
-
const convertStylesToCSS = (
|
|
38
|
-
styles: Record<string, unknown> | undefined
|
|
39
|
-
): React.CSSProperties => {
|
|
40
|
-
if (!styles) return {};
|
|
41
|
-
|
|
42
|
-
const cssStyles: React.CSSProperties = {};
|
|
43
|
-
|
|
44
|
-
Object.entries(styles).forEach(([key, value]) => {
|
|
45
|
-
const rawValue =
|
|
46
|
-
typeof value === 'object' && value !== null && 'desktop' in value
|
|
47
|
-
? (value as Record<string, unknown>).desktop
|
|
48
|
-
: value;
|
|
49
|
-
|
|
50
|
-
const cssValue =
|
|
51
|
-
typeof rawValue === 'number'
|
|
52
|
-
? rawValue
|
|
53
|
-
: typeof rawValue === 'string'
|
|
54
|
-
? rawValue
|
|
55
|
-
: '';
|
|
56
|
-
|
|
57
|
-
if (cssValue !== '' && cssValue !== null && cssValue !== undefined) {
|
|
58
|
-
const camelKey = key.replace(/-([a-z])/g, (_, letter) =>
|
|
59
|
-
letter.toUpperCase()
|
|
60
|
-
);
|
|
61
|
-
(cssStyles as Record<string, unknown>)[camelKey] = cssValue;
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
return cssStyles;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
const pickStyles = (
|
|
69
|
-
styles: React.CSSProperties,
|
|
70
|
-
keys: Array<keyof React.CSSProperties>
|
|
71
|
-
): React.CSSProperties => {
|
|
72
|
-
const picked: React.CSSProperties = {};
|
|
73
|
-
|
|
74
|
-
keys.forEach((key) => {
|
|
75
|
-
const value = styles[key];
|
|
76
|
-
|
|
77
|
-
if (value !== undefined && value !== null && value !== '') {
|
|
78
|
-
(picked as Record<string, unknown>)[key as string] = value;
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
return picked;
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
const omitStyles = (
|
|
86
|
-
styles: React.CSSProperties,
|
|
87
|
-
keys: Array<keyof React.CSSProperties>
|
|
88
|
-
): React.CSSProperties => {
|
|
89
|
-
const omitted = { ...styles };
|
|
90
|
-
|
|
91
|
-
keys.forEach((key) => {
|
|
92
|
-
delete omitted[key];
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
return omitted;
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
const getResponsiveValue = (value: unknown) => {
|
|
99
|
-
if (typeof value === 'object' && value !== null && 'desktop' in value) {
|
|
100
|
-
return (value as Record<string, unknown>).desktop;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return value;
|
|
104
|
-
};
|
|
105
|
-
|
|
106
24
|
export const BasketItem = (props: Props) => {
|
|
107
25
|
const { t } = useLocalization();
|
|
108
26
|
const { basketItem, namespace } = props;
|
|
@@ -111,228 +29,15 @@ export const BasketItem = (props: Props) => {
|
|
|
111
29
|
const [isRemoveBasketModalOpen, setRemoveBasketModalOpen] = useState(false);
|
|
112
30
|
const [addFavorite, { isLoading: addFavoriteLoading }] =
|
|
113
31
|
useAddFavoriteMutation();
|
|
32
|
+
const [updateQuantityLoading, setUpdateQuantityLoading] = useState(false);
|
|
114
33
|
const commonProductAttributes = useCommonProductAttributes({
|
|
115
34
|
attributes: basketItem.product.attributes_kwargs
|
|
116
35
|
});
|
|
117
|
-
const [updateQuantityLoading, setUpdateQuantityLoading] = useState(false);
|
|
118
|
-
const { isDesigner, selectedBlockId, getBlockStyles, getBlockProperties } =
|
|
119
|
-
useBasketDesigner();
|
|
120
|
-
const rowStyles = convertStylesToCSS(
|
|
121
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.ITEM_ROW.id)
|
|
122
|
-
);
|
|
123
|
-
const imageStyles = convertStylesToCSS(
|
|
124
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.IMAGE.id)
|
|
125
|
-
);
|
|
126
|
-
const nameStyles = convertStylesToCSS(
|
|
127
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.NAME.id)
|
|
128
|
-
);
|
|
129
|
-
const attributesStyles = convertStylesToCSS(
|
|
130
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.ATTRIBUTES.id)
|
|
131
|
-
);
|
|
132
|
-
const attributeLabelStyles = convertStylesToCSS(
|
|
133
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.ATTRIBUTE_LABEL.id)
|
|
134
|
-
);
|
|
135
|
-
const attributeValueStyles = convertStylesToCSS(
|
|
136
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.ATTRIBUTE_VALUE.id)
|
|
137
|
-
);
|
|
138
|
-
const quantityStyles = convertStylesToCSS(
|
|
139
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY.id)
|
|
140
|
-
);
|
|
141
|
-
const quantityWrapperStyles = convertStylesToCSS(
|
|
142
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_WRAPPER.id)
|
|
143
|
-
);
|
|
144
|
-
const quantityMinusButtonStyles = convertStylesToCSS(
|
|
145
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_MINUS_BUTTON.id)
|
|
146
|
-
);
|
|
147
|
-
const quantityMinusIconStyles = convertStylesToCSS(
|
|
148
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_MINUS_ICON.id)
|
|
149
|
-
);
|
|
150
|
-
const quantityValueStyles = convertStylesToCSS(
|
|
151
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_VALUE.id)
|
|
152
|
-
);
|
|
153
|
-
const quantityPlusButtonStyles = convertStylesToCSS(
|
|
154
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_PLUS_BUTTON.id)
|
|
155
|
-
);
|
|
156
|
-
const quantityPlusIconStyles = convertStylesToCSS(
|
|
157
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.QUANTITY_PLUS_ICON.id)
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
const quantityMinusIconProps =
|
|
161
|
-
getBlockProperties(BASKET_ITEM_BLOCKS.QUANTITY_MINUS_ICON.id) || {};
|
|
162
|
-
const quantityPlusIconProps =
|
|
163
|
-
getBlockProperties(BASKET_ITEM_BLOCKS.QUANTITY_PLUS_ICON.id) || {};
|
|
164
|
-
const priceStyles = convertStylesToCSS(
|
|
165
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.PRICE.id)
|
|
166
|
-
);
|
|
167
|
-
const priceTextBlockStyles = convertStylesToCSS(
|
|
168
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.PRICE_TEXT.id)
|
|
169
|
-
);
|
|
170
|
-
const removeStyles = convertStylesToCSS(
|
|
171
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.REMOVE.id)
|
|
172
|
-
);
|
|
173
|
-
const removeProperties = getBlockProperties(BASKET_ITEM_BLOCKS.REMOVE.id);
|
|
174
|
-
const removeIconRaw = getResponsiveValue(removeProperties?.icon);
|
|
175
|
-
const removeIconValue = removeIconRaw;
|
|
176
|
-
const hasCustomRemoveSvgIcon =
|
|
177
|
-
typeof removeIconValue === 'string' && removeIconValue.includes('<svg');
|
|
178
|
-
const removeIconName = (
|
|
179
|
-
typeof removeIconValue === 'string' ? removeIconValue : 'close'
|
|
180
|
-
) as ComponentProps<typeof Icon>['name'];
|
|
181
|
-
const giftPackStyles = convertStylesToCSS(
|
|
182
|
-
getBlockStyles(BASKET_ITEM_BLOCKS.GIFT_PACK.id)
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
const imageWrapperKeys: Array<keyof React.CSSProperties> = [
|
|
186
|
-
'width',
|
|
187
|
-
'height',
|
|
188
|
-
'marginRight',
|
|
189
|
-
'marginLeft',
|
|
190
|
-
'marginTop',
|
|
191
|
-
'marginBottom',
|
|
192
|
-
'alignSelf',
|
|
193
|
-
'justifySelf',
|
|
194
|
-
'flexGrow',
|
|
195
|
-
'flexShrink'
|
|
196
|
-
];
|
|
197
|
-
const priceWrapperKeys: Array<keyof React.CSSProperties> = [
|
|
198
|
-
'gap',
|
|
199
|
-
'marginRight',
|
|
200
|
-
'marginLeft',
|
|
201
|
-
'marginTop',
|
|
202
|
-
'marginBottom',
|
|
203
|
-
'alignSelf',
|
|
204
|
-
'justifySelf',
|
|
205
|
-
'justifyContent',
|
|
206
|
-
'alignItems'
|
|
207
|
-
];
|
|
208
|
-
const attributesWrapperKeys: Array<keyof React.CSSProperties> = [
|
|
209
|
-
'gap',
|
|
210
|
-
'marginRight',
|
|
211
|
-
'marginLeft',
|
|
212
|
-
'marginTop',
|
|
213
|
-
'marginBottom',
|
|
214
|
-
'alignSelf',
|
|
215
|
-
'justifySelf',
|
|
216
|
-
'justifyContent',
|
|
217
|
-
'alignItems'
|
|
218
|
-
];
|
|
219
|
-
const quantityContainerKeys: Array<keyof React.CSSProperties> = [
|
|
220
|
-
'gap',
|
|
221
|
-
'marginRight',
|
|
222
|
-
'marginLeft',
|
|
223
|
-
'marginTop',
|
|
224
|
-
'marginBottom',
|
|
225
|
-
'alignSelf',
|
|
226
|
-
'justifySelf',
|
|
227
|
-
'justifyContent',
|
|
228
|
-
'alignItems'
|
|
229
|
-
];
|
|
230
|
-
|
|
231
|
-
const imageWrapperStyles = pickStyles(imageStyles, imageWrapperKeys);
|
|
232
|
-
const imageElementStyles = {
|
|
233
|
-
...omitStyles(imageStyles, [
|
|
234
|
-
'marginRight',
|
|
235
|
-
'marginLeft',
|
|
236
|
-
'marginTop',
|
|
237
|
-
'marginBottom',
|
|
238
|
-
'alignSelf',
|
|
239
|
-
'justifySelf',
|
|
240
|
-
'flexGrow',
|
|
241
|
-
'flexShrink'
|
|
242
|
-
]),
|
|
243
|
-
width: imageStyles.width || undefined,
|
|
244
|
-
height: imageStyles.height || undefined
|
|
245
|
-
};
|
|
246
|
-
const priceWrapperStyles = pickStyles(priceStyles, priceWrapperKeys);
|
|
247
|
-
const priceTextStyles = priceTextBlockStyles;
|
|
248
|
-
const attributesWrapperStyles = pickStyles(
|
|
249
|
-
attributesStyles,
|
|
250
|
-
attributesWrapperKeys
|
|
251
|
-
);
|
|
252
|
-
const attributesTextStyles = omitStyles(
|
|
253
|
-
attributesStyles,
|
|
254
|
-
attributesWrapperKeys
|
|
255
|
-
);
|
|
256
|
-
const finalAttributeLabelStyles = {
|
|
257
|
-
...attributesTextStyles,
|
|
258
|
-
...attributeLabelStyles
|
|
259
|
-
};
|
|
260
|
-
const finalAttributeValueStyles = {
|
|
261
|
-
...attributesTextStyles,
|
|
262
|
-
...attributeValueStyles
|
|
263
|
-
};
|
|
264
|
-
const quantityContainerStyles = pickStyles(
|
|
265
|
-
quantityStyles,
|
|
266
|
-
quantityContainerKeys
|
|
267
|
-
);
|
|
268
|
-
const minusIconRaw = getResponsiveValue(quantityMinusIconProps.icon);
|
|
269
|
-
const plusIconRaw = getResponsiveValue(quantityPlusIconProps.icon);
|
|
270
|
-
const minusIcon = typeof minusIconRaw === 'string' ? minusIconRaw : 'minus';
|
|
271
|
-
const plusIcon = typeof plusIconRaw === 'string' ? plusIconRaw : 'plus';
|
|
272
|
-
|
|
273
|
-
const toNumber = (value: unknown, fallback = 12) => {
|
|
274
|
-
if (typeof value === 'number') return value;
|
|
275
|
-
if (typeof value === 'string') {
|
|
276
|
-
const parsed = parseInt(value, 10);
|
|
277
|
-
return Number.isNaN(parsed) ? fallback : parsed;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
return fallback;
|
|
281
|
-
};
|
|
282
|
-
|
|
283
|
-
const minusIconSize = toNumber(
|
|
284
|
-
quantityMinusIconStyles.width ||
|
|
285
|
-
quantityMinusIconStyles.height ||
|
|
286
|
-
quantityMinusIconStyles.fontSize,
|
|
287
|
-
12
|
|
288
|
-
);
|
|
289
|
-
const plusIconSize = toNumber(
|
|
290
|
-
quantityPlusIconStyles.width ||
|
|
291
|
-
quantityPlusIconStyles.height ||
|
|
292
|
-
quantityPlusIconStyles.fontSize,
|
|
293
|
-
12
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
const isCustomMinusSvg =
|
|
297
|
-
typeof minusIcon === 'string' && minusIcon.includes('<svg');
|
|
298
|
-
const isCustomPlusSvg =
|
|
299
|
-
typeof plusIcon === 'string' && plusIcon.includes('<svg');
|
|
300
|
-
|
|
301
|
-
const handleDesignerClick = (event: React.MouseEvent) => {
|
|
302
|
-
if (isDesigner) {
|
|
303
|
-
event.preventDefault();
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
// Check if any instance of this block type is selected
|
|
308
|
-
const isBlockSelected = (
|
|
309
|
-
block: typeof BASKET_ITEM_BLOCKS[keyof typeof BASKET_ITEM_BLOCKS]
|
|
310
|
-
) => {
|
|
311
|
-
if (selectedBlockId === block.id) return true;
|
|
312
|
-
// Match only numbered instances (e.g., basket-item-price-1), not sibling blocks
|
|
313
|
-
if (selectedBlockId?.match(new RegExp(`^${block.id}-\\d+$`))) return true;
|
|
314
|
-
return false;
|
|
315
|
-
};
|
|
316
|
-
|
|
317
|
-
// Block instance - uses base ID for styles (shared across all items)
|
|
318
|
-
const getBlockInstance = (
|
|
319
|
-
block: typeof BASKET_ITEM_BLOCKS[keyof typeof BASKET_ITEM_BLOCKS]
|
|
320
|
-
) => {
|
|
321
|
-
// Always get styles from base block ID (shared across all items)
|
|
322
|
-
const styles = getBlockStyles(block.id);
|
|
323
|
-
return {
|
|
324
|
-
...block,
|
|
325
|
-
// Use base ID so all items share the same block in theme editor
|
|
326
|
-
id: block.id,
|
|
327
|
-
styles
|
|
328
|
-
};
|
|
329
|
-
};
|
|
330
36
|
|
|
331
37
|
const updateQuantity = async (
|
|
332
38
|
productPk: number,
|
|
333
39
|
quantity: number,
|
|
334
|
-
attributes: object = {}
|
|
335
|
-
namespace?: string
|
|
40
|
+
attributes: object = {}
|
|
336
41
|
) => {
|
|
337
42
|
const requestParams: {
|
|
338
43
|
product: number;
|
|
@@ -349,11 +54,9 @@ export const BasketItem = (props: Props) => {
|
|
|
349
54
|
requestParams.namespace = namespace;
|
|
350
55
|
}
|
|
351
56
|
|
|
352
|
-
setUpdateQuantityLoading(true);
|
|
353
|
-
|
|
354
57
|
await updateQuantityMutation(requestParams)
|
|
355
58
|
.unwrap()
|
|
356
|
-
.then((data) =>
|
|
59
|
+
.then((data) =>
|
|
357
60
|
dispatch(
|
|
358
61
|
basketApi.util.updateQueryData(
|
|
359
62
|
'getBasket',
|
|
@@ -362,34 +65,15 @@ export const BasketItem = (props: Props) => {
|
|
|
362
65
|
Object.assign(draftBasket, data.basket);
|
|
363
66
|
}
|
|
364
67
|
)
|
|
365
|
-
)
|
|
366
|
-
|
|
367
|
-
.catch((err) => {
|
|
368
|
-
const formattedError =
|
|
369
|
-
err?.data?.non_field_errors ||
|
|
370
|
-
Object.keys(err?.data || {}).map(
|
|
371
|
-
(key) => `${key}: ${err?.data[key].join(', ')}`
|
|
372
|
-
);
|
|
373
|
-
|
|
374
|
-
console.error('Error in operation:', formattedError);
|
|
375
|
-
})
|
|
376
|
-
.finally(() => {
|
|
377
|
-
setTimeout(() => {
|
|
378
|
-
setUpdateQuantityLoading(false);
|
|
379
|
-
}, 200);
|
|
380
|
-
});
|
|
68
|
+
)
|
|
69
|
+
);
|
|
381
70
|
};
|
|
382
71
|
|
|
383
72
|
const deleteProduct = async (productPk?: number) => {
|
|
384
73
|
setUpdateQuantityLoading(true);
|
|
385
74
|
|
|
386
75
|
try {
|
|
387
|
-
await updateQuantity(
|
|
388
|
-
basketItem.product.pk,
|
|
389
|
-
0,
|
|
390
|
-
basketItem.attributes,
|
|
391
|
-
namespace
|
|
392
|
-
);
|
|
76
|
+
await updateQuantity(basketItem.product.pk, 0, basketItem.attributes);
|
|
393
77
|
pushRemoveFromCart(basketItem?.product);
|
|
394
78
|
|
|
395
79
|
if (productPk) {
|
|
@@ -403,385 +87,117 @@ export const BasketItem = (props: Props) => {
|
|
|
403
87
|
}
|
|
404
88
|
};
|
|
405
89
|
|
|
406
|
-
const handleQuantityChange = (newQuantity: number) => {
|
|
407
|
-
if (newQuantity === 0) {
|
|
408
|
-
setRemoveBasketModalOpen(true);
|
|
409
|
-
} else {
|
|
410
|
-
updateQuantity(
|
|
411
|
-
basketItem.product.pk,
|
|
412
|
-
newQuantity,
|
|
413
|
-
basketItem.attributes,
|
|
414
|
-
namespace
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
|
|
419
|
-
const handleDecrease = () => {
|
|
420
|
-
if (isDesigner) return;
|
|
421
|
-
if (updateQuantityLoading) return;
|
|
422
|
-
handleQuantityChange(basketItem.quantity - 1);
|
|
423
|
-
};
|
|
424
|
-
|
|
425
|
-
const handleIncrease = () => {
|
|
426
|
-
if (isDesigner) return;
|
|
427
|
-
if (updateQuantityLoading) return;
|
|
428
|
-
if (basketItem.quantity >= 999) return;
|
|
429
|
-
handleQuantityChange(basketItem.quantity + 1);
|
|
430
|
-
};
|
|
431
|
-
|
|
432
90
|
return (
|
|
433
91
|
<>
|
|
434
|
-
<li
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
<Image
|
|
468
|
-
src={basketItem.product.productimage_set[0]?.image}
|
|
469
|
-
alt={basketItem.product.name}
|
|
470
|
-
width={105}
|
|
471
|
-
height={158}
|
|
472
|
-
className="hidden md:block"
|
|
473
|
-
style={imageElementStyles}
|
|
474
|
-
/>
|
|
475
|
-
</Link>
|
|
476
|
-
</WithDesignerFeatures>
|
|
477
|
-
<div className="w-full flex flex-col justify-between">
|
|
478
|
-
<div className="flex h-full gap-4">
|
|
479
|
-
<div className="flex flex-1 flex-col gap-3 sm:flex-row sm:gap-4">
|
|
480
|
-
<div className="flex-1 space-y-2">
|
|
481
|
-
<WithDesignerFeatures
|
|
482
|
-
block={getBlockInstance(BASKET_ITEM_BLOCKS.NAME)}
|
|
483
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
484
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
485
|
-
isDesigner={isDesigner}
|
|
486
|
-
isSelected={isBlockSelected(BASKET_ITEM_BLOCKS.NAME)}
|
|
487
|
-
className="inline-block w-full text-xs"
|
|
488
|
-
style={nameStyles}
|
|
489
|
-
>
|
|
490
|
-
<Link
|
|
491
|
-
href={basketItem.product.absolute_url}
|
|
492
|
-
data-testid="basket-product-name"
|
|
493
|
-
passHref
|
|
494
|
-
onClick={handleDesignerClick}
|
|
495
|
-
>
|
|
496
|
-
<span>{basketItem.product.name}</span>
|
|
497
|
-
</Link>
|
|
498
|
-
</WithDesignerFeatures>
|
|
499
|
-
<WithDesignerFeatures
|
|
500
|
-
block={getBlockInstance(BASKET_ITEM_BLOCKS.ATTRIBUTES)}
|
|
501
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
502
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
503
|
-
isDesigner={isDesigner}
|
|
504
|
-
isSelected={isBlockSelected(BASKET_ITEM_BLOCKS.ATTRIBUTES)}
|
|
505
|
-
className="flex flex-col gap-1"
|
|
506
|
-
style={attributesWrapperStyles}
|
|
507
|
-
>
|
|
508
|
-
{commonProductAttributes.map((attribute, index) => (
|
|
509
|
-
<div
|
|
510
|
-
className="text-xs"
|
|
511
|
-
key={index}
|
|
512
|
-
style={attributesTextStyles}
|
|
513
|
-
>
|
|
514
|
-
<WithDesignerFeatures
|
|
515
|
-
block={getBlockInstance(
|
|
516
|
-
BASKET_ITEM_BLOCKS.ATTRIBUTE_LABEL
|
|
517
|
-
)}
|
|
518
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
519
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
520
|
-
isDesigner={isDesigner}
|
|
521
|
-
isSelected={isBlockSelected(
|
|
522
|
-
BASKET_ITEM_BLOCKS.ATTRIBUTE_LABEL
|
|
523
|
-
)}
|
|
524
|
-
className="inline-block"
|
|
525
|
-
>
|
|
526
|
-
<span style={finalAttributeLabelStyles}>
|
|
527
|
-
{attribute.name}
|
|
528
|
-
</span>
|
|
529
|
-
</WithDesignerFeatures>
|
|
530
|
-
:{' '}
|
|
531
|
-
<WithDesignerFeatures
|
|
532
|
-
block={getBlockInstance(
|
|
533
|
-
BASKET_ITEM_BLOCKS.ATTRIBUTE_VALUE
|
|
534
|
-
)}
|
|
535
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
536
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
537
|
-
isDesigner={isDesigner}
|
|
538
|
-
isSelected={isBlockSelected(
|
|
539
|
-
BASKET_ITEM_BLOCKS.ATTRIBUTE_VALUE
|
|
540
|
-
)}
|
|
541
|
-
className="inline-block"
|
|
542
|
-
>
|
|
543
|
-
<span
|
|
544
|
-
style={finalAttributeValueStyles}
|
|
545
|
-
data-testid={`basket-item-${attribute.name.toLowerCase()}`}
|
|
546
|
-
>
|
|
547
|
-
{attribute.value}
|
|
548
|
-
</span>
|
|
549
|
-
</WithDesignerFeatures>
|
|
550
|
-
</div>
|
|
551
|
-
))}
|
|
552
|
-
</WithDesignerFeatures>
|
|
553
|
-
</div>
|
|
554
|
-
<WithDesignerFeatures
|
|
555
|
-
block={getBlockInstance(BASKET_ITEM_BLOCKS.QUANTITY)}
|
|
556
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
557
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
558
|
-
isDesigner={isDesigner}
|
|
559
|
-
isSelected={isBlockSelected(BASKET_ITEM_BLOCKS.QUANTITY)}
|
|
560
|
-
className="flex flex-col justify-center md:flex-row md:items-center"
|
|
561
|
-
style={quantityContainerStyles}
|
|
92
|
+
<li
|
|
93
|
+
key={basketItem.id}
|
|
94
|
+
className="flex border-b border-gray-200 py-3 relative"
|
|
95
|
+
data-testid="basket-item"
|
|
96
|
+
>
|
|
97
|
+
<div className="w-20 lg:w-[105px] mr-4 shrink-0">
|
|
98
|
+
<Link href={basketItem.product.absolute_url} passHref>
|
|
99
|
+
<Image
|
|
100
|
+
src={basketItem.product.productimage_set[0]?.image}
|
|
101
|
+
alt={basketItem.product.name}
|
|
102
|
+
width={80}
|
|
103
|
+
height={128}
|
|
104
|
+
className="md:hidden"
|
|
105
|
+
/>
|
|
106
|
+
|
|
107
|
+
<Image
|
|
108
|
+
src={basketItem.product.productimage_set[0]?.image}
|
|
109
|
+
alt={basketItem.product.name}
|
|
110
|
+
width={105}
|
|
111
|
+
height={158}
|
|
112
|
+
className="hidden md:block"
|
|
113
|
+
/>
|
|
114
|
+
</Link>
|
|
115
|
+
</div>
|
|
116
|
+
<div className="w-full flex flex-col justify-between">
|
|
117
|
+
<div className="flex h-full">
|
|
118
|
+
<div className="flex flex-1 flex-col gap-3 sm:flex-row sm:gap-1">
|
|
119
|
+
<div className="flex-1">
|
|
120
|
+
<Link
|
|
121
|
+
href={basketItem.product.absolute_url}
|
|
122
|
+
data-testid="basket-product-name"
|
|
123
|
+
passHref
|
|
562
124
|
>
|
|
563
|
-
<
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
BASKET_ITEM_BLOCKS.QUANTITY_WRAPPER
|
|
572
|
-
)}
|
|
573
|
-
className="w-[138px] h-11 flex items-center justify-between border p-4"
|
|
574
|
-
style={quantityWrapperStyles}
|
|
575
|
-
>
|
|
576
|
-
<WithDesignerFeatures
|
|
577
|
-
block={getBlockInstance(
|
|
578
|
-
BASKET_ITEM_BLOCKS.QUANTITY_MINUS_BUTTON
|
|
579
|
-
)}
|
|
580
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
581
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
582
|
-
isDesigner={isDesigner}
|
|
583
|
-
isSelected={isBlockSelected(
|
|
584
|
-
BASKET_ITEM_BLOCKS.QUANTITY_MINUS_BUTTON
|
|
585
|
-
)}
|
|
586
|
-
className="inline-flex"
|
|
587
|
-
>
|
|
588
|
-
<Button
|
|
589
|
-
className="h-auto p-0 hover:bg-transparent hover:text-black"
|
|
590
|
-
appearance="ghost"
|
|
591
|
-
onClick={handleDecrease}
|
|
592
|
-
disabled={
|
|
593
|
-
updateQuantityLoading || basketItem.quantity <= 0
|
|
594
|
-
}
|
|
595
|
-
style={quantityMinusButtonStyles}
|
|
596
|
-
>
|
|
597
|
-
<WithDesignerFeatures
|
|
598
|
-
block={getBlockInstance(
|
|
599
|
-
BASKET_ITEM_BLOCKS.QUANTITY_MINUS_ICON
|
|
600
|
-
)}
|
|
601
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
602
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
603
|
-
isDesigner={isDesigner}
|
|
604
|
-
isSelected={isBlockSelected(
|
|
605
|
-
BASKET_ITEM_BLOCKS.QUANTITY_MINUS_ICON
|
|
606
|
-
)}
|
|
607
|
-
className="inline-flex"
|
|
608
|
-
style={quantityMinusIconStyles}
|
|
609
|
-
>
|
|
610
|
-
{isCustomMinusSvg ? (
|
|
611
|
-
<div
|
|
612
|
-
style={{
|
|
613
|
-
width: minusIconSize,
|
|
614
|
-
height: minusIconSize
|
|
615
|
-
}}
|
|
616
|
-
dangerouslySetInnerHTML={{ __html: minusIcon }}
|
|
617
|
-
/>
|
|
618
|
-
) : (
|
|
619
|
-
<Icon
|
|
620
|
-
name={
|
|
621
|
-
minusIcon as ComponentProps<typeof Icon>['name']
|
|
622
|
-
}
|
|
623
|
-
size={minusIconSize}
|
|
624
|
-
style={quantityMinusIconStyles}
|
|
625
|
-
/>
|
|
626
|
-
)}
|
|
627
|
-
</WithDesignerFeatures>
|
|
628
|
-
</Button>
|
|
629
|
-
</WithDesignerFeatures>
|
|
630
|
-
|
|
631
|
-
<WithDesignerFeatures
|
|
632
|
-
block={getBlockInstance(
|
|
633
|
-
BASKET_ITEM_BLOCKS.QUANTITY_VALUE
|
|
634
|
-
)}
|
|
635
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
636
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
637
|
-
isDesigner={isDesigner}
|
|
638
|
-
isSelected={isBlockSelected(
|
|
639
|
-
BASKET_ITEM_BLOCKS.QUANTITY_VALUE
|
|
640
|
-
)}
|
|
641
|
-
className="inline-flex"
|
|
642
|
-
style={quantityValueStyles}
|
|
643
|
-
>
|
|
644
|
-
{updateQuantityLoading ? (
|
|
645
|
-
<LoaderSpinner className="w-4 h-4" />
|
|
646
|
-
) : (
|
|
647
|
-
<span style={quantityValueStyles}>
|
|
648
|
-
{basketItem.quantity}
|
|
649
|
-
</span>
|
|
650
|
-
)}
|
|
651
|
-
</WithDesignerFeatures>
|
|
652
|
-
|
|
653
|
-
<WithDesignerFeatures
|
|
654
|
-
block={getBlockInstance(
|
|
655
|
-
BASKET_ITEM_BLOCKS.QUANTITY_PLUS_BUTTON
|
|
656
|
-
)}
|
|
657
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
658
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
659
|
-
isDesigner={isDesigner}
|
|
660
|
-
isSelected={isBlockSelected(
|
|
661
|
-
BASKET_ITEM_BLOCKS.QUANTITY_PLUS_BUTTON
|
|
662
|
-
)}
|
|
663
|
-
className="inline-flex"
|
|
664
|
-
>
|
|
665
|
-
<Button
|
|
666
|
-
className="h-auto p-0 hover:bg-transparent hover:text-black"
|
|
667
|
-
appearance="ghost"
|
|
668
|
-
onClick={handleIncrease}
|
|
669
|
-
disabled={
|
|
670
|
-
updateQuantityLoading || basketItem.quantity >= 999
|
|
671
|
-
}
|
|
672
|
-
style={quantityPlusButtonStyles}
|
|
125
|
+
<span className="text-xs">{basketItem.product.name}</span>
|
|
126
|
+
</Link>
|
|
127
|
+
<div className="flex flex-col gap-1">
|
|
128
|
+
{commonProductAttributes.map((attribute, index) => (
|
|
129
|
+
<span className="text-xs" key={index}>
|
|
130
|
+
<span>{attribute.name}</span>:{' '}
|
|
131
|
+
<span
|
|
132
|
+
data-testid={`basket-item-${attribute.name.toLowerCase()}`}
|
|
673
133
|
>
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
680
|
-
isDesigner={isDesigner}
|
|
681
|
-
isSelected={isBlockSelected(
|
|
682
|
-
BASKET_ITEM_BLOCKS.QUANTITY_PLUS_ICON
|
|
683
|
-
)}
|
|
684
|
-
className="inline-flex"
|
|
685
|
-
style={quantityPlusIconStyles}
|
|
686
|
-
>
|
|
687
|
-
{isCustomPlusSvg ? (
|
|
688
|
-
<div
|
|
689
|
-
style={{
|
|
690
|
-
width: plusIconSize,
|
|
691
|
-
height: plusIconSize
|
|
692
|
-
}}
|
|
693
|
-
dangerouslySetInnerHTML={{ __html: plusIcon }}
|
|
694
|
-
/>
|
|
695
|
-
) : (
|
|
696
|
-
<Icon
|
|
697
|
-
name={
|
|
698
|
-
plusIcon as ComponentProps<typeof Icon>['name']
|
|
699
|
-
}
|
|
700
|
-
size={plusIconSize}
|
|
701
|
-
style={quantityPlusIconStyles}
|
|
702
|
-
/>
|
|
703
|
-
)}
|
|
704
|
-
</WithDesignerFeatures>
|
|
705
|
-
</Button>
|
|
706
|
-
</WithDesignerFeatures>
|
|
707
|
-
</WithDesignerFeatures>
|
|
708
|
-
</WithDesignerFeatures>
|
|
709
|
-
<WithDesignerFeatures
|
|
710
|
-
block={getBlockInstance(BASKET_ITEM_BLOCKS.PRICE)}
|
|
711
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
712
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
713
|
-
isDesigner={isDesigner}
|
|
714
|
-
isSelected={isBlockSelected(BASKET_ITEM_BLOCKS.PRICE)}
|
|
715
|
-
className="flex flex-col shrink-0 text-sm gap-2 items-start justify-center lg:flex-row lg:mr-6 lg:gap-6 sm:items-center lg:justify-start"
|
|
716
|
-
style={priceWrapperStyles}
|
|
717
|
-
>
|
|
718
|
-
<WithDesignerFeatures
|
|
719
|
-
block={getBlockInstance(BASKET_ITEM_BLOCKS.PRICE_TEXT)}
|
|
720
|
-
placeholderId={BASKET_PLACEHOLDER_ID}
|
|
721
|
-
sectionId={BASKET_ITEMS_SECTION_ID}
|
|
722
|
-
isDesigner={isDesigner}
|
|
723
|
-
isSelected={isBlockSelected(BASKET_ITEM_BLOCKS.PRICE_TEXT)}
|
|
724
|
-
className="inline-block"
|
|
725
|
-
>
|
|
726
|
-
<Price
|
|
727
|
-
value={basketItem.product.price}
|
|
728
|
-
data-testid="basket-product-price"
|
|
729
|
-
style={priceTextStyles}
|
|
730
|
-
/>
|
|
731
|
-
</WithDesignerFeatures>
|
|
732
|
-
</WithDesignerFeatures>
|
|
134
|
+
{attribute.value}
|
|
135
|
+
</span>
|
|
136
|
+
</span>
|
|
137
|
+
))}
|
|
138
|
+
</div>
|
|
733
139
|
</div>
|
|
734
|
-
<
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
140
|
+
<div className="flex flex-col justify-center md:flex-row md:items-center lg:w-52">
|
|
141
|
+
<Select
|
|
142
|
+
className="px-2"
|
|
143
|
+
defaultValue={basketItem.quantity}
|
|
144
|
+
onChange={(event) => {
|
|
145
|
+
updateQuantity(
|
|
146
|
+
basketItem.product.pk,
|
|
147
|
+
Number(event.currentTarget.value)
|
|
148
|
+
);
|
|
149
|
+
}}
|
|
150
|
+
options={[
|
|
151
|
+
...Array.from({ length: 10 }, (_, i) => i + 1),
|
|
152
|
+
basketItem.quantity > 10 && basketItem.quantity
|
|
153
|
+
]
|
|
154
|
+
.filter((i) => i)
|
|
155
|
+
.map((i) => ({
|
|
156
|
+
label: `${t('basket.card.qty')} ${i}`,
|
|
157
|
+
value: `${i}`
|
|
158
|
+
}))}
|
|
159
|
+
data-testid="basket-product-quantity"
|
|
160
|
+
></Select>
|
|
161
|
+
</div>
|
|
162
|
+
<div className="flex flex-col shrink-0 text-sm gap-2 items-start justify-center w-48 lg:flex-row lg:mr-6 lg:gap-6 sm:items-center lg:justify-start">
|
|
163
|
+
{parseFloat(basketItem.product.retail_price) >
|
|
164
|
+
parseFloat(basketItem.product.price) && (
|
|
165
|
+
<Price
|
|
166
|
+
className="line-through"
|
|
167
|
+
value={basketItem.product.retail_price}
|
|
759
168
|
/>
|
|
760
169
|
)}
|
|
761
|
-
|
|
170
|
+
<Price
|
|
171
|
+
className={clsx(
|
|
172
|
+
parseFloat(basketItem.product.retail_price) >
|
|
173
|
+
parseFloat(basketItem.product.price)
|
|
174
|
+
? 'text-secondary-500'
|
|
175
|
+
: 'text-primary'
|
|
176
|
+
)}
|
|
177
|
+
value={basketItem.product.price}
|
|
178
|
+
data-testid="basket-product-price"
|
|
179
|
+
/>
|
|
180
|
+
</div>
|
|
762
181
|
</div>
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
className="mt-3"
|
|
771
|
-
style={giftPackStyles}
|
|
772
|
-
>
|
|
773
|
-
<PluginModule
|
|
774
|
-
component={Component.BasketGiftPack}
|
|
775
|
-
props={{ basketItem }}
|
|
776
|
-
/>
|
|
777
|
-
</WithDesignerFeatures>
|
|
182
|
+
<Icon
|
|
183
|
+
name="close"
|
|
184
|
+
size={16}
|
|
185
|
+
className="self-center cursor-pointer hover:fill-secondary-500" // TODO: Add hover color. Fill not working
|
|
186
|
+
onClick={() => setRemoveBasketModalOpen(true)}
|
|
187
|
+
data-testid="basket-product-remove"
|
|
188
|
+
/>
|
|
778
189
|
</div>
|
|
779
|
-
|
|
190
|
+
|
|
191
|
+
<PluginModule
|
|
192
|
+
component={Component.BasketGiftPack}
|
|
193
|
+
props={{ basketItem }}
|
|
194
|
+
/>
|
|
195
|
+
</div>
|
|
780
196
|
</li>
|
|
781
197
|
<Modal
|
|
782
198
|
portalId="remove-basket-item"
|
|
783
199
|
title={t('basket.card.modal.title')}
|
|
784
|
-
className="w-full
|
|
200
|
+
className="w-full sm:w-[28rem] max-h-[90vh] overflow-y-auto"
|
|
785
201
|
open={isRemoveBasketModalOpen}
|
|
786
202
|
setOpen={setRemoveBasketModalOpen}
|
|
787
203
|
>
|