@ecomplus/widget-martan 1.1.22 → 1.2.0

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 (97) hide show
  1. package/.version +0 -0
  2. package/CHANGELOG.md +14 -0
  3. package/cms.config.js +78 -83
  4. package/dist/public/widget-martan.0.min.js +62 -0
  5. package/dist/public/widget-martan.0.min.js.map +1 -0
  6. package/dist/public/widget-martan.1.min.js.map +1 -1
  7. package/dist/public/widget-martan.2.min.js +1 -1
  8. package/dist/public/widget-martan.2.min.js.map +1 -1
  9. package/dist/public/widget-martan.3.min.js +1 -1
  10. package/dist/public/widget-martan.3.min.js.map +1 -1
  11. package/dist/public/widget-martan.4.min.js +1 -1
  12. package/dist/public/widget-martan.4.min.js.map +1 -1
  13. package/dist/public/widget-martan.5.min.js +1 -1
  14. package/dist/public/widget-martan.5.min.js.map +1 -1
  15. package/dist/public/widget-martan.6.min.js +2 -0
  16. package/dist/public/widget-martan.6.min.js.map +1 -0
  17. package/dist/public/widget-martan.7.min.js +2 -0
  18. package/dist/public/widget-martan.7.min.js.map +1 -0
  19. package/dist/public/widget-martan.8.min.js +2 -0
  20. package/dist/public/widget-martan.8.min.js.map +1 -0
  21. package/dist/public/widget-martan.9.min.js +2 -0
  22. package/dist/public/widget-martan.9.min.js.map +1 -0
  23. package/dist/public/widget-martan.var.min.js +3 -3
  24. package/dist/public/widget-martan.var.min.js.map +1 -1
  25. package/dist/widget-martan.0.min.js +62 -0
  26. package/dist/widget-martan.0.min.js.map +1 -0
  27. package/dist/widget-martan.1.min.js.map +1 -1
  28. package/dist/widget-martan.2.min.js +1 -1
  29. package/dist/widget-martan.2.min.js.map +1 -1
  30. package/dist/widget-martan.3.min.js +1 -1
  31. package/dist/widget-martan.3.min.js.map +1 -1
  32. package/dist/widget-martan.4.min.js +1 -1
  33. package/dist/widget-martan.4.min.js.map +1 -1
  34. package/dist/widget-martan.5.min.js +1 -1
  35. package/dist/widget-martan.5.min.js.map +1 -1
  36. package/dist/widget-martan.6.min.js +2 -0
  37. package/dist/widget-martan.6.min.js.map +1 -0
  38. package/dist/widget-martan.7.min.js +2 -0
  39. package/dist/widget-martan.7.min.js.map +1 -0
  40. package/dist/widget-martan.8.min.js +2 -0
  41. package/dist/widget-martan.8.min.js.map +1 -0
  42. package/dist/widget-martan.9.min.js +2 -0
  43. package/dist/widget-martan.9.min.js.map +1 -0
  44. package/dist/widget-martan.min.js +3 -3
  45. package/dist/widget-martan.min.js.map +1 -1
  46. package/package.json +2 -2
  47. package/src/append/product-block.ejs +5 -1
  48. package/src/append/product-card-slots.ejs +1 -1
  49. package/src/append/product-slots.ejs +1 -9
  50. package/src/index.js +17 -12
  51. package/src/utils/configProps.js +29 -0
  52. package/src/utils/lighten-color.js +20 -0
  53. package/src/utils/widget-initializer.js +60 -0
  54. package/src/widgets/questions/Questions.vue +436 -0
  55. package/src/widgets/questions/index.js +10 -0
  56. package/src/widgets/ratings/Rating.vue +223 -0
  57. package/src/widgets/ratings/index.js +232 -0
  58. package/src/widgets/reviews/Reviews.vue +317 -288
  59. package/src/widgets/reviews/components/Quickview.vue +390 -0
  60. package/src/widgets/reviews/components/Rating.vue +106 -0
  61. package/src/widgets/reviews/components/RatingBreakdown.vue +171 -0
  62. package/src/widgets/reviews/components/RatingHistogram.vue +306 -0
  63. package/src/widgets/reviews/components/RatingSummary.vue +226 -0
  64. package/src/widgets/reviews/components/RatingSummaryG.vue +104 -0
  65. package/src/widgets/reviews/components/ReviewCard.vue +223 -0
  66. package/src/widgets/reviews/{ReviewReply.vue → components/ReviewReply.vue} +42 -1
  67. package/src/widgets/reviews/{Score.vue → components/Score.vue} +3 -4
  68. package/src/widgets/reviews/{Sort.vue → components/Sort.vue} +1 -1
  69. package/src/widgets/reviews/components/SortDropdown.vue +184 -0
  70. package/src/widgets/reviews/components/VerifiedPurchase.vue +121 -0
  71. package/src/widgets/reviews/headers/Center.vue +248 -0
  72. package/src/widgets/reviews/headers/Compact.vue +225 -0
  73. package/src/widgets/reviews/headers/Histogram.vue +224 -0
  74. package/src/widgets/reviews/headers/Padrao.vue +113 -0
  75. package/src/widgets/reviews/headers/Summary.vue +217 -0
  76. package/src/widgets/reviews/index.js +2 -48
  77. package/src/append/body.ejs +0 -79
  78. package/src/append/head.ejs +0 -5
  79. package/src/append/stamps.ejs +0 -3
  80. package/src/widgets/reviews/AuthorAndRating.vue +0 -30
  81. package/src/widgets/reviews/AverageScore.vue +0 -160
  82. package/src/widgets/reviews/AverageTotal.vue +0 -35
  83. package/src/widgets/reviews/CardReview.vue +0 -87
  84. package/src/widgets/reviews/GridView.vue +0 -113
  85. package/src/widgets/reviews/HeaderExpanded.vue +0 -84
  86. package/src/widgets/reviews/HeaderMinimal.vue +0 -110
  87. package/src/widgets/reviews/ListView.vue +0 -47
  88. package/src/widgets/reviews/Quickview.vue +0 -397
  89. package/src/widgets/reviews/ReviewBody.vue +0 -39
  90. package/src/widgets/reviews/ThumbsPictures.vue +0 -135
  91. package/src/widgets/reviews/Total.vue +0 -79
  92. package/src/widgets/reviews/VerifiedPurchase.vue +0 -110
  93. package/src/widgets/reviews/isRecommended.vue +0 -44
  94. package/src/widgets/snippets/Rating.vue +0 -71
  95. package/src/widgets/snippets/Snippets.vue +0 -311
  96. package/src/widgets/snippets/index.js +0 -45
  97. /package/src/widgets/reviews/{VideoPlayer.vue → components/VideoPlayer.vue} +0 -0
@@ -0,0 +1,390 @@
1
+ <template>
2
+ <div
3
+ class="modal fade"
4
+ id="martan-quickview"
5
+ tabindex="-1"
6
+ role="dialog"
7
+ aria-labelledby="quickviewModal"
8
+ aria-hidden="true"
9
+ >
10
+ <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
11
+ <div class="modal-content">
12
+ <div class="modal-header" v-show="false">
13
+ <h5 class="modal-title" id="quickviewModal">{{ i19quickview }}</h5>
14
+ <button
15
+ type="button"
16
+ class="close"
17
+ data-dismiss="modal"
18
+ aria-label="Close"
19
+ >
20
+ <span aria-hidden="true">&times;</span>
21
+ </button>
22
+ </div>
23
+
24
+ <div class="modal-body mt-quickview">
25
+ <button
26
+ type="button"
27
+ class="close"
28
+ data-dismiss="modal"
29
+ aria-label="Close"
30
+ >
31
+ <span aria-hidden="true">&times;</span>
32
+ </button>
33
+
34
+ <div class="mt-quickview__content">
35
+ <!-- Image Gallery Column -->
36
+ <div class="mt-quickview__gallery-column">
37
+ <!-- Main Image Display -->
38
+ <div class="mt-quickview__main-image">
39
+ <img
40
+ :src="currentImage"
41
+ :alt="'Review image'"
42
+ v-if="currentImage"
43
+ />
44
+ <VideoPlayer v-else-if="video" :videoUrl="video" />
45
+ </div>
46
+
47
+ <!-- Thumbnails -->
48
+ <div
49
+ class="mt-quickview__thumbnails"
50
+ v-if="pictures.length || video"
51
+ >
52
+ <div
53
+ v-for="(pic, index) in pictures"
54
+ :key="`thumb-${index}`"
55
+ class="mt-quickview__thumb"
56
+ :class="{ active: currentImageIndex === index }"
57
+ @click="setCurrentImage(index)"
58
+ >
59
+ <img :src="pic.thumb" :alt="'Thumbnail ' + (index + 1)" />
60
+ </div>
61
+ <div
62
+ v-if="video"
63
+ class="mt-quickview__thumb"
64
+ :class="{ active: currentImageIndex === pictures.length }"
65
+ @click="setCurrentImage(pictures.length)"
66
+ >
67
+ <i class="fas fa-play-circle"></i>
68
+ </div>
69
+ </div>
70
+ </div>
71
+
72
+ <!-- Review Info Column -->
73
+ <div class="mt-quickview__info-column" v-if="review">
74
+ <div class="mt-review">
75
+ <div class="mt-rating__group">
76
+ <ReviewCard
77
+ :truncate-body="false"
78
+ :review="review"
79
+ :star-color="starColor"
80
+ :full="true"
81
+ />
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ </div>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </template>
91
+
92
+ <script>
93
+ import { i19next, i19previous } from "@ecomplus/i18n";
94
+ import { i18n, formatDate } from "@ecomplus/utils";
95
+
96
+ import { timeAgo } from "../../../utils/time-ago";
97
+ import VideoPlayer from "./VideoPlayer.vue";
98
+ import ReviewCard from "./ReviewCard.vue";
99
+
100
+ export default {
101
+ name: "Quickview",
102
+
103
+ components: {
104
+ VideoPlayer,
105
+ ReviewCard,
106
+ },
107
+
108
+ props: {
109
+ review: Object,
110
+ isOpen: {
111
+ type: Boolean,
112
+ default: false,
113
+ },
114
+ starColor: String,
115
+ },
116
+
117
+ data() {
118
+ return {
119
+ currentImageIndex: 0,
120
+ currentImage: null,
121
+ };
122
+ },
123
+
124
+ computed: {
125
+ i19quickview: () => "Quickview",
126
+ i19next: () => i18n(i19next),
127
+ i19previous: () => i18n(i19previous),
128
+
129
+ reviewId: function () {
130
+ if (this.review && this.review.id) {
131
+ return this.review.id;
132
+ }
133
+
134
+ return null;
135
+ },
136
+
137
+ pictures: function () {
138
+ if (this.review && this.review.pictures) {
139
+ return this.review.pictures;
140
+ }
141
+ return [];
142
+ },
143
+
144
+ video: function () {
145
+ if (this.review && this.review.video_url) {
146
+ return this.review.video_url;
147
+ }
148
+ return null;
149
+ },
150
+
151
+ title: function () {
152
+ if (this.review && this.review.title) {
153
+ return this.review.title;
154
+ }
155
+ return null;
156
+ },
157
+
158
+ author: function () {
159
+ if (this.review && this.review.display_name) {
160
+ return this.review.display_name;
161
+ }
162
+ return null;
163
+ },
164
+
165
+ rating: function () {
166
+ if (this.review && this.review.rating) {
167
+ return this.review.rating;
168
+ }
169
+ return null;
170
+ },
171
+
172
+ recommended: function () {
173
+ if (this.review && this.review.is_recommended) {
174
+ return this.review.is_recommended;
175
+ }
176
+ return null;
177
+ },
178
+
179
+ isVerified: function () {
180
+ if (this.review && this.review.verified_purchase) {
181
+ return this.review.verified_purchase;
182
+ }
183
+ return null;
184
+ },
185
+
186
+ reply: function () {
187
+ if (this.review && this.review.reply) {
188
+ return this.review.reply;
189
+ }
190
+ return null;
191
+ },
192
+
193
+ created: function () {
194
+ if (this.review && this.review.created_at) {
195
+ return this.review.created_at;
196
+ }
197
+ return null;
198
+ },
199
+
200
+ body: function () {
201
+ if (this.review && this.review.body) {
202
+ return this.review.body;
203
+ }
204
+ return null;
205
+ },
206
+ },
207
+
208
+ watch: {
209
+ isOpen: function (isOpened) {
210
+ if (isOpened) {
211
+ $("#martan-quickview").modal("show");
212
+ }
213
+ },
214
+ pictures: {
215
+ immediate: true,
216
+ handler(newPics) {
217
+ if (newPics && newPics.length) {
218
+ this.currentImage = newPics[0].big || newPics[0].normal;
219
+ }
220
+ },
221
+ },
222
+ },
223
+
224
+ mounted() {
225
+ $("#martan-quickview").on("hidden.bs.modal", this.close);
226
+ $("#martan-quickview").on("shown.bs.modal", this.mount);
227
+ },
228
+
229
+ methods: {
230
+ formatDate,
231
+ timeAgo,
232
+ close: function () {
233
+ this.$emit("onClose", true);
234
+ },
235
+ setCurrentImage(index) {
236
+ this.currentImageIndex = index;
237
+ if (index < this.pictures.length) {
238
+ this.currentImage = this.pictures[index].big;
239
+ } else {
240
+ this.currentImage = null; // Will show video player
241
+ }
242
+ },
243
+ },
244
+ };
245
+ </script>
246
+
247
+ <style lang="scss">
248
+ #martan-quickview {
249
+ padding: 0 !important;
250
+ .modal-dialog {
251
+ margin: 0 auto;
252
+ }
253
+ }
254
+
255
+ .mt-quickview {
256
+ .review-card {
257
+ width: 100% !important;
258
+ margin-top: 0 !important;
259
+ }
260
+ .review-card__images {
261
+ display: none;
262
+ }
263
+ }
264
+ </style>
265
+
266
+ <style lang="scss" scoped>
267
+ .mt-quickview {
268
+ padding: 0;
269
+
270
+ &__content {
271
+ display: flex;
272
+ flex-direction: column;
273
+
274
+ @media (min-width: 992px) {
275
+ flex-direction: row;
276
+ }
277
+ }
278
+
279
+ &__gallery-column {
280
+ flex: 1;
281
+ max-width: 500px;
282
+ width: 100%;
283
+ }
284
+
285
+ &__main-image {
286
+ img {
287
+ max-width: 100%;
288
+ max-height: 100%;
289
+ object-fit: contain;
290
+ border-top-left-radius: 3px;
291
+ @media (max-width: 992px) {
292
+ border-top-right-radius: 3px;
293
+ }
294
+ }
295
+ }
296
+
297
+ &__thumbnails {
298
+ display: flex;
299
+ gap: 0.5rem;
300
+ overflow-x: auto;
301
+ padding: 0.5rem;
302
+
303
+ @media (min-width: 992px) {
304
+ flex-wrap: wrap;
305
+ max-height: 100px;
306
+ }
307
+ }
308
+
309
+ &__thumb {
310
+ width: 60px;
311
+ height: 60px;
312
+ border: 2px solid transparent;
313
+ cursor: pointer;
314
+ flex-shrink: 0;
315
+
316
+ &.active {
317
+ border-color: var(--primary);
318
+ }
319
+
320
+ img {
321
+ width: 100%;
322
+ height: 100%;
323
+ object-fit: cover;
324
+ }
325
+
326
+ i {
327
+ width: 100%;
328
+ height: 100%;
329
+ display: flex;
330
+ align-items: center;
331
+ justify-content: center;
332
+ background: #f8f9fa;
333
+ font-size: 1.5rem;
334
+ }
335
+ }
336
+
337
+ &__info-column {
338
+ flex: 1;
339
+ @media (min-width: 992px) {
340
+ max-height: 500px;
341
+ overflow-y: auto;
342
+ }
343
+ }
344
+
345
+ .close {
346
+ position: absolute;
347
+ z-index: 1;
348
+ padding: 8px 1rem;
349
+ }
350
+
351
+ &__galery {
352
+ max-width: 500px;
353
+ min-height: 500px;
354
+ width: 100%;
355
+ display: flex;
356
+ align-items: center;
357
+
358
+ img {
359
+ max-width: 500px;
360
+ max-height: 500px;
361
+ height: 100%;
362
+ object-fit: contain;
363
+ width: 100%;
364
+ }
365
+
366
+ .glide__slides {
367
+ align-items: center;
368
+ }
369
+ }
370
+
371
+ &__review {
372
+ padding: 1rem;
373
+
374
+ @media (min-width: 992px) {
375
+ max-height: 500px;
376
+ overflow: auto;
377
+ }
378
+
379
+ @media (min-width: 1200px) {
380
+ max-height: 500px;
381
+ overflow: auto;
382
+ }
383
+ }
384
+
385
+ .video-wrapper {
386
+ display: flex;
387
+ align-items: center;
388
+ }
389
+ }
390
+ </style>
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <span class="martan-rating">
3
+ <svg
4
+ v-for="(star, index) in stars"
5
+ :key="index"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ class="icon icon-tabler"
8
+ :class="getStarClass(star)"
9
+ width="14"
10
+ height="14"
11
+ viewBox="0 0 24 24"
12
+ stroke-width="2"
13
+ stroke="currentColor"
14
+ fill="none"
15
+ stroke-linecap="round"
16
+ stroke-linejoin="round"
17
+ :style="{ color }"
18
+ >
19
+ <defs v-if="star === 0.5">
20
+ <linearGradient :id="`gradient-${index}`" x1="0%" y1="0%" x2="100%" y2="0%">
21
+ <stop offset="50%" :style="`stop-color:${color};stop-opacity:1`" />
22
+ <stop offset="50%" :style="`stop-color:${color};stop-opacity:0`" />
23
+ </linearGradient>
24
+ </defs>
25
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
26
+ <path
27
+ d="M8.243 7.34l-6.38 .925l-.113 .023a1 1 0 0 0 -.44 1.684l4.622 4.499l-1.09 6.355l-.013 .11a1 1 0 0 0 1.464 .944l5.706 -3l5.693 3l.1 .046a1 1 0 0 0 1.352 -1.1l-1.091 -6.355l4.624 -4.5l.078 -.085a1 1 0 0 0 -.633 -1.62l-6.38 -.926l-2.852 -5.78a1 1 0 0 0 -1.794 0l-2.853 5.78z"
28
+ :fill="getStarFill(star, index)" />
29
+ </svg>
30
+ </span>
31
+ </template>
32
+
33
+ <script>
34
+ export default {
35
+ name: 'Rating',
36
+
37
+ props: {
38
+ rating: {
39
+ type: Number,
40
+ default: 5
41
+ },
42
+
43
+ color: {
44
+ type: String,
45
+ default: "#000000"
46
+ },
47
+ },
48
+
49
+ data() {
50
+ return {
51
+ stars: Array(5).fill(0)
52
+ };
53
+ },
54
+
55
+ mounted() {
56
+ this.updateStars();
57
+ },
58
+
59
+ methods: {
60
+ updateStars() {
61
+ const rating = Math.max(0, Math.min(5, this.rating));
62
+ this.stars = Array(5).fill(0).map((_, index) => {
63
+ const starPosition = index + 1;
64
+ if (rating >= starPosition) {
65
+ return 1;
66
+ } else if (rating > index) {
67
+ return 0.5;
68
+ } else {
69
+ return 0;
70
+ }
71
+ });
72
+ },
73
+
74
+ getStarClass(star) {
75
+ if (star === 1) {
76
+ return 'icon-tabler-star-filled';
77
+ } else if (star === 0.5) {
78
+ return 'icon-tabler-star-half';
79
+ } else {
80
+ return 'icon-tabler-star';
81
+ }
82
+ },
83
+
84
+ getStarFill(star, index) {
85
+ if (star === 1) {
86
+ return 'currentColor';
87
+ } else if (star === 0.5) {
88
+ return `url(#gradient-${index})`;
89
+ } else {
90
+ return 'none';
91
+ }
92
+ }
93
+ },
94
+
95
+ watch: {
96
+ rating: 'updateStars'
97
+ }
98
+ };
99
+ </script>
100
+
101
+ <style lang="css">
102
+ .martan-rating {
103
+ display: flex;
104
+ gap: 4px;
105
+ }
106
+ </style>
@@ -0,0 +1,171 @@
1
+ <template>
2
+ <div class="mrtn-rating-breakdown" :style="'--hover-color: ' + houverColor" :class="{ 'mrtn-rating-breakdown--has-active': currentActive !== null }">
3
+ <div v-for="(count, stars) in ratingBreakdown" :key="stars" class="mrtn-rating-row"
4
+ :class="{ 'mrtn-rating-row--active': currentActive === stars }" @click="selectRating(stars)">
5
+ <div class="mrtn-rating-stars">
6
+ <Rating :rating="parseInt(stars)" :color="config.widget_review.star_color" />
7
+ </div>
8
+
9
+ <div class="mrtn-rating-bar">
10
+ <div class="mrtn-rating-bar__fill" :style="{
11
+ width: getBarWidth(count) + '%',
12
+ backgroundColor: config.widget_review.star_color
13
+ }"></div>
14
+ </div>
15
+
16
+ <span class="mrtn-rating-count">({{ count }})</span>
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script>
22
+ import { configProp } from "../../../utils/configProps";
23
+ import Rating from "./Rating.vue";
24
+ import { lightenColor } from "../../../utils/lighten-color";
25
+
26
+ export default {
27
+ name: 'RatingBreakdown',
28
+
29
+ props: {
30
+ ...configProp,
31
+ rating: {
32
+ type: Object,
33
+ default: () => ({
34
+ five: 0,
35
+ four: 0,
36
+ three: 0,
37
+ two: 0,
38
+ one: 0
39
+ })
40
+ },
41
+
42
+ totalRating: {
43
+ type: Number,
44
+ default: 0
45
+ },
46
+
47
+
48
+ average: {
49
+ type: Number,
50
+ default: 0
51
+ }
52
+ },
53
+
54
+ data() {
55
+ return {
56
+ currentActive: null
57
+ }
58
+ },
59
+
60
+ computed: {
61
+ ratingBreakdown() {
62
+ return {
63
+ 5: this.rating.five,
64
+ 4: this.rating.four,
65
+ 3: this.rating.three,
66
+ 2: this.rating.two,
67
+ 1: this.rating.one
68
+ }
69
+ },
70
+
71
+ houverColor() {
72
+ if (!this.config.widget_review.star_color) return null
73
+ return lightenColor(this.config.widget_review.star_color, 0.9)
74
+ }
75
+ },
76
+
77
+ methods: {
78
+ lightenColor,
79
+ getBarWidth(count) {
80
+ if (this.totalRating === 0) return 0
81
+ return (count / this.totalRating) * 100
82
+ },
83
+
84
+ selectRating(rating) {
85
+ if (this.currentActive === rating) {
86
+ this.currentActive = null
87
+ } else {
88
+ this.currentActive = rating
89
+ }
90
+ this.$emit('rating-selected', this.currentActive)
91
+ }
92
+ },
93
+
94
+ components: {
95
+ Rating
96
+ }
97
+ }
98
+ </script>
99
+
100
+ <style lang="scss" scoped>
101
+ .mrtn-rating-breakdown {
102
+ display: flex;
103
+ flex-direction: column;
104
+ width: 100%;
105
+ }
106
+
107
+ .mrtn-rating-row {
108
+ display: flex;
109
+ align-items: center;
110
+ gap: 12px;
111
+ padding: 8px;
112
+ border-radius: 6px;
113
+ cursor: pointer;
114
+ transition: all 0.2s ease;
115
+ position: relative;
116
+
117
+ &:hover {
118
+ background: var(--hover-color);
119
+ }
120
+
121
+ &--active {
122
+ background: var(--hover-color);
123
+ box-shadow: 0 0 0 2px var(--hover-color);
124
+ transform: scale(1.02);
125
+ z-index: 10;
126
+ }
127
+ }
128
+
129
+ .mrtn-rating-breakdown--has-active .mrtn-rating-row:not(.mrtn-rating-row--active) {
130
+ opacity: 0.4;
131
+ filter: grayscale(0.8);
132
+ }
133
+
134
+ .mrtn-rating-stars {
135
+ display: flex;
136
+ gap: 2px;
137
+ min-width: 80px;
138
+ }
139
+
140
+ .mrtn-rating-star {
141
+ font-size: 14px;
142
+ color: #e5e5e5;
143
+
144
+ &--filled {
145
+ color: #000000;
146
+ }
147
+ }
148
+
149
+ .mrtn-rating-bar {
150
+ flex: 1;
151
+ height: 8px;
152
+ background: #f0f0f0;
153
+ border-radius: 4px;
154
+ overflow: hidden;
155
+ position: relative;
156
+ transition: all 0.2s ease;
157
+ }
158
+
159
+ .mrtn-rating-bar__fill {
160
+ height: 100%;
161
+ border-radius: 4px;
162
+ transition: width 0.3s ease;
163
+ }
164
+
165
+ .mrtn-rating-count {
166
+ font-size: 12px;
167
+ color: #666666;
168
+ min-width: 40px;
169
+ text-align: right;
170
+ }
171
+ </style>