@lancom/shared 0.0.429 → 0.0.431

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.
Files changed (47) hide show
  1. package/assets/js/api/index.js +2 -2
  2. package/assets/js/constants/product.js +14 -0
  3. package/assets/scss/_common.scss +9 -1
  4. package/assets/scss/variables/_breakpoints.scss +2 -0
  5. package/components/common/breadcrumbs/breadcrumbs.scss +4 -1
  6. package/components/common/breadcrumbs/breadcrumbs.vue +4 -1
  7. package/components/common/client_settings/client-settings.vue +2 -3
  8. package/components/common/client_settings_tax/client-settings-tax.vue +1 -0
  9. package/components/common/price.vue +1 -2
  10. package/components/common/pricing_discounts_table/pricing-discounts-table.vue +28 -5
  11. package/components/common/product_side_with_print/product-side-with-print.vue +3 -3
  12. package/components/common/stars-mark.vue +21 -9
  13. package/components/common/tabs.vue +17 -3
  14. package/components/editor/editor_colors/editor-colors.scss +79 -0
  15. package/components/editor/editor_colors/editor-colors.vue +90 -0
  16. package/components/editor/editor_layers/editor-layers.vue +11 -6
  17. package/components/editor/editor_workspace/editor-workspace.vue +17 -15
  18. package/components/editor/editor_workspace/editor_workspace_side/editor-workspace-side.vue +2 -9
  19. package/components/product/other_products/other-products.scss +34 -0
  20. package/components/product/other_products/other-products.vue +76 -0
  21. package/components/product/other_products/other_product/other-product.scss +80 -0
  22. package/components/product/other_products/other_product/other-product.vue +59 -0
  23. package/components/product/product.vue +0 -14
  24. package/components/product/product_check_delivery/product-check-delivery.scss +31 -0
  25. package/components/product/product_check_delivery/product-check-delivery.vue +73 -0
  26. package/components/product/product_colors_selector/product-colors-selector.scss +8 -1
  27. package/components/product/product_colors_selector/product-colors-selector.vue +8 -0
  28. package/components/product/product_pricing_tiers/product-pricing-tiers.scss +53 -0
  29. package/components/product/product_pricing_tiers/product-pricing-tiers.vue +40 -0
  30. package/components/product/product_reviews/product-reviews.vue +6 -6
  31. package/components/product/product_stock_status/product-stock-status.scss +28 -0
  32. package/components/product/product_stock_status/product-stock-status.vue +35 -0
  33. package/components/product/related_products/related-products.vue +4 -4
  34. package/components/product/wizard/wizard_print/wizard-print.vue +1 -1
  35. package/components/products/products_attributes/products_attribute/products-attribute.vue +19 -18
  36. package/components/products/products_brands/products-brands.vue +3 -1
  37. package/components/products/products_filters/products-filters.vue +9 -1
  38. package/components/products/products_tags/products-tags.vue +19 -18
  39. package/components/products/products_types/products-types.scss +1 -1
  40. package/layouts/products.vue +153 -432
  41. package/mixins/layouts/products.js +285 -0
  42. package/mixins/product-preview.js +13 -0
  43. package/package.json +1 -1
  44. package/store/index.js +2 -0
  45. package/store/product.js +50 -12
  46. package/components/the_breadcrumbs/the-breadcrumbs.scss +0 -36
  47. package/components/the_breadcrumbs/the-breadcrumbs.vue +0 -78
@@ -0,0 +1,34 @@
1
+ .OtherProducts {
2
+ &__head {
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: space-between;
6
+ margin: 4px 0 16px;
7
+ gap: 16px;
8
+ }
9
+
10
+ &__title {
11
+ color: #0A0A0A;
12
+ font-size: 14px;
13
+ font-style: normal;
14
+ font-weight: 600;
15
+ line-height: 20px;
16
+ }
17
+
18
+ &__all {
19
+ color: #194BB3;
20
+ text-align: center;
21
+ font-size: 12px;
22
+ font-style: normal;
23
+ font-weight: 600;
24
+ line-height: 16px;
25
+ text-decoration: underline;
26
+ &:hover {
27
+ text-decoration: none;
28
+ }
29
+ }
30
+ &__list {
31
+ display: grid;
32
+ gap: 14px;
33
+ }
34
+ }
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <section class="OtherProducts__wrapper">
3
+ <div class="OtherProducts__head">
4
+ <h2 class="OtherProducts__title">
5
+ Other Products
6
+ </h2>
7
+ <a href="#" class="OtherProducts__all">
8
+ View all products in this category
9
+ </a>
10
+ </div>
11
+ <div class="OtherProducts__list">
12
+ <other-product
13
+ v-for="product in products"
14
+ :key="product._id"
15
+ :product="product"
16
+ class="OtherProducts__product" />
17
+ </div>
18
+ </section>
19
+ </template>
20
+
21
+ <script>
22
+ import { mapGetters } from 'vuex';
23
+ import api from '@lancom/shared/assets/js/api';
24
+ import OtherProduct from './other_product/other-product';
25
+
26
+ export default {
27
+ name: 'OtherProducts',
28
+ components: {
29
+ OtherProduct
30
+ },
31
+ props: {
32
+ additionalCondition: {
33
+ type: Object,
34
+ default: () => ({})
35
+ },
36
+ limit: {
37
+ type: Number,
38
+ default: 5
39
+ }
40
+ },
41
+ data() {
42
+ return {
43
+ products: [],
44
+ loading: false
45
+ };
46
+ },
47
+ computed: {
48
+ ...mapGetters(['shop', 'country', 'currency'])
49
+ },
50
+ mounted() {
51
+ this.loadProducts();
52
+ },
53
+ methods: {
54
+ async loadProducts() {
55
+ try {
56
+ this.loading = true;
57
+ const condition = {
58
+ ...this.additionalCondition,
59
+ country: this.country?._id,
60
+ currency: this.currency?._id,
61
+ limit: this.limit
62
+ };
63
+ this.products = (await api.fetchProducts(this.shop._id, condition)).products;
64
+ console.log('this.products: ', this.products);
65
+ } catch (e) {
66
+ } finally {
67
+ this.loading = false;
68
+ }
69
+ }
70
+ }
71
+ };
72
+ </script>
73
+
74
+ <style lang="scss" scoped>
75
+ @import 'other-products';
76
+ </style>
@@ -0,0 +1,80 @@
1
+ .OtherProduct {
2
+ &__wrapper {
3
+ display: flex;
4
+ align-items: center;
5
+ gap: 18px;
6
+ background: #ffffff;
7
+ border-radius: 14px;
8
+ border: 1px solid #E5E5E5;
9
+ background: #FFF;
10
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.10), 0 1px 2px -1px rgba(0, 0, 0, 0.10);
11
+ padding: 16px 18px;
12
+ }
13
+ &__img {
14
+ width: 80px;
15
+ height: 80px;
16
+ object-fit: contain;
17
+ pointer-events: none;
18
+ border-radius: 4px;
19
+ border: 1px solid #E5E5E5;
20
+ opacity: 0.8;
21
+ }
22
+
23
+ &__body {
24
+ min-width: 0;
25
+ }
26
+
27
+ &__row {
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: space-between;
31
+ gap: 12px;
32
+ }
33
+
34
+ &__title {
35
+ color: #0A0A0A;
36
+ font-size: 19px;
37
+ font-style: normal;
38
+ font-weight:500;
39
+ line-height: 16px;
40
+ text-decoration: none;
41
+ }
42
+
43
+ &__pill {
44
+ padding: 8px 14px;
45
+ background: #e9efff;
46
+ color: #2946d5;
47
+ font-weight: 700;
48
+ border-radius: 999px;
49
+ font-size: 16px;
50
+ line-height: 1;
51
+ white-space: nowrap;
52
+ }
53
+
54
+ &__rating-val {
55
+ color: #6b7280;
56
+ font-weight: 600;
57
+ }
58
+
59
+ &__price {
60
+ display: flex;
61
+ align-items: baseline;
62
+ gap: 14px;
63
+ margin-top: 10px;
64
+ &-old {
65
+ color: #525252;
66
+ font-size: 14px;
67
+ font-style: normal;
68
+ font-weight: 700;
69
+ line-height: 16px;
70
+ text-decoration-line: line-through;
71
+ }
72
+ &-current {
73
+ color: #0A0A0A;
74
+ font-size: 14px;
75
+ font-style: normal;
76
+ font-weight: 600;
77
+ line-height: 16px;
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <div class="OtherProduct__wrapper">
3
+ <a
4
+ v-if="productСover"
5
+ :href="productLink">
6
+ <img
7
+ :src="productСover"
8
+ :alt="product.name"
9
+ class="OtherProduct__img" />
10
+ </a>
11
+ <div class="OtherProduct__body">
12
+ <div class="OtherProduct__row">
13
+ <a
14
+ :href="productLink"
15
+ class="OtherProduct__title">
16
+ {{ product.name }}
17
+ </a>
18
+ </div>
19
+ <div
20
+ v-if="product.isClearance"
21
+ class="OtherProduct__price">
22
+ <span v-if="product.oldPrice" class="OtherProduct__price-old">
23
+ {{ minPrice | price }}
24
+ </span>
25
+ <span class="OtherProduct__price-current">
26
+ {{ product.minPrice | price }}
27
+ </span>
28
+ </div>
29
+ <div
30
+ v-else
31
+ class="OtherProduct__price">
32
+ <span class="OtherProduct__price-current">
33
+ {{ minPrice | price }}
34
+ </span>
35
+ </div>
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <script>
41
+ import productPreview from '@lancom/shared/mixins/product-preview';
42
+ import { mapGetters } from 'vuex';
43
+ import { price } from '@lancom/shared/assets/js/utils/filters';
44
+
45
+ export default {
46
+ name: 'OtherProduct',
47
+ filters: {
48
+ price
49
+ },
50
+ mixins: [productPreview],
51
+ computed: {
52
+ ...mapGetters(['currency'])
53
+ }
54
+ };
55
+ </script>
56
+
57
+ <style lang="scss" scoped>
58
+ @import 'other-product';
59
+ </style>
@@ -32,12 +32,6 @@
32
32
  <section class="Product__section">
33
33
  <wizard-editor />
34
34
  </section>
35
- <!-- <section class="Product__section">
36
- <product-colors-selector v-if="productDetails" />
37
- </section> -->
38
- <!-- <section class="Product__section">
39
- <product-tier-prices :product="product" />
40
- </section> -->
41
35
  <section class="Product__section">
42
36
  <product-fabric-and-size-info :product="product" />
43
37
  </section>
@@ -59,23 +53,16 @@ import RelatedProducts from '@lancom/shared/components/product/related_products/
59
53
  import Gallery from '@lancom/shared/components/product/gallery/gallery';
60
54
  import { generateProductLink } from '@lancom/shared/assets/js/utils/product';
61
55
  import ProductMainInfo from './layouts/product_main_info/product-main-info';
62
- import ProductColorsSelector from './product_colors_selector/product-colors-selector';
63
- import ProductTierPrices from './layouts/product_tier_prices/product-tier-prices';
64
56
  import ProductFabricAndSizeInfo from './layouts/product_fabric_and_size_info/product-fabric-and-size-info';
65
57
  import ProductPackaging from './layouts/product_packaging/product-packaging';
66
58
  import ProductModelMeasurements from './layouts/product_model_measurements/product-model-measurements';
67
59
  import ProductSizeTable from './layouts/product_size_table/product-size-table';
68
60
  import WizardEditor from './wizard-editor/wizard-editor.vue';
69
61
 
70
-
71
- // import ProductLabelsCustomization from './layouts/product_labels_customization/product-labels-customization';
72
-
73
62
  export default {
74
63
  name: 'Product',
75
64
  components: {
76
65
  ProductMainInfo,
77
- ProductColorsSelector,
78
- ProductTierPrices,
79
66
  ProductFabricAndSizeInfo,
80
67
  ProductPackaging,
81
68
  ProductModelMeasurements,
@@ -83,7 +70,6 @@ export default {
83
70
  RelatedProducts,
84
71
  Gallery,
85
72
  WizardEditor
86
- // ProductLabelsCustomization
87
73
  },
88
74
  computed: {
89
75
  ...mapGetters('product', [
@@ -0,0 +1,31 @@
1
+ .ProductCheckDelivery {
2
+ &__title {
3
+ color: #0A0A0A;
4
+ font-size: 14px;
5
+ font-weight: 600;
6
+ line-height: 20px;
7
+ }
8
+ &__detected {
9
+ border-radius: 4px;
10
+ background: rgba(245, 245, 245, 0.50);
11
+ padding: 8px;
12
+ margin-top: 18px;
13
+ &-label {
14
+ color: #737373;
15
+ font-size: 12px;
16
+ font-weight: 600;
17
+ line-height: 16px;
18
+ }
19
+ &-position {
20
+ color: #0A0A0A;
21
+ font-size: 12px;
22
+ font-weight: 700;
23
+ line-height: 16px;
24
+ margin-top: 8px;
25
+ }
26
+ }
27
+
28
+ &__postcode {
29
+ margin-top: 18px;
30
+ }
31
+ }
@@ -0,0 +1,73 @@
1
+ <template>
2
+ <section class="ProductCheckDelivery__wrapper">
3
+ <div class="ProductCheckDelivery__title">
4
+ Delivery ETA
5
+ </div>
6
+ <div class="ProductCheckDelivery__detected">
7
+ <div class="ProductCheckDelivery__detected-label">
8
+ <i class="icon-palette"></i>
9
+ <span>Detected:</span>
10
+ </div>
11
+ <div class="ProductCheckDelivery__detected-position">
12
+ London, Greater London
13
+ </div>
14
+ </div>
15
+ <div class="ProductCheckDelivery__postcode">
16
+ <postcode-select v-model="postcode" />
17
+ </div>
18
+ <!-- <div class="ProductCheckDelivery__estimates">
19
+ <div class="ProductCheckDelivery__estimate">
20
+ <div class="ProductCheckDelivery__estimate-icon">
21
+ <i class="icon-map"></i>
22
+ </div>
23
+ <div class="ProductCheckDelivery__estimate-label">
24
+ Next day collection
25
+ </div>
26
+ <div class="ProductCheckDelivery__estimate-info">
27
+ - Order before 2pm
28
+ </div>
29
+ <div class="ProductCheckDelivery__estimate-price">
30
+ Free
31
+ </div>
32
+ </div>
33
+ <div class="ProductCheckDelivery__estimate">
34
+ <div class="ProductCheckDelivery__estimate-icon">
35
+ <i class="icon-local-shipping"></i>
36
+ </div>
37
+ <div class="ProductCheckDelivery__estimate-label">
38
+ Home delivery
39
+ </div>
40
+ <div class="ProductCheckDelivery__estimate-info">
41
+ - Next working day
42
+ </div>
43
+ <div class="ProductCheckDelivery__estimate-price">
44
+ £3.95
45
+ </div>
46
+ </div>
47
+ </div> -->
48
+ </section>
49
+ </template>
50
+
51
+ <script>
52
+ import { mapGetters } from 'vuex';
53
+ import PostcodeSelect from '@lancom/shared/components/common/postcode_select/postcode-select';
54
+
55
+ export default {
56
+ name: 'ProductCheckDelivery',
57
+ components: {
58
+ PostcodeSelect
59
+ },
60
+ data() {
61
+ return {
62
+ postcode: null
63
+ };
64
+ },
65
+ computed: {
66
+ ...mapGetters('product', ['product'])
67
+ }
68
+ };
69
+ </script>
70
+
71
+ <style lang="scss" scoped>
72
+ @import 'product-check-delivery';
73
+ </style>
@@ -4,6 +4,13 @@
4
4
  &__wrapper {
5
5
  margin-top: 35px;
6
6
  }
7
+ &__label {
8
+ color: #0A0A0A;
9
+ font-size: 14px;
10
+ font-style: normal;
11
+ font-weight: 700;
12
+ line-height: 20px;
13
+ }
7
14
  &__controls {
8
15
  display: flex;
9
16
  @media (max-width: $bp-extra-small-max) {
@@ -122,4 +129,4 @@
122
129
  .multiselect__input {
123
130
  font-weight: bold;
124
131
  }
125
- }
132
+ }
@@ -1,8 +1,12 @@
1
1
  <template>
2
2
  <product-colors-selector class="ProductColorsSelector__wrapper">
3
3
  <div>
4
+ <div class="ProductColorsSelector__label">
5
+ Choose a colour to see stock availability
6
+ </div>
4
7
  <div class="ProductColorsSelector__controls">
5
8
  <div
9
+ v-if="hasColorsDropdown"
6
10
  class="ProductColorsSelector__head"
7
11
  :class="{
8
12
  'ProductColorsSelector__head--opened': opened
@@ -123,6 +127,10 @@ export default {
123
127
  hasToggleGst: {
124
128
  type: Boolean,
125
129
  default: true
130
+ },
131
+ hasColorsDropdown: {
132
+ type: Boolean,
133
+ default: true
126
134
  }
127
135
  },
128
136
  data() {
@@ -0,0 +1,53 @@
1
+ .ProductPricingTiers {
2
+ &__title {
3
+ color: #0A0A0A;
4
+ font-size: 14px;
5
+ font-weight: 600;
6
+ line-height: 20px;
7
+ }
8
+ &__tiers {
9
+ display: flex;
10
+ gap: 6px;
11
+ margin-top: 16px;
12
+ }
13
+ &__tier {
14
+ padding: 4px;
15
+ width: 152px;
16
+ border-radius: 12px;
17
+ border: 1px solid #E5E5E5;
18
+ background: #FFF;
19
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.10), 0 2px 4px -2px rgba(0, 0, 0, 0.10);
20
+ &-single-price {
21
+ padding: 12px 0;
22
+ border-radius: 8px;
23
+ background: #EFEFEF;
24
+ text-align: center;
25
+ color: #525252;
26
+ font-size: 14px;
27
+ font-weight: 600;
28
+ line-height: 28px;
29
+ text-align: center;
30
+ span {
31
+ color: #194BB3;
32
+ font-size: 18px;
33
+ font-weight: 700;
34
+ line-height: 28px;
35
+ }
36
+ }
37
+ &-price {
38
+ color: #000;
39
+ font-size: 12px;
40
+ font-weight: 700;
41
+ line-height: 20px;
42
+ margin-top: 6px;
43
+ padding: 4px;
44
+ text-align: center;
45
+ span {
46
+ color: #194BB3;
47
+ font-size: 12px;
48
+ font-weight: 700;
49
+ line-height: 20px;
50
+ }
51
+ }
52
+ }
53
+ }
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <section class="ProductPricingTiers__wrapper">
3
+ <h3 class="ProductPricingTiers__title">
4
+ Pricing Tiers
5
+ </h3>
6
+ <div class="ProductPricingTiers__tiers">
7
+ <div
8
+ v-for="(tier, index) in product.pricing"
9
+ :key="index"
10
+ class="ProductPricingTiers__tier">
11
+ <div class="ProductPricingTiers__tier-single-price">
12
+ <span>{{ (tier.price / tier.min) | priceWithTax(pricingSettings, currency) }}</span> each
13
+ </div>
14
+ <div class="ProductPricingTiers__tier-price">
15
+ Buy {{ tier.min }} for <span>{{ tier.price | priceWithTax(pricingSettings, currency) }}</span>
16
+ </div>
17
+ </div>
18
+ </div>
19
+ </section>
20
+ </template>
21
+
22
+ <script>
23
+ import { mapGetters } from 'vuex';
24
+ import { priceWithTax } from '@lancom/shared/assets/js/utils/filters';
25
+
26
+ export default {
27
+ name: 'ProductPricingTiers',
28
+ filters: {
29
+ priceWithTax
30
+ },
31
+ computed: {
32
+ ...mapGetters('product', ['product']),
33
+ ...mapGetters(['pricingSettings'])
34
+ }
35
+ };
36
+ </script>
37
+
38
+ <style lang="scss" scoped>
39
+ @import 'product-pricing-tiers';
40
+ </style>
@@ -41,6 +41,12 @@ export default {
41
41
  ProductReview
42
42
  },
43
43
  mixins: [],
44
+ props: {
45
+ product: {
46
+ type: Object,
47
+ required: true
48
+ }
49
+ },
44
50
  data() {
45
51
  const reviews = this.product.reviews || [];
46
52
  const [, mainReviewId] = (this.$route.hash || '').match(/review-([a-z0-9]+)/i) || [];
@@ -56,12 +62,6 @@ export default {
56
62
  ].filter(review => !!review)
57
63
  };
58
64
  },
59
- props: {
60
- product: {
61
- type: Object,
62
- required: true
63
- }
64
- },
65
65
  computed: {
66
66
  currentReview() {
67
67
  return this.reviews[this.activeIndex];
@@ -0,0 +1,28 @@
1
+ .ProductStockStatus {
2
+ &__wrapper {
3
+ font-size: 14px;
4
+ font-weight: 500;
5
+ line-height: 20px;
6
+ padding: 4px 12px;
7
+ text-align: center;
8
+ border-radius: 4px;
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: 6px;
12
+ &--green {
13
+ background-color: #DCFCE7;
14
+ color: #155724;
15
+ border: 1px solid #c3e6cb;
16
+ }
17
+ &--orange {
18
+ background-color: #fff3cd;
19
+ color: #856404;
20
+ border: 1px solid #ffeaa7;
21
+ }
22
+ &--red {
23
+ background-color: #f8d7da;
24
+ color: #721c24;
25
+ border: 1px solid #f5c6cb;
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <div
3
+ class="ProductStockStatus__wrapper"
4
+ :class="`ProductStockStatus__wrapper--${stockStatusColor}`">
5
+ <i class="icon-ok-1"></i>
6
+ <span>
7
+ {{ capitalizedStockStatus }}
8
+ </span>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import { mapGetters } from 'vuex';
14
+ import { PRODUCT_STOCK_STATUS_COLORS } from '@lancom/shared/assets/js/constants/product';
15
+
16
+ export default {
17
+ name: 'ProductStockStatus',
18
+ computed: {
19
+ ...mapGetters('product', ['stockStatus']),
20
+ capitalizedStockStatus() {
21
+ if (!this.stockStatus) {
22
+ return '';
23
+ }
24
+ return this.stockStatus.charAt(0).toUpperCase() + this.stockStatus.slice(1);
25
+ },
26
+ stockStatusColor() {
27
+ return PRODUCT_STOCK_STATUS_COLORS[this.stockStatus] || 'green';
28
+ }
29
+ }
30
+ };
31
+ </script>
32
+
33
+ <style lang="scss" scoped>
34
+ @import 'product-stock-status';
35
+ </style>
@@ -36,15 +36,15 @@ export default {
36
36
  products: []
37
37
  };
38
38
  },
39
+ async fetch() {
40
+ const { products } = await api.fetchRelatedProducts(this.shop._id, this.product.alias, { needShuffle: true });
41
+ this.products = products.splice(0, 6);
42
+ },
39
43
  computed: {
40
44
  ...mapGetters(['shop']),
41
45
  hasProducts() {
42
46
  return this.products.length > 0;
43
47
  }
44
- },
45
- async fetch() {
46
- const { products } = await api.fetchRelatedProducts(this.shop._id, this.product.alias, { needShuffle: true });
47
- this.products = products.splice(0, 6);
48
48
  }
49
49
  };
50
50
  </script>
@@ -76,7 +76,7 @@ export default {
76
76
  'Free Setup on all Black prints',
77
77
  'Standard turn around time of 5-10 days',
78
78
  'Same or next day rush service available',
79
- 'Pickup from warehouse in Arndell Park'
79
+ 'Pickup from warehouse in Mount Druitt'
80
80
  ]
81
81
  // info: 'DIGITAL - minimum 12'
82
82
  }, {