@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.
@@ -284,6 +284,9 @@ export default {
284
284
  removeUser(id) {
285
285
  return _delete(`admin/user/${id}`);
286
286
  },
287
+ fetchCustomers() {
288
+ return _get('admin/customers');
289
+ },
287
290
  fetchCustomerById(id) {
288
291
  return _get(`admin/customer/${id}`);
289
292
  },
@@ -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: {{ value.minOrderValue | price(currency) }}
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.value?.minOrderValue || this.pricing.coupon;
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="form-row">
3
+ <div :class="containerClassname">
4
4
  <label
5
5
  v-if="labelless"
6
- class="form-label"
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,12 @@
1
+ @import "@/assets/scss/variables";
2
+
3
+ .CustomerPreferencesForm {
4
+ &__error {
5
+ font-weight: bold;
6
+ font-size: 14px;
7
+ padding: 18px 10px;
8
+ text-align: center;
9
+ color: $white;
10
+ background: #EA3434;
11
+ }
12
+ }
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lancom/shared",
3
- "version": "0.0.408",
3
+ "version": "0.0.410",
4
4
  "description": "lancom common scripts",
5
5
  "author": "e.tokovenko <e.tokovenko@gmail.com>",
6
6
  "repository": {
@@ -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',