PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.4
Booking for Appointments and Events Calendar – Amelia v2.4.4
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 / StepForm / RecurringSummary.vue
ameliabooking / v3 / src / views / admin / customize / steps / StepForm Last commit date
common 5 days ago BringingAnyone.vue 5 days ago CartStep.vue 5 days ago Congratulations.vue 5 days ago DateTimeStep.vue 5 days ago EmployeeStep.vue 5 days ago Extras.vue 5 days ago InfoStep.vue 5 days ago InitStep.vue 5 days ago LocationStep.vue 5 days ago PackageAppointmentsListStep.vue 5 days ago PackageAppointmentsStep.vue 5 days ago PackageInfoStep.vue 5 days ago PackageStep.vue 5 days ago PaymentStep.vue 5 days ago RecurringStep.vue 5 days ago RecurringSummary.vue 5 days ago ServiceStep.vue 5 days ago
RecurringSummary.vue
420 lines
1 <template>
2 <div class="am-fs__ro" :class="props.globalClass" :style="cssVars">
3 <div class="am-fs__ro-warning">
4 <AmAlert
5 type="warning"
6 :title="labelsDisplay('recurring_unavailable_slots')"
7 :description="`2 ${labelsDisplay('recurring_alert_content')}`"
8 :show-icon="true"
9 :closable="false"
10 ></AmAlert>
11 </div>
12 <AmCollapse>
13 <AmCollapseItem
14 v-for="(appointment, index) in serviceSelection.list"
15 :ref="(el) => (recurringList[index] = el)"
16 :key="index"
17 :name="index.toString()"
18 class="am-fs__ro-app-items"
19 :class="{ 'am-fs__ro-app-unavailable': appointment.isSubstitute }"
20 :side="true"
21 :delay="500"
22 :collapsable="false"
23 >
24 <template #heading>
25 <div class="am-fs__ro-app-heading">
26 <span>
27 {{
28 index +
29 1 +
30 '. ' +
31 (appointment.date && appointment.time
32 ? appointment.date + ' ' + appointment.time
33 : labelsDisplay('recurring_chose_date'))
34 }}
35 </span>
36 </div>
37 </template>
38
39 <template #icon-end>
40 <SideMenu :cancel-label="labelsDisplay('recurring_delete')"></SideMenu>
41 </template>
42
43 <template #default>
44 <div class="am-fs__ro-app-content">
45 <AmAdvancedSlotCalendar
46 v-if="showCalendar"
47 :id="0"
48 :slots="calendarEvents"
49 :calendar-minimum-date="moment().format('YYYY-MM-DD hh:mm')"
50 :calendar-maximum-date="moment().add(1, 'year').format('YYYY-MM-DD hh:mm')"
51 :time-zone="
52 features.timeZones &&
53 amCustomize[pageRenderKey].recurringSummary.options.timeZoneVisibility.visibility
54 "
55 :show-estimated-pricing="
56 amCustomize[pageRenderKey].recurringSummary.options.estimatedPricingVisibility
57 .visibility
58 "
59 :show-indicator-pricing="
60 amCustomize[pageRenderKey].recurringSummary.options.indicatorPricingVisibility
61 .visibility
62 "
63 :show-slot-pricing="
64 amCustomize[pageRenderKey].recurringSummary.options.slotPricingVisibility.visibility
65 "
66 :show-people-waiting="false"
67 :show-calendar-date-busyness="
68 amCustomize[pageRenderKey].recurringSummary.options.calendarDateBusynessVisibility
69 ?.visibility ?? true
70 "
71 :label-slots-selected="labelsDisplay('recurring_slots_selected')"
72 :period-pricing="periodPricing"
73 :busyness="previewCalendarBusyness"
74 ></AmAdvancedSlotCalendar>
75 </div>
76 </template>
77 </AmCollapseItem>
78 </AmCollapse>
79 </div>
80 </template>
81
82 <script setup>
83 import { computed, inject, provide, ref, onMounted } from 'vue'
84 import moment from 'moment'
85 import AmAlert from '../../../../_components/alert/AmAlert'
86 import AmCollapse from '../../../../_components/collapse/AmCollapse'
87 import AmCollapseItem from '../../../../_components/collapse/AmCollapseItem'
88 import SideMenu from '../../../../public/StepForm/RecurringStep/parts/SideMenu.vue'
89 import AmAdvancedSlotCalendar from '../../../../_components/advanced-slot-calendar/AmAdvancedSlotCalendar.vue'
90 import { useColorTransparency } from '../../../../../assets/js/common/colorManipulation'
91 import { useReactiveCustomize } from '../../../../../assets/js/admin/useReactiveCustomize.js'
92
93 let props = defineProps({
94 globalClass: {
95 type: String,
96 default: '',
97 },
98 })
99
100 // Container Width
101 let cWidth = inject('containerWidth', 0)
102
103 // * Plugin Licence
104 let licence = inject('licence')
105
106 // * Features
107 let features = inject('features')
108
109 // * Languages
110 let langKey = inject('langKey')
111
112 // * Global Labels
113 let amLabels = inject('labels')
114
115 let pageRenderKey = inject('pageRenderKey')
116 const { amCustomize } = useReactiveCustomize()
117
118 let previewCalendarBusyness = computed(() => {
119 const opts = amCustomize.value[pageRenderKey.value].recurringSummary.options
120 if (!(opts.calendarDateBusynessVisibility?.visibility ?? true)) {
121 return {}
122 }
123 const base = moment().startOf('day')
124 return {
125 [base.clone().add(6, 'days').format('YYYY-MM-DD')]: 40,
126 [base.clone().add(20, 'days').format('YYYY-MM-DD')]: 82,
127 }
128 })
129
130 // * Label computed function
131 function labelsDisplay(label) {
132 let computedLabel = computed(() => {
133 return amCustomize.value[pageRenderKey.value].recurringSummary.translations &&
134 amCustomize.value[pageRenderKey.value].recurringSummary.translations[label] &&
135 amCustomize.value[pageRenderKey.value].recurringSummary.translations[label][langKey.value]
136 ? amCustomize.value[pageRenderKey.value].recurringSummary.translations[label][langKey.value]
137 : amLabels[label]
138 })
139
140 return computedLabel.value
141 }
142
143 let serviceSelection = ref({
144 list: [
145 { date: moment().format('YYYY-MM-DD'), time: '13:05' },
146 {
147 date: moment().add(3, 'days').format('YYYY-MM-DD'),
148 time: '13:05',
149 isSubstitute: false,
150 },
151 { date: '', time: '', isSubstitute: true },
152 {
153 date: moment().add(9, 'days').format('YYYY-MM-DD'),
154 time: '13:05',
155 isSubstitute: true,
156 },
157 ],
158 })
159
160 /*****************
161 * Calendar Data *
162 ****************/
163 let showCalendar = ref(false)
164
165 let periodPricing = ref({})
166
167 function getCustomPeriodsPricing() {
168 let result = {}
169 let today = moment()
170
171 let current = today.clone()
172
173 for (let i = 0; i <= 31; i++) {
174 let type =
175 current.day() === 6 || current.day() === 0
176 ? 'high'
177 : current.day() === 1 || current.day() === 2
178 ? 'low'
179 : 'mid'
180
181 result[current.format('YYYY-MM-DD')] = {
182 type: type,
183 slots: {
184 '09:00': {
185 type: type === 'mid' ? 'low' : type,
186 price: type === 'mid' ? 5 : type === 'low' ? 5 : 15,
187 },
188 '09:30': {
189 type: type === 'mid' ? 'low' : type,
190 price: type === 'mid' ? 5 : type === 'low' ? 5 : 15,
191 },
192 '10:00': {
193 type: type,
194 price: type === 'mid' ? 10 : type === 'low' ? 5 : 15,
195 },
196 '10:30': {
197 type: type,
198 price: type === 'mid' ? 10 : type === 'low' ? 5 : 15,
199 },
200 '11:00': {
201 type: type,
202 price: type === 'mid' ? 10 : type === 'low' ? 5 : 15,
203 },
204 '11:30': {
205 type: type,
206 price: type === 'mid' ? 10 : type === 'low' ? 5 : 15,
207 },
208 '12:00': {
209 type: type === 'mid' ? 'high' : type,
210 price: type === 'mid' ? 15 : type === 'high' ? 15 : 5,
211 },
212 '12:30': {
213 type: type === 'mid' ? 'high' : type,
214 price: type === 'mid' ? 15 : type === 'high' ? 15 : 5,
215 },
216 },
217 }
218
219 current.add(1, 'day')
220 }
221
222 return {
223 price: {
224 low: 5,
225 mid: 10,
226 high: 15,
227 uniqueMin: true,
228 uniqueMid: true,
229 uniqueMax: true,
230 },
231 dates: result,
232 }
233 }
234
235 let calendarEvents = ref([])
236
237 let calendarEventDate = ref('')
238
239 let calendarServiceDuration = ref('0')
240
241 let today = moment().format('YYYY-MM-DD')
242
243 for (let i = 0; i <= 31; i++) {
244 let block = {
245 display: 'background',
246 extendedProps: {
247 slots: { '09:00': [7, 3] },
248 slotsAvailable: 1,
249 slotsTotal: 100,
250 },
251 start: moment(today).add(i, 'd').format('YYYY-MM-DD'),
252 title: 'e',
253 }
254 calendarEvents.value.push(block)
255 }
256
257 let calendarEventSlots = ref([])
258 let calendarEventSlot = ref('')
259 let calendarStartDate = ref(moment().format('YYYY-MM-DD'))
260 let calendarChangeSideBar = ref(true)
261 let calendarWaitingListSlots = ref([])
262 provide('calendarEvents', calendarEvents)
263 provide('calendarEventDate', calendarEventDate)
264 provide('calendarEventSlots', calendarEventSlots)
265 provide('calendarEventSlot', calendarEventSlot)
266 provide('calendarStartDate', calendarStartDate)
267 provide('calendarChangeSideBar', calendarChangeSideBar)
268 provide('calendarServiceDuration', calendarServiceDuration)
269 provide('calendarWaitingListSlots', calendarWaitingListSlots)
270
271 /*********
272 * Other *
273 ********/
274 let calendarSlotDuration = 3600
275
276 provide('calendarSlotDuration', calendarSlotDuration)
277
278 let recurringList = ref([])
279
280 onMounted(() => {
281 periodPricing.value =
282 !licence.isBasic && !licence.isStarter && !licence.isLite ? getCustomPeriodsPricing() : {}
283
284 showCalendar.value = true
285
286 recurringList.value[0].contentVisibility = true
287 })
288
289 let amColors = inject('amColors')
290
291 let cssVars = computed(() => {
292 return {
293 '--am-c-ro-warning-op10': useColorTransparency(amColors.value.colorWarning, 0.1),
294 '--am-c-ro-warning-op60': useColorTransparency(amColors.value.colorWarning, 0.6),
295 }
296 })
297 </script>
298
299 <script>
300 export default {
301 name: 'RecurringSummary',
302 key: 'recurringSummary',
303 sidebarData: {
304 label: 'recurring_summary',
305 icon: 'calendar-pencil',
306 stepSelectedData: [],
307 finished: false,
308 selected: false,
309 },
310 }
311 </script>
312
313 <style lang="scss">
314 #amelia-app-backend-new {
315 #amelia-container {
316 // ro - recurring overview
317 .am-fs__ro {
318 --am-c-ro-text: var(--am-c-main-text);
319 --am-c-ro-success: var(--am-c-success);
320
321 &-warning {
322 .am-alert {
323 i {
324 font-size: 20px;
325 }
326 margin-bottom: 16px;
327 }
328 }
329
330 .am-collapse-item {
331 &__heading {
332 transition-delay: 0.5s;
333
334 &-side {
335 transition-delay: 0s;
336 }
337 }
338 }
339
340 &-app {
341 &-unavailable {
342 .am-collapse-item__heading {
343 /* $yellow-300 */
344 background-color: var(--am-c-ro-warning-op10);
345 /* $yellow-600 */
346 border: 1px solid var(--am-c-ro-warning-op60);
347 &-active {
348 border-bottom: 0;
349 }
350 }
351 .am-collapse-item__content {
352 /* $yellow-300 */
353 background-color: var(--am-c-ro-warning-op10);
354 /* $yellow-600 */
355 border: 1px solid var(--am-c-ro-warning-op60);
356 }
357 }
358
359 &-items {
360 .am-collapse-item__content {
361 display: block;
362 }
363 .am-collapse-item__trigger {
364 padding: 0;
365 }
366 }
367
368 &-heading {
369 display: flex;
370 justify-content: space-between;
371 width: 100%;
372 font-size: 14px;
373 font-weight: 400;
374 line-height: 1.42857;
375 /* $shade-900 */
376 color: var(--am-c-ro-text);
377 margin: 0 20px 0 0;
378 }
379
380 &-text {
381 font-weight: 500;
382 font-size: 14px;
383 line-height: 20px;
384 /* $shade-900 */
385 color: var(--am-c-ro-text);
386 &-selected {
387 /* $green-900 */
388 color: var(--am-c-ro-success);
389 }
390 margin-right: 10px;
391 white-space: nowrap;
392 }
393 }
394 }
395
396 // Amelia Form Steps
397 .am-fs {
398 // Container Wrapper
399 &__main {
400 &-heading {
401 &-inner {
402 display: flex;
403 align-items: center;
404
405 .am-heading-prev {
406 margin-right: 12px;
407 }
408 }
409 }
410 &-inner {
411 &#{&}-dt {
412 padding: 0 20px;
413 }
414 }
415 }
416 }
417 }
418 }
419 </style>
420