@lancom/shared 0.0.265 → 0.0.267
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/components/common/file_uploader.vue +1 -0
- package/components/product/product_multipacks_carousel/product-multipacks-carousel.scss +29 -19
- package/components/product/product_multipacks_carousel/product-multipacks-carousel.vue +42 -3
- package/components/product/product_multipacks_carousel/product_multipack/product-multipack.scss +14 -14
- package/components/product/product_multipacks_carousel/product_multipack/product-multipack.vue +13 -18
- package/feeds/google-shopping.js +2 -2
- package/package.json +1 -1
- package/store/product.js +7 -0
|
@@ -15,35 +15,37 @@
|
|
|
15
15
|
::v-deep .slick-list {
|
|
16
16
|
min-height: 205px;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
::v-deep .slick-arrow
|
|
18
|
+
|
|
19
|
+
::v-deep .slick-arrow {
|
|
20
20
|
position: absolute;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
background-color:
|
|
24
|
-
|
|
25
|
-
background-image: url(./../../../static/icons/arrow-left.svg);
|
|
21
|
+
color: white;
|
|
22
|
+
top: 120px;
|
|
23
|
+
background-color: $gray;
|
|
24
|
+
background-image: url(./../../../static/icons/arrow-right.svg);
|
|
26
25
|
background-position: center;
|
|
27
26
|
background-repeat: no-repeat;
|
|
28
|
-
background-size:
|
|
29
|
-
width:
|
|
30
|
-
height:
|
|
27
|
+
background-size: 25px 25px;
|
|
28
|
+
width: 31px;
|
|
29
|
+
height: 47px;
|
|
30
|
+
margin-top: -45px;
|
|
31
31
|
text-indent: -9999px;
|
|
32
|
+
border: none;
|
|
32
33
|
cursor: pointer;
|
|
33
34
|
z-index: 2;
|
|
34
35
|
|
|
36
|
+
&.slick-prev {
|
|
37
|
+
left: 0;
|
|
38
|
+
transform: rotate(180deg);
|
|
39
|
+
}
|
|
40
|
+
&.slick-next {
|
|
41
|
+
right: 0;
|
|
42
|
+
}
|
|
35
43
|
&:hover {
|
|
36
44
|
box-shadow: 0 0 3px $grey_2;
|
|
37
45
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
left: 0;
|
|
42
|
-
right: auto;
|
|
43
|
-
}
|
|
44
|
-
::v-deep .slick-arrow.slick-prev:focus,
|
|
45
|
-
::v-deep .slick-arrow.slick-next:focus {
|
|
46
|
-
outline: none;
|
|
46
|
+
&:focus {
|
|
47
|
+
outline: none;
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
&__items {
|
|
@@ -56,5 +58,13 @@
|
|
|
56
58
|
height: 200px;
|
|
57
59
|
max-width: 300px;
|
|
58
60
|
flex-grow: 1;
|
|
61
|
+
&--active {
|
|
62
|
+
.elevation2 {
|
|
63
|
+
box-shadow: 0px 1px 5px $green !important;
|
|
64
|
+
}
|
|
65
|
+
::v-deep .ProductMultipack__price {
|
|
66
|
+
background-color: $green !important;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
59
69
|
}
|
|
60
70
|
}
|
|
@@ -4,11 +4,15 @@
|
|
|
4
4
|
<div
|
|
5
5
|
v-for="multipack in visibleMultipacks"
|
|
6
6
|
:key="multipack._id"
|
|
7
|
-
class="ProductMultipacksCarousel__item"
|
|
7
|
+
class="ProductMultipacksCarousel__item"
|
|
8
|
+
:class="{
|
|
9
|
+
'ProductMultipacksCarousel__item--active': multipack === selectedMultipack
|
|
10
|
+
}">
|
|
8
11
|
<product-multipack
|
|
9
12
|
:multipack="multipack"
|
|
10
13
|
:simple-products="simpleProducts"
|
|
11
|
-
class="elevation2"
|
|
14
|
+
class="elevation2"
|
|
15
|
+
@selected="toggleMultipack(multipack)" />
|
|
12
16
|
</div>
|
|
13
17
|
</div>
|
|
14
18
|
<button
|
|
@@ -27,6 +31,8 @@
|
|
|
27
31
|
</template>
|
|
28
32
|
|
|
29
33
|
<script>
|
|
34
|
+
import { mapMutations } from 'vuex';
|
|
35
|
+
import { inRange } from '@lancom/shared/assets/js/utils/filters';
|
|
30
36
|
import ProductMultipack from './product_multipack/product-multipack';
|
|
31
37
|
|
|
32
38
|
export default {
|
|
@@ -36,7 +42,8 @@ export default {
|
|
|
36
42
|
},
|
|
37
43
|
data() {
|
|
38
44
|
return {
|
|
39
|
-
thumbsPage: 0
|
|
45
|
+
thumbsPage: 0,
|
|
46
|
+
selectedMultipack: null
|
|
40
47
|
};
|
|
41
48
|
},
|
|
42
49
|
props: {
|
|
@@ -65,6 +72,38 @@ export default {
|
|
|
65
72
|
}
|
|
66
73
|
},
|
|
67
74
|
methods: {
|
|
75
|
+
toggleMultipack(multipack) {
|
|
76
|
+
this.selectedMultipack = this.selectedMultipack === multipack ? null : multipack;
|
|
77
|
+
this.clearSimpleProductsAmount();
|
|
78
|
+
if (this.selectedMultipack) {
|
|
79
|
+
this.buyMultipack()
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
...mapMutations('product', ['setSimpleProductAmount', 'clearSimpleProductsAmount']),
|
|
83
|
+
buyMultipack() {
|
|
84
|
+
const sizes = [
|
|
85
|
+
{ size: 'S', percent: 0.15 },
|
|
86
|
+
{ size: 'M', percent: 0.2 },
|
|
87
|
+
{ size: 'XL', percent: 0.3 },
|
|
88
|
+
{ size: '2XL', percent: 0.05 },
|
|
89
|
+
{ size: 'L' }
|
|
90
|
+
];
|
|
91
|
+
let leftQty = this.selectedMultipack.qty;
|
|
92
|
+
sizes.forEach(s => {
|
|
93
|
+
const simpleProduct = this.simpleProducts.find(simpleProduct => simpleProduct.size.shortName === s.size);
|
|
94
|
+
if (simpleProduct) {
|
|
95
|
+
const qty = s.percent ? +(s.percent * this.selectedMultipack.qty).toFixed(0) : leftQty;
|
|
96
|
+
const amount = inRange(qty, 0, simpleProduct.quantityStock || 999);
|
|
97
|
+
leftQty -= amount;
|
|
98
|
+
this.setSimpleProductAmount({
|
|
99
|
+
colorId: simpleProduct.color._id,
|
|
100
|
+
sizeId: simpleProduct.size._id,
|
|
101
|
+
amount
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
},
|
|
68
107
|
goToPrevPage() {
|
|
69
108
|
this.thumbsPage = Math.max(0, this.thumbsPage - 1);
|
|
70
109
|
},
|
package/components/product/product_multipacks_carousel/product_multipack/product-multipack.scss
CHANGED
|
@@ -2,11 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
.ProductMultipack {
|
|
4
4
|
&__price {
|
|
5
|
-
padding:
|
|
5
|
+
padding: 10px;
|
|
6
6
|
text-align: center;
|
|
7
7
|
font-size: 14px;
|
|
8
8
|
font-weight: bold;
|
|
9
9
|
background-color: $gray;
|
|
10
|
+
span {
|
|
11
|
+
text-align: center;
|
|
12
|
+
padding: 6px;
|
|
13
|
+
background-color: $orange;
|
|
14
|
+
color: $white;
|
|
15
|
+
display: inline-block;
|
|
16
|
+
font-weight: bold;
|
|
17
|
+
font-size: 15px;
|
|
18
|
+
margin-left: 14px;
|
|
19
|
+
}
|
|
10
20
|
}
|
|
11
21
|
&__image {
|
|
12
22
|
position: absolute;
|
|
@@ -16,28 +26,18 @@
|
|
|
16
26
|
bottom: 0;
|
|
17
27
|
background-position: left top;
|
|
18
28
|
background-repeat: no-repeat;
|
|
19
|
-
background-size:
|
|
29
|
+
background-size: cover;
|
|
20
30
|
}
|
|
21
31
|
&__banner {
|
|
22
32
|
position: relative;
|
|
23
33
|
height: 140px;
|
|
24
34
|
&-info {
|
|
25
35
|
position: absolute;
|
|
26
|
-
top:
|
|
27
|
-
right:
|
|
36
|
+
top: 0px;
|
|
37
|
+
right: 0px;
|
|
28
38
|
display: flex;
|
|
29
39
|
flex-direction: column;
|
|
30
40
|
align-items: end;
|
|
31
|
-
&-item span {
|
|
32
|
-
margin-bottom: 10px;
|
|
33
|
-
text-align: center;
|
|
34
|
-
padding: 6px;
|
|
35
|
-
background-color: $orange;
|
|
36
|
-
color: $white;
|
|
37
|
-
display: inline-block;
|
|
38
|
-
font-weight: bold;
|
|
39
|
-
font-size: 15px;
|
|
40
|
-
}
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
}
|
package/components/product/product_multipacks_carousel/product_multipack/product-multipack.vue
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
:id="`product-multipack-${multipack._id}`"
|
|
4
|
-
class="ProductMultipack__wrapper"
|
|
4
|
+
class="ProductMultipack__wrapper"
|
|
5
|
+
@click="buyMultipack()">
|
|
5
6
|
<div class="ProductMultipack__banner">
|
|
6
7
|
<div
|
|
7
8
|
class="ProductMultipack__image"
|
|
8
9
|
:style="{
|
|
9
|
-
'background-image':
|
|
10
|
+
'background-image': bannerImage ? `url('${bannerImage}'` : null
|
|
10
11
|
}">
|
|
11
12
|
</div>
|
|
12
13
|
<div class="ProductMultipack__banner-info">
|
|
@@ -14,27 +15,22 @@
|
|
|
14
15
|
<btn
|
|
15
16
|
style="padding: 10px; height: 35px; margin-bottom: 10px;"
|
|
16
17
|
btn-class="green"
|
|
17
|
-
btn-label="BUY"
|
|
18
|
+
:btn-label="`BUY ${multipack.qty}`"
|
|
18
19
|
size="sm"
|
|
19
20
|
@onclick="buyMultipack()" />
|
|
20
21
|
</div>
|
|
21
|
-
<div class="ProductMultipack__banner-info-item">
|
|
22
|
-
<span>{{ multipack.qty }}</span>
|
|
23
|
-
</div>
|
|
24
|
-
<div class="ProductMultipack__banner-info-item">
|
|
25
|
-
<span>{{ totalPrice | priceWithTax(pricingSettings, currency) }}</span>
|
|
26
|
-
</div>
|
|
27
22
|
</div>
|
|
28
23
|
</div>
|
|
29
24
|
<div class="ProductMultipack__price">
|
|
30
|
-
|
|
25
|
+
{{ oneItemPrice | priceWithTax(pricingSettings, currency) }} each
|
|
26
|
+
<span>{{ totalPrice | priceWithTax(pricingSettings, currency) }}</span>
|
|
31
27
|
</div>
|
|
32
28
|
</div>
|
|
33
29
|
</template>
|
|
34
30
|
|
|
35
31
|
<script>
|
|
36
|
-
import { mapGetters
|
|
37
|
-
import { priceWithTax
|
|
32
|
+
import { mapGetters } from 'vuex';
|
|
33
|
+
import { priceWithTax } from '@lancom/shared/assets/js/utils/filters';
|
|
38
34
|
|
|
39
35
|
export default {
|
|
40
36
|
name: 'LancomProductMultipack',
|
|
@@ -53,6 +49,10 @@ export default {
|
|
|
53
49
|
},
|
|
54
50
|
computed: {
|
|
55
51
|
...mapGetters(['pricingSettings', 'currency']),
|
|
52
|
+
bannerImage() {
|
|
53
|
+
const banner = this.multipack.banner?.editorImage || this.multipack.banner;
|
|
54
|
+
return banner?.origin;
|
|
55
|
+
},
|
|
56
56
|
simpleProduct() {
|
|
57
57
|
return (this.simpleProducts || []).find(sp => sp.SKU === this.multipack.SKU);
|
|
58
58
|
},
|
|
@@ -64,13 +64,8 @@ export default {
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
methods: {
|
|
67
|
-
...mapMutations('product', ['setSimpleProductAmount']),
|
|
68
67
|
buyMultipack() {
|
|
69
|
-
this.
|
|
70
|
-
colorId: this.simpleProduct.color._id,
|
|
71
|
-
sizeId: this.simpleProduct.size._id,
|
|
72
|
-
amount: inRange(this.multipack.qty, 0, this.simpleProduct.quantityStock || 999)
|
|
73
|
-
});
|
|
68
|
+
this.$emit('selected', this.multipack);
|
|
74
69
|
}
|
|
75
70
|
}
|
|
76
71
|
};
|
package/feeds/google-shopping.js
CHANGED
|
@@ -96,10 +96,10 @@ async function googleShoppingFeed(axios, config, availableStores) {
|
|
|
96
96
|
}
|
|
97
97
|
if (product.volume) {
|
|
98
98
|
if (product.volume.length) {
|
|
99
|
-
info['g:shipping_length'] = { _text: `${parseInt(product.volume.length
|
|
99
|
+
info['g:shipping_length'] = { _text: `${parseInt(product.volume.length)} cm` };
|
|
100
100
|
}
|
|
101
101
|
if (product.volume.width) {
|
|
102
|
-
info['g:shipping_width'] = { _text: `${parseInt(product.volume.width
|
|
102
|
+
info['g:shipping_width'] = { _text: `${parseInt(product.volume.width)} cm` };
|
|
103
103
|
}
|
|
104
104
|
if (product.volume.height) {
|
|
105
105
|
info['g:shipping_height'] = { _text: `${parseInt(product.volume.height * (sp.multipackQty || 1))} cm` };
|
package/package.json
CHANGED
package/store/product.js
CHANGED
|
@@ -67,6 +67,7 @@ export const getters = {
|
|
|
67
67
|
hasLayers: ({ template }) => (template.layers || []).length > 0,
|
|
68
68
|
visibleSteps: ({ template }) => template.visibleSteps,
|
|
69
69
|
simpleProducts: ({ template }) => template.simpleProducts || [],
|
|
70
|
+
editableColorSimpleProducts: ({ template, editableColor }) => (template.simpleProducts || []).filter(sp => sp.color._id === editableColor._id),
|
|
70
71
|
usedSimpleProducts: ({ template }) => (template.simpleProducts || []).filter(p => p.amount > 0),
|
|
71
72
|
usedSimpleProductsQuantity: ({ template }) => (template.simpleProducts || []).filter(p => p.amount > 0).reduce((sum, { amount }) => sum + amount, 0),
|
|
72
73
|
usedBigSizeSimpleProductsQuantity: (state, { usedSimpleProducts }) => filterBigSize(usedSimpleProducts).reduce((sum, { amount }) => sum + amount, 0),
|
|
@@ -409,6 +410,12 @@ export const mutations = {
|
|
|
409
410
|
Vue.set(state.template.simpleProducts, index, simpleProduct);
|
|
410
411
|
}
|
|
411
412
|
},
|
|
413
|
+
clearSimpleProductsAmount(state) {
|
|
414
|
+
state.template.simpleProducts.forEach((simpleProduct, index) => {
|
|
415
|
+
Vue.set(simpleProduct, 'amount', 0);
|
|
416
|
+
Vue.set(state.template.simpleProducts, index, simpleProduct);
|
|
417
|
+
})
|
|
418
|
+
},
|
|
412
419
|
setProductPricing(state, price) {
|
|
413
420
|
state.productPricing = price;
|
|
414
421
|
},
|