PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
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 / pages / CustomizeEventList.vue
ameliabooking / v3 / src / views / admin / customize / pages Last commit date
CustomizeCatalog.vue 1 month ago CustomizeCustomerPanel.vue 1 month ago CustomizeEmployeePanel.vue 1 month ago CustomizeEventCalendar.vue 1 month ago CustomizeEventList.vue 1 month ago CustomizeStepNew.vue 1 month ago
CustomizeEventList.vue
443 lines
1 <template>
2 <div
3 v-if="isLoaded"
4 id="amelia-container"
5 ref="ameliaContainer"
6 class="am-elf"
7 :class="{ 'am-elf-dialog': stepsArray[stepIndex].key !== 'list' }"
8 :style="cssVars"
9 >
10 <component :is="stepsArray[stepIndex]" v-if="stepsArray[stepIndex].key === 'list'"></component>
11
12 <template v-if="stepsArray[stepIndex].key !== 'list'">
13 <div v-if="stepIndex > 1" class="am-dialog-el-header">
14 <EventListHeader :ready="true" :loading="false" :customized-labels="globalStepLabels()" />
15 </div>
16 <component
17 :is="stepsArray[stepIndex]"
18 :in-dialog="true"
19 global-class="am-dialog-el__main-container"
20 ></component>
21 <EventListFooter
22 v-if="stepsArray[stepIndex].key !== 'list'"
23 :customized-labels="globalStepLabels()"
24 :primary-footer-button-type="
25 isWaiting && stepsArray[stepIndex].name === 'EventInfo' ? waitingBtnType : primBtn
26 "
27 :secondary-footer-button-type="secBtn"
28 :second-button-show="!licence.isLite ? secBtnVisible : false"
29 :is-waiting-list="isWaiting"
30 />
31 </template>
32 </div>
33 </template>
34
35 <script setup>
36 // * import from Vue
37 import {
38 computed,
39 ref,
40 inject,
41 provide,
42 markRaw,
43 onBeforeMount,
44 watchEffect,
45 onMounted,
46 onUnmounted,
47 nextTick,
48 } from 'vue'
49
50 // * Components Width and Height
51 import { useElementSize } from '@vueuse/core'
52
53 // * Import composables
54 import { defaultCustomizeSettings } from '../../../../assets/js/common/defaultCustomize.js'
55 import { useColorTransparency } from '../../../../assets/js/common/colorManipulation'
56 import { useReactiveCustomize } from '../../../../assets/js/admin/useReactiveCustomize.js'
57
58 // * Form Construction
59 import EventListHeader from '../../../common/EventListFormConstruction/Header/Header.vue'
60 import EventListFooter from '../../../common/EventListFormConstruction/Footer/Footer.vue'
61
62 // * Step Components
63 import EventsList from '../steps/Events/EventList/EventsList.vue'
64 import EventInfo from '../steps/Events/common/EventInfo/EventInfo.vue'
65 import EventTickets from '../steps/Events/common/EventTickets/EventTickets.vue'
66 import EventCustomerInfo from '../steps/Events/common/EventCustomerInfo/EventCustomerInfo.vue'
67 import EventPayment from '../steps/Events/common/EventPayment/EventPayment.vue'
68 import EventCongratulations from '../steps/Events/common/Congratulations/EventCongratulations.vue'
69
70 // * Form Component Collection
71 const eventsList = markRaw(EventsList)
72 const eventInfo = markRaw(EventInfo)
73 const eventTickets = markRaw(EventTickets)
74 const eventCustomerInfo = markRaw(EventCustomerInfo)
75 const eventPayment = markRaw(EventPayment)
76 const eventCongratulations = markRaw(EventCongratulations)
77
78 // * Root Settings
79 let amSettings = inject('settings')
80
81 // * Plugin Licence
82 let licence = inject('licence')
83
84 // * Features
85 let features = useReactiveCustomize().features
86 provide('features', features)
87
88 // * Base Urls
89 const baseUrls = inject('baseUrls')
90
91 // * Step index
92 let stepIndex = useReactiveCustomize().stepIndex
93 provide('stepIndex', stepIndex)
94
95 // * Bookable Type
96 const bookableType = ref('event')
97 provide('bookableType', bookableType)
98
99 // * Language Key
100 let langKey = useReactiveCustomize().langKey
101 provide('langKey', langKey)
102
103 // * Page Render Key
104 let pageRenderKey = ref('elf')
105 provide('pageRenderKey', pageRenderKey)
106
107 // * Step Name
108 let stepName = useReactiveCustomize().stepName || 'list'
109 provide('stepName', stepName)
110
111 // * Customize Data
112 const { amCustomize } = useReactiveCustomize()
113 provide('customize', amCustomize)
114
115 // * is waiting
116 let isWaiting = computed(() => {
117 return features.value.waitingList
118 })
119
120 let amFonts = computed(() => {
121 return amCustomize.value.fonts
122 })
123 provide('amFonts', amFonts)
124
125 let primBtn = computed(() => {
126 if (
127 amCustomize.value[pageRenderKey.value][stepName.value] &&
128 'primBtn' in amCustomize.value[pageRenderKey.value][stepName.value].options
129 ) {
130 return amCustomize.value[pageRenderKey.value][stepName.value].options.primBtn.buttonType
131 }
132 return 'filled'
133 })
134
135 let secBtn = computed(() => {
136 if (
137 amCustomize.value[pageRenderKey.value][stepName.value] &&
138 'secBtn' in amCustomize.value[pageRenderKey.value][stepName.value].options
139 ) {
140 return amCustomize.value[pageRenderKey.value][stepName.value].options.secBtn.buttonType
141 }
142 return 'plain'
143 })
144
145 let secBtnVisible = computed(() => {
146 if (
147 amCustomize.value[pageRenderKey.value][stepName.value] &&
148 'secBtn' in amCustomize.value[pageRenderKey.value][stepName.value].options
149 ) {
150 return amCustomize.value[pageRenderKey.value][stepName.value].options.secBtn.visibility
151 }
152 return true
153 })
154
155 let waitingBtnType = computed(() => {
156 if (
157 amCustomize.value[pageRenderKey.value][stepName.value] &&
158 'waitingBtn' in amCustomize.value[pageRenderKey.value][stepName.value].options
159 ) {
160 return amCustomize.value[pageRenderKey.value][stepName.value].options.waitingBtn.buttonType
161 }
162 return 'filled'
163 })
164
165 let stepsArray = ref([
166 eventsList,
167 eventInfo,
168 eventTickets,
169 eventCustomerInfo,
170 eventPayment,
171 eventCongratulations,
172 ])
173 provide('stepsArray', stepsArray)
174
175 onMounted(() => {
176 if (!features.value.tickets) {
177 stepsArray.value = [
178 eventsList,
179 eventInfo,
180 eventCustomerInfo,
181 eventPayment,
182 eventCongratulations,
183 ]
184 }
185 })
186
187 // * Component reference
188 let ameliaContainer = ref(null)
189
190 let isLoaded = ref(false)
191
192 onMounted(() => {
193 window.customizeComponentLoaded = true
194
195 if (typeof window.stylesInjectedV3 === 'function') {
196 if (window.v3.componentToMount === 'CustomizeEventList') {
197 window.stylesInjectedV3 = () => {
198 nextTick().then(() => {
199 isLoaded.value = true
200 })
201 }
202 }
203 }
204 })
205
206 onUnmounted(() => {
207 window.customizeComponentLoaded = false
208 // Reset to no-op function
209 window.stylesInjectedV3 = async function () {}
210 })
211
212 // * Plugin wrapper width
213 const { width: containerWidth } = useElementSize(ameliaContainer)
214 provide('containerWidth', containerWidth)
215
216 watchEffect(() => {
217 if (amCustomize.value.fonts.customFontSelected) {
218 activateCustomFontStyles()
219 } else {
220 importDefaultFonts()
221 }
222 })
223
224 function activateCustomFontStyles() {
225 let head = document.head || document.getElementsByTagName('head')[0]
226 if (head.querySelector('#amCustomFont')) {
227 head.querySelector('#amCustomFont').remove()
228 }
229
230 if (head.querySelector('#amDefaultFontImport')) {
231 head.querySelector('#amDefaultFontImport').remove()
232 }
233
234 let css = `@font-face {font-family: '${amCustomize.value.fonts.fontFamily}'; src: url(${amCustomize.value.fonts.fontUrl});}`
235 let style = document.createElement('style')
236 head.appendChild(style)
237 style.setAttribute('type', 'text/css')
238 style.setAttribute('id', 'amCustomFont')
239 style.appendChild(document.createTextNode(css))
240 }
241
242 function importDefaultFonts() {
243 const head = document.head || document.getElementsByTagName('head')[0]
244 if (head.querySelector('#amDefaultFontImport')) {
245 return
246 }
247
248 const base = baseUrls.value.wpAmeliaPluginURL
249 const style = document.createElement('style')
250 style.setAttribute('type', 'text/css')
251 style.setAttribute('id', 'amDefaultFontImport')
252 style.textContent = `@import url("${base}v3/src/assets/scss/common/fonts/font.css");`
253 head.appendChild(style)
254 }
255
256 /**
257 * Lifecycle Hooks
258 */
259 onBeforeMount(() => {
260 window.scrollTo({
261 top: 0,
262 left: 0,
263 behavior: 'smooth',
264 })
265 })
266
267 function globalStepLabels() {
268 let stepLabels = {}
269 let customizedLabels = amCustomize.value[pageRenderKey.value][stepName.value].translations
270 if (customizedLabels && Object.keys(customizedLabels)) {
271 Object.keys(amCustomize.value[pageRenderKey.value][stepName.value].translations).forEach(
272 (label) => {
273 stepLabels[label] =
274 amCustomize.value[pageRenderKey.value][stepName.value].translations[label][langKey.value]
275 },
276 )
277 } else {
278 stepLabels = {}
279 }
280
281 return stepLabels
282 }
283
284 // * Colors
285 // * Customize colors
286 let amColors = computed(() => {
287 const colors = amCustomize.value[pageRenderKey.value]
288 ? amCustomize.value[pageRenderKey.value].colors
289 : defaultCustomizeSettings[pageRenderKey.value].colors
290
291 return { ...colors }
292 })
293
294 provide('amColors', amColors)
295 let cssVars = computed(() => {
296 return {
297 '--am-c-primary': amColors.value.colorPrimary,
298 '--am-c-success': amColors.value.colorSuccess,
299 '--am-c-error': amColors.value.colorError,
300 '--am-c-warning': amColors.value.colorWarning,
301 '--am-c-main-bgr': amColors.value.colorMainBgr,
302 '--am-c-main-heading-text': amColors.value.colorMainHeadingText,
303 '--am-c-main-text': amColors.value.colorMainText,
304 '--am-c-sb-bgr': amColors.value.colorSbBgr,
305 '--am-c-sb-text': amColors.value.colorSbText,
306 '--am-c-inp-bgr': amColors.value.colorInpBgr,
307 '--am-c-inp-border': amColors.value.colorInpBorder,
308 '--am-c-inp-text': amColors.value.colorInpText,
309 '--am-c-inp-placeholder': amColors.value.colorInpPlaceHolder,
310 '--am-c-drop-bgr': amColors.value.colorDropBgr,
311 '--am-c-drop-text': amColors.value.colorDropText,
312 '--am-c-card-bgr': amColors.value.colorCardBgr,
313 '--am-c-card-text': amColors.value.colorCardText,
314 '--am-c-card-border': amColors.value.colorCardBorder,
315 '--am-c-btn-prim': amColors.value.colorBtnPrim,
316 '--am-c-btn-prim-text': amColors.value.colorBtnPrimText,
317 '--am-c-btn-sec': amColors.value.colorBtnSec,
318 '--am-c-btn-sec-text': amColors.value.colorBtnSecText,
319 '--am-c-skeleton-op20': useColorTransparency(amColors.value.colorMainText, 0.2),
320 '--am-c-skeleton-op60': useColorTransparency(amColors.value.colorMainText, 0.6),
321 '--am-font-family': amFonts.value.fontFamily,
322
323 // -mw- max width
324 '--am-mw-main': '792px',
325 '--am-hd-main': stepIndex.value > 0 ? '592px' : '652px',
326 '--am-c-scroll-op30': useColorTransparency(amColors.value.colorPrimary, 0.3),
327 '--am-c-scroll-op10': useColorTransparency(amColors.value.colorPrimary, 0.1),
328
329 '--am-rad-inp': '6px',
330
331 '--am-mb-dialog': '300px',
332 }
333 })
334 </script>
335
336 <script>
337 export default {
338 name: 'CustomizeEventList',
339 }
340 </script>
341
342 <style lang="scss">
343 :root {
344 // Colors
345 // shortcuts
346 // -c- color
347 // -bgr- background
348 // -prim- primary
349 // -sec- secondary
350 // primitive colors
351 --am-c-primary: #{$blue-1000};
352 --am-c-success: #{$green-1000};
353 --am-c-error: #{$red-900};
354 --am-c-warning: #{$yellow-1000};
355 // main container colors - right part of the form
356 --am-c-main-bgr: #{$am-white};
357 --am-c-main-heading-text: #{$shade-800};
358 --am-c-main-text: #{$shade-900};
359 // sidebar container colors - left part of the form
360 --am-c-sb-bgr: #17295a;
361 --am-c-sb-text: #{$am-white};
362 // input global colors - usage input, textarea, checkbox, radio button, select input, adv select input
363 --am-c-inp-bgr: #{$am-white};
364 --am-c-inp-border: #{$shade-250};
365 --am-c-inp-text: #{$shade-900};
366 --am-c-inp-placeholder: #{$shade-500};
367 // dropdown global colors - usage select dropdown, adv select dropdown
368 --am-c-drop-bgr: #{$am-white};
369 --am-c-drop-text: #{$shade-1000};
370 // button global colors
371 --am-c-btn-prim: #{$blue-900};
372 --am-c-btn-prim-text: #{$am-white};
373 --am-c-btn-sec: #{$am-white};
374 --am-c-btn-sec-text: #{$shade-900};
375
376 // Properties
377 // shortcuts
378 // -h- height
379 // -fs- font size
380 // -rad- border radius
381 --am-h-inp: 40px;
382 --am-fs-inp: 15px;
383 --am-rad-inp: 6px;
384 --am-fs-label: 15px;
385 --am-fs-btn: 15px;
386
387 // Font
388 --am-font-family: 'Amelia Roboto', sans-serif;
389 }
390
391 #amelia-app-backend-new #amelia-container {
392 * {
393 font-family: var(--am-font-family);
394 font-style: initial;
395 box-sizing: border-box;
396 word-break: break-word;
397 letter-spacing: normal;
398 }
399
400 // am - amelia
401 // elf - events list form
402 &.am-elf {
403 margin: 24px auto 0;
404 max-width: var(--am-mw-main);
405 background-color: var(--am-c-main-bgr);
406 padding: 16px;
407 border-radius: 12px;
408
409 &.am-elf-dialog {
410 max-width: 650px;
411 padding: 0;
412 border-radius: 8px;
413 position: relative;
414 }
415 }
416
417 .am-dialog-el {
418 &__main {
419 &-container {
420 height: var(--am-hd-main);
421 display: block;
422 overflow-x: hidden;
423 padding: 16px 24px 0;
424
425 &::-webkit-scrollbar {
426 width: 6px;
427 }
428
429 &::-webkit-scrollbar-thumb {
430 border-radius: 6px;
431 background: var(--am-c-scroll-op30);
432 }
433
434 &::-webkit-scrollbar-track {
435 border-radius: 6px;
436 background: var(--am-c-scroll-op10);
437 }
438 }
439 }
440 }
441 }
442 </style>
443