@lancom/shared 0.0.384 → 0.0.386
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/assets/js/api/admin.js +12 -0
- package/assets/js/api/index.js +8 -1
- package/assets/js/utils/scroll.js +11 -0
- package/components/checkout/cart/cart.vue +26 -1
- package/components/checkout/cart/cart_entity/cart-entity.mixin.js +4 -0
- package/components/checkout/cart/cart_entity/cart-entity.vue +2 -0
- package/components/checkout/cart/cart_entity/cart_entity_color_simple_products/cart-entity-color-simple-products.vue +2 -0
- package/components/checkout/cart/cart_products_kit_entity/cart-products-kit-entity.scss +24 -0
- package/components/checkout/cart/cart_products_kit_entity/cart-products-kit-entity.vue +66 -0
- package/components/common/number_input/number-input.scss +69 -0
- package/components/common/number_input/number-input.vue +97 -0
- package/components/editor/editor.vue +4 -12
- package/components/editor/mobile_editor_product_details/mobile-editor-product-details.vue +2 -10
- package/components/products_kit/products_kit/products-kit.scss +54 -0
- package/components/products_kit/products_kit/products-kit.vue +47 -0
- package/components/products_kit/products_kit/products_kit_cart/products-kit-cart.scss +32 -0
- package/components/products_kit/products_kit/products_kit_cart/products-kit-cart.vue +132 -0
- package/components/products_kit/products_kit/products_kit_cart/products_kit_cart_options/products-kit-cart-options.scss +15 -0
- package/components/products_kit/products_kit/products_kit_cart/products_kit_cart_options/products-kit-cart-options.vue +31 -0
- package/components/products_kit/products_kit/products_kit_cart/products_kit_cart_options/products_kit_cart_option/products-kit-cart-option.scss +41 -0
- package/components/products_kit/products_kit/products_kit_cart/products_kit_cart_options/products_kit_cart_option/products-kit-cart-option.vue +89 -0
- package/components/products_kit/products_kit/products_kit_options/products-kit-options.scss +9 -0
- package/components/products_kit/products_kit/products_kit_options/products-kit-options.vue +32 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products-kit-option.scss +1 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products-kit-option.vue +36 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_color/products-kit-option-color.scss +1 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_color/products-kit-option-color.vue +88 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_products/products-kit-option-products.scss +7 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_products/products-kit-option-products.vue +36 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_products/products_kit_option_product/products-kit-option-product.scss +20 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_products/products_kit_option_product/products-kit-option-product.vue +127 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_size/products-kit-option-size.scss +1 -0
- package/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_size/products-kit-option-size.vue +87 -0
- package/components/products_kit/products_kits_list/products-kits-list.scss +68 -0
- package/components/products_kit/products_kits_list/products-kits-list.vue +50 -0
- package/components/products_kit/products_kits_list/products_kits_list_item/products-kits-list-item.scss +84 -0
- package/components/products_kit/products_kits_list/products_kits_list_item/products-kits-list-item.vue +52 -0
- package/mixins/product-preview.js +6 -0
- package/package.json +1 -1
- package/pages/contact.vue +54 -0
- package/pages/products-kit/_alias.vue +103 -0
- package/pages/products-kit/index.vue +59 -0
- package/routes/index.js +15 -0
- package/server-middleware/robots.js +2 -1
- package/store/cart.js +1 -1
- package/store/productsKit.js +175 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitCart__wrapper">
|
|
3
|
+
<div class="ProductsKitCart__products">
|
|
4
|
+
<products-kit-cart-options :productsKit="productsKit" />
|
|
5
|
+
<div class="ProductsKitCart__qty">
|
|
6
|
+
<number-input
|
|
7
|
+
v-model="kitQty"
|
|
8
|
+
:disabled="addingToCart || !isAllOptionsSelected" />
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="ProductsKitCart__info">
|
|
12
|
+
<div class="ProductsKitCart__price">
|
|
13
|
+
{{ totalPrice | price }}
|
|
14
|
+
</div>
|
|
15
|
+
<div>
|
|
16
|
+
<btn
|
|
17
|
+
:btn-disabled="addingToCart || !isAllOptionsSelected"
|
|
18
|
+
btn-class="green"
|
|
19
|
+
btn-label="ADD TO CART"
|
|
20
|
+
@onclick="proceedToCard()"/>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script>
|
|
27
|
+
import { mapGetters, mapActions } from 'vuex';
|
|
28
|
+
import debounce from 'lodash.debounce';
|
|
29
|
+
import { price } from '@lancom/shared/assets/js/utils/filters';
|
|
30
|
+
import NumberInput from '@lancom/shared/components/common/number_input/number-input';
|
|
31
|
+
import ProductsKitCartOptions from './products_kit_cart_options/products-kit-cart-options';
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
name: 'ProductsKitCart',
|
|
36
|
+
filters: {
|
|
37
|
+
price
|
|
38
|
+
},
|
|
39
|
+
components: {
|
|
40
|
+
ProductsKitCartOptions,
|
|
41
|
+
NumberInput
|
|
42
|
+
},
|
|
43
|
+
data() {
|
|
44
|
+
return {
|
|
45
|
+
addingToCart: false,
|
|
46
|
+
calculateCartPriceWithDebounce: debounce(this.recalculatePricing, 300)
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
props: {
|
|
50
|
+
productsKit: {
|
|
51
|
+
type: Object,
|
|
52
|
+
required: true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
computed: {
|
|
56
|
+
...mapGetters(['shop', 'country', 'currency', 'googleClickId']),
|
|
57
|
+
...mapGetters('productsKit', [
|
|
58
|
+
'amount',
|
|
59
|
+
'isAllOptionsSelected',
|
|
60
|
+
'maxOrderQty',
|
|
61
|
+
'selectedOptionsProducts',
|
|
62
|
+
'selectedSimpleProducts',
|
|
63
|
+
'productsKitPricing',
|
|
64
|
+
'cartEntities'
|
|
65
|
+
]),
|
|
66
|
+
kitQty: {
|
|
67
|
+
get() {
|
|
68
|
+
return this.amount
|
|
69
|
+
},
|
|
70
|
+
set(qty) {
|
|
71
|
+
this.updateAmount(qty);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
totalPrice() {
|
|
75
|
+
return this.productsKitPricing?.totalPrice || 0;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
watch: {
|
|
79
|
+
selectedSimpleProducts() {
|
|
80
|
+
this.calculateCartPriceWithDebounce();
|
|
81
|
+
},
|
|
82
|
+
amount() {
|
|
83
|
+
this.calculateCartPriceWithDebounce();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
methods: {
|
|
87
|
+
...mapActions('productsKit', [
|
|
88
|
+
'calculateProductsKitPrice',
|
|
89
|
+
'clearOptions',
|
|
90
|
+
'clearProductsKitPricing',
|
|
91
|
+
'updateAmount'
|
|
92
|
+
]),
|
|
93
|
+
...mapActions('cart', ['addToCart']),
|
|
94
|
+
async proceedToCard() {
|
|
95
|
+
if (this.addingToCart || !this.isAllOptionsSelected) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
this.addingToCart = true;
|
|
100
|
+
const data = {
|
|
101
|
+
entities: this.cartEntities,
|
|
102
|
+
shop: this.shop,
|
|
103
|
+
pricing: this.productsKitPricing,
|
|
104
|
+
country: this.country,
|
|
105
|
+
currency: this.currency,
|
|
106
|
+
googleClickId: this.googleClickId
|
|
107
|
+
};
|
|
108
|
+
await this.addToCart(data);
|
|
109
|
+
this.$toastr.s('Products Kit successfully added to cart');
|
|
110
|
+
this.clearOptions();
|
|
111
|
+
this.clearProductsKitPricing();
|
|
112
|
+
} catch (e) {
|
|
113
|
+
console.log(e);
|
|
114
|
+
} finally {
|
|
115
|
+
this.addingToCart = false;
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
recalculatePricing() {
|
|
119
|
+
const params = {
|
|
120
|
+
country: this.country,
|
|
121
|
+
currency: this.currency,
|
|
122
|
+
shop: this.shop
|
|
123
|
+
};
|
|
124
|
+
this.calculateProductsKitPrice(params);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
</script>
|
|
129
|
+
|
|
130
|
+
<style lang="scss" scoped>
|
|
131
|
+
@import 'products-kit-cart';
|
|
132
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitCartOptions__wrapper">
|
|
3
|
+
<products-kit-cart-option
|
|
4
|
+
v-for="option in productsKit.options"
|
|
5
|
+
:key="option._id"
|
|
6
|
+
:products-kit="productsKit"
|
|
7
|
+
:option="option"
|
|
8
|
+
class="ProductsKitCartOptions__option" />
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
import ProductsKitCartOption from './products_kit_cart_option/products-kit-cart-option';
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
name: 'ProductsKitCartOptions',
|
|
17
|
+
components: {
|
|
18
|
+
ProductsKitCartOption
|
|
19
|
+
},
|
|
20
|
+
props: {
|
|
21
|
+
productsKit: {
|
|
22
|
+
type: Object,
|
|
23
|
+
required: true
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<style lang="scss" scoped>
|
|
30
|
+
@import 'products-kit-cart-options';
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|
|
2
|
+
|
|
3
|
+
.ProductsKitCartOption {
|
|
4
|
+
&__wrapper {
|
|
5
|
+
position: relative;
|
|
6
|
+
margin: 4px;
|
|
7
|
+
}
|
|
8
|
+
&__placeholder,
|
|
9
|
+
&__product {
|
|
10
|
+
position: absolute;
|
|
11
|
+
top: 0;
|
|
12
|
+
right: 0;
|
|
13
|
+
bottom: 0;
|
|
14
|
+
left: 0;
|
|
15
|
+
background-color: white;
|
|
16
|
+
background-size: contain;
|
|
17
|
+
background-repeat: no-repeat;
|
|
18
|
+
background-position: center center;
|
|
19
|
+
}
|
|
20
|
+
&__clear {
|
|
21
|
+
cursor: pointer;
|
|
22
|
+
font-size: 10px;
|
|
23
|
+
padding: 5px 7px;
|
|
24
|
+
border-radius: 50%;
|
|
25
|
+
background-color: rgb(205, 205, 205);
|
|
26
|
+
color: black;
|
|
27
|
+
position: absolute;
|
|
28
|
+
top: -5px;
|
|
29
|
+
right: -5px;
|
|
30
|
+
}
|
|
31
|
+
&__placeholder {
|
|
32
|
+
display: flex;
|
|
33
|
+
align-items: center;
|
|
34
|
+
justify-content: center;
|
|
35
|
+
span {
|
|
36
|
+
font-size: 24px;
|
|
37
|
+
font-weight: bold;
|
|
38
|
+
color: grey;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitCartOption__wrapper">
|
|
3
|
+
<div
|
|
4
|
+
v-if="selectedSimpleProduct"
|
|
5
|
+
class="ProductsKitCartOption__product"
|
|
6
|
+
:style="productСoverBg"
|
|
7
|
+
@click="scrollToOption()">
|
|
8
|
+
<div
|
|
9
|
+
class="ProductsKitCartOption__clear"
|
|
10
|
+
@click.stop.prevent="unselectOption()">
|
|
11
|
+
x
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
<div
|
|
15
|
+
v-else
|
|
16
|
+
class="ProductsKitCartOption__placeholder"
|
|
17
|
+
@click="scrollToOption()">
|
|
18
|
+
<span>+</span>
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script>
|
|
24
|
+
import { getProductMediumCover, getBgStyle } from '@lancom/shared/assets/js/utils/colors';
|
|
25
|
+
import { scrollToElement } from '@lancom/shared/assets/js/utils/scroll';
|
|
26
|
+
import { mapGetters, mapActions } from 'vuex';
|
|
27
|
+
|
|
28
|
+
export default {
|
|
29
|
+
name: 'ProductsKitCartOption',
|
|
30
|
+
props: {
|
|
31
|
+
productsKit: {
|
|
32
|
+
type: Object,
|
|
33
|
+
required: true
|
|
34
|
+
},
|
|
35
|
+
option: {
|
|
36
|
+
type: Object,
|
|
37
|
+
required: true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
computed: {
|
|
41
|
+
...mapGetters('productsKit', [
|
|
42
|
+
'selectedOptionsProducts',
|
|
43
|
+
'selectedOptionsSimpleProducts',
|
|
44
|
+
'selectedOptionsColors',
|
|
45
|
+
'selectedOptionsSizes'
|
|
46
|
+
]),
|
|
47
|
+
selectedColor() {
|
|
48
|
+
return this.selectedOptionsColors[this.option._id];
|
|
49
|
+
},
|
|
50
|
+
selectedSize() {
|
|
51
|
+
return this.selectedOptionsSizes[this.option._id];
|
|
52
|
+
},
|
|
53
|
+
selectedProduct() {
|
|
54
|
+
const selectedProductId = this.selectedOptionsProducts[this.option._id]?._id;
|
|
55
|
+
const product = this.option.products.find(p => p._id === selectedProductId);
|
|
56
|
+
return product;
|
|
57
|
+
},
|
|
58
|
+
selectedSimpleProduct() {
|
|
59
|
+
const simpleProducts = this.selectedOptionsSimpleProducts[this.option._id] || [];
|
|
60
|
+
return simpleProducts.find(sp => {
|
|
61
|
+
const isSameSize = sp.size?._id === this.selectedSize?._id;
|
|
62
|
+
const isSameColor = sp.color?._id === this.selectedColor?._id;
|
|
63
|
+
return isSameSize && isSameColor;
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
productСover() {
|
|
67
|
+
return getProductMediumCover(this.selectedProduct, 'front', this.selectedColor);
|
|
68
|
+
},
|
|
69
|
+
productСoverBg() {
|
|
70
|
+
return getBgStyle(this.productСover);
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
methods: {
|
|
74
|
+
...mapActions('productsKit', ['clearOption']),
|
|
75
|
+
unselectOption() {
|
|
76
|
+
const params = { option: this.option };
|
|
77
|
+
this.clearOption(params);
|
|
78
|
+
},
|
|
79
|
+
scrollToOption() {
|
|
80
|
+
console.log('option: ', this.option);
|
|
81
|
+
scrollToElement(`option_${this.option._id}`, 200);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<style lang="scss" scoped>
|
|
88
|
+
@import 'products-kit-cart-option';
|
|
89
|
+
</style>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitOptions__wrapper">
|
|
3
|
+
<products-kit-option
|
|
4
|
+
v-for="option in productsKit.options"
|
|
5
|
+
:key="option._id"
|
|
6
|
+
:products-kit="productsKit"
|
|
7
|
+
:option="option"
|
|
8
|
+
:id="`option_${option._id}`"
|
|
9
|
+
class="ProductsKitOptions__option" />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import ProductsKitOption from './products_kit_option/products-kit-option';
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
name: 'ProductsKitOptions',
|
|
18
|
+
components: {
|
|
19
|
+
ProductsKitOption
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
productsKit: {
|
|
23
|
+
type: Object,
|
|
24
|
+
required: true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
</script>
|
|
29
|
+
|
|
30
|
+
<style lang="scss" scoped>
|
|
31
|
+
@import 'products-kit-options';
|
|
32
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitOption__wrapper">
|
|
3
|
+
<div class="mb-6">
|
|
4
|
+
<div class="lc_h3">{{ option.name }}</div>
|
|
5
|
+
<div v-html="option.description"></div>
|
|
6
|
+
</div>
|
|
7
|
+
<products-kit-option-products
|
|
8
|
+
:products-kit="productsKit"
|
|
9
|
+
:option="option" />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import ProductsKitOptionProducts from './products_kit_option_products/products-kit-option-products';
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
name: 'ProductsKitOption',
|
|
18
|
+
components: {
|
|
19
|
+
ProductsKitOptionProducts
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
productsKit: {
|
|
23
|
+
type: Object,
|
|
24
|
+
required: true
|
|
25
|
+
},
|
|
26
|
+
option: {
|
|
27
|
+
type: Object,
|
|
28
|
+
required: true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<style lang="scss" scoped>
|
|
35
|
+
@import 'products-kit-option';
|
|
36
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitOptionColor__wrapper">
|
|
3
|
+
<multiselect
|
|
4
|
+
v-model="selectedColor"
|
|
5
|
+
value="_id"
|
|
6
|
+
label="name"
|
|
7
|
+
track-by="_id"
|
|
8
|
+
placeholder="Select colour"
|
|
9
|
+
:options="availableColors"
|
|
10
|
+
:allow-empty="false"
|
|
11
|
+
:searchable="false"
|
|
12
|
+
:option-height="60">
|
|
13
|
+
<template #option="{ option }">
|
|
14
|
+
<div class="ProductsKitOptionColor__option">
|
|
15
|
+
<span
|
|
16
|
+
class="ProductsKitOptionColor__option-name">
|
|
17
|
+
{{ option.name }}
|
|
18
|
+
</span>
|
|
19
|
+
<product-color-image
|
|
20
|
+
class="ProductsKitOptionColor__option-preview"
|
|
21
|
+
:color="option" />
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
<template #singleLabel="{ option }">
|
|
25
|
+
<div class="ProductsKitOptionColor__option">
|
|
26
|
+
{{ option.name }}
|
|
27
|
+
</div>
|
|
28
|
+
</template>
|
|
29
|
+
</multiselect>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script>
|
|
34
|
+
import { mapGetters, mapActions } from 'vuex';
|
|
35
|
+
import Multiselect from 'vue-multiselect';
|
|
36
|
+
import ProductColorImage from '@lancom/shared/components/product/product_color_image/product-color-image';
|
|
37
|
+
|
|
38
|
+
export default {
|
|
39
|
+
name: 'ProductsKitOptionColor',
|
|
40
|
+
components: {
|
|
41
|
+
Multiselect,
|
|
42
|
+
ProductColorImage
|
|
43
|
+
},
|
|
44
|
+
props: {
|
|
45
|
+
productsKit: {
|
|
46
|
+
type: Object,
|
|
47
|
+
required: true
|
|
48
|
+
},
|
|
49
|
+
option: {
|
|
50
|
+
type: Object,
|
|
51
|
+
required: true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
computed: {
|
|
55
|
+
...mapGetters('productsKit', [
|
|
56
|
+
'selectedOptionsSimpleProducts',
|
|
57
|
+
'selectedOptionsColors',
|
|
58
|
+
]),
|
|
59
|
+
selectedColor: {
|
|
60
|
+
get () {
|
|
61
|
+
return this.selectedOptionsColors[this.option._id];
|
|
62
|
+
},
|
|
63
|
+
set(color) {
|
|
64
|
+
this.selectOptionColor({ option: this.option, color });
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
availableColors() {
|
|
68
|
+
const simpleProducts = this.selectedOptionsSimpleProducts[this.option._id] || [];
|
|
69
|
+
const uniqueColorsMap = new Map();
|
|
70
|
+
simpleProducts
|
|
71
|
+
.filter(sp => sp.quantityStock > 0)
|
|
72
|
+
.forEach(sp => {
|
|
73
|
+
if (sp.color && !uniqueColorsMap.has(sp.color._id)) {
|
|
74
|
+
uniqueColorsMap.set(sp.color._id, sp.color);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return Array.from(uniqueColorsMap.values());
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
methods: {
|
|
81
|
+
...mapActions('productsKit', ['selectOptionColor'])
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<style lang="scss" scoped>
|
|
87
|
+
@import 'products-kit-option-color';
|
|
88
|
+
</style>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductsKitOptionProducts__wrapper">
|
|
3
|
+
<products-kit-option-product
|
|
4
|
+
v-for="product in option.products"
|
|
5
|
+
:key="product._id"
|
|
6
|
+
:products-kit="productsKit"
|
|
7
|
+
:option="option"
|
|
8
|
+
:product="product"
|
|
9
|
+
class="ProductsKitOptionProducts__product" />
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import ProductsKitOptionProduct from './products_kit_option_product/products-kit-option-product';
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
name: 'ProductsKitOptionProducts',
|
|
18
|
+
components: {
|
|
19
|
+
ProductsKitOptionProduct
|
|
20
|
+
},
|
|
21
|
+
props: {
|
|
22
|
+
productsKit: {
|
|
23
|
+
type: Object,
|
|
24
|
+
required: true
|
|
25
|
+
},
|
|
26
|
+
option: {
|
|
27
|
+
type: Object,
|
|
28
|
+
required: true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<style lang="scss" scoped>
|
|
35
|
+
@import 'products-kit-option-products';
|
|
36
|
+
</style>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|
|
2
|
+
|
|
3
|
+
.ProductsKitOptionProduct {
|
|
4
|
+
&__wrapper {
|
|
5
|
+
border: 1px solid $gray;
|
|
6
|
+
&--active {
|
|
7
|
+
border: 1px solid $green;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
&__preview {
|
|
11
|
+
width: 250px;
|
|
12
|
+
height: 490px;
|
|
13
|
+
margin: 0 0 15px 15px;
|
|
14
|
+
position: relative;
|
|
15
|
+
z-index: 1;
|
|
16
|
+
}
|
|
17
|
+
&__select {
|
|
18
|
+
padding: 0 20px 10px 20px;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="ProductsKitOptionProduct__wrapper"
|
|
4
|
+
:class="{
|
|
5
|
+
'ProductsKitOptionProduct__wrapper--active': isSelectedProduct
|
|
6
|
+
}">
|
|
7
|
+
<div class="ProductsKitOptionProduct__preview">
|
|
8
|
+
<product-preview-main
|
|
9
|
+
ref="preview"
|
|
10
|
+
:product="product"
|
|
11
|
+
:to-editor="false"
|
|
12
|
+
@color="onProductSelectColor($event)" />
|
|
13
|
+
</div>
|
|
14
|
+
<div class="ProductsKitOptionProduct__select">
|
|
15
|
+
<btn
|
|
16
|
+
:btn-block="true"
|
|
17
|
+
@onclick="selectProduct"
|
|
18
|
+
:btn-class="isSelectedProduct ? 'green' : 'gray'"
|
|
19
|
+
btn-label="SELECT" />
|
|
20
|
+
<div
|
|
21
|
+
v-if="isSelectedProduct"
|
|
22
|
+
class="mt-5">
|
|
23
|
+
<products-kit-option-color
|
|
24
|
+
:products-kit="productsKit"
|
|
25
|
+
:option="option"
|
|
26
|
+
@color="onChooseColor($event)" />
|
|
27
|
+
<products-kit-option-size
|
|
28
|
+
class="mt-5"
|
|
29
|
+
:products-kit="productsKit"
|
|
30
|
+
:option="option" />
|
|
31
|
+
<div
|
|
32
|
+
v-if="selectedSimpleProduct"
|
|
33
|
+
class="mt-5 lc_subtitle3">
|
|
34
|
+
Stock: {{ currentQuantityStockLabel }}
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script>
|
|
42
|
+
import { mapGetters, mapActions } from 'vuex';
|
|
43
|
+
import ProductPreviewMain from '@/components/product/product_preview_main/product-preview-main';
|
|
44
|
+
import ProductsKitOptionColor from '@lancom/shared/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_color/products-kit-option-color';
|
|
45
|
+
import ProductsKitOptionSize from '@lancom/shared/components/products_kit/products_kit/products_kit_options/products_kit_option/products_kit_option_size/products-kit-option-size';
|
|
46
|
+
|
|
47
|
+
export default {
|
|
48
|
+
name: 'ProductsKitOptionProduct',
|
|
49
|
+
components: {
|
|
50
|
+
ProductPreviewMain,
|
|
51
|
+
ProductsKitOptionColor,
|
|
52
|
+
ProductsKitOptionSize
|
|
53
|
+
},
|
|
54
|
+
props: {
|
|
55
|
+
productsKit: {
|
|
56
|
+
type: Object,
|
|
57
|
+
required: true
|
|
58
|
+
},
|
|
59
|
+
option: {
|
|
60
|
+
type: Object,
|
|
61
|
+
required: true
|
|
62
|
+
},
|
|
63
|
+
product: {
|
|
64
|
+
type: Object,
|
|
65
|
+
required: true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
computed: {
|
|
69
|
+
...mapGetters(['country', 'currency', 'stockCountry']),
|
|
70
|
+
...mapGetters('productsKit', [
|
|
71
|
+
'selectedOptionsProducts',
|
|
72
|
+
'selectedOptionsSimpleProducts',
|
|
73
|
+
'selectedOptionsColors',
|
|
74
|
+
'selectedOptionsSizes'
|
|
75
|
+
]),
|
|
76
|
+
isSelectedProduct() {
|
|
77
|
+
return this.selectedOptionsProducts[this.option._id]?._id === this.product._id;
|
|
78
|
+
},
|
|
79
|
+
selectedColor() {
|
|
80
|
+
return this.selectedOptionsColors[this.option._id];
|
|
81
|
+
},
|
|
82
|
+
selectedSize() {
|
|
83
|
+
return this.selectedOptionsSizes[this.option._id];
|
|
84
|
+
},
|
|
85
|
+
selectedSimpleProduct() {
|
|
86
|
+
const simpleProducts = this.selectedOptionsSimpleProducts[this.option._id] || [];
|
|
87
|
+
return simpleProducts.find(sp => {
|
|
88
|
+
const isSameSize = sp.size?._id === this.selectedSize?._id;
|
|
89
|
+
const isSameColor = sp.color?._id === this.selectedColor?._id;
|
|
90
|
+
return isSameSize && isSameColor;
|
|
91
|
+
});
|
|
92
|
+
},
|
|
93
|
+
currentQuantityStock() {
|
|
94
|
+
return (this.selectedSimpleProduct?.quantityStock || 0);
|
|
95
|
+
},
|
|
96
|
+
currentQuantityStockLabel() {
|
|
97
|
+
return this.currentQuantityStock > 100 ? '100+' : this.currentQuantityStock;
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
watch: {
|
|
101
|
+
selectedColor() {
|
|
102
|
+
const color = this.isSelectedProduct ? this.selectedColor : null;
|
|
103
|
+
this.$refs.preview.currentColor = color;
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
methods: {
|
|
107
|
+
...mapActions('productsKit', ['selectOptionProduct', 'selectOptionColor']),
|
|
108
|
+
selectProduct() {
|
|
109
|
+
const params = {
|
|
110
|
+
country: this.country?._id,
|
|
111
|
+
currency: this.currency?._id,
|
|
112
|
+
stockCountry: this.stockCountry?._id,
|
|
113
|
+
option: this.option,
|
|
114
|
+
product: this.product
|
|
115
|
+
};
|
|
116
|
+
this.selectOptionProduct(params);
|
|
117
|
+
},
|
|
118
|
+
onProductSelectColor(color) {
|
|
119
|
+
this.selectOptionColor({ option: this.option, color });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
</script>
|
|
124
|
+
|
|
125
|
+
<style lang="scss" scoped>
|
|
126
|
+
@import 'products-kit-option-product';
|
|
127
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|