@lancom/shared 0.0.421 → 0.0.423
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/product/product_colors_selector/product-colors-selector.vue +22 -13
- package/components/product/product_size_selector/product_size_selector_color/product_size_selector_color_cell/product-size-selector-color-cell.vue +23 -3
- package/components/product/products_multipacks_size_selector_color/product_multipacks_size_selector_color/product-multipacks-size-selector-color.scss +61 -0
- package/components/product/products_multipacks_size_selector_color/product_multipacks_size_selector_color/product-multipacks-size-selector-color.vue +102 -0
- package/components/product/products_multipacks_size_selector_color/products-multipacks-size-selector-color.scss +15 -0
- package/components/product/products_multipacks_size_selector_color/products-multipacks-size-selector-color.vue +95 -0
- package/components/product/wizard/wizard_print_underbase/wizard-print-underbase.vue +5 -1
- package/components/product/wizard-editor/wizard-editor.vue +5 -1
- package/components/products/children_categories/children-categories.scss +3 -3
- package/components/quotes/quote_view/quote-view.scss +14 -1
- package/components/quotes/quote_view/quote-view.vue +55 -23
- package/components/quotes/quote_view/quote_option_view/quote-option-view.vue +18 -6
- package/layouts/products.vue +7 -13
- package/package.json +1 -1
- package/pages/quotes/view/_id/option/_option.vue +24 -0
- package/routes/index.js +5 -0
- package/store/product.js +1 -0
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
:display-products-count="true"
|
|
64
64
|
class="ProductColorsSelector__section" />
|
|
65
65
|
<div
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
v-if="hasToggleGst"
|
|
67
|
+
class="ProductColorsSelector__toggle-gst">
|
|
68
68
|
<checkbox
|
|
69
69
|
v-model="inclGST"
|
|
70
70
|
:dark="true"
|
|
@@ -75,13 +75,14 @@
|
|
|
75
75
|
</div>
|
|
76
76
|
<div class="ProductColorsSelector__countries">
|
|
77
77
|
<div>
|
|
78
|
-
Stock by countries:
|
|
78
|
+
Stock by countries:
|
|
79
79
|
</div>
|
|
80
80
|
<div>
|
|
81
81
|
<client-settings-stock-country />
|
|
82
82
|
</div>
|
|
83
83
|
</div>
|
|
84
|
-
<
|
|
84
|
+
<component
|
|
85
|
+
:is="productsSizeSelector"
|
|
85
86
|
:key="productDetailsKey"
|
|
86
87
|
:with-gst="inclGSTFinal"
|
|
87
88
|
class="ProductColorsSelector__section"
|
|
@@ -101,6 +102,7 @@ import ProductColorsSelector from '@lancom/shared/components/product/layouts/pro
|
|
|
101
102
|
import ProductColorsSelectorOptions from '@lancom/shared/components/product/layouts/product_colors_selector/product_colors_selector_options/product-colors-selector-options';
|
|
102
103
|
import ProductColorImage from '@lancom/shared/components/product/product_color_image/product-color-image';
|
|
103
104
|
import ProductsSizeSelectorColor from '@lancom/shared/components/product/products_size_selector_color/products-size-selector-color';
|
|
105
|
+
import ProductsMultipacksSizeSelectorColor from '@lancom/shared/components/product/products_multipacks_size_selector_color/products-multipacks-size-selector-color';
|
|
104
106
|
import ClientSettingsStockCountry from '@lancom/shared/components/common/client_settings_stock_country/client-settings-stock-country';
|
|
105
107
|
|
|
106
108
|
export default {
|
|
@@ -113,14 +115,6 @@ export default {
|
|
|
113
115
|
Multiselect,
|
|
114
116
|
ClientSettingsStockCountry
|
|
115
117
|
},
|
|
116
|
-
data() {
|
|
117
|
-
return {
|
|
118
|
-
inclGSTFinal: false,
|
|
119
|
-
inclGSTSpinner: false,
|
|
120
|
-
inclGSTSpinnerTimer: null,
|
|
121
|
-
opened: true
|
|
122
|
-
};
|
|
123
|
-
},
|
|
124
118
|
props: {
|
|
125
119
|
hasAnotherPrintBtn: {
|
|
126
120
|
type: Boolean,
|
|
@@ -131,9 +125,17 @@ export default {
|
|
|
131
125
|
default: true
|
|
132
126
|
}
|
|
133
127
|
},
|
|
128
|
+
data() {
|
|
129
|
+
return {
|
|
130
|
+
inclGSTFinal: false,
|
|
131
|
+
inclGSTSpinner: false,
|
|
132
|
+
inclGSTSpinnerTimer: null,
|
|
133
|
+
opened: true
|
|
134
|
+
};
|
|
135
|
+
},
|
|
134
136
|
computed: {
|
|
135
137
|
...mapGetters(['stockCountry', 'taxName']),
|
|
136
|
-
...mapGetters('product', ['productDetailsKey', 'editableColor', 'availableColors', 'visibleSteps', 'hasLayers', 'isPrintPricing', 'priceIncludeGST']),
|
|
138
|
+
...mapGetters('product', ['product', 'productDetailsKey', 'editableColor', 'availableColors', 'visibleSteps', 'hasLayers', 'isPrintPricing', 'priceIncludeGST']),
|
|
137
139
|
selectedColor: {
|
|
138
140
|
get() {
|
|
139
141
|
return this.editableColor;
|
|
@@ -149,6 +151,13 @@ export default {
|
|
|
149
151
|
set(value) {
|
|
150
152
|
this.setPriceIncludeGST(value);
|
|
151
153
|
}
|
|
154
|
+
},
|
|
155
|
+
productsSizeSelector() {
|
|
156
|
+
return this.availableMultipacksColorsSelector ? ProductsMultipacksSizeSelectorColor : ProductsSizeSelectorColor;
|
|
157
|
+
},
|
|
158
|
+
availableMultipacksColorsSelector() {
|
|
159
|
+
const multipacks = (this.product.multipacks || []);
|
|
160
|
+
return multipacks.some(m => !m.SKU);
|
|
152
161
|
}
|
|
153
162
|
},
|
|
154
163
|
watch: {
|
|
@@ -63,6 +63,9 @@ export default {
|
|
|
63
63
|
type: Object,
|
|
64
64
|
required: true
|
|
65
65
|
},
|
|
66
|
+
multipack: {
|
|
67
|
+
type: Object
|
|
68
|
+
},
|
|
66
69
|
sideControls: {
|
|
67
70
|
type: Boolean,
|
|
68
71
|
default: false
|
|
@@ -88,7 +91,7 @@ export default {
|
|
|
88
91
|
},
|
|
89
92
|
computed: {
|
|
90
93
|
...mapGetters(['currency']),
|
|
91
|
-
...mapGetters('product', ['usedSimpleProducts', 'product']),
|
|
94
|
+
...mapGetters('product', ['commonProductsMultipacks', 'usedSimpleProducts', 'product']),
|
|
92
95
|
disabled() {
|
|
93
96
|
const sizeWithoutColor = this.color.sizes && !this.color.sizes.find(({ alias }) => alias === this.size.alias);
|
|
94
97
|
return sizeWithoutColor || this.outStock;
|
|
@@ -97,17 +100,34 @@ export default {
|
|
|
97
100
|
return this.usedSimpleProducts
|
|
98
101
|
.find(({ color, size }) => color._id === this.color._id && size._id === this.size._id);
|
|
99
102
|
},
|
|
103
|
+
simpleProductAmount() {
|
|
104
|
+
return (this.simpleProduct || {}).amount || this.defaultValue || 0;
|
|
105
|
+
},
|
|
100
106
|
model: {
|
|
101
107
|
get() {
|
|
102
|
-
|
|
108
|
+
const amount = this.simpleProductAmount;
|
|
109
|
+
if (this.multipack) {
|
|
110
|
+
const biggerMultipacks = [...this.commonProductsMultipacks]
|
|
111
|
+
.sort((a, b) => b.qty - a.qty)
|
|
112
|
+
.filter(p => p.qty > this.multipack.qty);
|
|
113
|
+
const biggerMultipacksAmount = amount - biggerMultipacks.reduce((leftAmount, p) => leftAmount % p.qty, amount);
|
|
114
|
+
const multipackAmount = amount - biggerMultipacksAmount;
|
|
115
|
+
const result = Math.floor(multipackAmount / this.multipack.qty);
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
return amount;
|
|
103
119
|
},
|
|
104
120
|
set(value) {
|
|
105
121
|
const outOfStockQuantity = this.simpleProduct?.quantityStock;
|
|
122
|
+
if (this.multipack) {
|
|
123
|
+
const leftAmount = this.simpleProductAmount - (this.model * this.multipack.qty);
|
|
124
|
+
value = leftAmount + Math.max(0, value) * this.multipack.qty;
|
|
125
|
+
}
|
|
106
126
|
if (outOfStockQuantity && outOfStockQuantity < value && this.showMaxModal) {
|
|
107
127
|
const message = `Maximum value: ${outOfStockQuantity}`;
|
|
108
128
|
this.showConfirmationModal(message);
|
|
109
129
|
}
|
|
110
|
-
const amount = inRange(value, 0, outOfStockQuantity ||
|
|
130
|
+
const amount = inRange(value, 0, outOfStockQuantity || 1000);
|
|
111
131
|
this.setSimpleProductAmount({
|
|
112
132
|
colorId: this.color._id,
|
|
113
133
|
sizeId: this.size._id,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
@import '@/assets/scss/variables';
|
|
2
|
+
|
|
3
|
+
.ProductMultipacksSizeSelectorColor {
|
|
4
|
+
&__wrapper td {
|
|
5
|
+
font-weight: 800;
|
|
6
|
+
font-size: 18px;
|
|
7
|
+
line-height: 25px;
|
|
8
|
+
text-transform: uppercase;
|
|
9
|
+
color: $black;
|
|
10
|
+
&.disabled {
|
|
11
|
+
color: $gray_main;
|
|
12
|
+
pointer-events: none !important;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
&__color-name {
|
|
16
|
+
width: 70px;
|
|
17
|
+
span {
|
|
18
|
+
writing-mode: vertical-lr;
|
|
19
|
+
transform: rotate(180deg);
|
|
20
|
+
width: 100%;
|
|
21
|
+
display: block;
|
|
22
|
+
margin-left: -20px;
|
|
23
|
+
}
|
|
24
|
+
@media (max-width: $bp-extra-small-max) {
|
|
25
|
+
width: 40px;
|
|
26
|
+
span {
|
|
27
|
+
margin-left: -6px;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
&__size {
|
|
32
|
+
width: 70px;
|
|
33
|
+
}
|
|
34
|
+
&__in-stock,
|
|
35
|
+
&__out-stock {
|
|
36
|
+
font-weight: 600;
|
|
37
|
+
text-transform: none;
|
|
38
|
+
}
|
|
39
|
+
&__out-stock {
|
|
40
|
+
color: $gray_main;
|
|
41
|
+
}
|
|
42
|
+
&__stock {
|
|
43
|
+
font-size: 11px;
|
|
44
|
+
letter-spacing: -1px;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
::v-deep .ProductSizeSelectorColorCell {
|
|
49
|
+
&__field {
|
|
50
|
+
line-height: 20px;
|
|
51
|
+
input {
|
|
52
|
+
height: 30px;
|
|
53
|
+
padding: 5px !important;
|
|
54
|
+
background-color: $gray;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
&__side-control {
|
|
58
|
+
background: $green;
|
|
59
|
+
width: 26px;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<tr class="ProductMultipacksSizeSelectorColor__wrapper">
|
|
3
|
+
<td
|
|
4
|
+
v-if="rowspan"
|
|
5
|
+
:rowspan="rowspan"
|
|
6
|
+
class="ProductMultipacksSizeSelectorColor__color-name">
|
|
7
|
+
<span>
|
|
8
|
+
{{ product.color.name }}
|
|
9
|
+
</span>
|
|
10
|
+
</td>
|
|
11
|
+
<td
|
|
12
|
+
class="ProductMultipacksSizeSelectorColor__size"
|
|
13
|
+
:class="{ disabled }">
|
|
14
|
+
<div>
|
|
15
|
+
{{ product.size.shortName }}
|
|
16
|
+
</div>
|
|
17
|
+
<div class="ProductMultipacksSizeSelectorColor__stock">
|
|
18
|
+
<div
|
|
19
|
+
v-if="product.quantityStock"
|
|
20
|
+
class="ProductMultipacksSizeSelectorColor__in-stock">
|
|
21
|
+
{{ currentQuantityStockLabel }} in stock
|
|
22
|
+
</div>
|
|
23
|
+
<div
|
|
24
|
+
v-else
|
|
25
|
+
class="ProductMultipacksSizeSelectorColor__out-stock">
|
|
26
|
+
out of stock
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</td>
|
|
30
|
+
<td
|
|
31
|
+
v-for="multipack in commonProductsMultipacks"
|
|
32
|
+
:key="multipack._id"
|
|
33
|
+
class="ProductMultipacksSizeSelectorColor__cell">
|
|
34
|
+
<product-size-selector-color-cell
|
|
35
|
+
:side-controls="true"
|
|
36
|
+
:show-max-modal="false"
|
|
37
|
+
:out-stock="disabled"
|
|
38
|
+
:color="product.color"
|
|
39
|
+
:size="product.size"
|
|
40
|
+
:multipack="multipack" />
|
|
41
|
+
</td>
|
|
42
|
+
</tr>
|
|
43
|
+
</template>
|
|
44
|
+
|
|
45
|
+
<script>
|
|
46
|
+
import { mapGetters } from 'vuex';
|
|
47
|
+
import { price, tax } from '@lancom/shared/assets/js/utils/filters';
|
|
48
|
+
import ProductSizeSelectorColorCell from '@lancom/shared/components/product/product_size_selector/product_size_selector_color/product_size_selector_color_cell/product-size-selector-color-cell';
|
|
49
|
+
|
|
50
|
+
export default {
|
|
51
|
+
name: 'ProductMultipacksSizeSelectorColor',
|
|
52
|
+
filters: {
|
|
53
|
+
price
|
|
54
|
+
},
|
|
55
|
+
components: {
|
|
56
|
+
ProductSizeSelectorColorCell
|
|
57
|
+
},
|
|
58
|
+
props: {
|
|
59
|
+
product: {
|
|
60
|
+
type: Object,
|
|
61
|
+
required: true
|
|
62
|
+
},
|
|
63
|
+
rowspan: {
|
|
64
|
+
type: Number,
|
|
65
|
+
default: 0
|
|
66
|
+
},
|
|
67
|
+
withGst: {
|
|
68
|
+
type: Boolean,
|
|
69
|
+
default: false
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
computed: {
|
|
73
|
+
...mapGetters('product', ['commonProductsMultipacks', 'isPrintPricing', 'usedSimpleProductsQuantity', 'printsPrice']),
|
|
74
|
+
...mapGetters(['gstTax', 'currency']),
|
|
75
|
+
currentQuantityStockLabel() {
|
|
76
|
+
return this.currentQuantityStock > 100 ? '100+' : this.currentQuantityStock;
|
|
77
|
+
},
|
|
78
|
+
pricing() {
|
|
79
|
+
return (this.isPrintPricing ? this.product.pricing : this.product.unprintedPricing) || [];
|
|
80
|
+
},
|
|
81
|
+
productPrice() {
|
|
82
|
+
const amount = this.usedSimpleProductsQuantity;
|
|
83
|
+
const pricing = this.pricing;
|
|
84
|
+
const price = (pricing.find(({ min, max }) => (!min || min <= amount) && (!max || max >= amount)) || pricing[0] || {}).price || 0;
|
|
85
|
+
return this.withGst ? tax(price, this.gstTax) : price;
|
|
86
|
+
},
|
|
87
|
+
productPrintsPrice() {
|
|
88
|
+
return this.withGst ? tax(this.printsPrice, this.gstTax) : this.printsPrice;
|
|
89
|
+
},
|
|
90
|
+
disabled() {
|
|
91
|
+
return !this.product.quantityStock || !this.productPrice;
|
|
92
|
+
},
|
|
93
|
+
currentQuantityStock() {
|
|
94
|
+
return (this.product.quantityStock || 0) - (this.product.amount || 0);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
</script>
|
|
99
|
+
|
|
100
|
+
<style lang="scss" scoped>
|
|
101
|
+
@import 'product-multipacks-size-selector-color.scss';
|
|
102
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@import '@/assets/scss/variables';
|
|
2
|
+
|
|
3
|
+
.ProductsMultipacksSizeSelectorColor {
|
|
4
|
+
&__table {
|
|
5
|
+
border: 1px solid $gray;
|
|
6
|
+
font-weight: 800;
|
|
7
|
+
font-size: 18px;
|
|
8
|
+
line-height: 25px;
|
|
9
|
+
text-transform: uppercase;
|
|
10
|
+
color: $black;
|
|
11
|
+
}
|
|
12
|
+
&__cost-column {
|
|
13
|
+
width: 150px;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<table class="ProductsMultipacksSizeSelectorColor__table lc_table bordered">
|
|
4
|
+
<thead class="centered">
|
|
5
|
+
<tr>
|
|
6
|
+
<th
|
|
7
|
+
colspan="2"
|
|
8
|
+
class="ProductsMultipacksSizeSelectorColor__cost-column">
|
|
9
|
+
</th>
|
|
10
|
+
<th
|
|
11
|
+
v-for="multipack in commonProductsMultipacks"
|
|
12
|
+
:key="multipack._id">
|
|
13
|
+
{{ multipack.name }} ({{ multipack.qty }})
|
|
14
|
+
</th>
|
|
15
|
+
</tr>
|
|
16
|
+
<tr>
|
|
17
|
+
<th
|
|
18
|
+
colspan="2"
|
|
19
|
+
class="ProductsMultipacksSizeSelectorColor__cost-column">
|
|
20
|
+
COST
|
|
21
|
+
</th>
|
|
22
|
+
<th
|
|
23
|
+
v-for="multipack in commonProductsMultipacks"
|
|
24
|
+
:key="multipack._id">
|
|
25
|
+
{{ priceFromRange(multipack.qty, multipack.qty) | price(currency) }}
|
|
26
|
+
</th>
|
|
27
|
+
</tr>
|
|
28
|
+
<tr>
|
|
29
|
+
<th
|
|
30
|
+
colspan="2"
|
|
31
|
+
style="width: 140px;">
|
|
32
|
+
UNiTCOST
|
|
33
|
+
</th>
|
|
34
|
+
<th
|
|
35
|
+
v-for="multipack in commonProductsMultipacks"
|
|
36
|
+
:key="multipack._id">
|
|
37
|
+
{{ priceFromRange(multipack.qty, 1) | price(currency) }}
|
|
38
|
+
</th>
|
|
39
|
+
</tr>
|
|
40
|
+
</thead>
|
|
41
|
+
<tbody class="centered">
|
|
42
|
+
<product-multipacks-size-selector-color
|
|
43
|
+
v-for="(product, index) in products"
|
|
44
|
+
:key="`${editableColor._id}_${product._id}`"
|
|
45
|
+
:rowspan="index === 0 ? products.length : 0"
|
|
46
|
+
:with-gst="withGst"
|
|
47
|
+
:product="product" />
|
|
48
|
+
</tbody>
|
|
49
|
+
</table>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<script>
|
|
54
|
+
import { mapGetters } from 'vuex';
|
|
55
|
+
import { sortBySize } from '@lancom/shared/assets/js/utils/sizes';
|
|
56
|
+
import { priceFromRange } from '@lancom/shared/assets/js/utils/pricing';
|
|
57
|
+
import { price, tax } from '@lancom/shared/assets/js/utils/filters';
|
|
58
|
+
import ProductMultipacksSizeSelectorColor from './product_multipacks_size_selector_color/product-multipacks-size-selector-color';
|
|
59
|
+
|
|
60
|
+
export default {
|
|
61
|
+
name: 'ProductsMultipacksSizeSelectorColor',
|
|
62
|
+
filters: {
|
|
63
|
+
price
|
|
64
|
+
},
|
|
65
|
+
components: {
|
|
66
|
+
ProductMultipacksSizeSelectorColor
|
|
67
|
+
},
|
|
68
|
+
props: {
|
|
69
|
+
withGst: {
|
|
70
|
+
type: Boolean,
|
|
71
|
+
default: false
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
computed: {
|
|
75
|
+
...mapGetters(['gstTax']),
|
|
76
|
+
...mapGetters('product', ['defaultSimpleProduct', 'commonProductsMultipacks', 'editableColor', 'editableColorSimpleProducts']),
|
|
77
|
+
products() {
|
|
78
|
+
return sortBySize(this.editableColorSimpleProducts);
|
|
79
|
+
},
|
|
80
|
+
pricing() {
|
|
81
|
+
return this.defaultSimpleProduct.pricing;
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
methods: {
|
|
85
|
+
priceFromRange(min, qty) {
|
|
86
|
+
const price = priceFromRange(min, this.pricing) * qty;
|
|
87
|
+
return this.withGst ? tax(price, this.gstTax) : price;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
</script>
|
|
92
|
+
|
|
93
|
+
<style lang="scss" scoped>
|
|
94
|
+
@import 'products-multipacks-size-selector-color.scss';
|
|
95
|
+
</style>
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
<btn
|
|
21
21
|
btn-class="green"
|
|
22
22
|
btn-label="NEXT"
|
|
23
|
+
:btn-disabled="!hasSelectedPrintUnderbases"
|
|
23
24
|
@onclick="$emit('next')">
|
|
24
25
|
<i
|
|
25
26
|
slot="icon-after"
|
|
@@ -39,7 +40,10 @@ export default {
|
|
|
39
40
|
WizardPrintAreaPrintUnderbase
|
|
40
41
|
},
|
|
41
42
|
computed: {
|
|
42
|
-
...mapGetters('product', ['editablePrintAreas'])
|
|
43
|
+
...mapGetters('product', ['editablePrintAreas', 'selectedPrintUnderbases']),
|
|
44
|
+
hasSelectedPrintUnderbases() {
|
|
45
|
+
return this.editablePrintAreas.every(e => typeof this.selectedPrintUnderbases[e._id] === 'boolean');
|
|
46
|
+
}
|
|
43
47
|
}
|
|
44
48
|
};
|
|
45
49
|
</script>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
v-show="visibleWizard" />
|
|
11
11
|
</div>
|
|
12
12
|
<div
|
|
13
|
-
v-if="editableColor"
|
|
13
|
+
v-if="editableColor && availableMultipacks"
|
|
14
14
|
class="Editor__section">
|
|
15
15
|
<product-multipacks-carousel
|
|
16
16
|
:key="editableColor._id"
|
|
@@ -77,6 +77,10 @@ export default {
|
|
|
77
77
|
'isPrintPricing',
|
|
78
78
|
'priceIncludeGST'
|
|
79
79
|
]),
|
|
80
|
+
availableMultipacks() {
|
|
81
|
+
const multipacks = (this.product.multipacks || []);
|
|
82
|
+
return multipacks.some(m => !!m.SKU);
|
|
83
|
+
},
|
|
80
84
|
visibleWizard() {
|
|
81
85
|
return (this.product.printTypes || []).length > 0;
|
|
82
86
|
},
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
.CategoryCard {
|
|
15
|
-
width:
|
|
15
|
+
width: 170px;
|
|
16
16
|
margin: 0 0 15px 15px;
|
|
17
17
|
position: relative;
|
|
18
18
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
&__image-wrapper {
|
|
36
36
|
width: 100%;
|
|
37
|
-
height:
|
|
37
|
+
height: 200px;
|
|
38
38
|
overflow: hidden;
|
|
39
39
|
position: relative;
|
|
40
40
|
}
|
|
@@ -62,4 +62,4 @@
|
|
|
62
62
|
@media (max-width: $bp-extra-small-max) {
|
|
63
63
|
margin: 0 auto 25px auto;
|
|
64
64
|
}
|
|
65
|
-
}
|
|
65
|
+
}
|
|
@@ -7,10 +7,23 @@
|
|
|
7
7
|
padding: 30px;
|
|
8
8
|
margin-bottom: 50px;
|
|
9
9
|
}
|
|
10
|
+
&__info {
|
|
11
|
+
display: flex;
|
|
12
|
+
justify-content: space-between;
|
|
13
|
+
margin-bottom: 10px;
|
|
14
|
+
}
|
|
10
15
|
&__logo {
|
|
11
16
|
margin-bottom: 20px;
|
|
12
17
|
}
|
|
18
|
+
&__table {
|
|
19
|
+
margin-top: 20px;
|
|
20
|
+
margin-bottom: 10px;
|
|
21
|
+
td {
|
|
22
|
+
width: 50%;
|
|
23
|
+
padding: 20px;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
13
26
|
}
|
|
14
27
|
.uppercase {
|
|
15
28
|
text-transform: uppercase;
|
|
16
|
-
}
|
|
29
|
+
}
|
|
@@ -5,46 +5,78 @@
|
|
|
5
5
|
class="QuoteView__logo">
|
|
6
6
|
<img :src="quote.shop.logo.small" />
|
|
7
7
|
</div>
|
|
8
|
-
<div class="
|
|
8
|
+
<div class="QuoteView__info">
|
|
9
9
|
<div>
|
|
10
|
-
<h2> {{ quote.shop.name }} </h2>
|
|
11
|
-
<h4 v-if="shopContacts"> ABN: {{ shopContacts.abn }} </h4>
|
|
10
|
+
<h2 class="lc_h2"> {{ quote.shop.name }} </h2>
|
|
11
|
+
<h4 v-if="shopContacts" class="lc_h4"> ABN: {{ shopContacts.abn }} </h4>
|
|
12
12
|
</div>
|
|
13
|
-
<h1 class="text-secondary">
|
|
13
|
+
<h1 class="text-secondary lc_h1">
|
|
14
14
|
QUOTE
|
|
15
15
|
</h1>
|
|
16
16
|
</div>
|
|
17
|
-
<div class="
|
|
17
|
+
<div class="QuoteView__info">
|
|
18
18
|
<div v-if="shopContacts">
|
|
19
|
-
<div
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
<div class="lc_regular16">
|
|
20
|
+
{{ shopContacts.company }}
|
|
21
|
+
</div>
|
|
22
|
+
<div class="lc_regular16">
|
|
23
|
+
{{ shopContacts.address }}
|
|
24
|
+
</div>
|
|
25
|
+
<div class="lc_regular16">
|
|
26
|
+
{{ shopContacts.phone }}
|
|
27
|
+
</div>
|
|
22
28
|
</div>
|
|
23
29
|
<div>
|
|
24
|
-
<div
|
|
25
|
-
|
|
30
|
+
<div class="lc_regular16">
|
|
31
|
+
DATE: {{ quote.createdAt | shortDate }}
|
|
32
|
+
</div>
|
|
33
|
+
<div class="lc_regular16">
|
|
34
|
+
QUOTE ID: {{ quoteId }}
|
|
35
|
+
</div>
|
|
26
36
|
</div>
|
|
27
37
|
</div>
|
|
28
38
|
|
|
29
|
-
<table class="mt-4
|
|
39
|
+
<table class="QuoteView__table mt-4 lc_table bordered">
|
|
30
40
|
<tr>
|
|
31
41
|
<td>
|
|
32
42
|
<div><b>QUOTE</b></div>
|
|
33
43
|
<div v-if="quote.address">
|
|
34
|
-
<div
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
<div
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
<div class="lc_regular16">
|
|
45
|
+
{{ quote.address.fullName }}
|
|
46
|
+
</div>
|
|
47
|
+
<div v-if="quote.address.company" class="lc_regular16">
|
|
48
|
+
{{ quote.address.company }}
|
|
49
|
+
</div>
|
|
50
|
+
<div v-if="quote.address.phone" class="lc_regular16">
|
|
51
|
+
{{ quote.address.phone }}
|
|
52
|
+
</div>
|
|
53
|
+
<div class="lc_regular16">
|
|
54
|
+
{{ quote.address.email }}
|
|
55
|
+
</div>
|
|
56
|
+
<div class="lc_regular16">
|
|
57
|
+
{{ quoteAddress }}
|
|
58
|
+
</div>
|
|
59
|
+
<div class="lc_regular16">
|
|
60
|
+
{{ quote.address.additionalInfo }}
|
|
61
|
+
</div>
|
|
40
62
|
</div>
|
|
41
63
|
</td>
|
|
42
64
|
<td class="w-50">
|
|
43
|
-
<div
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<div
|
|
47
|
-
|
|
65
|
+
<div class="lc_regular16">
|
|
66
|
+
<b>{{ MESSAGES.DIRECT_DEPOSIT_DETAILS || 'DIRECT DEPOSIT DETAILS' }}</b>
|
|
67
|
+
</div>
|
|
68
|
+
<div class="lc_regular16">
|
|
69
|
+
Bank: {{ depositInfo.bank }}
|
|
70
|
+
</div>
|
|
71
|
+
<div class="lc_regular16">
|
|
72
|
+
Account name: {{ depositInfo.accountName }}
|
|
73
|
+
</div>
|
|
74
|
+
<div class="lc_regular16">
|
|
75
|
+
{{ bsbLabel }}: {{ depositInfo.BSB }}
|
|
76
|
+
</div>
|
|
77
|
+
<div class="lc_regular16">
|
|
78
|
+
Account: {{ depositInfo.account }}
|
|
79
|
+
</div>
|
|
48
80
|
</td>
|
|
49
81
|
</tr>
|
|
50
82
|
</table>
|
|
@@ -58,7 +90,7 @@
|
|
|
58
90
|
</div>
|
|
59
91
|
<h6
|
|
60
92
|
v-if="quote.expiredAt"
|
|
61
|
-
class="mt-3">
|
|
93
|
+
class="mt-3 lc_title mb-5 lc_h3">
|
|
62
94
|
THIS QUOTE IS VALID UNTIL {{ quote.expiredAt | shortDate }}
|
|
63
95
|
</h6>
|
|
64
96
|
</div>
|
|
@@ -8,12 +8,24 @@
|
|
|
8
8
|
class="QuoteOptionView__product" />
|
|
9
9
|
</div>
|
|
10
10
|
<div class="QuoteOptionView__totals">
|
|
11
|
-
<div
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<div
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
<div class="lc_regular16">
|
|
12
|
+
Products Total: <b>{{ option.productsTotal | price(currency) }}</b>
|
|
13
|
+
</div>
|
|
14
|
+
<div class="lc_regular16">
|
|
15
|
+
Prints Total: <b>{{ option.printsTotal | price(currency) }}</b>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="lc_regular16">
|
|
18
|
+
Shipping Total: <b>{{ option.shippingTotal | price(currency) }}</b>
|
|
19
|
+
</div>
|
|
20
|
+
<div class="lc_regular16">
|
|
21
|
+
Total ex {{ taxName }}: <b>{{ option.total | price(currency) }}</b>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="lc_regular16">
|
|
24
|
+
{{ taxName }}: <b>{{ optionGst(option) | price(currency) }}</b>
|
|
25
|
+
</div>
|
|
26
|
+
<div class="lc_regular16">
|
|
27
|
+
Total inc {{ taxName }}: <b>{{ option.total | tax(gstTax) | price(currency) }}</b>
|
|
28
|
+
</div>
|
|
17
29
|
</div>
|
|
18
30
|
</div>
|
|
19
31
|
</template>
|
package/layouts/products.vue
CHANGED
|
@@ -20,16 +20,12 @@
|
|
|
20
20
|
<h1 class="Products__name">
|
|
21
21
|
{{ routeName }}
|
|
22
22
|
</h1>
|
|
23
|
-
<div
|
|
24
|
-
v-if="!visiblChildrenCategories"
|
|
25
|
-
class="Products__filters">
|
|
23
|
+
<div class="Products__filters">
|
|
26
24
|
<products-filters @open="openAside" />
|
|
27
25
|
</div>
|
|
28
26
|
</div>
|
|
29
27
|
<div class="Products__content">
|
|
30
|
-
<div
|
|
31
|
-
v-if="!visiblChildrenCategories"
|
|
32
|
-
class="Products__aside">
|
|
28
|
+
<div class="Products__aside">
|
|
33
29
|
<breakpoint
|
|
34
30
|
name="md"
|
|
35
31
|
mode="up">
|
|
@@ -37,10 +33,8 @@
|
|
|
37
33
|
</breakpoint>
|
|
38
34
|
</div>
|
|
39
35
|
<div class="Products__list">
|
|
40
|
-
<children-categories v-if="
|
|
41
|
-
<products-catalog
|
|
42
|
-
v-else
|
|
43
|
-
class="Products__catalog" />
|
|
36
|
+
<children-categories v-if="hasChildrenCategories" />
|
|
37
|
+
<products-catalog class="Products__catalog" />
|
|
44
38
|
</div>
|
|
45
39
|
</div>
|
|
46
40
|
<div
|
|
@@ -103,7 +97,7 @@
|
|
|
103
97
|
async fetch() {
|
|
104
98
|
await this.loadProducts();
|
|
105
99
|
|
|
106
|
-
if (this.page === 1
|
|
100
|
+
if (this.page === 1) {
|
|
107
101
|
await this.fetchChildrenCategories(this.currentCategory);
|
|
108
102
|
}
|
|
109
103
|
|
|
@@ -115,8 +109,8 @@
|
|
|
115
109
|
...mapGetters('page', ['routeInfo']),
|
|
116
110
|
...mapGetters(['notificationBar', 'shop', 'country', 'currency']),
|
|
117
111
|
...mapGetters('products', ['category', 'childrenCategories', 'categories', 'brands', 'types', 'tags', 'loadError', 'count', 'products', 'minPrice', 'maxPrice', 'page']),
|
|
118
|
-
|
|
119
|
-
return
|
|
112
|
+
hasChildrenCategories() {
|
|
113
|
+
return this.childrenCategories.length > 0;
|
|
120
114
|
},
|
|
121
115
|
pageItemCanonical() {
|
|
122
116
|
const page = +this.$route.query.page;
|
package/package.json
CHANGED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="QuoteViewPage__wrapper">
|
|
3
|
+
<div class="content-inner">
|
|
4
|
+
<lancom-quote-view
|
|
5
|
+
v-if="quote"
|
|
6
|
+
:quote="quote"
|
|
7
|
+
:option="option" />
|
|
8
|
+
</div>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
import QuoteViewPage from '@lancom/shared/pages/quotes/view/_id';
|
|
14
|
+
import LancomQuoteView from '@lancom/shared/components/quotes/quote_view/quote-view';
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
name: 'QuoteOptionView',
|
|
18
|
+
components: {
|
|
19
|
+
LancomQuoteView
|
|
20
|
+
},
|
|
21
|
+
mixins: [QuoteViewPage],
|
|
22
|
+
layout: 'empty'
|
|
23
|
+
};
|
|
24
|
+
</script>
|
package/routes/index.js
CHANGED
|
@@ -102,6 +102,11 @@ module.exports = function(routes, resolve, config) {
|
|
|
102
102
|
path: '/order/:token/refund/:refund',
|
|
103
103
|
component: resolve('@lancom/shared/pages/order/_token/refund/_refund.vue'),
|
|
104
104
|
chunkName: 'pages/order/view/refund'
|
|
105
|
+
}, {
|
|
106
|
+
name: 'quotes-view-option',
|
|
107
|
+
path: '/quotes/view/:id/option/:option',
|
|
108
|
+
component: resolve('@lancom/shared/pages/quotes/view/_id/option/_option.vue'),
|
|
109
|
+
chunkName: 'pages/quotes/view/option'
|
|
105
110
|
}, {
|
|
106
111
|
name: 'customer-signin',
|
|
107
112
|
path: '/customer/signin',
|
package/store/product.js
CHANGED
|
@@ -56,6 +56,7 @@ export const getters = {
|
|
|
56
56
|
productDetailsKey: ({ productDetailsKey }) => productDetailsKey,
|
|
57
57
|
loadingProductDetails: ({ loadingProductDetails }) => loadingProductDetails,
|
|
58
58
|
multipack: ({ multipack }) => multipack,
|
|
59
|
+
commonProductsMultipacks: ({ product }) => product?.multipacks?.filter(p => !p.SKU) || [],
|
|
59
60
|
calculatingPrice: ({ calculatingPrice }) => calculatingPrice,
|
|
60
61
|
product: ({ product }) => product,
|
|
61
62
|
preSetPrints: ({ preSetPrints }) => preSetPrints,
|