@lancom/shared 0.0.91 → 0.0.95
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/helpers.js +2 -1
- package/assets/js/utils/filters.js +6 -2
- package/assets/js/utils/product.js +3 -2
- package/components/checkout/cart/cart.mixin.js +3 -3
- package/components/checkout/cart/cart_entity/cart-entity.vue +8 -0
- package/components/checkout/cart/cart_price_info/cart-price-info.scss +10 -0
- package/components/checkout/cart/cart_price_info/cart-price-info.vue +9 -3
- package/components/checkout/cart/cart_shipments_pricing/cart-shipments-pricing.scss +54 -0
- package/components/checkout/cart/cart_shipments_pricing/cart-shipments-pricing.vue +110 -0
- package/components/checkout/order/address-form/address-form.vue +1 -1
- package/components/checkout/order/order-billing-information/order-billing-information.vue +0 -8
- package/components/checkout/order/order-shipping-method/order-shipping-method.vue +1 -1
- package/components/common/progress_steps/progress-steps.scss +1 -1
- package/components/editor/editor.vue +0 -8
- package/components/editor/editor_layers/editor_layer_forms/editor_layer_common_fields/editor-layer-common-fields.vue +0 -49
- package/components/editor/editor_layers/editor_layer_forms/editor_layer_form_art/editor-layer-form-art.vue +0 -6
- package/components/editor/editor_pricing/editor-pricing.vue +2 -4
- package/components/editor/editor_workspace/editor_workspace_side/editor-workspace-side.vue +0 -3
- package/components/modals/order_modal/order-modal.vue +1 -1
- package/components/order/order_payment/order-payment.vue +0 -4
- package/components/order/order_status/order-status.vue +0 -18
- package/components/product/layouts/product_model_measurements/product-model-measurements.vue +0 -5
- package/components/product/product.vue +0 -7
- package/components/products/products_attributes/products-attributes.vue +0 -3
- package/components/products/products_brands/products-brands.vue +2 -2
- package/components/products/products_colors/products-colors.scss +2 -1
- package/components/products/products_filters/products-filters.vue +0 -17
- package/components/quotes/quote_request/quote-request.vue +0 -6
- package/nuxt.config.js +3 -3
- package/package.json +1 -1
- package/store/auth.js +1 -0
- package/store/cart.js +86 -32
- package/store/order.js +1 -0
package/assets/js/api/admin.js
CHANGED
|
@@ -188,6 +188,18 @@ export default {
|
|
|
188
188
|
removeSupplier(id) {
|
|
189
189
|
return _delete(`admin/suppliers/${id}`);
|
|
190
190
|
},
|
|
191
|
+
async fetchWarehouses(params) {
|
|
192
|
+
return sortByName(await _get('admin/warehouse', params));
|
|
193
|
+
},
|
|
194
|
+
fetchWarehouseById(id) {
|
|
195
|
+
return _get(`admin/warehouse/${id}`);
|
|
196
|
+
},
|
|
197
|
+
saveWarehouse(brand) {
|
|
198
|
+
return brand._id ? _put(`admin/warehouse/${brand._id}`, brand) : _post('admin/warehouse', brand);
|
|
199
|
+
},
|
|
200
|
+
removeWarehouse(id) {
|
|
201
|
+
return _delete(`admin/warehouse/${id}`);
|
|
202
|
+
},
|
|
191
203
|
async fetchBanners(params) {
|
|
192
204
|
return sortByName(await _get('admin/banners', params));
|
|
193
205
|
},
|
package/assets/js/api/helpers.js
CHANGED
|
@@ -17,7 +17,8 @@ if (process.client) {
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const API_URL = process.client ? process.env.API_URL : process.env.LOCAL_API_URL;
|
|
21
|
+
export const buildPath = path => `${API_URL}/${path}`;
|
|
21
22
|
|
|
22
23
|
export const prepareHeaders = method => {
|
|
23
24
|
const headers = {};
|
|
@@ -16,7 +16,7 @@ export const number = (value, digits = 0) => {
|
|
|
16
16
|
return fixed.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
export const decimal = value => number(value || 0,
|
|
19
|
+
export const decimal = (value, digits = 2) => number(value || 0, digits);
|
|
20
20
|
|
|
21
21
|
export const price = (value = 0, currency = 'USD') => {
|
|
22
22
|
const amount = number(value, 2);
|
|
@@ -56,8 +56,12 @@ export const print = type => printsLabels[type];
|
|
|
56
56
|
|
|
57
57
|
export const side = type => SIDE_TYPES[type];
|
|
58
58
|
|
|
59
|
+
export const commaArray = (list = []) => {
|
|
60
|
+
return list.join(', ');
|
|
61
|
+
};
|
|
62
|
+
|
|
59
63
|
export const printsRange = (prints = []) => {
|
|
60
|
-
return prints
|
|
64
|
+
return commaArray(prints);
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
export const highlight = (string = '', query) => {
|
|
@@ -11,11 +11,12 @@ export function getProductsForCalculatePricing(mainProduct, simpleProducts, laye
|
|
|
11
11
|
_id: mainProduct._id,
|
|
12
12
|
prints: hasPrints ? prints.map(p => isCLearPrintsLayers ? ({ ...p, layers: null }) : p) : null,
|
|
13
13
|
printSurcharge: mainProduct.printSurcharge || 0,
|
|
14
|
-
simpleProducts: simpleProducts.map(({ _id, amount, pricing, unprintedPricing, weight }) => ({
|
|
14
|
+
simpleProducts: simpleProducts.map(({ _id, amount, pricing, unprintedPricing, weight, volume }) => ({
|
|
15
15
|
_id,
|
|
16
16
|
amount,
|
|
17
17
|
pricing: hasPrints ? pricing : unprintedPricing,
|
|
18
|
-
weight: weight || mainProduct.weight
|
|
18
|
+
weight: weight || mainProduct.weight,
|
|
19
|
+
volume: volume || mainProduct.volume
|
|
19
20
|
}))
|
|
20
21
|
}];
|
|
21
22
|
}
|
|
@@ -28,11 +28,11 @@ export default {
|
|
|
28
28
|
},
|
|
29
29
|
watch: {
|
|
30
30
|
entities() {
|
|
31
|
-
this.calculateCartPrice(this.shop);
|
|
31
|
+
this.calculateCartPrice({ shop: this.shop });
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
mounted() {
|
|
35
|
-
this.calculateCartPrice(this.shop);
|
|
35
|
+
this.calculateCartPrice({ shop: this.shop });
|
|
36
36
|
if (!this.suburb && this.user?.suburb) {
|
|
37
37
|
this.handleSuburbChange(this.user.suburb);
|
|
38
38
|
}
|
|
@@ -47,7 +47,7 @@ export default {
|
|
|
47
47
|
]),
|
|
48
48
|
handleSuburbChange(suburb) {
|
|
49
49
|
this.setSuburb(suburb);
|
|
50
|
-
this.calculateCartPrice(this.shop);
|
|
50
|
+
this.calculateCartPrice({ shop: this.shop });
|
|
51
51
|
},
|
|
52
52
|
async removeSimpleProducts(simpleProducts) {
|
|
53
53
|
const message = 'This will delete all items in this row, Press OK to continue or Cancel';
|
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
{{ product.SKU }}
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
20
|
+
<div class="CartEntity__feature">
|
|
21
|
+
<div class="lc_title-small">
|
|
22
|
+
Brand:
|
|
23
|
+
</div>
|
|
24
|
+
<div class="lc_body-small">
|
|
25
|
+
{{ product.brand.name }}
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
20
28
|
</div>
|
|
21
29
|
<div>
|
|
22
30
|
<cart-entity-color-simple-products
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div>
|
|
2
|
+
<div class="CartPriceInfo__wrapper">
|
|
3
3
|
<slot name="cart-pricing" v-bind="{ cartPricing, itemsLabel }">
|
|
4
4
|
<product-total-pricing
|
|
5
5
|
v-if="cartPricing && cartPricing.amount"
|
|
6
6
|
:pricing="cartPricing"
|
|
7
7
|
:items-label="itemsLabel" />
|
|
8
8
|
</slot>
|
|
9
|
+
<div
|
|
10
|
+
v-if="cartPricingError"
|
|
11
|
+
class="CartPriceInfo__error">
|
|
12
|
+
{{ cartPricingError }}
|
|
13
|
+
</div>
|
|
9
14
|
</div>
|
|
10
15
|
</template>
|
|
11
16
|
|
|
@@ -39,7 +44,8 @@ export default {
|
|
|
39
44
|
...mapGetters(['shop']),
|
|
40
45
|
...mapGetters('cart', [
|
|
41
46
|
'entities',
|
|
42
|
-
'cartPricing'
|
|
47
|
+
'cartPricing',
|
|
48
|
+
'cartPricingError'
|
|
43
49
|
])
|
|
44
50
|
},
|
|
45
51
|
watch: {
|
|
@@ -55,7 +61,7 @@ export default {
|
|
|
55
61
|
'calculateCartPrice'
|
|
56
62
|
]),
|
|
57
63
|
calculatePrice() {
|
|
58
|
-
this.calculateCartPrice(this.shop);
|
|
64
|
+
this.calculateCartPrice({ shop: this.shop });
|
|
59
65
|
}
|
|
60
66
|
}
|
|
61
67
|
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
@import '@/assets/scss/variables';
|
|
2
|
+
|
|
3
|
+
.CartShipmentsPricing {
|
|
4
|
+
&__title {
|
|
5
|
+
padding-top: 15px;
|
|
6
|
+
padding-bottom: 5px;
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
a {
|
|
10
|
+
color: $black
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
&__supplier {
|
|
14
|
+
padding: 15px 10px 15px 10px;
|
|
15
|
+
border-bottom: 1px solid #e3e3e3;
|
|
16
|
+
&:last-child {
|
|
17
|
+
border-bottom: none;
|
|
18
|
+
}
|
|
19
|
+
&-info {
|
|
20
|
+
display: flex;
|
|
21
|
+
justify-content: space-between;
|
|
22
|
+
font-weight: bold;
|
|
23
|
+
font-size: 16px;
|
|
24
|
+
}
|
|
25
|
+
&-brands {
|
|
26
|
+
display: flex;
|
|
27
|
+
i {
|
|
28
|
+
margin-left: -2px;
|
|
29
|
+
margin-right: 8px;
|
|
30
|
+
cursor: pointer;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
&__rate {
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
display: flex;
|
|
37
|
+
justify-content: space-between;
|
|
38
|
+
align-items: center;
|
|
39
|
+
margin-top: 10px;
|
|
40
|
+
font-size: 16px;
|
|
41
|
+
&--disabled {
|
|
42
|
+
pointer-events: none !important;
|
|
43
|
+
opacity: 0.6;
|
|
44
|
+
cursor: default;
|
|
45
|
+
}
|
|
46
|
+
&-icon {
|
|
47
|
+
margin-right: 10px;
|
|
48
|
+
}
|
|
49
|
+
&-info {
|
|
50
|
+
display: flex;
|
|
51
|
+
align-items: center;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="CartShipmentsPricing__wrapper">
|
|
3
|
+
<div v-if="hasSuppliersWithRates">
|
|
4
|
+
<div class="CartShipmentsPricing__title">
|
|
5
|
+
<div class="lc_body-large lc_gray-main">Delivery</div>
|
|
6
|
+
<a
|
|
7
|
+
href="/info/shipping-info"
|
|
8
|
+
target="_blank">
|
|
9
|
+
Learn more <i class="icon-target"></i>
|
|
10
|
+
</a>
|
|
11
|
+
</div>
|
|
12
|
+
<div
|
|
13
|
+
v-for="(supplier, index) of suppliersWithRates"
|
|
14
|
+
:key="index"
|
|
15
|
+
class="CartShipmentsPricing__supplier">
|
|
16
|
+
<div class="CartShipmentsPricing__supplier-info">
|
|
17
|
+
<div class="CartShipmentsPricing__supplier-brands">
|
|
18
|
+
<div @click="removeSupplierConfirm(supplier)">
|
|
19
|
+
<i class="icon-delete"></i>
|
|
20
|
+
</div>
|
|
21
|
+
<div>
|
|
22
|
+
{{ supplier.brands.map(b => b.name) | commaArray }}
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
<div>
|
|
26
|
+
{{ supplier | selectedRatePrice | price }}
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
<div
|
|
30
|
+
v-for="(rate, i) of supplier.rates"
|
|
31
|
+
:key="`rate-${i}`"
|
|
32
|
+
class="CartShipmentsPricing__rate"
|
|
33
|
+
:class="{
|
|
34
|
+
'CartShipmentsPricing__rate--disabled': rate.disabled
|
|
35
|
+
}"
|
|
36
|
+
@click="selectRate({ supplier, rate, shop })">
|
|
37
|
+
<div class="CartShipmentsPricing__rate-info">
|
|
38
|
+
<div class="CartShipmentsPricing__rate-icon">
|
|
39
|
+
<checked-icon :checked="rate.selected" />
|
|
40
|
+
</div>
|
|
41
|
+
<div class="CartShipmentsPricing__rate-name">
|
|
42
|
+
<div>{{ rate.name }}</div>
|
|
43
|
+
<div
|
|
44
|
+
v-if="rate.note"
|
|
45
|
+
class="lc_regular10">
|
|
46
|
+
{{ rate.note }}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
<div class="CartShipmentsPricing__rate-price">
|
|
51
|
+
{{ rate.totalPriceWithoutTax | price }}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<script>
|
|
60
|
+
import { mapGetters, mapActions } from 'vuex';
|
|
61
|
+
import { price, commaArray } from '@lancom/shared/assets/js/utils/filters';
|
|
62
|
+
import CheckedIcon from '@lancom/shared/components/common/checked-icon';
|
|
63
|
+
import confirm from '@lancom/shared/mixins/confirm';
|
|
64
|
+
|
|
65
|
+
export default {
|
|
66
|
+
name: 'LancomCartShipmentsPricing',
|
|
67
|
+
components: {
|
|
68
|
+
CheckedIcon
|
|
69
|
+
},
|
|
70
|
+
filters: {
|
|
71
|
+
price,
|
|
72
|
+
commaArray,
|
|
73
|
+
selectedRatePrice(supplier) {
|
|
74
|
+
const { totalPriceWithoutTax = 0 } = supplier.rates.find(r => r.selected) || {};
|
|
75
|
+
return totalPriceWithoutTax;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
mixins: [confirm],
|
|
79
|
+
computed: {
|
|
80
|
+
...mapGetters(['shop']),
|
|
81
|
+
...mapGetters('cart', [
|
|
82
|
+
'cartPricing'
|
|
83
|
+
]),
|
|
84
|
+
hasSuppliersWithRates() {
|
|
85
|
+
return this.suppliersWithRates.length > 0;
|
|
86
|
+
},
|
|
87
|
+
suppliersWithRates() {
|
|
88
|
+
return this.cartPricing?.shipping?.suppliersWithRates || [];
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
methods: {
|
|
92
|
+
...mapActions('cart', [
|
|
93
|
+
'selectRate',
|
|
94
|
+
'removeSupplier'
|
|
95
|
+
]),
|
|
96
|
+
async removeSupplierConfirm(supplier) {
|
|
97
|
+
const message = `Will be removed all products related to brands: ${commaArray(supplier.brands.map(b => b.name))}. Are you sure?`;
|
|
98
|
+
const reset = await this.showConfirmationModal(message);
|
|
99
|
+
|
|
100
|
+
if (reset) {
|
|
101
|
+
this.removeSupplier({ supplier, shop: this.shop });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
</script>
|
|
107
|
+
|
|
108
|
+
<style lang="scss" scoped>
|
|
109
|
+
@import 'cart-shipments-pricing.scss';
|
|
110
|
+
</style>
|
|
@@ -11,14 +11,6 @@
|
|
|
11
11
|
<address-form
|
|
12
12
|
:address="order.shippingAddress"
|
|
13
13
|
:without-additional-info="true" />
|
|
14
|
-
<!-- <div class="form-row mt-10">
|
|
15
|
-
<label class="form-label">
|
|
16
|
-
<checkbox v-model="copyToShippingAddress" />
|
|
17
|
-
<span class="lc_regular14 lc__grey1">
|
|
18
|
-
Ship to this address
|
|
19
|
-
</span>
|
|
20
|
-
</label>
|
|
21
|
-
</div> -->
|
|
22
14
|
</div>
|
|
23
15
|
<progress-steps-controls
|
|
24
16
|
:disabled-next="invalid || !order.shippingAddress.postcode"
|
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="Editor__wrapper">
|
|
3
|
-
<!-- <div class="Editor__header">
|
|
4
|
-
<nuxt-link
|
|
5
|
-
to="/"
|
|
6
|
-
class="lc_link">
|
|
7
|
-
<i class="icon-left"></i>
|
|
8
|
-
Go to all models
|
|
9
|
-
</nuxt-link>
|
|
10
|
-
</div> -->
|
|
11
3
|
<div class="Editor__content row">
|
|
12
4
|
<breakpoint
|
|
13
5
|
name="md"
|
|
@@ -20,55 +20,6 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
</div>
|
|
22
22
|
</div>
|
|
23
|
-
<!-- <div class="form-row">
|
|
24
|
-
<div class="form-label">
|
|
25
|
-
Align:
|
|
26
|
-
</div>
|
|
27
|
-
<div class="EditorLayerCommonFields__align-options">
|
|
28
|
-
<div
|
|
29
|
-
v-tooltip="'Center vertically'"
|
|
30
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
31
|
-
:class="{ active: alignVertically === 'center' }"
|
|
32
|
-
@click="alignVertically = 'center'">
|
|
33
|
-
<i class="icon-vertical-align-center"></i>
|
|
34
|
-
</div>
|
|
35
|
-
<div
|
|
36
|
-
v-tooltip="'Center horizontally'"
|
|
37
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
38
|
-
:class="{ active: alignHorizontally === 'center' }"
|
|
39
|
-
@click="alignHorizontally = 'center'">
|
|
40
|
-
<i class="icon-horizonal-align-center"></i>
|
|
41
|
-
</div>
|
|
42
|
-
<div
|
|
43
|
-
v-tooltip="'Left'"
|
|
44
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
45
|
-
:class="{ active: alignHorizontally === 'left' }"
|
|
46
|
-
@click="alignHorizontally = 'left'">
|
|
47
|
-
<i class="icon-horizonal-align-left"></i>
|
|
48
|
-
</div>
|
|
49
|
-
<div
|
|
50
|
-
v-tooltip="'Right'"
|
|
51
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
52
|
-
:class="{ active: alignHorizontally === 'right' }"
|
|
53
|
-
@click="alignHorizontally = 'right'">
|
|
54
|
-
<i class="icon-horizonal-align-right"></i>
|
|
55
|
-
</div>
|
|
56
|
-
<div
|
|
57
|
-
v-tooltip="'Top'"
|
|
58
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
59
|
-
:class="{ active: alignVertically === 'top' }"
|
|
60
|
-
@click="alignVertically = 'top'">
|
|
61
|
-
<i class="icon-vertical-align-top"></i>
|
|
62
|
-
</div>
|
|
63
|
-
<div
|
|
64
|
-
v-tooltip="'Bottom'"
|
|
65
|
-
class="EditorLayerCommonFields__align-option ripple"
|
|
66
|
-
:class="{ active: alignVertically === 'bottom' }"
|
|
67
|
-
@click="alignVertically = 'bottom'">
|
|
68
|
-
<i class="icon-vertical-align-bottom"></i>
|
|
69
|
-
</div>
|
|
70
|
-
</div>
|
|
71
|
-
</div> -->
|
|
72
23
|
</fragment>
|
|
73
24
|
</template>
|
|
74
25
|
|
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
name="header"
|
|
6
6
|
:invalid="invalid">
|
|
7
7
|
</slot>
|
|
8
|
-
<!-- <div class="EditorLayerFormArt__content">
|
|
9
|
-
<input
|
|
10
|
-
v-model="url"
|
|
11
|
-
readonly
|
|
12
|
-
class="form-field" />
|
|
13
|
-
</div> -->
|
|
14
8
|
<editor-layer-common-fields
|
|
15
9
|
:layer="layer"
|
|
16
10
|
@set-layer-field="data => $emit('set-layer-field', data)">
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="EditorPricing__wrapper">
|
|
3
3
|
<div class="EditorPricing__main">
|
|
4
|
-
<!-- no qty, no layers -->
|
|
5
4
|
<fragment v-if="!hasUsedSimpleProducts && !layers.length">
|
|
6
5
|
<div class="EditorPricing__main-alert">
|
|
7
6
|
<i class="icon-attention-circled"></i>
|
|
@@ -17,7 +16,6 @@
|
|
|
17
16
|
</div>
|
|
18
17
|
</fragment>
|
|
19
18
|
|
|
20
|
-
<!-- has qty, no layers -->
|
|
21
19
|
<fragment v-else-if="hasUsedSimpleProducts && !layers.length">
|
|
22
20
|
<div class="EditorPricing__main-alert">
|
|
23
21
|
<i class="icon-attention-circled"></i>
|
|
@@ -36,7 +34,7 @@
|
|
|
36
34
|
</div>
|
|
37
35
|
</div>
|
|
38
36
|
</fragment>
|
|
39
|
-
|
|
37
|
+
|
|
40
38
|
<fragment v-else-if="!hasUsedSimpleProducts && layers.length">
|
|
41
39
|
<div class="EditorPricing__main-alert">
|
|
42
40
|
<i class="icon-attention-circled"></i>
|
|
@@ -55,7 +53,7 @@
|
|
|
55
53
|
</div>
|
|
56
54
|
</div>
|
|
57
55
|
</fragment>
|
|
58
|
-
|
|
56
|
+
|
|
59
57
|
<fragment v-else>
|
|
60
58
|
<div class="EditorPricing__main-row">
|
|
61
59
|
<div class="lc_regular14 EditorPricing__main-col">
|
|
@@ -62,9 +62,6 @@
|
|
|
62
62
|
class="EditorWorkspaceSide__alert-error view-transition">
|
|
63
63
|
<i class="icon-attention-circled"></i>
|
|
64
64
|
Part of your design layer is outside the print area.
|
|
65
|
-
<!-- <i
|
|
66
|
-
class="icon-cancel EditorWorkspaceSide__offset-warning-close"
|
|
67
|
-
@click="offsetWarningVisible = false"></i> -->
|
|
68
65
|
</div>
|
|
69
66
|
</transition-group>
|
|
70
67
|
</div>
|
|
@@ -331,7 +331,7 @@ export default {
|
|
|
331
331
|
handleSuburbChange(suburb) {
|
|
332
332
|
this.form.suburb = suburb;
|
|
333
333
|
this.setSuburb(suburb);
|
|
334
|
-
this.calculateCartPrice(this.shop);
|
|
334
|
+
this.calculateCartPrice({ shop: this.shop });
|
|
335
335
|
},
|
|
336
336
|
back() {
|
|
337
337
|
this.switchModal('showCartModal');
|
|
@@ -18,24 +18,6 @@
|
|
|
18
18
|
{{ order.status }}
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
|
-
<!-- <h4 class="lc_h4">
|
|
22
|
-
Special
|
|
23
|
-
</h4>
|
|
24
|
-
<div class="OrderStatus__value">
|
|
25
|
-
<div v-if="isEditable">
|
|
26
|
-
<label class="form-label PaymentModal__label-with-checkbox">
|
|
27
|
-
<checkbox v-model="order.special" @change="changeStatus" />
|
|
28
|
-
<span class="lc_regular14 lc__grey1">
|
|
29
|
-
Special Order
|
|
30
|
-
</span>
|
|
31
|
-
</label>
|
|
32
|
-
</div>
|
|
33
|
-
<div
|
|
34
|
-
v-else
|
|
35
|
-
class="OrderStatus__status">
|
|
36
|
-
{{ order.special ? 'Yes' : 'No' }}
|
|
37
|
-
</div>
|
|
38
|
-
</div> -->
|
|
39
21
|
</div>
|
|
40
22
|
</template>
|
|
41
23
|
|
package/components/product/layouts/product_model_measurements/product-model-measurements.vue
CHANGED
|
@@ -9,11 +9,6 @@
|
|
|
9
9
|
src="~static/images/measurements_model.svg"
|
|
10
10
|
class="ProductModelMeasurements__icon" />
|
|
11
11
|
<div class="form-actions center">
|
|
12
|
-
<!-- <btn
|
|
13
|
-
btn-class="green-link"
|
|
14
|
-
btn-label="Show model image"
|
|
15
|
-
@click="showModel">
|
|
16
|
-
</btn> -->
|
|
17
12
|
</div>
|
|
18
13
|
</td>
|
|
19
14
|
<td>
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
<div
|
|
3
3
|
v-if="attributes.length"
|
|
4
4
|
class="ProductsAttributes__wrapper">
|
|
5
|
-
<!-- <toggle-content label="Attributes"> -->
|
|
6
5
|
<div
|
|
7
6
|
v-for="attribute in attributes"
|
|
8
7
|
:key="attribute._id"
|
|
@@ -11,13 +10,11 @@
|
|
|
11
10
|
:attribute="attribute"
|
|
12
11
|
:has-selected-icon="hasSelectedIcon" />
|
|
13
12
|
</div>
|
|
14
|
-
<!-- </toggle-content> -->
|
|
15
13
|
</div>
|
|
16
14
|
</template>
|
|
17
15
|
|
|
18
16
|
<script>
|
|
19
17
|
import { mapGetters } from 'vuex';
|
|
20
|
-
// import ToggleContent from '@lancom/shared/components/common/toggle-content';
|
|
21
18
|
import ProductsAttribute from './products_attribute/products-attribute';
|
|
22
19
|
|
|
23
20
|
export default {
|
|
@@ -43,8 +43,8 @@ export default {
|
|
|
43
43
|
computed: {
|
|
44
44
|
...mapGetters('products', ['brands', 'types']),
|
|
45
45
|
list() {
|
|
46
|
-
const type = this.types.find(type => type.alias === this.$route.params.type);
|
|
47
|
-
return
|
|
46
|
+
// const type = this.types.find(type => type.alias === this.$route.params.type);
|
|
47
|
+
return this.brands;
|
|
48
48
|
},
|
|
49
49
|
currentBrand() {
|
|
50
50
|
return this.$route.params.brand;
|
|
@@ -20,23 +20,6 @@
|
|
|
20
20
|
class="icon-filter ProductsFilters__menu-toggle"
|
|
21
21
|
@click="$emit('open')"></i>
|
|
22
22
|
</div>
|
|
23
|
-
<!-- <div class="ProductsFilters__search hidden-sm-and-down">
|
|
24
|
-
<input
|
|
25
|
-
v-model="search"
|
|
26
|
-
name="search"
|
|
27
|
-
placeholder="Search"
|
|
28
|
-
type="text"
|
|
29
|
-
class="form-field no-label tiny-placeholder labelless"
|
|
30
|
-
@change="goToTextSearch" />
|
|
31
|
-
<i class="icon-search"></i>
|
|
32
|
-
</div> -->
|
|
33
|
-
<!-- <multiselect
|
|
34
|
-
v-model="sortBy"
|
|
35
|
-
:options="sortByOptions"
|
|
36
|
-
:option-height="35"
|
|
37
|
-
value="value"
|
|
38
|
-
label="label"
|
|
39
|
-
class="labelless" /> -->
|
|
40
23
|
</div>
|
|
41
24
|
</template>
|
|
42
25
|
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="QuoteRequest__wrapper">
|
|
3
|
-
<!-- <div class="QuoteRequest__title">
|
|
4
|
-
Quick Quote
|
|
5
|
-
</div>
|
|
6
|
-
<div class="QuoteRequest__info">
|
|
7
|
-
Fill our the form below and one of our team members will respond with a Quote ASAP!
|
|
8
|
-
</div> -->
|
|
9
3
|
<div class="QuoteRequest__content">
|
|
10
4
|
<validation-observer
|
|
11
5
|
v-slot="{ invalid, handleSubmit, errors: submittedErrors }"
|
package/nuxt.config.js
CHANGED
|
@@ -32,7 +32,7 @@ module.exports = (config, axios) => ({
|
|
|
32
32
|
'/customer/**'
|
|
33
33
|
],
|
|
34
34
|
routes: async () => {
|
|
35
|
-
const { data } = await axios.get(`${config.
|
|
35
|
+
const { data } = await axios.get(`${config.LOCAL_API_URL}/feed/sitemap?host=${config.HOST_NAME}`);
|
|
36
36
|
return data.map(url => ({ url, priority: 0.8 }));
|
|
37
37
|
}
|
|
38
38
|
},
|
|
@@ -82,7 +82,7 @@ module.exports = (config, axios) => ({
|
|
|
82
82
|
feed: [{
|
|
83
83
|
path: '/google-shopping.xml',
|
|
84
84
|
async get() {
|
|
85
|
-
const { data } = await axios.get(`${config.
|
|
85
|
+
const { data } = await axios.get(`${config.LOCAL_API_URL}/feed/products?host=${config.HOST_NAME}`);
|
|
86
86
|
const spliceFirstImage = images => (images || []).splice(0, 1)[0];
|
|
87
87
|
const getImages = images => (images || []).length > 0 ? images : null;
|
|
88
88
|
return {
|
|
@@ -100,7 +100,7 @@ module.exports = (config, axios) => ({
|
|
|
100
100
|
const image = spliceFirstImage(feedImages) || spliceFirstImage(frontImages) || spliceFirstImage(catalogFrontImages) || spliceFirstImage(backImages) || {};
|
|
101
101
|
const images = getImages(backImages) || getImages(frontImages) || [];
|
|
102
102
|
const info = {
|
|
103
|
-
title: { _text: `${product.name} ${sp.color.name}
|
|
103
|
+
title: { _text: `${product.name} ${sp.color.name}` },
|
|
104
104
|
description: { _text: product.description || product.fabricInfoShort || product.name },
|
|
105
105
|
link: { _text: `https://${config.HOST_NAME}/${product.brand.alias}/${product.productType.alias}/${product.alias}?color=${sp.color.alias}` },
|
|
106
106
|
'g:id': { _text: sp.SKU },
|
package/package.json
CHANGED
package/store/auth.js
CHANGED
|
@@ -18,6 +18,7 @@ export const getters = {
|
|
|
18
18
|
isGuestUser: state => !state.token,
|
|
19
19
|
isAdmin: state => checkRoles(state.user, ['admin']),
|
|
20
20
|
isContentEditor: state => checkRoles(state.user, ['admin', 'content-editor']),
|
|
21
|
+
isWarehouse: state => checkRoles(state.user, ['admin', 'warehouse']),
|
|
21
22
|
user: state => state.user,
|
|
22
23
|
authStatus: state => state.status,
|
|
23
24
|
stateError: state => state.err
|
package/store/cart.js
CHANGED
|
@@ -6,7 +6,8 @@ export const state = () => ({
|
|
|
6
6
|
id: null,
|
|
7
7
|
entities: [],
|
|
8
8
|
suburb: null,
|
|
9
|
-
cartPricing: null
|
|
9
|
+
cartPricing: null,
|
|
10
|
+
cartPricingError: null
|
|
10
11
|
});
|
|
11
12
|
|
|
12
13
|
const getSimpleProductsQuantity = simpleProducts => {
|
|
@@ -56,6 +57,7 @@ export const getters = {
|
|
|
56
57
|
notValidPrintsQuantities(state, { quantities }) {
|
|
57
58
|
return (quantities?.prints || []).filter(({ minQuantity, quantity }) => quantity < minQuantity);
|
|
58
59
|
},
|
|
60
|
+
cartPricingError: ({ cartPricingError }) => cartPricingError
|
|
59
61
|
};
|
|
60
62
|
|
|
61
63
|
export const actions = {
|
|
@@ -96,37 +98,24 @@ export const actions = {
|
|
|
96
98
|
await api.saveCart(payload, shop._id);
|
|
97
99
|
commit('setEntities', entities);
|
|
98
100
|
},
|
|
99
|
-
async
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
printCost,
|
|
118
|
-
freeSetupOver,
|
|
119
|
-
printType: getSimpleObj(print.printType),
|
|
120
|
-
printArea: getSimpleObj(print.printArea),
|
|
121
|
-
printSize: getSimpleObj(print.printSize)
|
|
122
|
-
};
|
|
123
|
-
}),
|
|
124
|
-
printSurcharge: product.printSurcharge || 0
|
|
125
|
-
})),
|
|
126
|
-
postcode: suburb && suburb.postcode
|
|
127
|
-
};
|
|
128
|
-
const response = await api.calculateProductPrice(payload, shop._id);
|
|
129
|
-
commit('setCartPricing', response);
|
|
101
|
+
async removeSupplier({ commit, state }, { supplier, shop }) {
|
|
102
|
+
const brands = supplier.brands.map(({ _id }) => _id);
|
|
103
|
+
const entities = state.entities.filter(entity => !brands.includes(entity.product.brand._id));
|
|
104
|
+
const payload = { _id: state.id, entities };
|
|
105
|
+
await api.saveCart(payload, shop._id);
|
|
106
|
+
commit('setEntities', entities);
|
|
107
|
+
},
|
|
108
|
+
async calculateCartPrice({ state: { suburb, entities }, commit }, { shop }) {
|
|
109
|
+
const payload = generateCalculatePriceData(entities, suburb);
|
|
110
|
+
try {
|
|
111
|
+
const response = await api.calculateProductPrice(payload, shop._id);
|
|
112
|
+
commit('setCartPricing', response);
|
|
113
|
+
commit('setCartPricingError', null);
|
|
114
|
+
} catch (e) {
|
|
115
|
+
const { error = 'Error calculate pricing' } = e.response?.data || {};
|
|
116
|
+
commit('setCartPricingError', error);
|
|
117
|
+
commit('setCartPricing', null);
|
|
118
|
+
}
|
|
130
119
|
},
|
|
131
120
|
async setSimpleProductAmount({ state, commit }, { guid, amount, shop }) {
|
|
132
121
|
const entities = (state.entities || []).map(product => ({
|
|
@@ -142,6 +131,28 @@ export const actions = {
|
|
|
142
131
|
},
|
|
143
132
|
clearCart({ commit }) {
|
|
144
133
|
commit('clearCart');
|
|
134
|
+
},
|
|
135
|
+
async selectRate({ state: { cartPricing, entities, suburb }, commit }, { supplier, rate, shop }) {
|
|
136
|
+
const suppliersWithRates = cartPricing.shipping.suppliersWithRates
|
|
137
|
+
.map(supplierWithRates => ({
|
|
138
|
+
...(
|
|
139
|
+
supplierWithRates === supplier
|
|
140
|
+
? ({
|
|
141
|
+
...supplierWithRates,
|
|
142
|
+
rates: supplierWithRates.rates.map(r => ({ ...r, selected: rate === r }))
|
|
143
|
+
})
|
|
144
|
+
: supplierWithRates)
|
|
145
|
+
}));
|
|
146
|
+
const payload = generateCalculatePriceData(entities, suburb, suppliersWithRates);
|
|
147
|
+
try {
|
|
148
|
+
const response = await api.calculateProductPrice(payload, shop._id);
|
|
149
|
+
commit('setCartPricing', response);
|
|
150
|
+
commit('setCartPricingError', null);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
const { error = 'Error calculate pricing' } = e.response?.data || {};
|
|
153
|
+
commit('setCartPricingError', error);
|
|
154
|
+
commit('setCartPricing', null);
|
|
155
|
+
}
|
|
145
156
|
}
|
|
146
157
|
};
|
|
147
158
|
|
|
@@ -162,10 +173,53 @@ export const mutations = {
|
|
|
162
173
|
setCartPricing(state, price) {
|
|
163
174
|
state.cartPricing = price;
|
|
164
175
|
},
|
|
176
|
+
setCartPricingError(state, error) {
|
|
177
|
+
state.cartPricingError = error;
|
|
178
|
+
},
|
|
179
|
+
setSelectedRates(state, selectedRates) {
|
|
180
|
+
state.selectedRates = selectedRates;
|
|
181
|
+
},
|
|
165
182
|
clearCart(state) {
|
|
166
183
|
state.id = null;
|
|
167
184
|
state.entities = [];
|
|
168
185
|
state.cartPricing = null;
|
|
169
186
|
state.suburb = null;
|
|
187
|
+
state.cartPricingError = null;
|
|
170
188
|
}
|
|
171
189
|
};
|
|
190
|
+
|
|
191
|
+
function generateCalculatePriceData(entities, suburb, suppliersWithRates) {
|
|
192
|
+
console.log('suburb: ', suburb);
|
|
193
|
+
const getSimpleObj = i => i && ({ _id: i._id, name: i.name });
|
|
194
|
+
return {
|
|
195
|
+
entities: entities.map(({ _id, guid, prints, simpleProducts, product }) => ({
|
|
196
|
+
_id,
|
|
197
|
+
guid,
|
|
198
|
+
brand: getSimpleObj(product.brand),
|
|
199
|
+
simpleProducts: simpleProducts.map(({ _id, guid, amount, pricing, unprintedPricing, weight = 0 }) => ({
|
|
200
|
+
amount,
|
|
201
|
+
pricing: (prints || []).length > 0 ? pricing : unprintedPricing,
|
|
202
|
+
weight: product.weight,
|
|
203
|
+
volume: product.volume,
|
|
204
|
+
guid,
|
|
205
|
+
_id
|
|
206
|
+
})).filter(({ amount }) => +amount > 0),
|
|
207
|
+
prints: (prints || []).map(print => {
|
|
208
|
+
const { setupCost, freeSetupOver, printCost } = getPrintTypeSizePricing(print.printType, print.printSize?._id) || {};
|
|
209
|
+
return {
|
|
210
|
+
costType: print.printType.costType,
|
|
211
|
+
setupCost,
|
|
212
|
+
printCost,
|
|
213
|
+
freeSetupOver,
|
|
214
|
+
printType: getSimpleObj(print.printType),
|
|
215
|
+
printArea: getSimpleObj(print.printArea),
|
|
216
|
+
printSize: getSimpleObj(print.printSize)
|
|
217
|
+
};
|
|
218
|
+
}),
|
|
219
|
+
printSurcharge: product.printSurcharge || 0
|
|
220
|
+
})),
|
|
221
|
+
postcode: suburb && suburb.postcode,
|
|
222
|
+
address: suburb ? [suburb.locality, suburb.state, suburb.postcode].filter(i => !!i).join(', ') : null,
|
|
223
|
+
suppliersWithRates
|
|
224
|
+
};
|
|
225
|
+
}
|
package/store/order.js
CHANGED
|
@@ -22,6 +22,7 @@ export const actions = {
|
|
|
22
22
|
order.productsTotal = pricing.products?.products?.totalPriceWithoutTax || 0;
|
|
23
23
|
order.printsTotal = pricing.products?.prints?.totalPriceWithoutTax || 0;
|
|
24
24
|
order.shippingTotal = pricing.shipping?.totalPriceWithoutTax || 0;
|
|
25
|
+
order.suppliersWithRates = pricing.shipping?.suppliersWithRates || [];
|
|
25
26
|
}
|
|
26
27
|
const response = await api.createOrder(order, shop);
|
|
27
28
|
commit('setOrderData', response);
|