@lancom/shared 0.0.408 → 0.0.410
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 +3 -0
- package/assets/js/api/index.js +3 -1
- package/components/checkout/order/order-payment-information/order-payment-information.vue +2 -0
- package/components/checkout/order/order-review/order-review.vue +2 -0
- package/components/common/coupon_select/coupon-select.vue +12 -2
- package/components/common/phone_input/phone-input.vue +15 -3
- package/components/customer/customer_navigation_menu/customer-navigation-menu.vue +11 -7
- package/components/customer/customer_preferences_form/customer-preferences-form.scss +12 -0
- package/components/customer/customer_preferences_form/customer-preferences-form.vue +87 -0
- package/components/modals/order_modal/order-modal.vue +2 -0
- package/components/pages/customer/preferences/preferences.vue +79 -0
- package/components/quotes/quote_view/quote-view.mixin.js +2 -1
- package/package.json +1 -1
- package/pages/customer/preferences.vue +33 -0
- package/routes/index.js +10 -0
package/assets/js/api/admin.js
CHANGED
package/assets/js/api/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
import { _get, _post, _put, _delete, _patch } from './helpers';
|
|
3
2
|
import adminApi from './admin';
|
|
4
3
|
import { unminifySimpleProducts } from './utils/simple-products';
|
|
@@ -20,6 +19,9 @@ const api = {
|
|
|
20
19
|
saveCustomer(customer, shop) {
|
|
21
20
|
return customer._id ? _patch(`shop/${shop}/customer/${customer.accessToken}`, customer) : _post(`shop/${shop}/customer`, customer);
|
|
22
21
|
},
|
|
22
|
+
fetchCustomer(accessToken, shop) {
|
|
23
|
+
return _get(`shop/${shop}/customer/${accessToken}`);
|
|
24
|
+
},
|
|
23
25
|
authCustomer(customer, shop) {
|
|
24
26
|
return _post(`shop/${shop}/customer/login`, customer);
|
|
25
27
|
},
|
|
@@ -142,6 +142,7 @@ export default {
|
|
|
142
142
|
};
|
|
143
143
|
},
|
|
144
144
|
computed: {
|
|
145
|
+
...mapGetters('auth', ['user']),
|
|
145
146
|
...mapGetters(['MESSAGES']),
|
|
146
147
|
...mapGetters(['country', 'currency', 'app', 'googleClickId']),
|
|
147
148
|
...mapGetters(['orderSettings']),
|
|
@@ -178,6 +179,7 @@ export default {
|
|
|
178
179
|
const recaptchaToken = await this.getRecaptcha('create_order');
|
|
179
180
|
await this.createOrder({
|
|
180
181
|
...this.order,
|
|
182
|
+
customer: this.user?._id,
|
|
181
183
|
paymentStatus: paymentStatus || 'abandoned',
|
|
182
184
|
recaptchaToken,
|
|
183
185
|
products: this.entities,
|
|
@@ -74,6 +74,7 @@ export default {
|
|
|
74
74
|
};
|
|
75
75
|
},
|
|
76
76
|
computed: {
|
|
77
|
+
...mapGetters('auth', ['user']),
|
|
77
78
|
...mapGetters(['shop', 'country','currency', 'googleClickId']),
|
|
78
79
|
...mapGetters('cart', ['entities', 'notEmptySimpleProducts', 'cartPricing']),
|
|
79
80
|
isPaymentOrder() {
|
|
@@ -95,6 +96,7 @@ export default {
|
|
|
95
96
|
const recaptchaToken = await this.getRecaptcha('create_order');
|
|
96
97
|
await this.createOrder({
|
|
97
98
|
...this.order,
|
|
99
|
+
customer: this.user?._id,
|
|
98
100
|
recaptchaToken,
|
|
99
101
|
products: this.entities,
|
|
100
102
|
pricing: this.cartPricing,
|
|
@@ -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: {{
|
|
77
|
+
Invalid coupon: Min Order for Coupon: {{ minOrderValue | price(currency) }}
|
|
78
78
|
</div>
|
|
79
79
|
<div v-if="hasQualifyingProducts" class="lc_caption mb-10">
|
|
80
80
|
<div v-if="noQualifyingProductsInCart">
|
|
@@ -129,8 +129,18 @@ 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
|
+
},
|
|
132
142
|
isValidPricing() {
|
|
133
|
-
return !this.
|
|
143
|
+
return !this.minOrderValue || this.pricing.coupon;
|
|
134
144
|
},
|
|
135
145
|
model: {
|
|
136
146
|
get() {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div class="
|
|
3
|
+
<div :class="containerClassname">
|
|
4
4
|
<label
|
|
5
5
|
v-if="labelless"
|
|
6
|
-
class="
|
|
6
|
+
:class="labelClassname"
|
|
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"
|
|
35
34
|
:class="{
|
|
35
|
+
[inputClassname]: true,
|
|
36
36
|
'is-danger': errors.length,
|
|
37
37
|
filled: model,
|
|
38
38
|
labelless
|
|
@@ -115,6 +115,18 @@ 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'
|
|
118
130
|
}
|
|
119
131
|
},
|
|
120
132
|
data() {
|
|
@@ -15,6 +15,12 @@
|
|
|
15
15
|
<script>
|
|
16
16
|
export default {
|
|
17
17
|
name: 'CustomerMenu',
|
|
18
|
+
props: {
|
|
19
|
+
activeMenuItem: {
|
|
20
|
+
type: String,
|
|
21
|
+
required: true
|
|
22
|
+
}
|
|
23
|
+
},
|
|
18
24
|
data() {
|
|
19
25
|
return {
|
|
20
26
|
menuItems: [{
|
|
@@ -29,14 +35,12 @@ export default {
|
|
|
29
35
|
label: 'Coupons',
|
|
30
36
|
key: 'coupons',
|
|
31
37
|
url: '/customer/coupons'
|
|
38
|
+
}, {
|
|
39
|
+
label: 'Preferences',
|
|
40
|
+
key: 'preferences',
|
|
41
|
+
url: '/customer/preferences'
|
|
32
42
|
}]
|
|
33
43
|
};
|
|
34
|
-
},
|
|
35
|
-
props: {
|
|
36
|
-
activeMenuItem: {
|
|
37
|
-
type: String,
|
|
38
|
-
required: true
|
|
39
|
-
}
|
|
40
44
|
}
|
|
41
45
|
};
|
|
42
46
|
</script>
|
|
@@ -68,5 +72,5 @@ export default {
|
|
|
68
72
|
background-color: $green;
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
|
-
}
|
|
75
|
+
}
|
|
72
76
|
</style>
|
|
@@ -0,0 +1,87 @@
|
|
|
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>
|
|
@@ -268,6 +268,7 @@ export default {
|
|
|
268
268
|
};
|
|
269
269
|
},
|
|
270
270
|
computed: {
|
|
271
|
+
...mapGetters('auth', ['user']),
|
|
271
272
|
...mapGetters(['shop', 'country', 'currency', 'googleClickId']),
|
|
272
273
|
...mapGetters('order', ['orderData']),
|
|
273
274
|
...mapGetters('cart', [
|
|
@@ -332,6 +333,7 @@ export default {
|
|
|
332
333
|
this.processing = true;
|
|
333
334
|
const recaptchaToken = await this.getRecaptcha('create_order');
|
|
334
335
|
await this.createOrder({
|
|
336
|
+
customer: this.user?._id,
|
|
335
337
|
recaptchaToken,
|
|
336
338
|
currency: this.currency?._id,
|
|
337
339
|
googleClickId: this.googleClickId,
|
|
@@ -0,0 +1,79 @@
|
|
|
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>
|
|
@@ -27,6 +27,7 @@ export default {
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
computed: {
|
|
30
|
+
...mapGetters('auth', ['user']),
|
|
30
31
|
...mapGetters(['MESSAGES']),
|
|
31
32
|
...mapGetters('quote', ['quote', 'option', 'proceedOption', 'selectedOption', 'depositInfo', 'shopContacts', 'quoteAddress', 'quoteId', 'options', 'gstTax']),
|
|
32
33
|
...mapGetters(['shop', 'country', 'currency', 'googleClickId'])
|
|
@@ -40,7 +41,7 @@ export default {
|
|
|
40
41
|
async convertToOrder(option) {
|
|
41
42
|
try {
|
|
42
43
|
this.processing = true;
|
|
43
|
-
this.order = await this.createOrder({ ...option });
|
|
44
|
+
this.order = await this.createOrder({ ...option, customer: this.user?._id });
|
|
44
45
|
this.setOrder(this.order);
|
|
45
46
|
// gtm.purchase(this.order, this.currency);
|
|
46
47
|
gapis.surveyOptin(this.order, this.shop);
|
package/package.json
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
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>
|
package/routes/index.js
CHANGED
|
@@ -122,6 +122,11 @@ 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'
|
|
125
130
|
}, {
|
|
126
131
|
name: 'customer-recovery',
|
|
127
132
|
path: '/customer/recovery',
|
|
@@ -137,6 +142,11 @@ module.exports = function(routes, resolve, config) {
|
|
|
137
142
|
path: '/customer/password/:token',
|
|
138
143
|
component: resolve('@lancom/shared/pages/customer/password/_token.vue'),
|
|
139
144
|
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'
|
|
140
150
|
}, {
|
|
141
151
|
name: 'checkout-cart',
|
|
142
152
|
path: '/checkout/cart',
|