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 / admin / customize / steps / Events / common / EventInfo / EventInfo.vue
ameliabooking / v3 / src / views / admin / customize / steps / Events / common / EventInfo Last commit date
parts 1 month ago EventInfo.vue 1 month ago
EventInfo.vue
661 lines
1 <template>
2 <!-- Event List (elf) -->
3 <div class="am-eli" :class="props.globalClass" :style="cssVars">
4 <GalleryCarousel
5 v-if="selectedEvent.gallery.length && customizeOptions.gallery.visibility"
6 :gallery="selectedEvent.gallery"
7 class="am-eli__image"
8 ></GalleryCarousel>
9
10 <div class="am-eli__header">
11 <EventCard
12 :parent-key="stepName"
13 :event="selectedEvent"
14 :labels="amLabels"
15 :locations="locations"
16 :tickets="tickets"
17 :date-string-visibility="true"
18 :border-visibility="false"
19 :btn-visibility="false"
20 :auto-info-height="true"
21 :image-visibility="false"
22 vertical-orientation="start"
23 :in-header="true"
24 :in-dialog="true"
25 ></EventCard>
26 </div>
27
28 <div class="am-eli__main">
29 <AmTabs v-model="activeName">
30 <AmTabsItem :label="labelsDisplay('event_info')" name="first">
31 <div v-if="selectedEvent.periods.length" class="am-eli__timetable am-eli__main-item">
32 <p class="am-eli__timetable-title am-eli__main-title">
33 {{ labelsDisplay('event_timetable') }}
34 <span v-if="eventRange.start !== eventRange.end">
35 {{ `: ${eventRange.start} - ${eventRange.end}` }}
36 </span>
37 </p>
38 <p
39 v-for="period in selectedEventsPeriods"
40 :key="period.id"
41 class="am-eli__timetable-main"
42 >
43 <span class="am-eli__timetable-main__date am-eli__main-text">
44 {{ period.dateOfMonth }}
45 </span>
46 <span class="am-eli__timetable-main__time am-eli__main-text">
47 {{ ` - ${period.timeStart} - ${period.timeEnd}` }}
48 </span>
49 </p>
50 </div>
51
52 <DescriptionItem
53 v-if="customizeOptions.eventDescription.visibility"
54 class="am-eli__main-item"
55 :title="labelsDisplay('description')"
56 :description="selectedEvent.description"
57 :customized-labels="customLabels"
58 :limit="250"
59 ></DescriptionItem>
60
61 <EventEmployee
62 v-if="customizeOptions.eventOrganizer.visibility && !licence.isLite"
63 :divider="true"
64 :employee="eventOrganizer"
65 :rank="labelsDisplay('event_organizer')"
66 :customized-labels="customLabels"
67 class="am-eli__main-item"
68 ></EventEmployee>
69
70 <template v-if="customizeOptions.eventEmployees.visibility">
71 <EventEmployee
72 v-for="employee in eventProviders"
73 :key="employee.id"
74 :divider="true"
75 :employee="employee"
76 :customized-labels="customLabels"
77 class="am-eli__main-item"
78 ></EventEmployee>
79 </template>
80 </AmTabsItem>
81 <AmTabsItem v-if="features.tickets" :label="labelsDisplay('event_tickets')" name="second">
82 <EventTicket
83 v-for="ticket in tickets"
84 :key="ticket.id"
85 :ticket="ticket"
86 :capacity="selectedEvent.maxCustomCapacity"
87 :extra-people="selectedEvent.maxExtraPeople"
88 :customized-labels="customLabels"
89 :readonly="true"
90 />
91 </AmTabsItem>
92 </AmTabs>
93 </div>
94 </div>
95
96 <!-- Bringing Anyone with you -->
97 <AmSlidePopup :visibility="bringingAnyoneVisibility" custom-class="am-eli__bringing-wrapper">
98 <EventBringingAnyone />
99
100 <template #footer>
101 <div class="am-eli__bringing-footer" :class="responsiveClass">
102 <AmButton
103 :type="amCustomize[pageRenderKey].bringingAnyone.options.secBtn.buttonType"
104 category="secondary"
105 :disabled="false"
106 @click="noOneBringWith"
107 >
108 {{ labelsDisplay('back_btn', 'bringingAnyone') }}
109 </AmButton>
110 <AmButton
111 :category="isWaiting ? 'waiting' : 'primary'"
112 :type="amCustomize[pageRenderKey].bringingAnyone.options.primBtn.buttonType"
113 :disabled="false"
114 @click="bringPeopleWithYou"
115 >
116 {{ labelsDisplay('continue', 'bringingAnyone') }}
117 </AmButton>
118 </div>
119 </template>
120 </AmSlidePopup>
121 <!--/ Bringing Anyone with you -->
122 </template>
123
124 <script setup>
125 import AmTabs from '../../../../../../_components/tabs/AmTabs.vue'
126 import AmTabsItem from '../../../../../../_components/tabs/AmTabsItem.vue'
127 // * _components
128 import AmButton from '../../../../../../_components/button/AmButton.vue'
129 import AmSlidePopup from '../../../../../../_components/slide-popup/AmSlidePopup.vue'
130
131 // * Dedicated Components
132 import EventCard from '../../EventList/parts/EventCard.vue'
133 import DescriptionItem from '../../../../../../public/EventForm/Common/Parts/DescriptionItem.vue'
134 import EventEmployee from '../../../../../../public/EventForm/Common/Parts/EventEmployee.vue'
135
136 // * Parts
137 import EventTicket from '../EventTickets/parts/EventTicket.vue'
138 import GalleryCarousel from '../../../../../../public/EventForm/Common/Parts/GalleryCarousel.vue'
139
140 // * Dialogs
141 import EventBringingAnyone from './parts/EventBringingAnyone.vue'
142
143 // * Import from Vue
144 import { computed, inject, ref, reactive } from 'vue'
145 import moment from 'moment/moment'
146
147 // * Composables
148 import { useColorTransparency } from '../../../../../../../assets/js/common/colorManipulation'
149 import {
150 getEventFrontedFormattedTime,
151 getFrontedFormattedDate,
152 } from '../../../../../../../assets/js/common/date'
153 import { useResponsiveClass } from '../../../../../../../assets/js/common/responsive'
154 import { useReactiveCustomize } from '../../../../../../../assets/js/admin/useReactiveCustomize.js'
155
156 // * Components Properties
157 let props = defineProps({
158 globalClass: {
159 type: String,
160 default: '',
161 },
162 inDialog: {
163 type: Boolean,
164 default: false,
165 },
166 })
167
168 // * Plugin Licence
169 let licence = inject('licence')
170
171 // * Features
172 let features = inject('features')
173
174 let isWaiting = computed(() => {
175 return features.value.waitingList
176 })
177
178 // * Base Urls
179 const baseUrls = inject('baseUrls')
180
181 let selectedEvent = ref({
182 id: 3,
183 bookable: true,
184 color: '#1788FB',
185 opened: true,
186 full: !!isWaiting.value,
187 closed: false,
188 description:
189 "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
190 fullPayment: false,
191 gallery: [
192 {
193 pictureFullPath: `${baseUrls.value.wpAmeliaPluginURL}v3/src/assets/img/admin/customize/img_holder1.svg`,
194 },
195 {
196 pictureFullPath: `${baseUrls.value.wpAmeliaPluginURL}v3/src/assets/img/admin/customize/img_holder1.svg`,
197 },
198 {
199 pictureFullPath: `${baseUrls.value.wpAmeliaPluginURL}v3/src/assets/img/admin/customize/img_holder1.svg`,
200 },
201 {
202 pictureFullPath: `${baseUrls.value.wpAmeliaPluginURL}v3/src/assets/img/admin/customize/img_holder1.svg`,
203 },
204 {
205 pictureFullPath: `${baseUrls.value.wpAmeliaPluginURL}v3/src/assets/img/admin/customize/img_holder1.svg`,
206 },
207 ],
208 locationId: 1,
209 customPricing: true,
210 customTickets: [
211 {
212 enabled: true,
213 id: 1,
214 eventId: 1,
215 name: 'Ticket one',
216 price: 10,
217 sold: 0,
218 spots: 20,
219 },
220 {
221 enabled: true,
222 id: 2,
223 eventId: 1,
224 name: 'Ticket two',
225 price: 50,
226 sold: 0,
227 spots: 20,
228 },
229 {
230 enabled: true,
231 id: 2,
232 eventId: 1,
233 name: 'Ticket three',
234 price: 100,
235 sold: 0,
236 spots: 20,
237 },
238 ],
239 depositPerPerson: true,
240 depositPayment: 'percentage',
241 deposit: 10,
242 maxCapacity: 9,
243 maxCustomCapacity: null,
244 maxExtraPeople: 3,
245 name: 'Event 3',
246 organizerId: 1,
247 periods: [
248 {
249 id: 1,
250 eventId: 1,
251 periodStart: moment().add(2, 'days').add(5, 'hours').format('YYYY-MM-DD hh:mm:ss'),
252 periodEnd: moment().add(4, 'days').add(10, 'hours').format('YYYY-MM-DD hh:mm:ss'),
253 },
254 ],
255 pictureFullPath: null,
256 pictureThumbPath: null,
257 places: 30,
258 price: 10,
259 providers: [
260 {
261 id: 1,
262 firstName: 'Jane',
263 lastName: 'Doe',
264 description:
265 "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
266 },
267 {
268 id: 2,
269 firstName: 'Sahar',
270 lastName: 'Potter',
271 description:
272 "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
273 },
274 {
275 id: 3,
276 firstName: 'Miles',
277 lastName: 'Shannon',
278 description:
279 "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
280 },
281 ],
282 show: true,
283 status: 'approved',
284 tags: [{}],
285 })
286
287 // * Locations array
288 let locations = computed(() => {
289 if (licence.isLite) return []
290
291 return [
292 {
293 id: 1,
294 name: 'Location 1',
295 address: 'Location 1',
296 },
297 {
298 id: 2,
299 name: 'Location 2',
300 address: 'Location 2',
301 },
302 {
303 id: 3,
304 name: 'Location 3',
305 address: 'Location 3',
306 },
307 ]
308 })
309
310 // * Employees - limit to 1 for lite licence
311 let eventProviders = computed(() => {
312 if (licence.isLite) return selectedEvent.value.providers.slice(0, 1)
313 return selectedEvent.value.providers
314 })
315
316 // * Event Tickets
317 let tickets = ref([
318 {
319 id: 1,
320 eventTicketId: 1,
321 name: 'Ticket one',
322 persons: 0,
323 price: 10,
324 sold: 5,
325 spots: 10,
326 },
327 {
328 id: 2,
329 eventTicketId: 2,
330 name: 'Ticket two',
331 persons: 0,
332 price: 10,
333 sold: 1,
334 spots: 10,
335 },
336 {
337 id: 3,
338 eventTicketId: 3,
339 name: 'Ticket three',
340 persons: 0,
341 price: 10,
342 sold: 0,
343 spots: 10,
344 },
345 ])
346
347 const activeName = ref('first')
348
349 let selectedEventsPeriods = computed(() => {
350 let periodsArr = []
351 selectedEvent.value.periods.forEach(function (period) {
352 let periodStartDate = moment(period.periodStart.split(' ')[0], 'YYYY-MM-DD')
353 let periodEndDate = moment(period.periodEnd.split(' ')[0], 'YYYY-MM-DD')
354 let periodStartTime = moment(period.periodStart.split(' ')[1], 'HH:mm:ss').format('HH:mm:ss')
355 let periodEndTime = moment(period.periodEnd.split(' ')[1], 'HH:mm:ss').format('HH:mm:ss')
356
357 if (periodEndTime === '00:00:00') {
358 periodEndTime = '24:00:00'
359 periodEndDate.subtract(1, 'days')
360 }
361
362 /** if the period in the event lasts for several days */
363 if (periodStartDate.diff(periodEndDate, 'days') < 0) {
364 let periodDates = []
365
366 while (periodStartDate.isSameOrBefore(periodEndDate)) {
367 periodDates.push(periodStartDate.format('YYYY-MM-DD'))
368 periodStartDate.add(1, 'days')
369 }
370
371 periodDates.forEach((dayPeriod) => {
372 periodsArr.push({
373 id: period.id,
374 start: dayPeriod + ' ' + periodStartTime,
375 end: dayPeriod + ' ' + periodEndTime,
376 })
377 })
378 } else {
379 periodsArr.push({
380 id: period.id,
381 start: periodStartDate.format('YYYY-MM-DD') + ' ' + periodStartTime,
382 end: periodEndDate.format('YYYY-MM-DD') + ' ' + periodEndTime,
383 })
384 }
385 })
386
387 let periods = []
388 periodsArr
389 .sort((a, b) => moment(a.start, 'YYYY-MM-DD HH:mm:ss') - moment(b.start, 'YYYY-MM-DD HH:mm:ss'))
390 .forEach((item) => {
391 periods.push({
392 dateOfMonth: getFrontedFormattedDate(item.start.split(' ')[0]),
393 timeStart: getEventFrontedFormattedTime(item.start.split(' ')[1]),
394 timeEnd: getEventFrontedFormattedTime(item.end.split(' ')[1]),
395 })
396 })
397
398 return periods
399 })
400
401 let eventRange = computed(() => {
402 let rangeArr = []
403 let rangeObj = {}
404
405 selectedEvent.value.periods.forEach((item) => {
406 rangeArr.push(
407 moment(item.periodStart, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD'),
408 moment(item.periodEnd, 'YYYY-MM-DD HH:mm:ss').format('YYYY-MM-DD'),
409 )
410 })
411
412 rangeArr = rangeArr.sort()
413 rangeObj.start = getFrontedFormattedDate(rangeArr[0])
414 rangeObj.end = getFrontedFormattedDate(rangeArr[rangeArr.length - 1])
415
416 return rangeObj
417 })
418
419 let eventOrganizer = ref({
420 firstName: 'John',
421 lastName: 'Doe',
422 description:
423 "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
424 })
425
426 function noOneBringWith() {}
427
428 function bringPeopleWithYou() {}
429
430 // * Customize
431 let pageRenderKey = inject('pageRenderKey')
432 let stepName = inject('stepName')
433 let subStepName = useReactiveCustomize().subStepName
434
435 // * Bringing Anyone With You
436 let bringingAnyoneVisibility = computed(() => {
437 return subStepName.value === 'bringingAnyone'
438 })
439
440 const { amCustomize } = useReactiveCustomize()
441
442 // * Options
443 let customizeOptions = computed(() => {
444 return amCustomize.value[pageRenderKey.value].info.options
445 })
446
447 // * Labels
448 let langKey = inject('langKey')
449 let amLabels = inject('labels')
450
451 function labelsDisplay(label, stepKey = 'info') {
452 let computedLabel = computed(() => {
453 let translations = amCustomize.value[pageRenderKey.value][stepKey].translations
454 return translations && translations[label] && translations[label][langKey.value]
455 ? translations[label][langKey.value]
456 : amLabels[label]
457 })
458
459 return computedLabel.value
460 }
461
462 // * Computed labels
463 let customLabels = computed(() => {
464 let computedLabels = reactive({ ...amLabels })
465
466 if (amCustomize.value.elf.info.translations) {
467 let customizedLabels = amCustomize.value.elf.info.translations
468 Object.keys(customizedLabels).forEach((labelKey) => {
469 if (customizedLabels[labelKey][langKey.value]) {
470 computedLabels[labelKey] = customizedLabels[labelKey][langKey.value]
471 } else if (customizedLabels[labelKey].default) {
472 computedLabels[labelKey] = customizedLabels[labelKey].default
473 }
474 })
475 }
476 return computedLabels
477 })
478
479 // * Responsive
480 let cWidth = inject('containerWidth')
481 let responsiveClass = computed(() => {
482 return useResponsiveClass(cWidth.value)
483 })
484
485 // * Fonts
486 let amFonts = inject('amFonts')
487
488 // * Colors
489 let amColors = inject('amColors')
490
491 // * Css Vars
492 let cssVars = computed(() => {
493 return {
494 '--am-font-family': amFonts.value.fontFamily,
495 '--am-c-eli-primary': amColors.value.colorPrimary,
496 '--am-c-eli-bgr': amColors.value.colorMainBgr,
497 '--am-c-eli-text': amColors.value.colorMainText,
498 '--am-c-eli-text-op90': useColorTransparency(amColors.value.colorMainText, 0.9),
499 '--am-c-eli-text-op80': useColorTransparency(amColors.value.colorMainText, 0.8),
500 '--am-c-eli-text-op70': useColorTransparency(amColors.value.colorMainText, 0.7),
501 '--am-c-eli-text-op60': useColorTransparency(amColors.value.colorMainText, 0.7),
502 '--am-c-eli-text-op20': useColorTransparency(amColors.value.colorMainText, 0.1),
503 }
504 })
505 </script>
506
507 <script>
508 export default {
509 name: 'EventInfo',
510 key: 'info',
511 label: 'event_info',
512 }
513 </script>
514
515 <style lang="scss">
516 #amelia-app-backend-new #amelia-container {
517 // eli - event list info
518 .am-eli {
519 * {
520 font-family: var(--am-font-family), sans-serif;
521 letter-spacing: normal;
522 }
523
524 .am-eli {
525 &__image {
526 position: relative;
527 overflow: hidden;
528 margin: 8px 0 16px;
529 }
530
531 &__header {
532 display: flex;
533 flex-direction: row;
534 margin: 24px 0 0;
535
536 p {
537 margin-bottom: 0;
538 }
539 }
540
541 &__main {
542 padding-bottom: 16px;
543
544 &-item {
545 margin-bottom: 12px;
546 }
547
548 .el-tab {
549 &s {
550 &__nav {
551 &-wrap {
552 &:after {
553 background-color: var(--am-c-eli-text-op20);
554 }
555 }
556 }
557
558 &__item {
559 display: inline-flex;
560 align-items: center;
561 justify-content: center;
562 margin-right: 16px;
563 padding: 0;
564 font-size: 14px;
565 font-weight: 500;
566 line-height: 1.42857;
567 color: var(--am-c-eli-text-op90);
568
569 &:focus {
570 box-shadow: none;
571 }
572
573 &.is-active {
574 color: var(--am-c-eli-primary);
575 }
576 }
577
578 &__active-bar {
579 background-color: var(--am-c-eli-primary);
580 }
581
582 &__header {
583 margin: 0;
584 }
585
586 &__content {
587 padding: 12px 0;
588 }
589 }
590
591 &-pane {
592 padding: 0;
593 }
594 }
595 }
596
597 &__timetable {
598 &-title {
599 font-size: 14px;
600 font-weight: 500;
601 line-height: 1.42857;
602 color: var(--am-c-eli-text-op70);
603 margin: 0 0 8px;
604 }
605
606 &-range {
607 font-size: 14px;
608 font-weight: 500;
609 line-height: 1.42857;
610 color: var(--am-c-eli-text-op80);
611 border-bottom: 1px solid var(--am-c-eli-text-op20);
612 margin: 0 0 8px;
613 }
614
615 &-main {
616 margin: 0 0 2px;
617
618 & > * {
619 font-size: 14px;
620 line-height: 1.42857;
621 color: var(--am-c-eli-text-op80);
622 }
623
624 &__date {
625 font-weight: 500;
626 }
627
628 &__time {
629 font-weight: 400;
630 }
631 }
632 }
633 }
634
635 &__bringing {
636 &-footer {
637 display: flex;
638 align-items: center;
639 justify-content: flex-end;
640 width: 100%;
641 gap: 8px;
642
643 &.am-rw-500 {
644 flex-direction: column;
645
646 .am-button--secondary {
647 order: 2;
648 width: 100%;
649 }
650
651 .am-button--primary {
652 order: 1;
653 width: 100%;
654 }
655 }
656 }
657 }
658 }
659 }
660 </style>
661