@lancom/shared 0.0.460 → 0.0.461
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/scss/variables/_theme.scss +12 -0
- package/components/common/toggle-content.vue +9 -2
- package/components/products/children_categories/children-categories.vue +1 -1
- package/components/products/products_aside/products-aside.scss +1 -1
- package/components/products/products_aside/products-aside.vue +50 -12
- package/components/products/products_attributes/products-attributes.vue +6 -1
- package/components/products/products_attributes/products_attribute/products-attribute.vue +6 -2
- package/components/products/products_brands/products-brands.vue +6 -2
- package/components/products/products_color_groups/products-color-groups.scss +29 -0
- package/components/products/products_color_groups/products-color-groups.vue +48 -4
- package/components/products/products_colors/products-colors.scss +30 -1
- package/components/products/products_colors/products-colors.vue +48 -4
- package/components/products/products_minimum_qty/products-minimum-qty.vue +5 -1
- package/components/products/products_production_time/products-production-time.vue +5 -1
- package/components/products/products_selected_filters/products-selected-filters.scss +59 -0
- package/components/products/products_selected_filters/products-selected-filters.vue +109 -0
- package/components/products/products_tags/products-tags.vue +5 -1
- package/components/products/products_types/products-types.vue +5 -1
- package/components/static_page/static-page.scss +6 -0
- package/mixins/product-preview.js +3 -0
- package/mixins/products/selected-filters.js +49 -0
- package/package.json +1 -1
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
// theme variables
|
|
2
2
|
|
|
3
|
+
:root {
|
|
4
|
+
--accu-primary: #3B4BA4; /* Blue accent color */
|
|
5
|
+
--accu-bg: #F5F0EB; /* Warm cream background */
|
|
6
|
+
--accu-card: #FFFFFF; /* Card background */
|
|
7
|
+
--accu-text-dark: #1E1E1E; /* Primary text */
|
|
8
|
+
--accu-text-muted: #666666; /* Secondary text */
|
|
9
|
+
--accu-star: #FF9800; /* Star rating color */
|
|
10
|
+
--accu-green: #22C55E; /* Success/shipping color */
|
|
11
|
+
--accu-border: #E5E5E5; /* Border color */
|
|
12
|
+
--accu-hover: #f8f8f8; /* Hover state */
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
// Layouts
|
|
4
16
|
$navbar_height: 88px !default;
|
|
5
17
|
$notification_bar_height: 40px !default;
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
<div
|
|
4
4
|
class="ToggleContent__header"
|
|
5
5
|
@click="toggle()">
|
|
6
|
-
<div class="ToggleContent__label">
|
|
6
|
+
<div class="ToggleContent__label accu-filter-header">
|
|
7
7
|
{{ label }}
|
|
8
8
|
</div>
|
|
9
9
|
<div
|
|
10
|
+
v-if="toggleable"
|
|
10
11
|
class="ToggleContent__arrow"
|
|
11
12
|
:class="{ opened }">
|
|
12
13
|
<i class="icon-arrow-left"></i>
|
|
@@ -27,6 +28,10 @@ export default {
|
|
|
27
28
|
label: {
|
|
28
29
|
type: String,
|
|
29
30
|
required: true
|
|
31
|
+
},
|
|
32
|
+
toggleable: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: true
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
37
|
data() {
|
|
@@ -36,7 +41,9 @@ export default {
|
|
|
36
41
|
},
|
|
37
42
|
methods: {
|
|
38
43
|
toggle() {
|
|
39
|
-
this.
|
|
44
|
+
if (this.toggleable) {
|
|
45
|
+
this.opened = !this.opened;
|
|
46
|
+
}
|
|
40
47
|
}
|
|
41
48
|
}
|
|
42
49
|
};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
'CategoryCard--selected': category && category._id === cat._id
|
|
9
9
|
}">
|
|
10
10
|
<a
|
|
11
|
-
:href="generateProductsLink($route, { category: cat }, true)"
|
|
11
|
+
:href="generateProductsLink($route, { category: (category && category._id === cat._id) ? (cat.parent || cat) : cat }, true)"
|
|
12
12
|
class="CategoryCard__link">
|
|
13
13
|
<span
|
|
14
14
|
v-if="visibleImages"
|
|
@@ -10,45 +10,64 @@
|
|
|
10
10
|
<span class="ProductsAside__info ProductsAside__info--small"></span>
|
|
11
11
|
<span class="ProductsAside__info ProductsAside__info--small2"></span>
|
|
12
12
|
</div>
|
|
13
|
-
<div
|
|
13
|
+
<div
|
|
14
|
+
v-else
|
|
15
|
+
class="ProductsAside__list">
|
|
16
|
+
<div
|
|
17
|
+
v-if="hasSelectedFilters"
|
|
18
|
+
class="ProductsAside__item">
|
|
19
|
+
<products-selected-filters />
|
|
20
|
+
</div>
|
|
14
21
|
<div
|
|
15
22
|
v-if="hasProductTypes"
|
|
16
23
|
class="ProductsAside__item">
|
|
17
24
|
<products-types
|
|
18
25
|
:has-selected-icon="hasSelectedIcon"
|
|
19
|
-
:selected-icon-circle="selectedIconCircle"
|
|
26
|
+
:selected-icon-circle="selectedIconCircle"
|
|
27
|
+
:toggleable="toggleable" />
|
|
20
28
|
</div>
|
|
21
29
|
<div class="ProductsAside__item">
|
|
22
30
|
<products-brands
|
|
23
31
|
:has-selected-icon="hasSelectedIcon"
|
|
24
|
-
:selected-icon-circle="selectedIconCircle"
|
|
32
|
+
:selected-icon-circle="selectedIconCircle"
|
|
33
|
+
:toggleable="toggleable" />
|
|
25
34
|
</div>
|
|
26
35
|
<div
|
|
27
36
|
v-if="hasProductionTime"
|
|
28
37
|
class="ProductsAside__item">
|
|
29
38
|
<products-production-time
|
|
30
39
|
:has-selected-icon="hasSelectedIcon"
|
|
31
|
-
:selected-icon-circle="selectedIconCircle"
|
|
40
|
+
:selected-icon-circle="selectedIconCircle"
|
|
41
|
+
:toggleable="toggleable" />
|
|
32
42
|
</div>
|
|
33
43
|
<div
|
|
34
44
|
v-if="hasMinimumQty"
|
|
35
45
|
class="ProductsAside__item">
|
|
36
46
|
<products-minimum-qty
|
|
37
47
|
:has-selected-icon="hasSelectedIcon"
|
|
38
|
-
:selected-icon-circle="selectedIconCircle"
|
|
39
|
-
|
|
40
|
-
<div class="ProductsAside__item">
|
|
41
|
-
<products-color-groups />
|
|
48
|
+
:selected-icon-circle="selectedIconCircle"
|
|
49
|
+
:toggleable="toggleable" />
|
|
42
50
|
</div>
|
|
43
51
|
<div class="ProductsAside__item">
|
|
44
|
-
<products-
|
|
52
|
+
<products-color-groups
|
|
53
|
+
:toggleable="toggleable"
|
|
54
|
+
:display-mode="colorDisplayMode" />
|
|
55
|
+
<products-colors
|
|
56
|
+
:toggleable="toggleable"
|
|
57
|
+
:display-mode="colorDisplayMode" />
|
|
45
58
|
</div>
|
|
46
59
|
<div class="ProductsAside__item">
|
|
47
60
|
<products-attributes
|
|
48
|
-
:has-selected-icon="hasSelectedIcon"
|
|
61
|
+
:has-selected-icon="hasSelectedIcon"
|
|
62
|
+
:toggleable="toggleable" />
|
|
63
|
+
</div>
|
|
64
|
+
<div
|
|
65
|
+
v-if="hasTags"
|
|
66
|
+
class="ProductsAside__item">
|
|
49
67
|
<products-tags
|
|
50
68
|
:has-selected-icon="haAttributesSelectedIcon"
|
|
51
|
-
:has-remove-icon="hasRemoveIcon"
|
|
69
|
+
:has-remove-icon="hasRemoveIcon"
|
|
70
|
+
:toggleable="toggleable" />
|
|
52
71
|
</div>
|
|
53
72
|
</div>
|
|
54
73
|
</div>
|
|
@@ -64,6 +83,7 @@ import ProductsColors from '@lancom/shared/components/products/products_colors/p
|
|
|
64
83
|
import ProductsColorGroups from '@lancom/shared/components/products/products_color_groups/products-color-groups';
|
|
65
84
|
import ProductsProductionTime from '@lancom/shared/components/products/products_production_time/products-production-time';
|
|
66
85
|
import ProductsMinimumQty from '@lancom/shared/components/products/products_minimum_qty/products-minimum-qty';
|
|
86
|
+
import ProductsSelectedFilters from '@lancom/shared/components/products/products_selected_filters/products-selected-filters';
|
|
67
87
|
import { generateProductsLink } from '@lancom/shared/assets/js/utils/product';
|
|
68
88
|
|
|
69
89
|
export default {
|
|
@@ -76,7 +96,8 @@ export default {
|
|
|
76
96
|
ProductsColors,
|
|
77
97
|
ProductsColorGroups,
|
|
78
98
|
ProductsProductionTime,
|
|
79
|
-
ProductsMinimumQty
|
|
99
|
+
ProductsMinimumQty,
|
|
100
|
+
ProductsSelectedFilters
|
|
80
101
|
},
|
|
81
102
|
props: {
|
|
82
103
|
hasSelectedIcon: {
|
|
@@ -110,6 +131,23 @@ export default {
|
|
|
110
131
|
hasMinimumQty: {
|
|
111
132
|
type: Boolean,
|
|
112
133
|
default: true
|
|
134
|
+
},
|
|
135
|
+
hasTags: {
|
|
136
|
+
type: Boolean,
|
|
137
|
+
default: true
|
|
138
|
+
},
|
|
139
|
+
toggleable: {
|
|
140
|
+
type: Boolean,
|
|
141
|
+
default: true
|
|
142
|
+
},
|
|
143
|
+
colorDisplayMode: {
|
|
144
|
+
type: String,
|
|
145
|
+
default: 'grid', // 'grid' or 'list'
|
|
146
|
+
validator: value => ['grid', 'list'].includes(value)
|
|
147
|
+
},
|
|
148
|
+
hasSelectedFilters: {
|
|
149
|
+
type: Boolean,
|
|
150
|
+
default: false
|
|
113
151
|
}
|
|
114
152
|
},
|
|
115
153
|
data() {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
class="ProductsAttributes__item">
|
|
9
9
|
<products-attribute
|
|
10
10
|
:attribute="attribute"
|
|
11
|
-
:has-selected-icon="hasSelectedIcon"
|
|
11
|
+
:has-selected-icon="hasSelectedIcon"
|
|
12
|
+
:toggleable="toggleable" />
|
|
12
13
|
</div>
|
|
13
14
|
</div>
|
|
14
15
|
</template>
|
|
@@ -27,6 +28,10 @@ export default {
|
|
|
27
28
|
hasSelectedIcon: {
|
|
28
29
|
type: Boolean,
|
|
29
30
|
default: false
|
|
31
|
+
},
|
|
32
|
+
toggleable: {
|
|
33
|
+
type: Boolean,
|
|
34
|
+
default: true
|
|
30
35
|
}
|
|
31
36
|
},
|
|
32
37
|
computed: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ProductsAttribute__wrapper">
|
|
3
|
-
<toggle-content :label="attribute.name">
|
|
3
|
+
<toggle-content :label="attribute.name" :toggleable="toggleable">
|
|
4
4
|
<div class="ProductsAttribute__options">
|
|
5
5
|
<div
|
|
6
6
|
v-for="option in options"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<checked-icon
|
|
14
14
|
v-if="hasSelectedIcon"
|
|
15
15
|
:checked="selectedOptions.includes(option.alias)" />
|
|
16
|
-
<span>{{ option.name }}</span>
|
|
16
|
+
<span class="accu-filter-item">{{ option.name }}</span>
|
|
17
17
|
</products-link>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
@@ -37,6 +37,10 @@ export default {
|
|
|
37
37
|
type: Boolean,
|
|
38
38
|
default: false
|
|
39
39
|
},
|
|
40
|
+
toggleable: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
default: true
|
|
43
|
+
},
|
|
40
44
|
attribute: {
|
|
41
45
|
type: Object
|
|
42
46
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div
|
|
3
3
|
v-if="list.length"
|
|
4
4
|
class="ProductsBrands__wrapper">
|
|
5
|
-
<toggle-content label="Brands">
|
|
5
|
+
<toggle-content label="Brands" :toggleable="toggleable">
|
|
6
6
|
<div
|
|
7
7
|
v-for="brand in list"
|
|
8
8
|
:key="brand.alias"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
v-if="hasSelectedIcon"
|
|
18
18
|
:checked="brand.alias === currentBrand"
|
|
19
19
|
:circle="selectedIconCircle" />
|
|
20
|
-
<span>
|
|
20
|
+
<span class="accu-filter-item">
|
|
21
21
|
{{ brand.name }}
|
|
22
22
|
</span>
|
|
23
23
|
</products-link>
|
|
@@ -47,6 +47,10 @@ export default {
|
|
|
47
47
|
selectedIconCircle: {
|
|
48
48
|
type: Boolean,
|
|
49
49
|
default: false
|
|
50
|
+
},
|
|
51
|
+
toggleable: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: true
|
|
50
54
|
}
|
|
51
55
|
},
|
|
52
56
|
computed: {
|
|
@@ -66,4 +66,33 @@
|
|
|
66
66
|
cursor: pointer;
|
|
67
67
|
text-align: right;
|
|
68
68
|
}
|
|
69
|
+
&__list {
|
|
70
|
+
margin-top: 20px;
|
|
71
|
+
&-item {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
padding: 8px 0;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
transition: background-color 0.2s;
|
|
77
|
+
&--selected {
|
|
78
|
+
.ProductsColorGroups__list-label {
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
color: $grey_1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
&-checkbox {
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
margin-right: 12px;
|
|
87
|
+
}
|
|
88
|
+
&-thumb {
|
|
89
|
+
flex-shrink: 0;
|
|
90
|
+
margin-right: 12px;
|
|
91
|
+
}
|
|
92
|
+
&-label {
|
|
93
|
+
flex-grow: 1;
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
color: $black;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
69
98
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ProductsColorGroups__wrapper">
|
|
3
|
-
<toggle-content label="Colour Groups">
|
|
4
|
-
<div
|
|
3
|
+
<toggle-content label="Colour Groups" :toggleable="toggleable">
|
|
4
|
+
<div
|
|
5
|
+
v-if="displayMode === 'grid'"
|
|
6
|
+
class="ProductsColorGroups__selected">
|
|
5
7
|
<div
|
|
6
8
|
v-for="colorGroup in selectedColorGroups"
|
|
7
9
|
:key="colorGroup._id"
|
|
@@ -19,7 +21,9 @@
|
|
|
19
21
|
</products-link>
|
|
20
22
|
</div>
|
|
21
23
|
</div>
|
|
22
|
-
<div
|
|
24
|
+
<div
|
|
25
|
+
v-if="displayMode === 'grid'"
|
|
26
|
+
class="ProductsColorGroups__items">
|
|
23
27
|
<products-link
|
|
24
28
|
v-for="colorGroup in visibleColorGroups"
|
|
25
29
|
:key="colorGroup._id"
|
|
@@ -37,6 +41,33 @@
|
|
|
37
41
|
</div>
|
|
38
42
|
</products-link>
|
|
39
43
|
</div>
|
|
44
|
+
<div
|
|
45
|
+
v-else
|
|
46
|
+
class="ProductsColorGroups__list">
|
|
47
|
+
<products-link
|
|
48
|
+
v-for="colorGroup in visibleColorGroups"
|
|
49
|
+
:key="colorGroup._id"
|
|
50
|
+
:color-group="colorGroup.alias">
|
|
51
|
+
<div
|
|
52
|
+
class="ProductsColorGroups__list-item"
|
|
53
|
+
:class="{
|
|
54
|
+
'ProductsColorGroups__list-item--selected': isSelectedColorGroup(colorGroup)
|
|
55
|
+
}">
|
|
56
|
+
<div class="ProductsColorGroups__list-checkbox">
|
|
57
|
+
<checked-icon :checked="isSelectedColorGroup(colorGroup)" />
|
|
58
|
+
</div>
|
|
59
|
+
<div class="ProductsColorGroups__list-thumb ProductsColorGroups__color-group">
|
|
60
|
+
<product-color-image
|
|
61
|
+
v-if="canLoadImages"
|
|
62
|
+
:color="colorGroup"
|
|
63
|
+
class="ProductsColorGroups__color-group-image" />
|
|
64
|
+
</div>
|
|
65
|
+
<div class="ProductsColorGroups__list-label accu-filter-item">
|
|
66
|
+
{{ colorGroup.name }}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</products-link>
|
|
70
|
+
</div>
|
|
40
71
|
<div
|
|
41
72
|
v-if="shortListColorGroupsLimit < colorGroupsCount"
|
|
42
73
|
@click="toggleDisplayAllColorGroups()"
|
|
@@ -52,13 +83,26 @@ import { mapGetters } from 'vuex';
|
|
|
52
83
|
import ToggleContent from '@lancom/shared/components/common/toggle-content';
|
|
53
84
|
import ProductsLink from '@lancom/shared/components/products/products_link/products-link';
|
|
54
85
|
import ProductColorImage from '@lancom/shared/components/product/product_color_image/product-color-image';
|
|
86
|
+
import CheckedIcon from '@lancom/shared/components/common/checked-icon';
|
|
55
87
|
|
|
56
88
|
export default {
|
|
57
89
|
name: 'ProductsColorGroups',
|
|
58
90
|
components: {
|
|
59
91
|
ProductColorImage,
|
|
60
92
|
ProductsLink,
|
|
61
|
-
ToggleContent
|
|
93
|
+
ToggleContent,
|
|
94
|
+
CheckedIcon
|
|
95
|
+
},
|
|
96
|
+
props: {
|
|
97
|
+
toggleable: {
|
|
98
|
+
type: Boolean,
|
|
99
|
+
default: true
|
|
100
|
+
},
|
|
101
|
+
displayMode: {
|
|
102
|
+
type: String,
|
|
103
|
+
default: 'grid', // 'grid' or 'list'
|
|
104
|
+
validator: value => ['grid', 'list'].includes(value)
|
|
105
|
+
}
|
|
62
106
|
},
|
|
63
107
|
data() {
|
|
64
108
|
return {
|
|
@@ -66,4 +66,33 @@
|
|
|
66
66
|
cursor: pointer;
|
|
67
67
|
text-align: right;
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
&__list {
|
|
70
|
+
margin-top: 20px;
|
|
71
|
+
&-item {
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
padding: 8px 0;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
transition: background-color 0.2s;
|
|
77
|
+
&--selected {
|
|
78
|
+
.ProductsColorGroups__list-label {
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
color: $grey_1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
&-checkbox {
|
|
85
|
+
flex-shrink: 0;
|
|
86
|
+
margin-right: 12px;
|
|
87
|
+
}
|
|
88
|
+
&-thumb {
|
|
89
|
+
flex-shrink: 0;
|
|
90
|
+
margin-right: 12px;
|
|
91
|
+
}
|
|
92
|
+
&-label {
|
|
93
|
+
flex-grow: 1;
|
|
94
|
+
font-size: 14px;
|
|
95
|
+
color: $black;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
<div
|
|
3
3
|
v-if="visibleColors.length > 0"
|
|
4
4
|
class="ProductsColors__wrapper">
|
|
5
|
-
<toggle-content label="Colours">
|
|
6
|
-
<div
|
|
5
|
+
<toggle-content label="Colours" :toggleable="toggleable">
|
|
6
|
+
<div
|
|
7
|
+
v-if="displayMode === 'grid'"
|
|
8
|
+
class="ProductsColors__selected">
|
|
7
9
|
<div
|
|
8
10
|
v-for="color in selectedColors"
|
|
9
11
|
:key="color._id"
|
|
@@ -21,7 +23,9 @@
|
|
|
21
23
|
</products-link>
|
|
22
24
|
</div>
|
|
23
25
|
</div>
|
|
24
|
-
<div
|
|
26
|
+
<div
|
|
27
|
+
v-if="displayMode === 'grid'"
|
|
28
|
+
class="ProductsColors__items">
|
|
25
29
|
<products-link
|
|
26
30
|
v-for="color in visibleColors"
|
|
27
31
|
:key="color._id"
|
|
@@ -39,6 +43,33 @@
|
|
|
39
43
|
</div>
|
|
40
44
|
</products-link>
|
|
41
45
|
</div>
|
|
46
|
+
<div
|
|
47
|
+
v-else
|
|
48
|
+
class="ProductsColors__list">
|
|
49
|
+
<products-link
|
|
50
|
+
v-for="color in visibleColors"
|
|
51
|
+
:key="color._id"
|
|
52
|
+
:color="color.alias">
|
|
53
|
+
<div
|
|
54
|
+
class="ProductsColors__list-item"
|
|
55
|
+
:class="{
|
|
56
|
+
'ProductsColors__list-item--selected': isSelectedColor(color)
|
|
57
|
+
}">
|
|
58
|
+
<div class="ProductsColors__list-checkbox">
|
|
59
|
+
<checked-icon :checked="isSelectedColor(color)" />
|
|
60
|
+
</div>
|
|
61
|
+
<div class="ProductsColors__list-thumb ProductsColors__color">
|
|
62
|
+
<product-color-image
|
|
63
|
+
v-if="canLoadImages"
|
|
64
|
+
:color="color"
|
|
65
|
+
class="ProductsColors__color-image" />
|
|
66
|
+
</div>
|
|
67
|
+
<div class="ProductsColors__list-label accu-filter-item">
|
|
68
|
+
{{ color.name }}
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</products-link>
|
|
72
|
+
</div>
|
|
42
73
|
<div
|
|
43
74
|
v-if="shortListColorsLimit < colorsCount"
|
|
44
75
|
@click="toggleDisplayAllColors()"
|
|
@@ -54,13 +85,26 @@ import { mapGetters } from 'vuex';
|
|
|
54
85
|
import ToggleContent from '@lancom/shared/components/common/toggle-content';
|
|
55
86
|
import ProductsLink from '@lancom/shared/components/products/products_link/products-link';
|
|
56
87
|
import ProductColorImage from '@lancom/shared/components/product/product_color_image/product-color-image';
|
|
88
|
+
import CheckedIcon from '@lancom/shared/components/common/checked-icon';
|
|
57
89
|
|
|
58
90
|
export default {
|
|
59
91
|
name: 'ProductsColors',
|
|
60
92
|
components: {
|
|
61
93
|
ProductColorImage,
|
|
62
94
|
ProductsLink,
|
|
63
|
-
ToggleContent
|
|
95
|
+
ToggleContent,
|
|
96
|
+
CheckedIcon
|
|
97
|
+
},
|
|
98
|
+
props: {
|
|
99
|
+
toggleable: {
|
|
100
|
+
type: Boolean,
|
|
101
|
+
default: true
|
|
102
|
+
},
|
|
103
|
+
displayMode: {
|
|
104
|
+
type: String,
|
|
105
|
+
default: 'grid', // 'grid' or 'list'
|
|
106
|
+
validator: value => ['grid', 'list'].includes(value)
|
|
107
|
+
}
|
|
64
108
|
},
|
|
65
109
|
data() {
|
|
66
110
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ProductsMinimumQty__wrapper">
|
|
3
|
-
<toggle-content label="Minimum Qty">
|
|
3
|
+
<toggle-content label="Minimum Qty" :toggleable="toggleable">
|
|
4
4
|
<div
|
|
5
5
|
v-for="minimumQtyRange in minimumQtyRanges"
|
|
6
6
|
:key="minimumQtyRange.alias"
|
|
@@ -44,6 +44,10 @@ export default {
|
|
|
44
44
|
selectedIconCircle: {
|
|
45
45
|
type: Boolean,
|
|
46
46
|
default: false
|
|
47
|
+
},
|
|
48
|
+
toggleable: {
|
|
49
|
+
type: Boolean,
|
|
50
|
+
default: true
|
|
47
51
|
}
|
|
48
52
|
},
|
|
49
53
|
data() {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ProductsProductionTime__wrapper">
|
|
3
|
-
<toggle-content label="Production Time">
|
|
3
|
+
<toggle-content label="Production Time" :toggleable="toggleable">
|
|
4
4
|
<div
|
|
5
5
|
v-for="produnctionRange in produnctionTimesRanges"
|
|
6
6
|
:key="produnctionRange.alias"
|
|
@@ -44,6 +44,10 @@ export default {
|
|
|
44
44
|
selectedIconCircle: {
|
|
45
45
|
type: Boolean,
|
|
46
46
|
default: false
|
|
47
|
+
},
|
|
48
|
+
toggleable: {
|
|
49
|
+
type: Boolean,
|
|
50
|
+
default: true
|
|
47
51
|
}
|
|
48
52
|
},
|
|
49
53
|
data() {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
@import "@/assets/scss/variables";
|
|
2
|
+
|
|
3
|
+
.ProductsSelectedFilters {
|
|
4
|
+
&__wrapper {
|
|
5
|
+
display: flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: space-between;
|
|
8
|
+
width: 100%;
|
|
9
|
+
}
|
|
10
|
+
&__title {
|
|
11
|
+
font-weight: 600;
|
|
12
|
+
font-size: 0.875rem;
|
|
13
|
+
color: var(--accu-text-dark);
|
|
14
|
+
margin-right: 0.5rem;
|
|
15
|
+
}
|
|
16
|
+
&__list {
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-wrap: wrap;
|
|
19
|
+
gap: 8px;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
&__item {
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 0.25rem;
|
|
26
|
+
background: #EEF0FB;
|
|
27
|
+
color: var(--accu-primary);
|
|
28
|
+
padding: 0.25rem 0.75rem;
|
|
29
|
+
border-radius: 20px;
|
|
30
|
+
font-size: 0.8rem;
|
|
31
|
+
&-label {
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
margin-right: 4px;
|
|
34
|
+
}
|
|
35
|
+
&-value {
|
|
36
|
+
margin-right: 8px;
|
|
37
|
+
}
|
|
38
|
+
&-remove {
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
transition: color 0.2s;
|
|
41
|
+
&:hover {
|
|
42
|
+
color: darken($grey_1, 15%);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
a {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
color: inherit;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
&__clear-all {
|
|
53
|
+
color: var(--accu-primary);
|
|
54
|
+
font-size: 0.875rem;
|
|
55
|
+
text-decoration: underline;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
margin-left: auto;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="hasSelectedFilters"
|
|
4
|
+
class="ProductsSelectedFilters__wrapper">
|
|
5
|
+
<div class="ProductsSelectedFilters__list">
|
|
6
|
+
<div class="ProductsSelectedFilters__title">
|
|
7
|
+
Selected Filters:
|
|
8
|
+
</div>
|
|
9
|
+
<div
|
|
10
|
+
v-if="selectedBrand"
|
|
11
|
+
class="ProductsSelectedFilters__item">
|
|
12
|
+
<span class="ProductsSelectedFilters__item-label">Brands:</span>
|
|
13
|
+
<span class="ProductsSelectedFilters__item-value">{{ selectedBrand.name }}</span>
|
|
14
|
+
<products-link :brand="null">
|
|
15
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
16
|
+
</products-link>
|
|
17
|
+
</div>
|
|
18
|
+
<div
|
|
19
|
+
v-if="selectedType"
|
|
20
|
+
class="ProductsSelectedFilters__item">
|
|
21
|
+
<span class="ProductsSelectedFilters__item-label">Product Type:</span>
|
|
22
|
+
<span class="ProductsSelectedFilters__item-value">{{ selectedType.name }}</span>
|
|
23
|
+
<products-link :type="null">
|
|
24
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
25
|
+
</products-link>
|
|
26
|
+
</div>
|
|
27
|
+
<div
|
|
28
|
+
v-for="colorGroup in selectedColorGroups"
|
|
29
|
+
:key="`colorGroup-${colorGroup._id}`"
|
|
30
|
+
class="ProductsSelectedFilters__item">
|
|
31
|
+
<span class="ProductsSelectedFilters__item-label">Colour Groups:</span>
|
|
32
|
+
<span class="ProductsSelectedFilters__item-value">{{ colorGroup.name }}</span>
|
|
33
|
+
<products-link :color-group="colorGroup.alias">
|
|
34
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
35
|
+
</products-link>
|
|
36
|
+
</div>
|
|
37
|
+
<div
|
|
38
|
+
v-for="color in selectedColors"
|
|
39
|
+
:key="`color-${color._id}`"
|
|
40
|
+
class="ProductsSelectedFilters__item">
|
|
41
|
+
<span class="ProductsSelectedFilters__item-label">Colours:</span>
|
|
42
|
+
<span class="ProductsSelectedFilters__item-value">{{ color.name }}</span>
|
|
43
|
+
<products-link :color="color.alias">
|
|
44
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
45
|
+
</products-link>
|
|
46
|
+
</div>
|
|
47
|
+
<template v-for="attribute in attributes">
|
|
48
|
+
<div
|
|
49
|
+
v-for="option in getSelectedAttributeOptions(attribute)"
|
|
50
|
+
:key="`attr-${attribute._id}-${option._id}`"
|
|
51
|
+
class="ProductsSelectedFilters__item">
|
|
52
|
+
<span class="ProductsSelectedFilters__item-label">{{ attribute.name }}:</span>
|
|
53
|
+
<span class="ProductsSelectedFilters__item-value">{{ option.name }}</span>
|
|
54
|
+
<products-link :attributes="{ [attribute.alias]: option.alias }">
|
|
55
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
56
|
+
</products-link>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
<div
|
|
60
|
+
v-for="tag in selectedTagsList"
|
|
61
|
+
:key="`tag-${tag.alias}`"
|
|
62
|
+
class="ProductsSelectedFilters__item">
|
|
63
|
+
<span class="ProductsSelectedFilters__item-label">Tags:</span>
|
|
64
|
+
<span class="ProductsSelectedFilters__item-value">{{ tag.name }}</span>
|
|
65
|
+
<products-link :tags="tag.alias">
|
|
66
|
+
<i class="icon-cancel ProductsSelectedFilters__item-remove"></i>
|
|
67
|
+
</products-link>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
<div
|
|
71
|
+
v-if="hasSelectedFilters"
|
|
72
|
+
class="ProductsSelectedFilters__clear-all"
|
|
73
|
+
@click="clearAllFilters">
|
|
74
|
+
Clear All
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<script>
|
|
80
|
+
import ProductsLink from '@lancom/shared/components/products/products_link/products-link';
|
|
81
|
+
import selectedFiltersMixin from '@lancom/shared/mixins/products/selected-filters';
|
|
82
|
+
|
|
83
|
+
export default {
|
|
84
|
+
name: 'ProductsSelectedFilters',
|
|
85
|
+
components: {
|
|
86
|
+
ProductsLink
|
|
87
|
+
},
|
|
88
|
+
mixins: [selectedFiltersMixin],
|
|
89
|
+
methods: {
|
|
90
|
+
clearAllFilters() {
|
|
91
|
+
// Navigate to the base products route without any filters
|
|
92
|
+
const baseRoute = {
|
|
93
|
+
name: this.$route.name,
|
|
94
|
+
params: {
|
|
95
|
+
...this.$route.params,
|
|
96
|
+
brand: undefined,
|
|
97
|
+
type: undefined
|
|
98
|
+
},
|
|
99
|
+
query: {}
|
|
100
|
+
};
|
|
101
|
+
this.$router.push(baseRoute);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style lang="scss" scoped>
|
|
108
|
+
@import 'products-selected-filters';
|
|
109
|
+
</style>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div
|
|
3
3
|
v-if="tags.length"
|
|
4
4
|
class="ProductsTags__wrapper">
|
|
5
|
-
<toggle-content label="Tags">
|
|
5
|
+
<toggle-content label="Tags" :toggleable="toggleable">
|
|
6
6
|
<div class="ProductsTags__options">
|
|
7
7
|
<div
|
|
8
8
|
v-for="tag in tags"
|
|
@@ -42,6 +42,10 @@ export default {
|
|
|
42
42
|
hasRemoveIcon: {
|
|
43
43
|
type: Boolean,
|
|
44
44
|
default: false
|
|
45
|
+
},
|
|
46
|
+
toggleable: {
|
|
47
|
+
type: Boolean,
|
|
48
|
+
default: true
|
|
45
49
|
}
|
|
46
50
|
},
|
|
47
51
|
computed: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="ProductsTypes__wrapper">
|
|
3
|
-
<toggle-content label="Product type">
|
|
3
|
+
<toggle-content label="Product type" :toggleable="toggleable">
|
|
4
4
|
<div
|
|
5
5
|
v-for="type in types"
|
|
6
6
|
:key="type.alias"
|
|
@@ -56,6 +56,10 @@ export default {
|
|
|
56
56
|
hasThumbs: {
|
|
57
57
|
type: Boolean,
|
|
58
58
|
default: true
|
|
59
|
+
},
|
|
60
|
+
toggleable: {
|
|
61
|
+
type: Boolean,
|
|
62
|
+
default: true
|
|
59
63
|
}
|
|
60
64
|
},
|
|
61
65
|
computed: {
|
|
@@ -61,6 +61,9 @@ const productPreview = {
|
|
|
61
61
|
productCountries() {
|
|
62
62
|
return this.countries.filter(c => this.product.countries?.includes(c._id));
|
|
63
63
|
},
|
|
64
|
+
aggregateRating() {
|
|
65
|
+
return this.product?.aggregateRating || { value: 0, count: 0 };
|
|
66
|
+
},
|
|
64
67
|
noMinimum() {
|
|
65
68
|
return !(this.product.minimumPrintOrderQuantity > 1) && !(this.product.minimumOrderQuantity > 1);
|
|
66
69
|
},
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { mapGetters } from 'vuex';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
computed: {
|
|
5
|
+
...mapGetters('products', ['brands', 'types', 'colorGroups', 'colors', 'attributes', 'tags']),
|
|
6
|
+
|
|
7
|
+
selectedBrand() {
|
|
8
|
+
const brandAlias = this.$route.params.brand || this.$route.query.brand;
|
|
9
|
+
return brandAlias ? this.brands.find(b => b.alias === brandAlias) : null;
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
selectedType() {
|
|
13
|
+
const typeAlias = this.$route.params.type || this.$route.query.type;
|
|
14
|
+
return typeAlias ? this.types.find(t => t.alias === typeAlias) : null;
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
selectedColorGroups() {
|
|
18
|
+
const colorGroupsAliases = (this.$route.query.colorGroups || '').split(',').filter(Boolean);
|
|
19
|
+
return this.colorGroups.filter(cg => colorGroupsAliases.includes(cg.alias));
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
selectedColors() {
|
|
23
|
+
const colorsAliases = (this.$route.query.colors || '').split(',').filter(Boolean);
|
|
24
|
+
return this.colors.filter(c => colorsAliases.includes(c.alias));
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
selectedTagsList() {
|
|
28
|
+
const tagsAliases = (this.$route.query.tags || '').split(',').filter(Boolean);
|
|
29
|
+
return this.tags.filter(t => tagsAliases.includes(t.alias));
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
hasSelectedFilters() {
|
|
33
|
+
return this.selectedBrand ||
|
|
34
|
+
this.selectedType ||
|
|
35
|
+
this.selectedColorGroups.length > 0 ||
|
|
36
|
+
this.selectedColors.length > 0 ||
|
|
37
|
+
this.selectedTagsList.length > 0 ||
|
|
38
|
+
this.attributes.some(attr => this.getSelectedAttributeOptions(attr).length > 0);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
methods: {
|
|
43
|
+
getSelectedAttributeOptions(attribute) {
|
|
44
|
+
const selectedAliases = (this.$route.query[attribute.alias] || '').split(',').filter(Boolean);
|
|
45
|
+
const options = attribute.options || [];
|
|
46
|
+
return options.filter(option => selectedAliases.includes(option.alias));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|