@lancom/shared 0.0.412 → 0.0.413
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 +5 -24
- package/assets/js/api/index.js +1 -3
- package/components/common/coupon_select/coupon-select.vue +2 -12
- package/components/common/phone_input/phone-input.vue +3 -15
- package/components/common/postcode_select/postcode-select.vue +1 -3
- package/components/customer/customer_navigation_menu/customer-navigation-menu.vue +7 -11
- package/components/product/product_banners/product-banners.scss +10 -0
- package/components/product/product_banners/product-banners.vue +34 -0
- package/components/product/product_multipacks_carousel/product-multipacks-carousel.vue +4 -7
- package/components/product/product_multipacks_carousel/product_multipack/product-multipack.vue +4 -2
- package/components/product/wizard/wizard.scss +4 -1
- package/components/product/wizard/wizard.vue +6 -1
- package/feeds/google-shopping.js +4 -0
- package/layouts/products.vue +2 -2
- package/mixins/product-view.js +10 -5
- package/package.json +1 -1
- package/routes/index.js +0 -10
- package/store/product.js +12 -0
- package/components/customer/customer_preferences_form/customer-preferences-form.scss +0 -12
- package/components/customer/customer_preferences_form/customer-preferences-form.vue +0 -87
- package/components/pages/customer/preferences/preferences.vue +0 -79
- package/pages/customer/preferences.vue +0 -33
package/assets/js/api/admin.js
CHANGED
|
@@ -3,12 +3,6 @@ import { _get, _post, _delete, _put } from './helpers';
|
|
|
3
3
|
import { sortSizes } from './../utils/sizes';
|
|
4
4
|
import { sortByName } from './../utils/filters';
|
|
5
5
|
|
|
6
|
-
const CACHE = {
|
|
7
|
-
PRINT_AREAS: 'print-areas',
|
|
8
|
-
PACKAGES: 'packages'
|
|
9
|
-
};
|
|
10
|
-
const promiseCache = new Map();
|
|
11
|
-
|
|
12
6
|
export default {
|
|
13
7
|
updateInventoryFromLink(link, warehouse) {
|
|
14
8
|
const url = `admin/products/inventory/link${warehouse ? `?warehouse=${warehouse}` : ''}`;
|
|
@@ -218,13 +212,8 @@ export default {
|
|
|
218
212
|
removeCategory(id) {
|
|
219
213
|
return _delete(`admin/categories/${id}`);
|
|
220
214
|
},
|
|
221
|
-
dropPackagesCache() {
|
|
222
|
-
promiseCache.delete(CACHE.PACKAGES);
|
|
223
|
-
},
|
|
224
215
|
fetchPackages() {
|
|
225
|
-
|
|
226
|
-
promiseCache.set(CACHE.PACKAGES, promise);
|
|
227
|
-
return promise;
|
|
216
|
+
return _get('admin/packages');
|
|
228
217
|
},
|
|
229
218
|
fetchPackageById(id) {
|
|
230
219
|
return _get(`admin/packages/${id}`);
|
|
@@ -668,16 +657,8 @@ export default {
|
|
|
668
657
|
removePrintType(id) {
|
|
669
658
|
return _delete(`admin/print-types/${id}`);
|
|
670
659
|
},
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
},
|
|
674
|
-
fetchPrintAreas(params) {
|
|
675
|
-
if (params) {
|
|
676
|
-
return _get('admin/print-areas', params);
|
|
677
|
-
}
|
|
678
|
-
const promise = promiseCache.get(CACHE.PRINT_AREAS) || _get('admin/print-areas');
|
|
679
|
-
promiseCache.set(CACHE.PRINT_AREAS, promise);
|
|
680
|
-
return promise;
|
|
660
|
+
fetchPrintAreas() {
|
|
661
|
+
return _get('admin/print-areas');
|
|
681
662
|
},
|
|
682
663
|
fetchPrintAreaById(id) {
|
|
683
664
|
return _get(`admin/print-areas/${id}`);
|
|
@@ -688,8 +669,8 @@ export default {
|
|
|
688
669
|
removePrintArea(id) {
|
|
689
670
|
return _delete(`admin/print-areas/${id}`);
|
|
690
671
|
},
|
|
691
|
-
fetchPrintSizes(
|
|
692
|
-
return _get('admin/print-sizes'
|
|
672
|
+
fetchPrintSizes() {
|
|
673
|
+
return _get('admin/print-sizes');
|
|
693
674
|
},
|
|
694
675
|
fetchPrintSizeById(id) {
|
|
695
676
|
return _get(`admin/print-sizes/${id}`);
|
package/assets/js/api/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
import { _get, _post, _put, _delete, _patch } from './helpers';
|
|
2
3
|
import adminApi from './admin';
|
|
3
4
|
import { unminifySimpleProducts } from './utils/simple-products';
|
|
@@ -19,9 +20,6 @@ const api = {
|
|
|
19
20
|
saveCustomer(customer, shop) {
|
|
20
21
|
return customer._id ? _patch(`shop/${shop}/customer/${customer.accessToken}`, customer) : _post(`shop/${shop}/customer`, customer);
|
|
21
22
|
},
|
|
22
|
-
fetchCustomer(accessToken, shop) {
|
|
23
|
-
return _get(`shop/${shop}/customer/${accessToken}`);
|
|
24
|
-
},
|
|
25
23
|
authCustomer(customer, shop) {
|
|
26
24
|
return _post(`shop/${shop}/customer/login`, customer);
|
|
27
25
|
},
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
<div
|
|
75
75
|
v-else
|
|
76
76
|
class="lc_caption form-help is-danger">
|
|
77
|
-
Invalid coupon: Min Order for Coupon: {{ minOrderValue | price(currency) }}
|
|
77
|
+
Invalid coupon: Min Order for Coupon: {{ value.minOrderValue | price(currency) }}
|
|
78
78
|
</div>
|
|
79
79
|
<div v-if="hasQualifyingProducts" class="lc_caption mb-10">
|
|
80
80
|
<div v-if="noQualifyingProductsInCart">
|
|
@@ -129,18 +129,8 @@ export default {
|
|
|
129
129
|
hasQualifyingProductsInCart() {
|
|
130
130
|
return this.sumQualifyingProductsInCart > 0;
|
|
131
131
|
},
|
|
132
|
-
minOrderValue() {
|
|
133
|
-
const value = [
|
|
134
|
-
this.value,
|
|
135
|
-
...(this.value?.values || [])
|
|
136
|
-
]
|
|
137
|
-
.filter(v => v?.minOrderValue > 0)
|
|
138
|
-
.sort((a, b) => a.minOrderValue - b.minOrderValue)[0];
|
|
139
|
-
|
|
140
|
-
return value?.minOrderValue || 0;
|
|
141
|
-
},
|
|
142
132
|
isValidPricing() {
|
|
143
|
-
return !this.minOrderValue || this.pricing.coupon;
|
|
133
|
+
return !this.value?.minOrderValue || this.pricing.coupon;
|
|
144
134
|
},
|
|
145
135
|
model: {
|
|
146
136
|
get() {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
3
|
+
<div class="form-row">
|
|
4
4
|
<label
|
|
5
5
|
v-if="labelless"
|
|
6
|
-
|
|
6
|
+
class="form-label"
|
|
7
7
|
@click="$refs.phone.$el.focus()">
|
|
8
8
|
{{ displayLabelText }}
|
|
9
9
|
</label>
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
:disabled="disabled"
|
|
32
32
|
:name="'phone' + uniqueKey"
|
|
33
33
|
type="text"
|
|
34
|
+
class="form-field"
|
|
34
35
|
:class="{
|
|
35
|
-
[inputClassname]: true,
|
|
36
36
|
'is-danger': errors.length,
|
|
37
37
|
filled: model,
|
|
38
38
|
labelless
|
|
@@ -115,18 +115,6 @@ export default {
|
|
|
115
115
|
namePrefix: {
|
|
116
116
|
type: String,
|
|
117
117
|
default: ''
|
|
118
|
-
},
|
|
119
|
-
containerClassname: {
|
|
120
|
-
type: String,
|
|
121
|
-
default: 'form-row'
|
|
122
|
-
},
|
|
123
|
-
labelClassname: {
|
|
124
|
-
type: String,
|
|
125
|
-
default: 'form-label'
|
|
126
|
-
},
|
|
127
|
-
inputClassname: {
|
|
128
|
-
type: String,
|
|
129
|
-
default: 'form-field'
|
|
130
118
|
}
|
|
131
119
|
},
|
|
132
120
|
data() {
|
|
@@ -177,9 +177,7 @@ export default {
|
|
|
177
177
|
if (this.suburb) {
|
|
178
178
|
const option = this.createOptionFromSuburb(this.suburb);
|
|
179
179
|
this.selected = option;
|
|
180
|
-
|
|
181
|
-
await this.handleSearch(this.selected.value.trim());
|
|
182
|
-
}
|
|
180
|
+
await this.handleSearch(this.selected.value.trim())
|
|
183
181
|
}
|
|
184
182
|
},
|
|
185
183
|
methods: {
|
|
@@ -15,12 +15,6 @@
|
|
|
15
15
|
<script>
|
|
16
16
|
export default {
|
|
17
17
|
name: 'CustomerMenu',
|
|
18
|
-
props: {
|
|
19
|
-
activeMenuItem: {
|
|
20
|
-
type: String,
|
|
21
|
-
required: true
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
18
|
data() {
|
|
25
19
|
return {
|
|
26
20
|
menuItems: [{
|
|
@@ -35,12 +29,14 @@ export default {
|
|
|
35
29
|
label: 'Coupons',
|
|
36
30
|
key: 'coupons',
|
|
37
31
|
url: '/customer/coupons'
|
|
38
|
-
}, {
|
|
39
|
-
label: 'Preferences',
|
|
40
|
-
key: 'preferences',
|
|
41
|
-
url: '/customer/preferences'
|
|
42
32
|
}]
|
|
43
33
|
};
|
|
34
|
+
},
|
|
35
|
+
props: {
|
|
36
|
+
activeMenuItem: {
|
|
37
|
+
type: String,
|
|
38
|
+
required: true
|
|
39
|
+
}
|
|
44
40
|
}
|
|
45
41
|
};
|
|
46
42
|
</script>
|
|
@@ -72,5 +68,5 @@ export default {
|
|
|
72
68
|
background-color: $green;
|
|
73
69
|
}
|
|
74
70
|
}
|
|
75
|
-
}
|
|
71
|
+
}
|
|
76
72
|
</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="ProductBanners__wrapper">
|
|
3
|
+
<a :href="mainBanner.link" class="ProductBanners__banner">
|
|
4
|
+
<img :src="mainBanner.image.origin" :alt="mainBanner.label" />
|
|
5
|
+
</a>
|
|
6
|
+
</div>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import { mapGetters } from 'vuex';
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
name: 'ProductBanners',
|
|
14
|
+
props: {
|
|
15
|
+
product: {
|
|
16
|
+
type: Object,
|
|
17
|
+
required: true
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
computed: {
|
|
21
|
+
...mapGetters(['shop']),
|
|
22
|
+
...mapGetters('product', ['banners']),
|
|
23
|
+
mainBanner() {
|
|
24
|
+
const bannersItems = this.banners.reduce((items, banner) => ([...items, ...banner.items]), []);
|
|
25
|
+
const productBanner = bannersItems.find(item => item.products?.includes(this.product._id));
|
|
26
|
+
return productBanner || bannersItems[0];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
</script>
|
|
31
|
+
|
|
32
|
+
<style lang="scss" scoped>
|
|
33
|
+
@import 'product-banners';
|
|
34
|
+
</style>
|
|
@@ -43,11 +43,6 @@ export default {
|
|
|
43
43
|
components: {
|
|
44
44
|
ProductMultipack
|
|
45
45
|
},
|
|
46
|
-
data() {
|
|
47
|
-
return {
|
|
48
|
-
thumbsPage: 0
|
|
49
|
-
};
|
|
50
|
-
},
|
|
51
46
|
props: {
|
|
52
47
|
product: {
|
|
53
48
|
type: Object,
|
|
@@ -70,8 +65,10 @@ export default {
|
|
|
70
65
|
default: 3
|
|
71
66
|
}
|
|
72
67
|
},
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
data() {
|
|
69
|
+
return {
|
|
70
|
+
thumbsPage: 0
|
|
71
|
+
};
|
|
75
72
|
},
|
|
76
73
|
computed: {
|
|
77
74
|
...mapGetters(['currency']),
|
package/components/product/product_multipacks_carousel/product_multipack/product-multipack.vue
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
<div class="ProductMultipack__price">
|
|
28
|
-
{{ oneItemPrice | price(currency) }} each
|
|
28
|
+
{{ oneItemPrice | price(currency) }} each
|
|
29
29
|
<span>{{ totalPrice | price(currency) }}</span>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
@@ -79,7 +79,9 @@ export default {
|
|
|
79
79
|
return simpleProducts.find(sp => sp.size?.shortName === simpleProduct?.size?.shortName) || simpleProducts[0];
|
|
80
80
|
},
|
|
81
81
|
totalPrice() {
|
|
82
|
-
|
|
82
|
+
const itemPrice = priceFromRange(this.multipack.qty, this.simpleProduct?.pricing);
|
|
83
|
+
const price = itemPrice * this.multipack.qty;
|
|
84
|
+
return this.withGst ? tax(price, this.gstTax) : price;
|
|
83
85
|
},
|
|
84
86
|
oneItemPrice() {
|
|
85
87
|
const price = priceFromRange(this.multipack.qty, this.simpleProduct?.pricing);
|
|
@@ -28,6 +28,9 @@
|
|
|
28
28
|
{{ isVisible ? 'CANCEL PRINT' : 'ADD PRINT' }}
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
|
+
<div class="Wizard__banners">
|
|
32
|
+
<product-banners :product="product" />
|
|
33
|
+
</div>
|
|
31
34
|
<div
|
|
32
35
|
v-if="isVisible"
|
|
33
36
|
class="Wizard__content"
|
|
@@ -119,6 +122,7 @@ import gtm from '@lancom/shared/assets/js/utils/gtm';
|
|
|
119
122
|
import Info from '@lancom/shared/components/common/info-popover';
|
|
120
123
|
import { getPrintAreaSizes } from '@lancom/shared/assets/js/utils/prints';
|
|
121
124
|
import ProgressSteps from '@lancom/shared/components/common/progress_steps/progress-steps';
|
|
125
|
+
import ProductBanners from '@lancom/shared/components/product/product_banners/product-banners';
|
|
122
126
|
import WizardPrintArea from './wizard_print_area/wizard-print-area';
|
|
123
127
|
import WizardPrintSize from './wizard_print_size/wizard-print-size';
|
|
124
128
|
import WizardPrintType from './wizard_print_type/wizard-print-type';
|
|
@@ -143,6 +147,7 @@ export default {
|
|
|
143
147
|
name: 'Editor',
|
|
144
148
|
components: {
|
|
145
149
|
ProgressSteps,
|
|
150
|
+
ProductBanners,
|
|
146
151
|
WizardPrintArea,
|
|
147
152
|
WizardPrintSize,
|
|
148
153
|
WizardPrintType,
|
|
@@ -232,7 +237,7 @@ export default {
|
|
|
232
237
|
},
|
|
233
238
|
editLayer(layer) {
|
|
234
239
|
this.clearWizardData();
|
|
235
|
-
|
|
240
|
+
|
|
236
241
|
this.setEditableLayers([layer]);
|
|
237
242
|
const printArea = this.productPrintAreas.find(pa => pa._id === layer.printArea);
|
|
238
243
|
this.addEditablePrintArea(printArea);
|
package/feeds/google-shopping.js
CHANGED
|
@@ -102,6 +102,10 @@ async function googleShoppingFeed(axios, config, availableStores, country, isEdi
|
|
|
102
102
|
info['g:gtin'] = { _text: sp.gtin || '' };
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
if (sp.clearancePrice > 0) {
|
|
106
|
+
info['g:sale_price'] = { _text: `${(sp.clearancePrice)} ${sp.currencyCode || 'AUD'}` };
|
|
107
|
+
}
|
|
108
|
+
|
|
105
109
|
if (sp.storeCode) {
|
|
106
110
|
info['g:store_code'] = { _text: sp.storeCode };
|
|
107
111
|
info['g:link_template'] = { _text: `${link}&store={store_code}` };
|
package/layouts/products.vue
CHANGED
|
@@ -126,10 +126,10 @@
|
|
|
126
126
|
return 'product';
|
|
127
127
|
},
|
|
128
128
|
pageItemImage() {
|
|
129
|
-
const images = this.products
|
|
129
|
+
const images = this.products?.reduce((images, product) => {
|
|
130
130
|
const image = getProductLargeCover(product, 'front') || getProductMediumCover(product, 'front');
|
|
131
131
|
return image ? [...images, image] : images;
|
|
132
|
-
}, []);
|
|
132
|
+
}, []) || [];
|
|
133
133
|
return images.slice(0, 1);
|
|
134
134
|
},
|
|
135
135
|
currentBrand() {
|
package/mixins/product-view.js
CHANGED
|
@@ -42,7 +42,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
42
42
|
const redirectUrl = generateProductLink(product, data.defaultColor, isEditor);
|
|
43
43
|
return redirect(301, redirectUrl);
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
if (params.sku && params.sku !== product?.SKU?.toLowerCase()) {
|
|
47
47
|
return error({ statusCode: 404, message: 'Product not found' });
|
|
48
48
|
}
|
|
@@ -58,6 +58,11 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
58
58
|
if (query.price) {
|
|
59
59
|
store.commit('product/setPriceIncludeGST', query.price === 'IT');
|
|
60
60
|
}
|
|
61
|
+
if (query.multipack) {
|
|
62
|
+
const multipackQty = +query.multipack.split('-multipack-')[1];
|
|
63
|
+
const multipack = product.multipacks?.find(m => m.qty === multipackQty);
|
|
64
|
+
store.commit('product/setMultipack', multipack);
|
|
65
|
+
}
|
|
61
66
|
} catch (e) {
|
|
62
67
|
console.log(e);
|
|
63
68
|
}
|
|
@@ -179,7 +184,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
179
184
|
}
|
|
180
185
|
} catch (e) {
|
|
181
186
|
}
|
|
182
|
-
|
|
187
|
+
|
|
183
188
|
this.fillBreadcrumbs();
|
|
184
189
|
const { multipack } = this.$route.query;
|
|
185
190
|
if (multipack) {
|
|
@@ -277,7 +282,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
277
282
|
const maxPrice = this.printsPrice ? spMaxPrice + this.printsPrice : spMaxPrice;
|
|
278
283
|
const availability = sp.quantityStock > 0 ? 'InStock' : 'OutOfStock';
|
|
279
284
|
const name = `${this.product.name} | ${sp.size?.shortName || ''} ${sp.color?.name || ''}`;
|
|
280
|
-
|
|
285
|
+
|
|
281
286
|
const offer = {
|
|
282
287
|
'@type': 'Offer',
|
|
283
288
|
name,
|
|
@@ -309,7 +314,7 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
309
314
|
// if (sp.quantityStock > 0) {
|
|
310
315
|
// }
|
|
311
316
|
}
|
|
312
|
-
|
|
317
|
+
|
|
313
318
|
offer.shippingDetails = { "@id": "#shipping_policy" };
|
|
314
319
|
offer.hasMerchantReturnPolicy = { "@id": "#return_policy" };
|
|
315
320
|
|
|
@@ -422,4 +427,4 @@ export default (IS_PRODUCT_PRESET_PRINT_PRICING, isEditor = false) => ({
|
|
|
422
427
|
this.$store.state.shop?.shippingPolicySchema
|
|
423
428
|
].filter(s => !!s);
|
|
424
429
|
}
|
|
425
|
-
});
|
|
430
|
+
});
|
package/package.json
CHANGED
package/routes/index.js
CHANGED
|
@@ -122,11 +122,6 @@ module.exports = function(routes, resolve, config) {
|
|
|
122
122
|
path: '/customer/coupons',
|
|
123
123
|
component: resolve('@lancom/shared/pages/customer/coupons.vue'),
|
|
124
124
|
chunkName: 'pages/customer/coupons'
|
|
125
|
-
}, {
|
|
126
|
-
name: 'customer-preferences',
|
|
127
|
-
path: '/customer/preferences',
|
|
128
|
-
component: resolve('@lancom/shared/pages/customer/preferences.vue'),
|
|
129
|
-
chunkName: 'pages/customer/preferences'
|
|
130
125
|
}, {
|
|
131
126
|
name: 'customer-recovery',
|
|
132
127
|
path: '/customer/recovery',
|
|
@@ -142,11 +137,6 @@ module.exports = function(routes, resolve, config) {
|
|
|
142
137
|
path: '/customer/password/:token',
|
|
143
138
|
component: resolve('@lancom/shared/pages/customer/password/_token.vue'),
|
|
144
139
|
chunkName: 'pages/customer/password/reset'
|
|
145
|
-
}, {
|
|
146
|
-
name: 'customer-preferences',
|
|
147
|
-
path: '/customer/preferences',
|
|
148
|
-
component: resolve('@lancom/shared/pages/customer/preferences.vue'),
|
|
149
|
-
chunkName: 'pages/customer/preferences'
|
|
150
140
|
}, {
|
|
151
141
|
name: 'checkout-cart',
|
|
152
142
|
path: '/checkout/cart',
|
package/store/product.js
CHANGED
|
@@ -11,6 +11,7 @@ import { sortByName } from '../assets/js/utils/filters';
|
|
|
11
11
|
|
|
12
12
|
export const state = () => ({
|
|
13
13
|
multipack: null,
|
|
14
|
+
banners: [],
|
|
14
15
|
calculatingPrice: false,
|
|
15
16
|
loadingProductDetails: false,
|
|
16
17
|
productDetailsKey: Date.now(),
|
|
@@ -64,6 +65,7 @@ export const getters = {
|
|
|
64
65
|
editorSize: ({ editorSize }) => editorSize,
|
|
65
66
|
template: ({ template }) => template,
|
|
66
67
|
layers: ({ template }) => template.layers || [],
|
|
68
|
+
banners: ({ banners }) => banners || [],
|
|
67
69
|
templateColors: ({ template }) => template.colors || [],
|
|
68
70
|
hasLayers: ({ template }) => (template.layers || []).length > 0,
|
|
69
71
|
visibleSteps: ({ template }) => template.visibleSteps,
|
|
@@ -166,6 +168,13 @@ export const actions = {
|
|
|
166
168
|
const product = await api.fetchProduct(shop, slug, query);
|
|
167
169
|
commit('setProduct', product);
|
|
168
170
|
|
|
171
|
+
const bannersParams = {
|
|
172
|
+
type: 'product view main',
|
|
173
|
+
product: product._id
|
|
174
|
+
};
|
|
175
|
+
const banners = await api.fetchBanners(shop, bannersParams) || [];
|
|
176
|
+
commit('setBanners', banners);
|
|
177
|
+
|
|
169
178
|
const prints = (product.prints || []).filter(({ _id, printTemplate }) => _id === print || (!print && !!printTemplate));
|
|
170
179
|
commit('setPreSetPrints', prints);
|
|
171
180
|
if (prints?.length > 0) {
|
|
@@ -300,6 +309,9 @@ export const mutations = {
|
|
|
300
309
|
setProduct(state, product) {
|
|
301
310
|
state.product = product;
|
|
302
311
|
},
|
|
312
|
+
setBanners(state, banners) {
|
|
313
|
+
state.banners = banners;
|
|
314
|
+
},
|
|
303
315
|
setPriceIncludeGST(state, priceIncludeGST) {
|
|
304
316
|
state.priceIncludeGST = priceIncludeGST;
|
|
305
317
|
},
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="form__wrapper CustomerFrom__wrapper">
|
|
3
|
-
<validation-observer ref="form">
|
|
4
|
-
<div class="mt-10">
|
|
5
|
-
<div
|
|
6
|
-
class="row"
|
|
7
|
-
style="margin-top: -20px">
|
|
8
|
-
<div class="col-12">
|
|
9
|
-
<div class="form-row">
|
|
10
|
-
<label class="form-label">
|
|
11
|
-
<checkbox v-model="customer.signUpForNewsletter" />
|
|
12
|
-
<span class="lc_regular12 lc__grey1">
|
|
13
|
-
Sign up for newsletter
|
|
14
|
-
</span>
|
|
15
|
-
</label>
|
|
16
|
-
</div>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
<div class="form__footer mt-5">
|
|
21
|
-
<div
|
|
22
|
-
v-if="errorMessage"
|
|
23
|
-
class="CustomerForm__error">
|
|
24
|
-
{{ errorMessage }}
|
|
25
|
-
</div>
|
|
26
|
-
<div class="form-actions full">
|
|
27
|
-
<btn
|
|
28
|
-
class="btn btn-black"
|
|
29
|
-
:btn-processing="processing"
|
|
30
|
-
:btn-disabled="processing"
|
|
31
|
-
:btn-label="customer._id ? 'Save' : 'Create Account'"
|
|
32
|
-
@onclick="submit()">
|
|
33
|
-
</btn>
|
|
34
|
-
</div>
|
|
35
|
-
</div>
|
|
36
|
-
</validation-observer>
|
|
37
|
-
</div>
|
|
38
|
-
</template>
|
|
39
|
-
|
|
40
|
-
<script>
|
|
41
|
-
import { mapGetters } from 'vuex';
|
|
42
|
-
import api from '@lancom/shared/assets/js/api';
|
|
43
|
-
|
|
44
|
-
export default {
|
|
45
|
-
name: 'CustomerPreferencesForm',
|
|
46
|
-
props: {
|
|
47
|
-
customer: {
|
|
48
|
-
type: Object,
|
|
49
|
-
required: true
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
data() {
|
|
53
|
-
return {
|
|
54
|
-
errorMessage: null,
|
|
55
|
-
processing: false
|
|
56
|
-
};
|
|
57
|
-
},
|
|
58
|
-
computed: {
|
|
59
|
-
...mapGetters(['shop'])
|
|
60
|
-
},
|
|
61
|
-
methods: {
|
|
62
|
-
async submit() {
|
|
63
|
-
this.errorMessage = null;
|
|
64
|
-
|
|
65
|
-
const isValid = await this.$refs.form.validate();
|
|
66
|
-
if (!isValid) {
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
try {
|
|
71
|
-
this.processing = true;
|
|
72
|
-
const result = await api.saveCustomer(this.customer, this.shop._id);
|
|
73
|
-
this.$emit('save', result);
|
|
74
|
-
} catch ({ response }) {
|
|
75
|
-
const { data } = response || {};
|
|
76
|
-
this.errorMessage = data && data.error;
|
|
77
|
-
} finally {
|
|
78
|
-
this.processing = false;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
</script>
|
|
84
|
-
|
|
85
|
-
<style lang="scss" scoped>
|
|
86
|
-
@import 'customer-preferences-form.scss';
|
|
87
|
-
</style>
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div class="CustomerPreferences__wrapper">
|
|
3
|
-
<customer-preferences-form
|
|
4
|
-
v-if="customer"
|
|
5
|
-
ref="customerForm"
|
|
6
|
-
:customer="customer"
|
|
7
|
-
@save="onSave"
|
|
8
|
-
@customer-loaded="onCustomerLoaded" />
|
|
9
|
-
</div>
|
|
10
|
-
</template>
|
|
11
|
-
|
|
12
|
-
<script>
|
|
13
|
-
import api from '@lancom/shared/assets/js/api';
|
|
14
|
-
import { mapGetters, mapActions } from 'vuex';
|
|
15
|
-
import CustomerPreferencesForm from '@lancom/shared/components/customer/customer_preferences_form/customer-preferences-form';
|
|
16
|
-
|
|
17
|
-
export default {
|
|
18
|
-
name: 'CustomerPreferences',
|
|
19
|
-
components: {
|
|
20
|
-
CustomerPreferencesForm
|
|
21
|
-
},
|
|
22
|
-
data() {
|
|
23
|
-
return {
|
|
24
|
-
customer: null,
|
|
25
|
-
loading: false,
|
|
26
|
-
error: null
|
|
27
|
-
};
|
|
28
|
-
},
|
|
29
|
-
computed: {
|
|
30
|
-
...mapGetters(['shop']),
|
|
31
|
-
...mapGetters('auth', ['user'])
|
|
32
|
-
},
|
|
33
|
-
async created() {
|
|
34
|
-
await this.loadCustomerData();
|
|
35
|
-
},
|
|
36
|
-
methods: {
|
|
37
|
-
...mapActions('auth', ['update_user']),
|
|
38
|
-
async loadCustomerData() {
|
|
39
|
-
try {
|
|
40
|
-
this.processing = true;
|
|
41
|
-
const customer = await api.fetchCustomer(this.user.accessToken, this.shop._id);
|
|
42
|
-
console.log('customer: ', customer);
|
|
43
|
-
this.customer = customer;
|
|
44
|
-
} catch (e) {
|
|
45
|
-
console.log(e);
|
|
46
|
-
const errorMessage = e?.response?.data?.error;
|
|
47
|
-
this.$toastr.e(errorMessage || 'Customer failed to load');
|
|
48
|
-
} finally {
|
|
49
|
-
this.processing = false;
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
onSave({ customer: user, token }) {
|
|
53
|
-
this.$toastr.s('Customer successfully saved');
|
|
54
|
-
this.update_user({ user, token });
|
|
55
|
-
},
|
|
56
|
-
onCustomerLoaded(customer) {
|
|
57
|
-
this.customer = customer;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
</script>
|
|
62
|
-
|
|
63
|
-
<style lang="scss" scoped>
|
|
64
|
-
.loading-message {
|
|
65
|
-
text-align: center;
|
|
66
|
-
padding: 2rem;
|
|
67
|
-
font-size: 1.1rem;
|
|
68
|
-
color: #666;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
.error-message {
|
|
72
|
-
text-align: center;
|
|
73
|
-
padding: 2rem;
|
|
74
|
-
color: #d32f2f;
|
|
75
|
-
background-color: #ffebee;
|
|
76
|
-
border-radius: 4px;
|
|
77
|
-
margin: 1rem 0;
|
|
78
|
-
}
|
|
79
|
-
</style>
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div
|
|
3
|
-
:data-aos="aosFadeLeft"
|
|
4
|
-
class="CustomerPreferencesPage__wrapper">
|
|
5
|
-
<customer-preferences />
|
|
6
|
-
</div>
|
|
7
|
-
</template>
|
|
8
|
-
|
|
9
|
-
<script>
|
|
10
|
-
import metaInfo from '@lancom/shared/mixins/meta-info';
|
|
11
|
-
|
|
12
|
-
export default {
|
|
13
|
-
name: 'CustomerPreferencesPage',
|
|
14
|
-
components: {
|
|
15
|
-
CustomerPreferences: () => import('@lancom/shared/components/pages/customer/preferences/preferences')
|
|
16
|
-
},
|
|
17
|
-
mixins: [metaInfo]
|
|
18
|
-
};
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
<style lang="scss" scoped>
|
|
22
|
-
@import "@/assets/scss/variables";
|
|
23
|
-
|
|
24
|
-
.CustomerPreferencesPage {
|
|
25
|
-
&__wrapper {
|
|
26
|
-
margin: 100px auto;
|
|
27
|
-
width: 500px;
|
|
28
|
-
@media (max-width: $bp-extra-small-max) {
|
|
29
|
-
width: auto;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
</style>
|