@lancom/shared 0.0.295 → 0.0.297
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/models/product-layers.js +4 -3
- package/assets/js/utils/export-print-to-svg.js +12 -20
- package/assets/js/utils/fabric/wireframe.js +4 -4
- package/assets/js/utils/fabric-helper.js +2 -2
- package/assets/js/utils/order.js +6 -3
- package/assets/js/utils/prints.js +8 -1
- package/assets/js/utils/product.js +11 -2
- package/assets/scss/ui_kit/_table.scss +1 -1
- package/components/checkout/cart/cart_entity/cart_entity_color_simple_products/cart-entity-color-simple-products.vue +10 -0
- package/components/checkout/cart/cart_shipments_pricing/cart-shipments-pricing.vue +2 -1
- package/components/common/price.vue +10 -3
- package/components/common/product_side_with_print/product-side-with-print.vue +2 -1
- package/components/editor/editor.vue +14 -4
- package/components/editor/editor_layers/editor_layers_layer/editor-layers-layer.vue +4 -3
- package/components/editor/editor_layers/editor_layers_toolbar/editor-layers-toolbar.vue +2 -2
- package/components/editor/editor_print_area_options/editor-print-area-options.scss +3 -2
- package/components/editor/editor_print_area_options/editor_print_area_option/editor-print-area-option.scss +8 -0
- package/components/editor/editor_print_area_options/editor_print_area_option/editor-print-area-option.vue +10 -5
- package/components/editor/editor_product_details/editor-product-details.scss +18 -0
- package/components/editor/editor_product_details/editor-product-details.vue +50 -9
- package/components/editor/editor_workspace/editor-workspace.scss +4 -4
- package/components/editor/editor_workspace/editor-workspace.vue +0 -5
- package/components/editor/editor_workspace/editor_workspace_side/editor-workspace-side.scss +12 -0
- package/components/editor/editor_workspace/editor_workspace_side/editor-workspace-side.vue +35 -4
- package/components/editor/mobile_editor_product_details/mobile-editor-product-details.scss +2 -2
- package/components/editor/mobile_editor_product_details/mobile-editor-product-details.vue +4 -6
- package/components/order/order_product_prints_preview/order-product-prints-preview.scss +9 -0
- package/components/order/order_product_prints_preview/order-product-prints-preview.vue +44 -0
- package/components/order/order_view/order-view.vue +8 -1
- package/components/order/order_view/order_product_color_simple_products/order-product-color-simple-products.mixin.js +12 -0
- package/components/order/order_view/order_product_color_simple_products/order-product-color-simple-products.scss +12 -1
- package/components/order/order_view/order_product_color_simple_products/order-product-color-simple-products.vue +30 -3
- package/components/order/order_view/order_view_product/order-view-product.vue +23 -2
- package/components/product/gallery/gallery.vue +5 -2
- package/components/product/product_colors_selector/product-colors-selector.vue +7 -1
- package/components/product/product_print_preview/product-print-preview.vue +103 -0
- package/components/product/products_size_selector_color/product_size_selector_color/product-size-selector-color.vue +5 -2
- package/components/quotes/quote_view/quote-view.vue +9 -2
- package/feeds/google-shopping.js +6 -1
- package/mixins/add-to-cart.js +4 -1
- package/package.json +1 -1
- package/store/layers.js +1 -0
- package/store/product.js +3 -1
|
@@ -71,15 +71,16 @@ export class ArtLayer extends Layer {
|
|
|
71
71
|
width = null;
|
|
72
72
|
height = null;
|
|
73
73
|
|
|
74
|
-
constructor(type, colorId, top, left, url, originalSize) {
|
|
74
|
+
constructor(type, colorId, top, left, url, originalSize, fileName) {
|
|
75
75
|
super(colorId, top, left);
|
|
76
76
|
this.type = type;
|
|
77
77
|
this.url = url;
|
|
78
78
|
this.originalSize = originalSize;
|
|
79
|
+
this.fileName = fileName;
|
|
79
80
|
}
|
|
80
81
|
};
|
|
81
82
|
|
|
82
|
-
export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url, originalSize, sideId, properties = {} }) => {
|
|
83
|
+
export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url, originalSize, sideId, fileName, properties = {} }) => {
|
|
83
84
|
if (!type) {
|
|
84
85
|
throw new Error('When creating a new layer, you must specify its type');
|
|
85
86
|
}
|
|
@@ -95,7 +96,7 @@ export const getLayerModel = async ({ type, colorId, top, left, isEditMode, url,
|
|
|
95
96
|
}
|
|
96
97
|
break;
|
|
97
98
|
case 'art':
|
|
98
|
-
layer = new ArtLayer(type, colorId, top, left, url, originalSize);
|
|
99
|
+
layer = new ArtLayer(type, colorId, top, left, url, originalSize, fileName);
|
|
99
100
|
break;
|
|
100
101
|
default:
|
|
101
102
|
throw new Error(`Layer type '${type}' not found or not supported.`);
|
|
@@ -7,14 +7,13 @@ import { createObject } from './fabric/object-factory';
|
|
|
7
7
|
|
|
8
8
|
const sizes = [];
|
|
9
9
|
|
|
10
|
-
export function convertPrintToSVG(
|
|
10
|
+
export function convertPrintToSVG(layers, printSize) {
|
|
11
11
|
return new Promise(resolve => {
|
|
12
|
-
const svgSize = getSVGSize(
|
|
12
|
+
const svgSize = getSVGSize(printSize);
|
|
13
|
+
console.log('svgSize: ', svgSize);
|
|
13
14
|
const canvas = new fabric.Canvas(document.createElement('canvas'), { ...svgSize, uniScaleTransform: false });
|
|
14
|
-
|
|
15
|
-
const sideLayers = getSideLayers(entity, sideId);
|
|
16
15
|
Promise.all(
|
|
17
|
-
|
|
16
|
+
layers
|
|
18
17
|
.map(layer => {
|
|
19
18
|
if (layer.type === 'art') {
|
|
20
19
|
layer.url = layer.url.replace('thumb', 'origin');
|
|
@@ -27,7 +26,7 @@ export function convertPrintToSVG(entity, sideId) {
|
|
|
27
26
|
.map(l => createObject(l, true))
|
|
28
27
|
).then(objects => {
|
|
29
28
|
objects.forEach(object => {
|
|
30
|
-
const zoom =
|
|
29
|
+
const zoom = 1;
|
|
31
30
|
let artOriginZoom = 1;
|
|
32
31
|
if (object.layer.type === 'art') {
|
|
33
32
|
artOriginZoom *= object.layer._width / object.width;
|
|
@@ -40,33 +39,26 @@ export function convertPrintToSVG(entity, sideId) {
|
|
|
40
39
|
});
|
|
41
40
|
|
|
42
41
|
let svg = canvas.toSVG();
|
|
43
|
-
svg = insertFontsStyleToSvg(
|
|
42
|
+
svg = insertFontsStyleToSvg(layers, svg);
|
|
44
43
|
resolve(svg);
|
|
45
44
|
});
|
|
46
45
|
});
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
export function exportPrintToSVG(
|
|
50
|
-
convertPrintToSVG(
|
|
48
|
+
export function exportPrintToSVG(layers, printSize) {
|
|
49
|
+
convertPrintToSVG(layers, printSize).then(svg => {
|
|
51
50
|
const blob = new Blob([svg], { type: 'image/svg+xml' });
|
|
52
|
-
FileSaver.saveAs(blob,
|
|
51
|
+
FileSaver.saveAs(blob, `Pint-${Date.now()}.svg`);
|
|
53
52
|
});
|
|
54
53
|
};
|
|
55
54
|
|
|
56
|
-
function getSVGSize(
|
|
57
|
-
const printArea = getPrintArea(entity, sideId);
|
|
58
|
-
const printSize = sizes[printArea];
|
|
55
|
+
function getSVGSize(printSize) {
|
|
59
56
|
return {
|
|
60
|
-
width: printSize
|
|
61
|
-
height: printSize
|
|
57
|
+
width: printSize.width * PIXELS_PER_CM,
|
|
58
|
+
height: printSize.height * PIXELS_PER_CM
|
|
62
59
|
};
|
|
63
60
|
}
|
|
64
61
|
|
|
65
|
-
function getPrintArea(entity, sideId) {
|
|
66
|
-
const printAreas = entity.printAreas || {};
|
|
67
|
-
return printAreas[sideId];
|
|
68
|
-
}
|
|
69
|
-
|
|
70
62
|
function getSideLayers(entity, sideId) {
|
|
71
63
|
return (entity.layers || []).filter(layer => layer.sideId === sideId);
|
|
72
64
|
}
|
|
@@ -3,9 +3,9 @@ import { fabric } from 'fabric';
|
|
|
3
3
|
|
|
4
4
|
const sizes = [];
|
|
5
5
|
|
|
6
|
-
export const buildWireframe = ({ width, height, editor, print }) => {
|
|
6
|
+
export const buildWireframe = ({ width, height, editor, print, printSize }) => {
|
|
7
7
|
const layers = editor.getObjects();
|
|
8
|
-
const printAreaSize = print
|
|
8
|
+
const printAreaSize = printSize || print?.printSize || { width: 1, height: 1};
|
|
9
9
|
const group = new fabric.Group(layers);
|
|
10
10
|
const groupBounding = group.getBoundingRect();
|
|
11
11
|
const ratioX = (width / groupBounding.width) * 0.8;
|
|
@@ -108,8 +108,8 @@ export const buildWireframe = ({ width, height, editor, print }) => {
|
|
|
108
108
|
], 'h');
|
|
109
109
|
verticalArrow.set({ selectable: false });
|
|
110
110
|
horizontalArrow.set({ selectable: false });
|
|
111
|
-
const W = Math.round(groupBounding.width / printAreaSize.width);
|
|
112
|
-
const H = Math.round(groupBounding.height / printAreaSize.height);
|
|
111
|
+
const W = Math.round(groupBounding.width / printAreaSize.width * 10);
|
|
112
|
+
const H = Math.round(groupBounding.height / printAreaSize.height * 10);
|
|
113
113
|
const verticalSize = new fabric.Text(`H: ${H * 10}mm`, {
|
|
114
114
|
top: bounding.top + (bounding.height / 2),
|
|
115
115
|
left: 0,
|
|
@@ -220,8 +220,8 @@ export default class FabricHelper {
|
|
|
220
220
|
});
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
buildWireframe({ width, height, print }) {
|
|
224
|
-
buildWireframe({ width, height, editor: this.editor, print });
|
|
223
|
+
buildWireframe({ width, height, print, printSize }) {
|
|
224
|
+
buildWireframe({ width, height, editor: this.editor, print, printSize });
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
checkBoundingIntersection(object) {
|
package/assets/js/utils/order.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getProductSides } from './product';
|
|
1
|
+
import { getProductSides, getProductLayers } from './product';
|
|
2
2
|
import { getPrintTypeSizePricing } from '@lancom/shared/assets/js/utils/prints';
|
|
3
3
|
|
|
4
4
|
export function populateProductsFields(products, pricing) {
|
|
@@ -9,7 +9,8 @@ export function populateProductsFields(products, pricing) {
|
|
|
9
9
|
const sides = getProductSides(product);
|
|
10
10
|
const sidesKeys = [];
|
|
11
11
|
sides.forEach(side => {
|
|
12
|
-
const
|
|
12
|
+
const layers = getProductLayers(product);
|
|
13
|
+
const sideLayers = layers.filter(l => l.sideId === side);
|
|
13
14
|
const lastModifiedLayer = sideLayers.sort((l1, l2) => l2.modifiedAt - l1.modifiedAt)[0];
|
|
14
15
|
const key = `${side}-${lastModifiedLayer.modifiedAt}`;
|
|
15
16
|
|
|
@@ -23,7 +24,9 @@ export function populateProductsFields(products, pricing) {
|
|
|
23
24
|
sideLayers.forEach(l => {
|
|
24
25
|
l.printId = printId;
|
|
25
26
|
});
|
|
26
|
-
|
|
27
|
+
if (!product.printIds) {
|
|
28
|
+
product.printIds = {};
|
|
29
|
+
}
|
|
27
30
|
product.printIds[side] = printId;
|
|
28
31
|
});
|
|
29
32
|
|
|
@@ -21,11 +21,18 @@ export function getPrintAreaSizes({ printSize, sizes = [] }) {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
export const generatePrintLayer = layer => {
|
|
24
|
-
|
|
24
|
+
const model = {
|
|
25
25
|
...layer,
|
|
26
26
|
text: layer.copy,
|
|
27
27
|
params: layer
|
|
28
28
|
};
|
|
29
|
+
if (layer.url) {
|
|
30
|
+
model.file = {
|
|
31
|
+
fileName: layer.fileName,
|
|
32
|
+
origin: layer.url
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return model
|
|
29
36
|
};
|
|
30
37
|
|
|
31
38
|
export function getPrintsFromLayers(layers, product) {
|
|
@@ -58,12 +58,21 @@ export function generateCartProducts(mainProduct, simpleProducts, layers, hasPri
|
|
|
58
58
|
// });
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export function
|
|
61
|
+
export function getProductLayers(product, layersSideId) {
|
|
62
|
+
const layers = (product?.prints || [])
|
|
63
|
+
.reduce((layers, print) => [
|
|
64
|
+
...layers,
|
|
65
|
+
...(print.layers || []).map(l => ({ ...(l.params || {}) }))
|
|
66
|
+
], []);
|
|
67
|
+
return layers.filter(({ sideId }) => !layersSideId || sideId === layersSideId);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function getProductSides(product) {
|
|
71
|
+
const layers = getProductLayers(product);
|
|
62
72
|
const sidesSet = layers.reduce((sides, layer) => {
|
|
63
73
|
sides.add(layer.sideId);
|
|
64
74
|
return sides;
|
|
65
75
|
}, new Set());
|
|
66
|
-
|
|
67
76
|
return [...sidesSet];
|
|
68
77
|
}
|
|
69
78
|
|
|
@@ -10,6 +10,16 @@
|
|
|
10
10
|
side="front"
|
|
11
11
|
size="medium" />
|
|
12
12
|
</div>
|
|
13
|
+
<div
|
|
14
|
+
v-if="entity && entity.printsThumbnails && entity.printsThumbnails.back"
|
|
15
|
+
class="CartEntityColorSimpleProducts__image"
|
|
16
|
+
@click="showImage(images, 1)">
|
|
17
|
+
<product-side-with-print
|
|
18
|
+
:product="group"
|
|
19
|
+
:default-preview="defaultPreview"
|
|
20
|
+
side="back"
|
|
21
|
+
size="medium" />
|
|
22
|
+
</div>
|
|
13
23
|
</div>
|
|
14
24
|
<div class="CartEntityColorSimpleProducts__info">
|
|
15
25
|
<div class="CartEntityColorSimpleProducts__features">
|
|
@@ -94,7 +94,8 @@ export default {
|
|
|
94
94
|
'removeSupplier'
|
|
95
95
|
]),
|
|
96
96
|
async removeSupplierConfirm(supplier) {
|
|
97
|
-
|
|
97
|
+
|
|
98
|
+
const message = `All products from ${commaArray(supplier.brands.map(b => b.name))} will be removed from the cart. Click OK to proceed`;
|
|
98
99
|
const reset = await this.showConfirmationModal(message);
|
|
99
100
|
|
|
100
101
|
if (reset) {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<span>
|
|
3
|
-
{{
|
|
3
|
+
{{ displayPrice }}
|
|
4
4
|
</span>
|
|
5
5
|
</template>
|
|
6
6
|
|
|
7
7
|
<script>
|
|
8
|
-
import { priceWithTax } from '@lancom/shared/assets/js/utils/filters';
|
|
8
|
+
import { priceWithTax, price } from '@lancom/shared/assets/js/utils/filters';
|
|
9
9
|
import { mapGetters } from 'vuex';
|
|
10
10
|
|
|
11
11
|
export default {
|
|
@@ -16,10 +16,17 @@ export default {
|
|
|
16
16
|
props: {
|
|
17
17
|
price: {
|
|
18
18
|
type: Number
|
|
19
|
+
},
|
|
20
|
+
withGst: {
|
|
21
|
+
type: Boolean,
|
|
22
|
+
default: true
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
25
|
computed: {
|
|
22
|
-
...mapGetters(['pricingSettings', 'currency'])
|
|
26
|
+
...mapGetters(['pricingSettings', 'currency']),
|
|
27
|
+
displayPrice() {
|
|
28
|
+
return this.withGst ? priceWithTax(this.price, this.pricingSettings, this.currency) : price(this.price, this.currency);
|
|
29
|
+
}
|
|
23
30
|
}
|
|
24
31
|
};
|
|
25
32
|
</script>
|
|
@@ -82,7 +82,8 @@ export default {
|
|
|
82
82
|
},
|
|
83
83
|
image() {
|
|
84
84
|
const color = this.defaultPreview ? null : this.product.color;
|
|
85
|
-
|
|
85
|
+
const product = this.product?.product || this.product;
|
|
86
|
+
return getColorImage(product, this.size, this.side, color) || getProductCover(product, this.size, this.side, color);
|
|
86
87
|
},
|
|
87
88
|
print() {
|
|
88
89
|
const { printsThumbnails = {} } = this.product || {};
|
|
@@ -56,9 +56,20 @@
|
|
|
56
56
|
</div>
|
|
57
57
|
</breakpoint>
|
|
58
58
|
<div class="col-md-6 col-12 Editor__col">
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
<breakpoint
|
|
60
|
+
name="sm"
|
|
61
|
+
mode="down">
|
|
62
|
+
<client-only>
|
|
63
|
+
<editor-product-details />
|
|
64
|
+
</client-only>
|
|
65
|
+
</breakpoint>
|
|
66
|
+
<breakpoint
|
|
67
|
+
name="sm"
|
|
68
|
+
mode="up">
|
|
69
|
+
<client-only>
|
|
70
|
+
<editor-workspace class="Editor__workspace" />
|
|
71
|
+
</client-only>
|
|
72
|
+
</breakpoint>
|
|
62
73
|
</div>
|
|
63
74
|
</div>
|
|
64
75
|
<breakpoint
|
|
@@ -75,7 +86,6 @@
|
|
|
75
86
|
|
|
76
87
|
<script>
|
|
77
88
|
import { mapGetters, mapActions, mapMutations } from 'vuex';
|
|
78
|
-
import { generateCartProducts } from '@lancom/shared/assets/js/utils/product';
|
|
79
89
|
import modals from '@lancom/shared/mixins/modals';
|
|
80
90
|
import confirmModal from '@lancom/shared/mixins/confirm';
|
|
81
91
|
import OfferScreenPrinting from '@lancom/shared/components/asides/offer_screen_printing/offer-screen-printing';
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
<div
|
|
44
44
|
class="EditorLayersLayer__quality-value"
|
|
45
45
|
:class="artQuality.class">
|
|
46
|
-
{{ artQuality.value }}
|
|
46
|
+
{{ artQuality.value || artQuality.class }}
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
@@ -105,6 +105,7 @@ export default {
|
|
|
105
105
|
if (this.layer.type !== 'art') {
|
|
106
106
|
return null;
|
|
107
107
|
}
|
|
108
|
+
const isVector = /\.(ai|pdf|svg|eps)$/.test((this.layer.url || '').toLowerCase());
|
|
108
109
|
let quality;
|
|
109
110
|
switch (true) {
|
|
110
111
|
case this.layer.dpi < 75:
|
|
@@ -113,13 +114,13 @@ export default {
|
|
|
113
114
|
case this.layer.dpi >= 75 && this.layer.dpi < 100:
|
|
114
115
|
quality = 'low quality';
|
|
115
116
|
break;
|
|
116
|
-
case this.layer.dpi >= 100:
|
|
117
|
+
case this.layer.dpi >= 100 || isVector:
|
|
117
118
|
quality = 'good quality';
|
|
118
119
|
break;
|
|
119
120
|
}
|
|
120
121
|
return {
|
|
121
122
|
class: quality ? quality.replace(' ', '_') : null,
|
|
122
|
-
value: `${quality} / ${this.layer.dpi} DPI`
|
|
123
|
+
value: isVector ? null : `${quality} / ${this.layer.dpi} DPI`
|
|
123
124
|
};
|
|
124
125
|
}
|
|
125
126
|
},
|
|
@@ -103,8 +103,8 @@ export default {
|
|
|
103
103
|
const layer = await this.createLayer({ type: 'text' });
|
|
104
104
|
this.$emit('layer-added', { layer, toEditMode: true });
|
|
105
105
|
},
|
|
106
|
-
async handleUploaded({ url, size }) {
|
|
107
|
-
const layer = await this.createLayer({ type: 'art', url, size });
|
|
106
|
+
async handleUploaded({ url, size, fileName }) {
|
|
107
|
+
const layer = await this.createLayer({ type: 'art', url, size, fileName });
|
|
108
108
|
this.$emit('layer-added', { layer, toEditMode: false });
|
|
109
109
|
}
|
|
110
110
|
}
|
|
@@ -6,14 +6,15 @@
|
|
|
6
6
|
align-items: center;
|
|
7
7
|
justify-content: center;
|
|
8
8
|
padding: 8px 0;
|
|
9
|
+
flex-wrap: wrap;
|
|
9
10
|
&.singleRow {
|
|
10
11
|
grid-template-columns: repeat(4, 1fr);
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
&__option {
|
|
15
|
-
margin: 0 5px;
|
|
16
|
-
min-width:
|
|
16
|
+
margin: 0 5px 10px 5px;
|
|
17
|
+
min-width: 144px;
|
|
17
18
|
display: flex;
|
|
18
19
|
align-items: center;
|
|
19
20
|
justify-content: center;
|
|
@@ -18,6 +18,14 @@
|
|
|
18
18
|
background-color: $green;
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
&__info {
|
|
22
|
+
text-align: center;
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
justify-content: center;
|
|
26
|
+
align-items: center;
|
|
27
|
+
min-width: 50px;
|
|
28
|
+
}
|
|
21
29
|
&__suboptions {
|
|
22
30
|
position: absolute;
|
|
23
31
|
bottom: 100%;
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
[productType]: true
|
|
16
16
|
}">
|
|
17
17
|
</div>
|
|
18
|
-
<div>
|
|
18
|
+
<div class="EditorPrintAreaOption__info">
|
|
19
19
|
<div class="lc_caption">
|
|
20
20
|
{{ option.label }}
|
|
21
21
|
</div>
|
|
22
22
|
<div class="lc_regular10">
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
<price
|
|
24
|
+
:price="calcPrintPrice(option)"
|
|
25
|
+
:with-gst="priceIncludeGST" />
|
|
26
26
|
</div>
|
|
27
27
|
</div>
|
|
28
28
|
</div>
|
|
@@ -58,9 +58,13 @@
|
|
|
58
58
|
import { mapGetters } from 'vuex';
|
|
59
59
|
import { priceWithTax, priceInRange } from '@lancom/shared/assets/js/utils/filters';
|
|
60
60
|
import { getProductPrintsAreasPrices } from '@lancom/shared/assets/js/models/print-area';
|
|
61
|
+
import Price from '@lancom/shared/components/common/price';
|
|
61
62
|
|
|
62
63
|
export default {
|
|
63
64
|
name: 'EditorPrintAreaOption',
|
|
65
|
+
components: {
|
|
66
|
+
Price
|
|
67
|
+
},
|
|
64
68
|
filters: {
|
|
65
69
|
priceWithTax
|
|
66
70
|
},
|
|
@@ -92,7 +96,8 @@ export default {
|
|
|
92
96
|
]),
|
|
93
97
|
...mapGetters('product', [
|
|
94
98
|
'usedSimpleProducts',
|
|
95
|
-
'selectedPrintType'
|
|
99
|
+
'selectedPrintType',
|
|
100
|
+
'priceIncludeGST'
|
|
96
101
|
]),
|
|
97
102
|
printsPricing() {
|
|
98
103
|
return getProductPrintsAreasPrices(this.product, this.selectedPrintType);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@import "@/assets/scss/variables";
|
|
2
|
+
|
|
2
3
|
.EditorProductDetails {
|
|
3
4
|
&__wrapper {
|
|
4
5
|
padding-top: 36px;
|
|
@@ -7,6 +8,11 @@
|
|
|
7
8
|
display: flex;
|
|
8
9
|
align-items: center;
|
|
9
10
|
margin-top: 5px;
|
|
11
|
+
@media (max-width: $bp-extra-small-max) {
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
align-items: start;
|
|
14
|
+
margin-top: 10px;
|
|
15
|
+
}
|
|
10
16
|
&-logo {
|
|
11
17
|
img {
|
|
12
18
|
max-width: 75px;
|
|
@@ -16,6 +22,9 @@
|
|
|
16
22
|
&-info {
|
|
17
23
|
margin-left: 10px;
|
|
18
24
|
flex-grow: 1;
|
|
25
|
+
@media (max-width: $bp-extra-small-max) {
|
|
26
|
+
margin-left: 0px;
|
|
27
|
+
}
|
|
19
28
|
}
|
|
20
29
|
&-row {
|
|
21
30
|
display: flex;
|
|
@@ -59,4 +68,13 @@
|
|
|
59
68
|
padding: 10px;
|
|
60
69
|
margin-top: 10px;
|
|
61
70
|
}
|
|
71
|
+
&__product-image {
|
|
72
|
+
width: 100%;
|
|
73
|
+
text-align: center;
|
|
74
|
+
margin: 15px 0;
|
|
75
|
+
img {
|
|
76
|
+
width: 100%;
|
|
77
|
+
max-width: 330px;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
62
80
|
}
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
:delay="{ show: 200, hide: 400 }"
|
|
22
22
|
popover-class="tooltip popover white"
|
|
23
23
|
class="EditorProductDetails__discounts-table">
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
<price
|
|
25
|
+
class="lc_semibold22 lc_black EditorProductDetails__dashed-underline"
|
|
26
|
+
:price="defaultSimpleProductPricing[0].price"
|
|
27
|
+
:with-gst="inclGST" />
|
|
27
28
|
<template slot="popover">
|
|
28
|
-
<pricing-discounts-table
|
|
29
|
+
<pricing-discounts-table
|
|
30
|
+
:prices="defaultSimpleProductPricing"
|
|
31
|
+
:with-gst="inclGST" />
|
|
29
32
|
</template>
|
|
30
33
|
</v-popover>
|
|
31
34
|
</span>
|
|
@@ -45,10 +48,18 @@
|
|
|
45
48
|
:items="printTypePrices"
|
|
46
49
|
:bordered="true"
|
|
47
50
|
:striped="false"
|
|
51
|
+
:with-gst="inclGST"
|
|
48
52
|
class="EditorProductDetails__prints-table" />
|
|
49
53
|
</template>
|
|
50
54
|
</v-popover>
|
|
51
55
|
</span>
|
|
56
|
+
<span class="ml-10">
|
|
57
|
+
<checkbox
|
|
58
|
+
v-model="inclGST"
|
|
59
|
+
:dark="true">
|
|
60
|
+
<div class="ml-5">Inc. {{ taxName }}</div>
|
|
61
|
+
</checkbox>
|
|
62
|
+
</span>
|
|
52
63
|
</div>
|
|
53
64
|
<div class="EditorProductDetails__header-row">
|
|
54
65
|
<span class="EditorProductDetails__product-link">
|
|
@@ -68,20 +79,27 @@
|
|
|
68
79
|
class="EditorProductDetails__available-warning">
|
|
69
80
|
Product Not Available in {{ country.name }}
|
|
70
81
|
</div>
|
|
71
|
-
<
|
|
82
|
+
<div
|
|
83
|
+
v-if="mainProductImageSrc"
|
|
84
|
+
class="EditorProductDetails__product-image">
|
|
85
|
+
<img :src="mainProductImageSrc" />
|
|
86
|
+
</div>
|
|
87
|
+
<div
|
|
72
88
|
v-if="productDetailsLoaded && productAvailableInCurrentCountry">
|
|
73
89
|
<div class="EditorProductDetails__section">
|
|
74
|
-
<product-colors-selector
|
|
90
|
+
<product-colors-selector
|
|
91
|
+
:has-another-print-btn="false"
|
|
92
|
+
:has-toggle-gst="false" />
|
|
75
93
|
</div>
|
|
76
94
|
<div class="EditorProductDetails__section">
|
|
77
95
|
<editor-pricing :has-cart-btn="false" />
|
|
78
96
|
</div>
|
|
79
|
-
</
|
|
97
|
+
</div>
|
|
80
98
|
</div>
|
|
81
99
|
</template>
|
|
82
100
|
|
|
83
101
|
<script>
|
|
84
|
-
import { mapGetters } from 'vuex';
|
|
102
|
+
import { mapGetters, mapMutations } from 'vuex';
|
|
85
103
|
import ProductColorsSelector from '@lancom/shared/components/product/product_colors_selector/product-colors-selector';
|
|
86
104
|
import EditorPricing from '@lancom/shared/components/product/editor_pricing/editor-pricing';
|
|
87
105
|
import PricingDiscountsTable from '@lancom/shared/components/common/pricing_discounts_table/pricing-discounts-table';
|
|
@@ -89,6 +107,7 @@ import modals from '@lancom/shared/mixins/modals';
|
|
|
89
107
|
import { staticLink, priceWithTax } from '@lancom/shared/assets/js/utils/filters';
|
|
90
108
|
import PricingTable from '@lancom/shared/components/common/pricing_table/pricing-table';
|
|
91
109
|
import { generateProductLink } from '@lancom/shared/assets/js/utils/product';
|
|
110
|
+
import Price from '@lancom/shared/components/common/price';
|
|
92
111
|
|
|
93
112
|
export default {
|
|
94
113
|
name: 'EditorProductDetails',
|
|
@@ -96,7 +115,8 @@ export default {
|
|
|
96
115
|
ProductColorsSelector,
|
|
97
116
|
PricingDiscountsTable,
|
|
98
117
|
EditorPricing,
|
|
99
|
-
PricingTable
|
|
118
|
+
PricingTable,
|
|
119
|
+
Price
|
|
100
120
|
},
|
|
101
121
|
filters: {
|
|
102
122
|
priceWithTax,
|
|
@@ -104,8 +124,12 @@ export default {
|
|
|
104
124
|
},
|
|
105
125
|
mixins: [modals],
|
|
106
126
|
computed: {
|
|
127
|
+
...mapGetters(['taxName']),
|
|
107
128
|
...mapGetters('product', [
|
|
108
129
|
'product',
|
|
130
|
+
'editableColor',
|
|
131
|
+
'images',
|
|
132
|
+
'priceIncludeGST',
|
|
109
133
|
'productDetailsLoaded',
|
|
110
134
|
'defaultSimpleProduct',
|
|
111
135
|
'selectedPrintType',
|
|
@@ -118,6 +142,14 @@ export default {
|
|
|
118
142
|
'pricingSettings',
|
|
119
143
|
'country'
|
|
120
144
|
]),
|
|
145
|
+
inclGST: {
|
|
146
|
+
get() {
|
|
147
|
+
return this.priceIncludeGST;
|
|
148
|
+
},
|
|
149
|
+
set(value) {
|
|
150
|
+
this.setPriceIncludeGST(value);
|
|
151
|
+
}
|
|
152
|
+
},
|
|
121
153
|
defaultSimpleProductPricing() {
|
|
122
154
|
return (this.isPrintPricing ? this.defaultSimpleProduct?.pricing : this.defaultSimpleProduct?.unprintedPricing);
|
|
123
155
|
},
|
|
@@ -138,7 +170,16 @@ export default {
|
|
|
138
170
|
});
|
|
139
171
|
return sizes;
|
|
140
172
|
}, new Map()).values()];
|
|
173
|
+
},
|
|
174
|
+
mainProductImage() {
|
|
175
|
+
return this.images.find(i => i.color === this.editableColor?._id) || this.images[0];
|
|
176
|
+
},
|
|
177
|
+
mainProductImageSrc() {
|
|
178
|
+
return this.mainProductImage && this.mainProductImage.large;
|
|
141
179
|
}
|
|
180
|
+
},
|
|
181
|
+
methods: {
|
|
182
|
+
...mapMutations('product', ['setPriceIncludeGST']),
|
|
142
183
|
}
|
|
143
184
|
};
|
|
144
185
|
</script>
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
&-container {
|
|
10
10
|
position: relative;
|
|
11
11
|
margin: 0 auto;
|
|
12
|
-
width:
|
|
13
|
-
height:
|
|
12
|
+
width: 310px;
|
|
13
|
+
height: 370px;
|
|
14
14
|
max-width: 100%;
|
|
15
15
|
@media (min-width: $bp-small-min) {
|
|
16
16
|
width: 580px;
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
top: -90px;
|
|
36
36
|
left: calc((-720px + 100vw) / 2);
|
|
37
37
|
max-width: none;
|
|
38
|
-
z-index:
|
|
38
|
+
z-index: 1003;
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
&-toggle {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
position: sticky;
|
|
87
87
|
bottom: 20px;
|
|
88
88
|
background: white;
|
|
89
|
-
width:
|
|
89
|
+
width: 310px;
|
|
90
90
|
@media (min-width: $bp-small-min) {
|
|
91
91
|
width: 580px;
|
|
92
92
|
}
|
|
@@ -100,11 +100,6 @@
|
|
|
100
100
|
@option-mouseleave="toogleBoundBox(false, $event)">
|
|
101
101
|
</editor-print-area-options>
|
|
102
102
|
</div>
|
|
103
|
-
<breakpoint
|
|
104
|
-
name="md"
|
|
105
|
-
mode="down">
|
|
106
|
-
<editor-pricing v-if="productDetailsLoaded" />
|
|
107
|
-
</breakpoint>
|
|
108
103
|
</div>
|
|
109
104
|
</template>
|
|
110
105
|
|