PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.8
Booking for Appointments and Events Calendar – Amelia v2.4.8
2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / v3 / src / views / _components / select / parts / AmOptionTemplate2.vue
ameliabooking / v3 / src / views / _components / select / parts Last commit date
AmOptionTemplate1.vue 1 month ago AmOptionTemplate2.vue 1 month ago
AmOptionTemplate2.vue
474 lines
1 <template>
2 <span class="am-oit__wrapper">
3 <span class="am-oit">
4 <span class="am-oit__img">
5 <span
6 class="am-oit__img-placeholder"
7 :style="{ backgroundImage: `url(${prop.imageThumb})` }"
8 >
9 <span v-if="!prop.imageThumb">
10 {{ imagePlaceholder() }}
11 </span>
12 </span>
13 </span>
14 <span class="am-oit__content">
15 <span class="am-oit__data">
16 <span :class="`am-oit__data-label ${badge ? 'am-oit__data-label-wrap' : ''}`">
17 <span class="am-oit__data-label-name">
18 {{ label }}
19 </span>
20 <span
21 v-if="badge"
22 class="am-oit__data-label-badge"
23 :style="{ background: badge.color }"
24 >
25 {{ badge.content }}
26 </span>
27 </span>
28 <span
29 v-if="!badge && useDescriptionVisibility(description)"
30 class="am-oit__data-description"
31 v-html="replaceNewLines(description)"
32 ></span>
33 </span>
34 <span class="am-oit__meta">
35 <span v-if="prop.price" class="am-oit__price" :style="cssVarsPrice">
36 {{ prop.price }}
37 </span>
38 <span
39 v-if="useDescriptionVisibility(description)"
40 class="am-oit__info-trigger"
41 @click="dialogInfoVisible"
42 >
43 <span class="am-icon-circle-info"></span>
44 </span>
45 </span>
46 </span>
47 </span>
48 <AmDialog
49 v-if="useDescriptionVisibility(description)"
50 v-model="infoVisible"
51 :custom-class="'am-option-template-dialog am-dialog ql-description'"
52 :append-to-body="true"
53 :custom-styles="cssVars"
54 :destroy-on-close="true"
55 :align-center="true"
56 :modal-class="'am-dialog-employee-description'"
57 >
58 <template #title>
59 <span class="am-dialog__title">
60 {{ dialogTitle }}
61 </span>
62 </template>
63 <div class="am-dialog__body">
64 <div class="am-dialog__body-heading">
65 <span class="am-oit__img">
66 <span
67 class="am-oit__img-placeholder"
68 :style="{ backgroundImage: `url(${prop.imageThumb})` }"
69 >
70 <span v-if="!prop.imageThumb">
71 {{ imagePlaceholder() }}
72 </span>
73 </span>
74 </span>
75 <div class="am-dialog__body-heading__text">
76 <span class="am-dialog__body-heading__text-name">
77 {{ label }}
78 </span>
79 <span
80 v-if="badge"
81 class="am-dialog__body-heading__text-badge"
82 :style="{ background: badge.color }"
83 >
84 {{ badge.content }}
85 </span>
86 </div>
87 </div>
88 <div class="am-dialog__body-content" v-html="description"></div>
89 </div>
90 <template #footer>
91 <AmButton :type="primFooterBtnType" category="primary" @click="handleClick">
92 {{ dialogButtonText }}
93 </AmButton>
94 </template>
95 </AmDialog>
96 </span>
97 </template>
98
99 <script setup>
100 // * Import components
101 import AmDialog from '../../dialog/AmDialog.vue'
102 import AmButton from '../../button/AmButton.vue'
103
104 // * Import from Vue
105 import { computed, inject, ref } from 'vue'
106
107 // * Composables
108 import { useColorTransparency } from '../../../../assets/js/common/colorManipulation'
109 import { useDescriptionVisibility } from '../../../../assets/js/common/helper'
110
111 /**
112 * Component Props
113 */
114 const prop = defineProps({
115 identifier: {
116 type: [String, Number],
117 required: true,
118 },
119 imageThumb: {
120 type: String,
121 default: '',
122 },
123 label: {
124 type: [String, Number],
125 default: '',
126 },
127 description: {
128 type: String,
129 default: '',
130 },
131 price: {
132 type: [String, Number],
133 default: '',
134 },
135 dialogTitle: {
136 type: String,
137 default: '',
138 },
139 dialogButtonText: {
140 type: String,
141 default: '',
142 },
143 badge: {
144 type: [String, Number, Object],
145 },
146 })
147
148 /**
149 * Component Emits
150 * */
151 const emits = defineEmits(['click'])
152
153 // * Dialog Visibility
154 let infoVisible = ref(false)
155
156 /**
157 * Component Methods
158 */
159 const dialogInfoVisible = (e) => {
160 e.stopPropagation()
161 infoVisible.value = true
162 }
163
164 /**
165 * Component Event Handlers
166 */
167 const handleClick = () => {
168 infoVisible.value = false
169 emits('click', prop.identifier)
170 }
171
172 function replaceNewLines(description) {
173 if (!description) return ''
174 let text = description.replace(/<br\s*\/?>/gi, ' ')
175 text = text
176 .replace(/<\/p>/gi, ' ')
177 .replace(/<\/div>/gi, ' ')
178 .replace(/<\/li>/gi, ' ')
179 text = text.replace(/<[^>]*>/g, '')
180 text = text.replace(/&nbsp;/g, ' ')
181 text = text.replace(/\s+/g, ' ').trim()
182 return text
183 }
184
185 function imagePlaceholder() {
186 if (prop.label) {
187 let shortLabel = ''
188 prop.label.split(' ').forEach((item) => {
189 shortLabel += item.charAt(0).toUpperCase()
190 })
191
192 return shortLabel
193 }
194 }
195
196 let primFooterBtnType = inject('primDescBtnType', 'filled')
197
198 // * Global colors
199 let amColors = inject('amColors')
200 let cssVars = computed(() => {
201 return {
202 '--am-oit-c-main-bgr': amColors.value.colorMainBgr,
203 '--am-oit-c-main-btn-color': amColors.value.colorBtnPrim,
204 '--am-oit-c-main-btn-color-text': amColors.value.colorBtnPrimText,
205 '--am-oit-c-main-heading-text': amColors.value.colorMainHeadingText,
206 '--am-oit-c-main-heading-text-op90': useColorTransparency(
207 amColors.value.colorMainHeadingText,
208 0.9,
209 ),
210 '--am-oit-c-main-text': amColors.value.colorMainText,
211 '--am-c-option-img-text': amColors.value.colorMainBgr,
212 }
213 })
214 let cssVarsPrice = computed(() => {
215 return {
216 '--am-c-option-selected': amColors.value.colorPrimary,
217 }
218 })
219 </script>
220
221 <script>
222 export default {
223 inheritAttrs: false,
224 }
225 </script>
226
227 <style lang="scss">
228 // am - Amelia
229 // oit - option inner template
230 .am-select-popper {
231 .am-oit {
232 width: 100%;
233 display: flex;
234 align-items: center;
235
236 * {
237 font-family: var(--am-font-family);
238 }
239
240 &__wrapper {
241 display: flex;
242 width: 100%;
243 }
244
245 &__img {
246 display: flex;
247 flex-shrink: 0;
248 width: 36px;
249 height: 36px;
250 margin-right: 8px;
251
252 &-placeholder {
253 position: relative;
254 display: block;
255 width: 100%;
256 height: 100%;
257 background-color: #00a32a;
258 border-radius: 50%;
259 background-size: cover;
260 background-repeat: no-repeat;
261 background-position: center;
262
263 span {
264 display: block;
265 position: absolute;
266 top: 50%;
267 left: 50%;
268 transform: translate(-50%, -50%);
269 font-size: 11px;
270 font-weight: 500;
271 line-height: 1;
272 color: var(--am-c-option-img-text);
273 }
274 }
275 }
276
277 &__content {
278 display: flex;
279 align-items: center;
280 flex: 1;
281 min-width: 0;
282 }
283
284 &__meta {
285 display: flex;
286 flex-shrink: 0;
287 align-items: center;
288 }
289
290 &__data {
291 display: flex;
292 flex: 1;
293 min-width: 0;
294 justify-content: space-between;
295 flex-direction: column;
296
297 &-label {
298 font-size: 16px;
299 font-weight: 500;
300 line-height: 1.25;
301
302 &-name {
303 color: var(--am-c-option-text);
304 min-width: 0;
305 white-space: nowrap;
306 overflow: hidden;
307 text-overflow: ellipsis;
308 margin-right: 4px;
309 }
310
311 &-badge {
312 color: #fff;
313 border-radius: 4px;
314 padding: 0 4px;
315 font-size: 13px;
316 line-height: 19px;
317 }
318
319 &-wrap {
320 display: flex;
321 flex-wrap: wrap;
322 }
323 }
324
325 &-description {
326 font-size: 12px;
327 font-weight: 400;
328 line-height: 1.5;
329 white-space: nowrap;
330 overflow: hidden;
331 text-overflow: ellipsis;
332 color: var(--am-c-option-text);
333
334 & * {
335 white-space: nowrap;
336 overflow: hidden;
337 text-overflow: ellipsis;
338 margin: 0;
339 padding: 0;
340 all: unset;
341 }
342
343 & br,
344 img {
345 display: none !important;
346 }
347 }
348 }
349
350 &__price {
351 display: flex;
352 flex-shrink: 0;
353 align-self: center;
354 justify-content: center;
355 min-width: 70px;
356 font-size: 16px;
357 font-weight: 500;
358 line-height: 1.25;
359 color: var(--am-c-option-selected);
360 }
361
362 &__info {
363 &-trigger {
364 .am-icon-circle-info {
365 font-size: 44px;
366 color: var(--am-c-option-text);
367
368 &:hover {
369 color: var(--am-c-option-selected);
370 }
371 }
372 }
373 }
374 }
375
376 .am-select-option {
377 &.is-selected {
378 .am-oit {
379 &__data {
380 &-label {
381 &-name {
382 color: var(--am-c-primary);
383 }
384 }
385
386 &-description {
387 color: var(--am-c-primary);
388 }
389 }
390 }
391 }
392 }
393 }
394
395 .am-dialog-employee-description {
396 z-index: 9999999999 !important;
397 }
398
399 .am-option-template-dialog {
400 box-shadow: 0 3px 15px rgba(0, 0, 0, 0.25);
401 border-radius: 6px;
402 background-color: var(--am-oit-c-main-bgr);
403
404 font-family: var(--am-font-family);
405
406 &.el-dialog {
407 max-width: 520px;
408 }
409
410 .am-dialog {
411 &__title {
412 color: var(--am-oit-c-main-heading-text-op90);
413 }
414 &__body {
415 &-heading {
416 display: flex;
417 align-items: center;
418 margin-bottom: 8px;
419
420 &__avatar {
421 display: flex;
422 width: 54px;
423 height: 54px;
424 background-color: #00a32a;
425 border-radius: 50%;
426 background-size: cover;
427 background-repeat: no-repeat;
428 background-position: center;
429 margin-right: 12px;
430 }
431
432 &__text {
433 font-size: 18px;
434 font-weight: 500;
435 line-height: 1.555555;
436
437 &-name {
438 color: var(--am-oit-c-main-text);
439 margin-right: 4px;
440 }
441
442 &-badge {
443 color: #fff;
444 border-radius: 4px;
445 padding: 0 4px;
446 }
447 }
448 }
449
450 &-content {
451 font-size: 16px;
452 font-weight: 400;
453 line-height: 1.5;
454 word-break: break-word;
455 color: var(--am-oit-c-main-text);
456 * {
457 color: var(--am-oit-c-main-text);
458 }
459 & p > * {
460 color: var(--am-oit-c-main-text);
461 }
462 }
463 }
464 }
465
466 .el-dialog__footer {
467 .el-button {
468 background-color: var(--am-oit-c-main-btn-color);
469 color: var(--am-oit-c-main-btn-color-text);
470 }
471 }
472 }
473 </style>
474