PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.2.0
LatePoint – Calendar Booking Plugin for Appointments and Events v5.2.0
5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / assets / javascripts / bin / front / main.js
latepoint / lib / assets / javascripts / bin / front Last commit date
_customer.js 1 year ago _events.js 1 year ago _stripe_connect.js 1 year ago main.js 9 months ago
main.js
2227 lines
1 /*
2 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
3 */
4
5
6 function latepoint_init_order_summary_lightbox() {
7 let $lightbox = jQuery('.customer-dashboard-order-summary-lightbox');
8 latepoint_init_qr_trigger($lightbox);
9 latepoint_init_item_details_popup($lightbox);
10 }
11
12 function latepoint_init_qr_trigger($lightbox) {
13 $lightbox.on('click', '.qr-show-trigger', function () {
14 jQuery(this).closest('.summary-box-wrapper').find('.qr-code-on-full-summary').toggleClass('show-vevent-qr-code');
15 return false;
16 });
17 }
18
19 function latepoint_init_item_details_popup($lightbox) {
20
21 $lightbox.on('click', '.os-item-details-popup-close', function () {
22 var $ligthbox = jQuery(this).closest('.latepoint-lightbox-content');
23 $ligthbox.find('.os-item-details-popup.open').remove();
24 $ligthbox.find('.full-summary-wrapper').show();
25 $ligthbox.find('.booking-status-info-wrapper').show();
26 return false;
27 });
28
29 $lightbox.on('click', '.os-trigger-item-details-popup', function () {
30 var $ligthbox = jQuery(this).closest('.latepoint-lightbox-content');
31 $ligthbox.find('.full-summary-wrapper').hide();
32 $ligthbox.find('.booking-status-info-wrapper').hide();
33 $ligthbox.find('.os-item-details-popup.open').remove();
34 var $popup = $ligthbox.find('#' + jQuery(this).data('item-details-popup-id')).clone();
35 $popup.addClass('open').appendTo($ligthbox);
36 return false;
37 });
38 }
39
40 function latepoint_init_bundle_scheduling_summary() {
41
42 }
43
44
45 function latepoint_manage_by_key_reload_booking() {
46 let $wrapper = jQuery('.manage-booking-wrapper');
47 $wrapper.addClass('os-loading')
48 let params = {
49 key: $wrapper.data('key')
50 }
51 let data = {
52 action: latepoint_helper.route_action,
53 route_name: $wrapper.data('route-name'),
54 params: params,
55 layout: 'none',
56 return_format: 'json'
57 };
58
59 jQuery.ajax({
60 type: "post",
61 dataType: "json",
62 url: latepoint_timestamped_ajaxurl(),
63 data: data,
64 success: function (data) {
65 $wrapper.removeClass('os-loading')
66 if (data.status === "success") {
67 $wrapper.replaceWith(data.message);
68 } else {
69 latepoint_show_message_inside_element(data.message, $wrapper, 'error');
70 }
71 }
72 });
73 }
74
75 function latepoint_init_manage_booking_by_key() {
76 let $wrapper = jQuery('.manage-booking-wrapper');
77 if (!$wrapper.length) return;
78 jQuery('.latepoint-w').on('change', '.change-booking-status-trigger', function () {
79 $wrapper.addClass('os-loading')
80 let params = {
81 key: $wrapper.data('key'),
82 status: jQuery(this).val()
83 }
84 let data = {
85 action: latepoint_helper.route_action,
86 route_name: jQuery(this).closest('.change-booking-status-trigger-wrapper').data('route-name'),
87 params: params,
88 layout: 'none',
89 return_format: 'json'
90 };
91
92 jQuery.ajax({
93 type: "post",
94 dataType: "json",
95 url: latepoint_timestamped_ajaxurl(),
96 data: data,
97 success: function (data) {
98 $wrapper.removeClass('os-loading')
99 if (data.status === "success") {
100 latepoint_manage_by_key_reload_booking();
101 } else {
102 latepoint_show_message_inside_element(data.message, $wrapper, 'error');
103 }
104 }
105 });
106 return false;
107 });
108
109
110 $wrapper.on('click', '.qr-show-trigger', function () {
111 jQuery(this).closest('.manage-booking-wrapper').find('.qr-code-on-full-summary').addClass('show-vevent-qr-code');
112 return false;
113 });
114 $wrapper.on('click', '.os-item-details-popup-close', function () {
115 var $wrapper = jQuery(this).closest('.manage-booking-wrapper');
116 $wrapper.find('.os-item-details-popup.open').remove();
117 $wrapper.find('.manage-booking-inner, .manage-booking-controls').show();
118 return false;
119 });
120
121 $wrapper.on('click', '.os-trigger-item-details-popup', function () {
122 var $wrapper = jQuery(this).closest('.manage-booking-wrapper');
123 $wrapper.find('.manage-booking-inner, .manage-booking-controls').hide();
124 $wrapper.find('.os-item-details-popup.open').remove();
125 var $popup = $wrapper.find('#' + jQuery(this).data('item-details-popup-id')).clone();
126 $popup.addClass('open').appendTo($wrapper);
127 return false;
128 });
129 }
130
131 function latepoint_init_form_masks() {
132 if (('lp_intlTelInput' in window) && ('lp_intlTelInputGlobals' in window)) {
133 jQuery('.os-mask-phone').each(function () {
134 latepoint_mask_phone(jQuery(this));
135 });
136 }
137 }
138
139 function latepoint_scroll_to_top_of_booking_form($booking_form_element) {
140 // if it's a form shortcode (not lightbox), scroll to top of the form
141 if ($booking_form_element.parent().hasClass('latepoint-inline-form')) {
142 $booking_form_element[0].scrollIntoView({block: "nearest", behavior: 'smooth'}); // SHOULD NOT BE FIRST!! Also need to FIX, scroll only if TOP of the booking form is above the viewport
143 }
144 // if lightbox - scroll body of lightbox to top
145 if ($booking_form_element.parent().hasClass('latepoint-lightbox-i')) {
146 $booking_form_element.find('.latepoint-body').scrollTop(0);
147 }
148 }
149
150 async function latepoint_init_payment_method_actions($booking_form_element, payment_method) {
151 let callbacks_list = [];
152 let is_last_step = $booking_form_element.data('next-submit-is-last') == 'yes';
153 $booking_form_element.trigger('latepoint:initPaymentMethod', [{
154 payment_method: payment_method,
155 callbacks_list: callbacks_list,
156 is_last_step: is_last_step
157 }]);
158 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
159
160
161 try {
162 for (const callback of callbacks_list) {
163 await callback.action();
164 }
165 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded').find('.lp-payment-method-content[data-payment-method="' + payment_method + '"]').show();
166 } catch (error) {
167 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
168 }
169 }
170
171 function latepoint_lightbox_close() {
172 jQuery('body').removeClass('latepoint-lightbox-active');
173 jQuery('.latepoint-lightbox-w').remove();
174 }
175
176 function latepoint_show_next_btn($booking_form_element) {
177 $booking_form_element.find('.latepoint-next-btn').removeClass('disabled');
178 $booking_form_element.removeClass('hidden-buttons');
179 }
180
181 function latepoint_clear_step_services($booking_form_element) {
182 }
183
184 function latepoint_clear_step_service_extras($booking_form_element) {
185 }
186
187 function latepoint_clear_step_locations($booking_form_element) {
188 }
189
190 function latepoint_clear_step_agents($booking_form_element) {
191 }
192
193 function latepoint_clear_step_datepicker($booking_form_element) {
194 }
195
196 function latepoint_hide_next_btn($booking_form_element) {
197 $booking_form_element.find('.latepoint-next-btn').addClass('disabled');
198 if ($booking_form_element.find('.latepoint-prev-btn.disabled').length) $booking_form_element.addClass('hidden-buttons');
199 }
200
201
202 function latepoint_show_prev_btn($booking_form_element) {
203 $booking_form_element.find('.latepoint-prev-btn').removeClass('disabled');
204 $booking_form_element.removeClass('hidden-buttons');
205 }
206
207 function latepoint_hide_prev_btn($booking_form_element) {
208 $booking_form_element.find('.latepoint-prev-btn').addClass('disabled');
209 if ($booking_form_element.find('.latepoint-next-btn.disabled').length) $booking_form_element.addClass('hidden-buttons');
210 }
211
212
213 function latepoint_remove_cart_item($trigger) {
214 let $booking_form_element = $trigger.closest('.latepoint-booking-form-element');
215 let cart_item_id = $trigger.data('cart-item-id');
216
217
218 $trigger.addClass('os-loading');
219 let data = {
220 action: latepoint_helper.route_action,
221 route_name: $trigger.data('route'),
222 params: jQuery.param({cart_item_id: cart_item_id}),
223 layout: 'none',
224 return_format: 'json'
225 }
226 jQuery.ajax({
227 type: "post",
228 dataType: "json",
229 url: latepoint_timestamped_ajaxurl(),
230 data: data,
231 success: function (data) {
232 if (data.status === "success") {
233 if (cart_item_id != $booking_form_element.find('input[name="active_cart_item[id]"]').val()) {
234 // cart has other items - just reload the summary/step
235 if ($trigger.closest('.latepoint-summary-w').length) {
236 // removed by clicking on summary side panel
237 latepoint_reload_summary($booking_form_element);
238 } else {
239 // remove by clicking on cart item on verify step
240 latepoint_reload_step($booking_form_element);
241 }
242 } else {
243 // this was a last item, need to go back to the start of a booking process
244 latepoint_restart_booking_process($booking_form_element);
245 }
246 } else {
247 $trigger.removeClass('os-loading');
248 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'error');
249 }
250 }
251 });
252 }
253
254 function latepoint_apply_coupon($elem) {
255 var $booking_form_element = $elem.closest('.latepoint-booking-form-element');
256
257 var $coupon_input = $elem;
258 $coupon_input.closest('.coupon-code-input-w').addClass('os-loading');
259 var form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
260 var data = {
261 action: latepoint_helper.route_action,
262 route_name: $elem.data('route'),
263 params: latepoint_formdata_to_url_encoded_string(form_data),
264 layout: 'none',
265 return_format: 'json'
266 }
267 jQuery.ajax({
268 type: "post",
269 dataType: "json",
270 url: latepoint_timestamped_ajaxurl(),
271 data: data,
272 success: function (data) {
273 $coupon_input.closest('.coupon-code-input-w').removeClass('os-loading');
274 if (data.status === "success") {
275 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'success');
276 $booking_form_element.find('.step-payment-w input[name="cart[payment_method]"]').val('');
277 $booking_form_element.find('input[name="cart[payment_token]"]').val('');
278 $booking_form_element.find('input[name="cart[payment_portion]"]').val('');
279 latepoint_reload_step($booking_form_element);
280 } else {
281 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'error');
282 }
283 }
284 });
285 }
286
287 function latepoint_remove_coupon($elem) {
288 $elem.closest('.applied-coupon-code-wrapper').fadeOut();
289 var $booking_form_element = $elem.closest('.latepoint-booking-form-element');
290 let $coupon_input = $booking_form_element.find('input[name="coupon_code"]');
291 $coupon_input.val('');
292 latepoint_apply_coupon($coupon_input);
293 }
294
295 function latepoint_restart_booking_process($booking_form_element) {
296 // first first step
297 let first_step_code = $booking_form_element.find('.latepoint-step-content').first().data('step-code');
298 latepoint_reload_step($booking_form_element, first_step_code);
299 return false;
300 }
301
302 function latepoint_reload_step($booking_form_element, step_code = false) {
303
304 if (step_code) {
305 $booking_form_element.find('.latepoint_current_step_code').val(step_code);
306 $booking_form_element.removeClass(function (index, className) {
307 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
308 }).addClass('current-step-' + step_code);
309 if ($booking_form_element.find('.latepoint-step-content[data-step-code="' + step_code + '"]')) {
310 $booking_form_element.find('.latepoint-step-content[data-step-code="' + step_code + '"]').nextAll('.latepoint-step-content').remove();
311 $booking_form_element.find('.latepoint-step-content[data-step-code="' + step_code + '"]').remove();
312 }
313 }
314
315 $booking_form_element.data('next-submit-is-last', 'no');
316 $booking_form_element.find('.latepoint_step_direction').val('specific');
317 latepoint_submit_booking_form($booking_form_element.find('.latepoint-form'));
318
319 return false;
320 }
321
322
323 function latepoint_reset_password_from_booking_init() {
324 jQuery('.os-step-existing-customer-login-w').hide();
325 jQuery('.os-password-reset-form-holder').on('click', '.password-reset-back-to-login', function () {
326 jQuery('.os-password-reset-form-holder').html('');
327 jQuery('.os-step-existing-customer-login-w').show();
328 return false;
329 });
330 }
331
332 function latepoint_bundle_selected($item) {
333 let $booking_form_element = $item.closest('.latepoint-booking-form-element');
334 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('bundle');
335 $booking_form_element.find('input[name="booking[service_id]"]').val('');
336 }
337
338 function latepoint_service_selected($item) {
339 let $booking_form_element = $item.closest('.latepoint-booking-form-element');
340 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('booking');
341 }
342
343 async function latepoint_reload_summary($booking_form_element) {
344 let $summary_panel = $booking_form_element.closest('.latepoint-with-summary');
345 if (!$summary_panel.length) return;
346
347 if ($booking_form_element.hasClass('is-bundle-scheduling')) {
348 return;
349 }
350
351 let current_step = $booking_form_element.find('.latepoint_current_step_code').val();
352
353 $booking_form_element.find('.latepoint-summary-w').addClass('os-loading');
354 let $booking_form = $booking_form_element.find('.latepoint-form');
355 let form_data = new FormData($booking_form[0]);
356 let data = {
357 action: latepoint_helper.route_action,
358 route_name: latepoint_helper.reload_booking_form_summary_route,
359 params: latepoint_formdata_to_url_encoded_string(form_data),
360 layout: 'none',
361 return_format: 'json'
362 }
363
364 let response = await jQuery.ajax({
365 type: "post",
366 dataType: "json",
367 url: latepoint_timestamped_ajaxurl(),
368 data: data
369 });
370 if (response.status === 'success') {
371 $booking_form_element.find('.os-summary-contents').html(response.message);
372 $booking_form_element.find('.latepoint-summary-w').removeClass('os-loading');
373 // hide on verify and confirmation steps
374 if (current_step && !['verify', 'confirmation'].includes(current_step) && response.message) {
375 $summary_panel.addClass('latepoint-summary-is-open');
376 } else {
377 $summary_panel.removeClass('latepoint-summary-is-open');
378 }
379 latepoint_init_booking_summary_panel($booking_form_element);
380 } else {
381 throw new Error(response.message ? response.message : 'Error reloading summary');
382 }
383 }
384
385 function latepoint_init_booking_summary_panel($booking_form_element) {
386 let $summary_panel = $booking_form_element.find('.latepoint-summary-w');
387 if (!$summary_panel.length) return;
388
389 $summary_panel.find('.load-customer-step-trigger').on('click', function () {
390 jQuery(this).addClass('os-loading');
391 latepoint_reload_step($booking_form_element, 'customer');
392 return false;
393 });
394
395 $summary_panel.find('.price-breakdown-unfold').on('click', function () {
396 jQuery(this).closest('.summary-price-breakdown-wrapper').removeClass('compact-summary');
397 return false;
398 });
399
400 $summary_panel.find('.os-remove-item-from-cart').on('click keydown', function (event) {
401 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
402 latepoint_remove_cart_item(jQuery(this));
403 return false;
404 });
405 }
406
407 function latepoint_password_changed_show_login(response) {
408 jQuery('.os-step-existing-customer-login-w').show();
409 jQuery('.os-password-reset-form-holder').html('');
410 latepoint_show_message_inside_element(response.message, jQuery('.os-step-existing-customer-login-w'), 'success');
411 }
412
413 function latepoint_hide_message_inside_element($elem = jQuery('.latepoint-body')) {
414 if ($elem.length && $elem.find('.latepoint-message').length) {
415 $elem.find('.latepoint-message').remove();
416 }
417 }
418
419 function latepoint_show_message_inside_element(message, $elem = jQuery('.latepoint-body'), message_type = 'error') {
420 message = message || 'Error. Please try again.';
421 if ($elem.length) {
422 if ($elem.find('.latepoint-message').length) {
423 $elem.find('.latepoint-message').removeClass('latepoint-message-success').removeClass('latepoint-message-error').addClass('latepoint-message-' + message_type + '').html(message).show();
424 } else {
425 $elem.prepend('<div class="latepoint-message latepoint-message-' + message_type + '">' + message + '</div>');
426 }
427 // scroll errors into view
428 if (message_type == 'error') $elem.find('.latepoint-message')[0].scrollIntoView({block: "nearest", behavior: 'smooth'});
429 }
430 }
431
432 function latepoint_add_action(callbacks_list, action, priority = 10) {
433 callbacks_list.push({priority: priority, action: action});
434 callbacks_list.sort((a, b) => a.priority - b.priority);
435 return callbacks_list;
436 }
437
438 function latepoint_update_next_btn_label($booking_form_element) {
439 let btn_label = $booking_form_element.find('.latepoint-step-content').last().data('next-btn-label')
440 if (btn_label) {
441 $booking_form_element.find('.latepoint-next-btn span').text(btn_label);
442 }
443 }
444
445 function latepoint_init_step(step_code, $booking_form_element) {
446 latepoint_init_step_selectable_items($booking_form_element);
447 latepoint_init_step_category_items(step_code);
448 switch (step_code) {
449 case 'customer':
450 latepoint_init_step_customer($booking_form_element);
451 break;
452 case 'booking__datepicker':
453 latepoint_init_step_datepicker($booking_form_element);
454 break;
455 case 'booking__agents':
456 latepoint_init_step_agents();
457 break;
458 case 'booking__locations':
459 latepoint_init_step_locations();
460 break;
461 case 'booking__services':
462 latepoint_init_step_services();
463 break;
464 case 'payment__methods':
465 latepoint_init_step_payment__methods($booking_form_element);
466 break;
467 case 'payment__times':
468 latepoint_init_step_payment__times($booking_form_element);
469 break;
470 case 'payment__portions':
471 latepoint_init_step_payment__portions($booking_form_element);
472 break;
473 case 'payment__pay':
474 latepoint_init_step_payment__pay($booking_form_element);
475 break;
476 case 'verify':
477 latepoint_init_step_verify($booking_form_element);
478 break;
479 case 'confirmation':
480 latepoint_init_step_confirmation($booking_form_element);
481 break;
482 }
483
484 $booking_form_element.trigger("latepoint:initStep", [{step_code: step_code}]);
485 $booking_form_element.trigger("latepoint:initStep:" + step_code);
486 }
487
488
489 async function latepoint_generate_day_timeslots($day, $wrapper_element = false, $scrollable_wrapper = false) {
490 if (!$wrapper_element) $wrapper_element = $day.closest('.latepoint-booking-form-element');
491
492 $day.addClass('selected');
493
494 var service_duration = $day.data('service-duration');
495 var interval = $day.data('interval');
496 var work_start_minutes = $day.data('work-start-time');
497 var work_end_minutes = $day.data('work-end-time');
498 var total_work_minutes = $day.data('total-work-minutes');
499 var bookable_minutes = [];
500 var available_capacities_of_bookable_minute = [];
501 if ($day.attr('data-bookable-minutes')) {
502 if ($day.data('bookable-minutes').toString().indexOf(':') > -1) {
503 // has capacity information embedded into bookable minutes string
504 let bookable_minutes_with_capacity = $day.data('bookable-minutes').toString().split(',');
505 for (let i = 0; i < bookable_minutes_with_capacity.length; i++) {
506 bookable_minutes.push(parseInt(bookable_minutes_with_capacity[i].split(':')[0]));
507 available_capacities_of_bookable_minute.push(parseInt(bookable_minutes_with_capacity[i].split(':')[1]));
508 }
509 } else {
510 bookable_minutes = $day.data('bookable-minutes').toString().split(',').map(Number);
511 }
512 }
513 var work_minutes = $day.data('work-minutes').toString().split(',').map(Number);
514
515 var $timeslots = $wrapper_element.find('.timeslots');
516 $timeslots.html('');
517
518 if (total_work_minutes > 0 && bookable_minutes.length && work_minutes.length) {
519 var prev_minutes = false;
520 work_minutes.forEach(function (current_minutes) {
521 var ampm = latepoint_am_or_pm(current_minutes);
522
523 var timeslot_class = 'dp-timepicker-trigger';
524 var timeslot_available_capacity = 0;
525 if (latepoint_helper.time_pick_style == 'timeline') {
526 timeslot_class += ' dp-timeslot';
527 } else {
528 timeslot_class += ' dp-timebox';
529 }
530
531 if (prev_minutes !== false && ((current_minutes - prev_minutes) > service_duration)) {
532 // show interval that is off between two work periods
533 var off_label = latepoint_minutes_to_hours_and_minutes(prev_minutes + service_duration) + ' ' + latepoint_am_or_pm(prev_minutes + service_duration) + ' - ' + latepoint_minutes_to_hours_and_minutes(current_minutes) + ' ' + latepoint_am_or_pm(current_minutes);
534 var off_width = (((current_minutes - prev_minutes - service_duration) / total_work_minutes) * 100);
535 $timeslots.append('<div class="' + timeslot_class + ' is-off" style="max-width:' + off_width + '%; width:' + off_width + '%"><span class="dp-label">' + off_label + '</span></div>');
536 }
537
538 if (!bookable_minutes.includes(current_minutes)) {
539 timeslot_class += ' is-booked';
540 } else {
541 if (available_capacities_of_bookable_minute.length) timeslot_available_capacity = available_capacities_of_bookable_minute[bookable_minutes.indexOf(current_minutes)];
542 }
543 var tick_html = '';
544 var capacity_label = '';
545 var capacity_label_html = '';
546 var capacity_internal_label_html = '';
547
548 if (((current_minutes % 60) == 0) || (interval >= 60)) {
549 timeslot_class += ' with-tick';
550 tick_html = '<span class="dp-tick"><strong>' + latepoint_minutes_to_hours_preferably(current_minutes) + '</strong>' + ' ' + ampm + '</span>';
551 }
552 var timeslot_label = latepoint_minutes_to_hours_and_minutes(current_minutes) + ' ' + ampm;
553 if (latepoint_show_booking_end_time()) {
554 var end_minutes = current_minutes + service_duration;
555 if (end_minutes > 1440) end_minutes = end_minutes - 1440;
556 var end_minutes_ampm = latepoint_am_or_pm(end_minutes);
557 timeslot_label += ' - <span class="dp-label-end-time">' + latepoint_minutes_to_hours_and_minutes(end_minutes) + ' ' + end_minutes_ampm + '</span>';
558 }
559 if (timeslot_available_capacity) {
560 var spaces_message = timeslot_available_capacity > 1 ? latepoint_helper.many_spaces_message : latepoint_helper.single_space_message;
561 capacity_label = timeslot_available_capacity + ' ' + spaces_message;
562 capacity_label_html = '<span class="dp-capacity">' + capacity_label + '</span>';
563 capacity_internal_label_html = '<span class="dp-label-capacity">' + capacity_label + '</span>';
564 }
565 timeslot_label = timeslot_label.trim();
566 $timeslots.removeClass('slots-not-available').append('<div tabindex="0" class="' + timeslot_class + '" data-minutes="' + current_minutes + '"><span class="dp-label">' + capacity_internal_label_html + '<span class="dp-label-time">' + timeslot_label + '</span>' + '</span>' + tick_html + capacity_label_html + '</div>');
567 prev_minutes = current_minutes;
568 });
569 } else {
570 // No working hours this day
571 $timeslots.addClass('slots-not-available').append('<div class="not-working-message">' + latepoint_helper.msg_not_available + "</div>");
572 }
573 jQuery('.times-header-label span').text($day.data('nice-date'));
574 $wrapper_element.find('.time-selector-w').slideDown(200, function () {
575 if (!$scrollable_wrapper) $scrollable_wrapper = $wrapper_element.find('.latepoint-body');
576 $scrollable_wrapper.stop();
577 $wrapper_element.find('.time-selector-w')[0].scrollIntoView({block: "nearest", behavior: 'smooth'});
578 });
579 }
580
581
582 function latepoint_recurring_option_clicked(event) {
583 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
584 let $btn = jQuery(this);
585 let $booking_form_element = $btn.closest('.latepoint-booking-form-element');
586 $booking_form_element.find('.latepoint_is_recurring').val($btn.data('value'));
587 latepoint_trigger_next_btn($booking_form_element);
588 $booking_form_element.find('.step-datepicker-w').removeClass('show-recurring-prompt');
589 return false;
590 }
591
592 function latepoint_timeslot_clicked(event) {
593 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
594 event.preventDefault();
595 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
596 let $trigger = jQuery(this);
597 if ($trigger.hasClass('is-booked') || jQuery(this).hasClass('is-off')) {
598 // Show error message that you cant select a booked period
599 } else {
600 if ($trigger.hasClass('selected')) {
601 $trigger.removeClass('selected');
602 $trigger.find('.dp-success-label').remove();
603 $booking_form_element.find('.latepoint_start_time').val('');
604 latepoint_hide_next_btn($booking_form_element);
605 latepoint_reload_summary($booking_form_element);
606 } else {
607 $booking_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove();
608 let selected_timeslot_time = $trigger.find('.dp-label-time').html();
609 $trigger.addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>');
610
611 let start_minutes = parseInt($trigger.data('minutes'));
612 let start_date = $trigger.closest('.os-dates-and-times-w').find('.os-day.selected').data('date');
613
614 if ($booking_form_element.find('.recurring-bookings-preview-wrapper').length && $booking_form_element.find('.os-recurrence-rules').length) {
615 // recurring datepicker
616 if ($booking_form_element.find('.recurring-bookings-preview-wrapper .recurring-booking-preview.is-editing').length) {
617 // editing one of timeslots, not the recurrence settings
618 let $recurring_bookings_fields = $booking_form_element.find('.os-recurrence-selection-fields-wrapper');
619 let $edited_booking = $booking_form_element.find('.recurring-bookings-preview-wrapper .recurring-booking-preview.is-editing');
620
621 $recurring_bookings_fields.find('input[name="recurrence[overrides][' + $edited_booking.data('stamp') + '][custom_day]"]').val(start_date);
622 $recurring_bookings_fields.find('input[name="recurrence[overrides][' + $edited_booking.data('stamp') + '][custom_minutes]"]').val(start_minutes);
623
624 return window.latepointRecurringBookingsFrontFeature.reload_recurrence_rules($booking_form_element, false);
625 } else {
626 // editing recurrence start date/time
627 $booking_form_element.find('.latepoint_start_date').val(start_date);
628 $booking_form_element.find('.latepoint_start_time').val(start_minutes);
629 return window.latepointRecurringBookingsFrontFeature.reload_recurrence_rules($booking_form_element, true);
630 }
631 } else {
632 $booking_form_element.find('.latepoint_start_date').val(start_date);
633 $booking_form_element.find('.latepoint_start_time').val(start_minutes);
634 if ($trigger.closest('.os-dates-and-times-w').data('allow-recurring') === 'yes') {
635 $booking_form_element.find('.step-datepicker-w').addClass('show-recurring-prompt');
636 $booking_form_element.find('.os-recurring-suggestion-wrapper')[0].scrollIntoView({block: "nearest", behavior: 'smooth'});
637 latepoint_hide_next_btn($booking_form_element);
638 latepoint_hide_prev_btn($booking_form_element);
639 } else {
640 latepoint_trigger_next_btn($booking_form_element);
641 }
642 }
643 }
644 }
645 return false;
646 }
647
648 function latepoint_init_timeslots($booking_form_element = false) {
649 if (!$booking_form_element) return;
650 $booking_form_element.off('click', '.dp-timepicker-trigger', latepoint_timeslot_clicked);
651 $booking_form_element.on('click', '.dp-timepicker-trigger', latepoint_timeslot_clicked);
652 $booking_form_element.off('keydown', '.dp-timepicker-trigger', latepoint_timeslot_clicked);
653 $booking_form_element.on('keydown', '.dp-timepicker-trigger', latepoint_timeslot_clicked);
654
655 $booking_form_element.off('click', '.os-recurring-suggestion-option', latepoint_recurring_option_clicked);
656 $booking_form_element.on('click', '.os-recurring-suggestion-option', latepoint_recurring_option_clicked);
657 $booking_form_element.off('keydown', '.os-recurring-suggestion-option', latepoint_recurring_option_clicked);
658 $booking_form_element.on('keydown', '.os-recurring-suggestion-option', latepoint_recurring_option_clicked);
659 }
660
661 async function latepoint_monthly_calendar_load_next_month($booking_form_element) {
662 try {
663
664 if ($booking_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length) {
665 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active');
666 $booking_form_element.find('.os-month-prev-btn').removeClass('disabled');
667 latepoint_calendar_set_month_label($booking_form_element);
668 return true;
669 } else {
670 let $btn = $booking_form_element.find('.os-month-next-btn');
671 let next_month_route_name = $btn.data('route');
672 $btn.addClass('os-loading');
673 let $calendar_element = $booking_form_element.find('.os-monthly-calendar-days-w').last();
674 let calendar_year = $calendar_element.data('calendar-year');
675 let calendar_month = $calendar_element.data('calendar-month');
676 if (calendar_month == 12) {
677 calendar_year = calendar_year + 1;
678 calendar_month = 1;
679 } else {
680 calendar_month = calendar_month + 1;
681 }
682 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
683 form_data.set('target_date_string', `${calendar_year}-${calendar_month}-1`);
684 let params = latepoint_formdata_to_url_encoded_string(form_data);
685 let data = {
686 action: latepoint_helper.route_action,
687 route_name: next_month_route_name,
688 params: params,
689 layout: 'none',
690 return_format: 'json'
691 }
692 let response = await jQuery.ajax({
693 type: "post",
694 dataType: "json",
695 url: latepoint_timestamped_ajaxurl(),
696 data: data,
697 success: function (data) {
698 }
699 });
700 $btn.removeClass('os-loading');
701 if (response.status === "success") {
702 $booking_form_element.find('.os-months').append(response.message);
703 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active');
704 latepoint_calendar_set_month_label($booking_form_element);
705 latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element);
706 return true;
707 } else {
708 console.log(response.message);
709 return false;
710 }
711
712 }
713 } catch (e) {
714 console.log(e);
715 alert('Error:' + e);
716 return false;
717 }
718 }
719
720 function latepoint_init_monthly_calendar_navigation($booking_form_element = false) {
721 if (!$booking_form_element) return;
722 $booking_form_element.find('.os-month-next-btn').on('click', async function () {
723 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
724 return latepoint_monthly_calendar_load_next_month($booking_form_element);
725 });
726 $booking_form_element.find('.os-month-prev-btn').on('click', function () {
727 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
728 if ($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length) {
729 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active');
730 latepoint_calendar_set_month_label($booking_form_element);
731 }
732 latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element);
733 return false;
734 });
735 }
736
737 function latepoint_calendar_set_month_label($booking_form_element) {
738 $booking_form_element.find('.os-current-month-label .current-year').text($booking_form_element.find('.os-monthly-calendar-days-w.active').data('calendar-year'));
739 $booking_form_element.find('.os-current-month-label .current-month').text($booking_form_element.find('.os-monthly-calendar-days-w.active').data('calendar-month-label'));
740 }
741
742
743 function latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element) {
744 $booking_form_element.find('.os-current-month-label .current-year').text($booking_form_element.find('.os-monthly-calendar-days-w.active .os-monthly-calendar-days').data('calendar-year'));
745 $booking_form_element.find('.os-current-month-label .current-month').text($booking_form_element.find('.os-monthly-calendar-days-w.active .os-monthly-calendar-days').data('calendar-month-label'));
746
747 if ($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length) {
748 $booking_form_element.find('.os-month-prev-btn').removeClass('disabled');
749 } else {
750 $booking_form_element.find('.os-month-prev-btn').addClass('disabled');
751 }
752 }
753
754 function latepoint_format_minutes_to_time(minutes, service_duration) {
755 var ampm = latepoint_am_or_pm(minutes);
756 var formatted_time = latepoint_minutes_to_hours_and_minutes(minutes) + ' ' + ampm;
757 if (latepoint_show_booking_end_time()) {
758 var end_minutes = minutes + service_duration;
759 var end_minutes_ampm = latepoint_am_or_pm(end_minutes);
760 formatted_time += ' - ' + latepoint_minutes_to_hours_and_minutes(end_minutes) + ' ' + end_minutes_ampm;
761 }
762 formatted_time = formatted_time.trim();
763 return formatted_time;
764 }
765
766 function latepoint_monthly_calendar_day_clicked(event) {
767 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
768 let $day = jQuery(this);
769 if ($day.hasClass('os-day-passed')) return false;
770 if ($day.hasClass('os-not-in-allowed-period')) return false;
771 if ($day.closest('.os-dates-and-times-w').hasClass('calendar-style-modern')) {
772 if ($day.hasClass('os-month-prev')) return false;
773 if ($day.hasClass('os-month-next')) return false;
774 }
775 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
776 if ($day.closest('.os-recurrence-datepicker-wrapper').length) {
777 // recurrent datepicker
778 $day.closest('.os-recurrence-datepicker-wrapper').find('.os-day.selected').removeClass('selected');
779 $day.addClass('selected');
780 if ($day.closest('.os-dates-and-times-w').hasClass('days-only')) {
781 $day.closest('.step-recurring-bookings-w').find('input[name="recurrence[rules][repeat_end_date]"]').val($day.data('date'));
782 window.latepointRecurringBookingsFrontFeature.reload_recurrence_rules($booking_form_element, true);
783 } else {
784 latepoint_generate_day_timeslots($day);
785 $day.closest('.os-recurrence-datepicker-wrapper').find('.time-selector-w')[0].scrollIntoView({block: "nearest", behavior: 'smooth'});
786 }
787 } else {
788 // regular datepicker
789 if ($day.closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')) {
790 // HIDE TIMESLOT IF ONLY ONE TIMEPOINT
791 if ($day.hasClass('os-not-available')) {
792 // clicked on a day that has no available timeslots
793 // do nothing
794 } else {
795 $booking_form_element.find('.os-day.selected').removeClass('selected');
796 $day.addClass('selected');
797 // set date
798 $booking_form_element.find('.latepoint_start_date').val($day.data('date'));
799 if ($day.hasClass('os-one-slot-only')) {
800 // clicked on a day that has only one slot available
801 var bookable_minutes = $day.data('bookable-minutes').toString().split(':')[0];
802 var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number($day.data('service-duration')));
803 $booking_form_element.find('.latepoint_start_time').val($day.data('bookable-minutes'));
804 latepoint_show_next_btn($booking_form_element);
805 $booking_form_element.find('.time-selector-w').slideUp(200);
806 } else {
807 // regular day with more than 1 timeslots available
808 // build timeslots
809 latepoint_generate_day_timeslots($day);
810 // clear time and hide next btn
811 $booking_form_element.find('.latepoint_start_time').val('');
812 latepoint_hide_next_btn($booking_form_element);
813 }
814 latepoint_reload_summary($booking_form_element);
815 }
816 } else {
817
818 // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT
819 $booking_form_element.find('.latepoint_start_date').val($day.data('date'));
820 $booking_form_element.find('.os-day.selected').removeClass('selected');
821 $day.addClass('selected');
822
823 // build timeslots
824 latepoint_generate_day_timeslots($day);
825 // clear time and hide next btn
826 latepoint_reload_summary($booking_form_element);
827 $booking_form_element.find('.latepoint_start_time').val('');
828 latepoint_hide_next_btn($booking_form_element);
829 }
830 }
831
832
833 return false;
834 }
835
836 async function latepoint_init_step_datepicker($booking_form_element = false) {
837 if (!$booking_form_element) return true;
838 latepoint_init_timeslots($booking_form_element);
839 latepoint_init_monthly_calendar_navigation($booking_form_element);
840 $booking_form_element.off('click', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
841 $booking_form_element.on('click', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
842 $booking_form_element.off('keydown', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
843 $booking_form_element.on('keydown', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
844
845 if ($booking_form_element.find('input[name="booking[start_date]"]').val()) {
846 $booking_form_element.find('.os-day[data-date="' + $booking_form_element.find('input[name="booking[start_date]"]').val() + '"]').trigger('click');
847 } else {
848 if ($booking_form_element.find('.os-dates-and-times-w').hasClass('auto-search')) {
849 let max_number_of_months_to_check = 24;
850 let current_year = new Date().getFullYear();
851 for (let i = 0; i < max_number_of_months_to_check; i++) {
852 let $active_month = $booking_form_element.find('.os-monthly-calendar-days-w.active');
853 let searching_month_label = $active_month.data('calendar-month-label');
854 if ($active_month.data('calendar-year') != current_year) searching_month_label += ' ' + $active_month.data('calendar-year');
855 $booking_form_element.find('.os-calendar-searching-info span').text(searching_month_label);
856 // check if active month has any days available for booking
857 let $first_available = $active_month.find('.os-day.os-month-current').not('.os-not-available').first();
858 if ($first_available.length) {
859 break;
860 } else {
861 await latepoint_monthly_calendar_load_next_month($booking_form_element);
862 }
863 }
864 }
865 }
866 $booking_form_element.find('.os-dates-and-times-w').removeClass('is-searching');
867 return true;
868 }
869
870
871 function latepoint_init_step_verify($booking_form_element = false) {
872 if (!$booking_form_element) return;
873 $booking_form_element.closest('.latepoint-summary-is-open').removeClass('latepoint-summary-is-open');
874
875 $booking_form_element.find('.latepoint-body .load-customer-step-trigger').on('click', function () {
876 jQuery(this).addClass('os-loading');
877 latepoint_reload_step($booking_form_element, 'customer');
878 return false;
879 });
880
881 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-trigger-on-verify-w a').on('click', function (e) {
882 jQuery(this).closest('.coupon-code-wrapper-on-verify').addClass('entering-coupon').find('.coupon-code-input').trigger('focus');
883 return false;
884 });
885 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-input-cancel').on('click', function (e) {
886 jQuery(this).closest('.coupon-code-wrapper-on-verify').removeClass('entering-coupon');
887 return false;
888 });
889
890 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-input-submit').on('click', function (e) {
891 latepoint_apply_coupon(jQuery(this).closest('.coupon-code-input-w').find('.coupon-code-input'));
892 return false;
893 });
894
895 $booking_form_element.find('.os-remove-item-from-cart').on('click keydown', function (event) {
896 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
897 //make sure to clear active cart item so it doesn't add it again on reload!
898 if (confirm(jQuery(this).data('confirm-text'))) {
899 latepoint_remove_cart_item(jQuery(this));
900 }
901 return false;
902 });
903
904 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-clear').on('click', function (e) {
905 latepoint_remove_coupon(jQuery(this));
906 return false;
907 });
908
909 $booking_form_element.find('.coupon-code-wrapper-on-verify input.coupon-code-input').on('keyup', function (e) {
910 if (e.which === 13) {
911 latepoint_apply_coupon(jQuery(this));
912 return false;
913 }
914 });
915 }
916
917
918 function latepoint_init_step_payment__pay($booking_form_element = false) {
919 var selected_payment_method = $booking_form_element.find('input[name="cart[payment_method]"]').val();
920 latepoint_init_payment_method_actions($booking_form_element, selected_payment_method);
921 }
922
923 function latepoint_init_step_payment__portions($booking_form_element = false) {
924 // Selecting Payment Time
925 $booking_form_element.find('.lp-payment-trigger-payment-portion-selector').on('click keydown', function (event) {
926 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
927 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
928 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
929 latepoint_show_prev_btn($booking_form_element);
930 latepoint_trigger_next_btn($booking_form_element);
931 return false;
932 });
933 }
934
935 function latepoint_init_step_payment__times($booking_form_element = false) {
936 // Selecting Payment Time
937 $booking_form_element.find('.lp-payment-trigger-payment-time-selector').on('click keydown', function (event) {
938 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
939 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
940 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
941 latepoint_show_prev_btn($booking_form_element);
942 latepoint_trigger_next_btn($booking_form_element);
943 return false;
944 });
945 }
946
947
948 function latepoint_init_step_payment__methods($booking_form_element = false) {
949 // Selecting Payment Time
950 $booking_form_element.find('.lp-payment-trigger-payment-method-selector').on('click', function (e) {
951 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
952 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
953 latepoint_show_prev_btn($booking_form_element);
954 latepoint_trigger_next_btn($booking_form_element);
955 return false;
956 });
957 }
958
959 function latepoint_category_item_clicked(event) {
960 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
961 let $item = jQuery(event.target);
962
963 let $booking_form_element = $item.closest('.latepoint-booking-form-element');
964 latepoint_show_prev_btn($booking_form_element);
965 $item.closest('.latepoint-step-content').addClass('selecting-item-category');
966 let $category_wrapper = $item.closest('.os-item-category-w');
967 let $main_parent = $item.closest('.os-item-categories-main-parent');
968 if ($category_wrapper.hasClass('selected')) {
969 $category_wrapper.removeClass('selected');
970 if ($category_wrapper.parent().closest('.os-item-category-w').length) {
971 $category_wrapper.parent().closest('.os-item-category-w').addClass('selected');
972 } else {
973 $main_parent.removeClass('show-selected-only');
974 }
975 } else {
976 $main_parent.find('.os-item-category-w.selected').removeClass('selected');
977 $main_parent.addClass('show-selected-only');
978 $category_wrapper.addClass('selected');
979 }
980 return false;
981 }
982
983 function latepoint_init_step_category_items(step_code) {
984 let $category_items = jQuery('.latepoint-step-content[data-step-code="' + step_code + '"] .os-item-category-info');
985 $category_items.on('click', latepoint_category_item_clicked);
986 $category_items.on('keydown', latepoint_category_item_clicked);
987 }
988
989
990 function latepoint_init_step_selectable_items($booking_form_element) {
991 $booking_form_element.off('click', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
992 $booking_form_element.on('click', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
993
994 $booking_form_element.off('click', '.os-selectable-items .os-selectable-item .item-quantity-selector-input', latepoint_selectable_item_quantity_keyup);
995 $booking_form_element.on('click', '.os-selectable-items .os-selectable-item .item-quantity-selector-input', latepoint_selectable_item_quantity_keyup);
996
997
998 $booking_form_element.off('keydown', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
999 $booking_form_element.on('keydown', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
1000 }
1001
1002
1003 function latepoint_update_quantity_for_selectable_items($item) {
1004 var ids = $item.closest('.os-selectable-items')
1005 .find('.os-selectable-item.selected')
1006 .map(function () {
1007 if (jQuery(this).hasClass('has-quantity')) {
1008 return jQuery(this).data('item-id') + ':' + jQuery(this).find('input.item-quantity-selector-input').val();
1009 } else {
1010 return jQuery(this).data('item-id');
1011 }
1012 }).get();
1013 $item.closest('.latepoint-booking-form-element').find($item.data('id-holder')).val(ids);
1014 }
1015
1016 function latepoint_selectable_item_quantity_keyup(event) {
1017 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1018 var $item = jQuery(this).closest('.os-selectable-item');
1019 var new_value = jQuery(this).val();
1020 if (new_value && new_value.match(/^\d+$/)) {
1021 var max_quantity = $item.data('max-quantity');
1022 if (max_quantity && (new_value > max_quantity)) new_value = max_quantity;
1023 } else {
1024 new_value = 0;
1025 }
1026 jQuery(this).val(new_value);
1027
1028 if (($item.hasClass('selected') && (new_value > 0)) || (!$item.hasClass('selected') && (new_value == 0))) {
1029 latepoint_update_quantity_for_selectable_items($item);
1030 latepoint_reload_summary($booking_form_element);
1031 return false;
1032 } else {
1033 $item.trigger('click');
1034 }
1035 }
1036
1037 function latepoint_selectable_item_clicked(event) {
1038 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1039 event.stopPropagation();
1040 event.stopImmediatePropagation();
1041 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1042 if (jQuery(this).hasClass('has-quantity')) {
1043 if (jQuery(event.target).hasClass('item-quantity-selector')) {
1044 var current_value = parseInt(jQuery(this).find('input.item-quantity-selector-input').val());
1045 var new_value = (jQuery(event.target).data('sign') == 'minus') ? current_value - 1 : current_value + 1;
1046 var max_quantity = jQuery(this).data('max-quantity');
1047 if (new_value < 0) new_value = 0;
1048 if (max_quantity && (new_value > max_quantity)) new_value = max_quantity;
1049 jQuery(this).find('input.item-quantity-selector-input').val(new_value);
1050 if ((jQuery(this).hasClass('selected') && (new_value > 0)) || (!jQuery(this).hasClass('selected') && (new_value == 0))) {
1051 latepoint_update_quantity_for_selectable_items(jQuery(this));
1052 latepoint_reload_summary($booking_form_element);
1053 return false;
1054 }
1055 }
1056 if (jQuery(event.target).hasClass('item-quantity-selector-input')) {
1057 latepoint_update_quantity_for_selectable_items(jQuery(this));
1058 latepoint_reload_summary($booking_form_element);
1059 return false;
1060 }
1061 }
1062 var summary_value = '';
1063 if (jQuery(this).hasClass('os-allow-multiselect')) {
1064 if (jQuery(this).hasClass('selected')) {
1065 jQuery(this).removeClass('selected');
1066 if (jQuery(this).hasClass('has-quantity')) jQuery(this).find('input.item-quantity-selector-input').val(0);
1067 } else {
1068 jQuery(this).addClass('selected');
1069 if (jQuery(this).hasClass('has-quantity') && !(jQuery(this).find('input.item-quantity-selector-input').val() > 0)) {
1070 jQuery(this).find('input.item-quantity-selector-input').val(1);
1071 }
1072 }
1073 latepoint_update_quantity_for_selectable_items(jQuery(this));
1074 latepoint_reload_summary($booking_form_element);
1075 latepoint_show_next_btn($booking_form_element);
1076 } else {
1077 if (!jQuery(this).hasClass('os-duration-item')) jQuery(this).closest('.os-item-categories-main-parent').find('.os-selectable-item.selected').removeClass('selected');
1078 jQuery(this).closest('.os-selectable-items').find('.os-selectable-item.selected').removeClass('selected');
1079 jQuery(this).addClass('selected');
1080 $booking_form_element.find(jQuery(this).data('id-holder')).val(jQuery(this).data('item-id'));
1081 if (jQuery(this).data('cart-item-item-data-key')) {
1082 latepoint_update_active_cart_item_item_data($booking_form_element, jQuery(this).data('cart-item-item-data-key'), jQuery(this).data('item-id'));
1083 }
1084 if (jQuery(this).data('os-call-func')) {
1085 window[jQuery(this).data('os-call-func')](jQuery(this));
1086 }
1087 if (jQuery(this).data('activate-sub-step')) {
1088 window[jQuery(this).data('activate-sub-step')](jQuery(this));
1089 } else {
1090 latepoint_trigger_next_btn($booking_form_element);
1091 }
1092 }
1093 return false;
1094 }
1095
1096 function latepoint_update_active_cart_item_item_data($booking_form_element, key, value) {
1097 let item_data_json = $booking_form_element.find('input[name="active_cart_item[item_data]"]').val();
1098 let item_data = item_data_json ? JSON.parse($booking_form_element.find('input[name="active_cart_item[item_data]"]').val()) : {};
1099 item_data[key] = value;
1100 $booking_form_element.find('input[name="active_cart_item[item_data]"]').val(JSON.stringify(item_data));
1101 }
1102
1103 function latepoint_format_price(price) {
1104 // replace default decimal separator dot with comma if it's in settings
1105 if (latepoint_helper.decimal_separator == ',') price = String(price).replace('.', ',');
1106 return latepoint_helper.currency_symbol_before + String(price) + latepoint_helper.currency_symbol_after;
1107 }
1108
1109
1110 function latepoint_init_step_services() {
1111 }
1112
1113
1114 function latepoint_trigger_next_btn($booking_form_element) {
1115 $booking_form_element.find('.latepoint_step_direction').val('next');
1116 latepoint_submit_booking_form($booking_form_element.find('.latepoint-form'));
1117 }
1118
1119 function latepoint_init_step_locations() {
1120 }
1121
1122 function latepoint_init_agent_details_link($booking_form_element) {
1123 $booking_form_element.on('click', '.os-trigger-item-details-popup', function () {
1124 $booking_form_element.find('.os-item-details-popup.open').remove();
1125 var $popup = $booking_form_element.find('#' + jQuery(this).data('item-details-popup-id')).first().clone().attr('id', '');
1126 $booking_form_element.find('.latepoint-form-w').addClass('showing-item-details-popup');
1127 $popup.addClass('open').appendTo($booking_form_element.find('.latepoint-body'));
1128 return false;
1129 });
1130 $booking_form_element.on('click', '.os-item-details-popup.open .os-item-details-popup-close', function () {
1131 $booking_form_element.find('.latepoint-form-w').removeClass('showing-item-details-popup');
1132 jQuery(this).closest('.os-item-details-popup.open').remove();
1133 return false;
1134 });
1135 }
1136
1137 function latepoint_init_step_agents() {
1138 }
1139
1140
1141 function latepoint_init_booking_summary_lightbox() {
1142 let $lightbox = jQuery('.customer-dashboard-booking-summary-lightbox');
1143 latepoint_init_qr_trigger($lightbox);
1144 latepoint_init_item_details_popup($lightbox);
1145 }
1146
1147 function latepoint_init_step_confirmation($booking_form_element = false) {
1148 if (!$booking_form_element) return;
1149 $booking_form_element.on('click', '.set-customer-password-btn', function () {
1150 let $btn = jQuery(this);
1151 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1152
1153 $btn.addClass('os-loading');
1154 let params = {
1155 password_nonce: jQuery('input[name="new_password_nonce"]').val(),
1156 password: jQuery('input[name="customer[password]"]').val()
1157 }
1158 let data = {
1159 action: latepoint_helper.route_action,
1160 route_name: jQuery(this).data('btn-action'),
1161 params: jQuery.param(params),
1162 layout: 'none',
1163 return_format: 'json'
1164 }
1165 jQuery.ajax({
1166 type: "post",
1167 dataType: "json",
1168 url: latepoint_timestamped_ajaxurl(),
1169 data: data,
1170 success: function (data) {
1171 $btn.removeClass('os-loading');
1172 if (data.status === "success") {
1173 $booking_form_element.find('.step-confirmation-set-password').html('').hide();
1174 $booking_form_element.find('.confirmation-cabinet-info').show();
1175 } else {
1176 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.step-confirmation-set-password'), 'error');
1177 }
1178 }
1179 });
1180 return false;
1181 });
1182
1183 $booking_form_element.on('click', '.qr-show-trigger', function () {
1184 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1185 $booking_form_element.find('.qr-code-on-full-summary').addClass('show-vevent-qr-code');
1186 return false;
1187 });
1188
1189 $booking_form_element.on('click', '.show-set-password-fields', function () {
1190 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1191
1192 $booking_form_element.find('.step-confirmation-set-password').show();
1193 $booking_form_element.find('#customer_password').trigger('focus');
1194 jQuery(this).closest('.info-box').hide();
1195 return false;
1196 });
1197 }
1198
1199 function latepoint_init_customer_login_form(){
1200 if(jQuery('.latepoint-login-form-w').length){
1201 latepoint_init_auth_form(jQuery('.latepoint-login-form-w'));
1202 }
1203 }
1204
1205 function latepoint_init_customer_dashboard() {
1206 latepoint_init_form_masks();
1207 jQuery('.latepoint-customer-timezone-selector-w select').on('change', function (e) {
1208 var $select_box = jQuery(this);
1209 $select_box.closest('.latepoint-customer-timezone-selector-w').addClass('os-loading');
1210 var data = {
1211 action: latepoint_helper.route_action,
1212 route_name: jQuery(this).closest('.latepoint-customer-timezone-selector-w').data('route-name'),
1213 params: {timezone_name: jQuery(this).val()},
1214 layout: 'none',
1215 return_format: 'json'
1216 }
1217 jQuery.ajax({
1218 type: "post",
1219 dataType: "json",
1220 url: latepoint_timestamped_ajaxurl(),
1221 data: data,
1222 success: function (data) {
1223 $select_box.closest('.latepoint-customer-timezone-selector-w').removeClass('os-loading');
1224 if (data.status === "success") {
1225 location.reload();
1226 } else {
1227
1228 }
1229 }
1230 });
1231 });
1232
1233
1234 jQuery('.latepoint-request-booking-cancellation').on('click', function () {
1235 if (!confirm(latepoint_helper.cancel_booking_prompt)) return false;
1236 var $this = jQuery(this);
1237 var $booking_box = $this.closest('.customer-booking');
1238
1239 var route = jQuery(this).data('route');
1240 var params = {id: $booking_box.data('id')};
1241
1242 var data = {
1243 action: latepoint_helper.route_action,
1244 route_name: route,
1245 params: params,
1246 layout: 'none',
1247 return_format: 'json'
1248 }
1249 $this.addClass('os-loading');
1250 jQuery.ajax({
1251 type: "post",
1252 dataType: "json",
1253 url: latepoint_timestamped_ajaxurl(),
1254 data: data,
1255 success: function (data) {
1256 if (data.status === "success") {
1257 $this.remove();
1258 location.reload();
1259 } else {
1260 $this.removeClass('os-loading');
1261 }
1262 }
1263 });
1264 return false;
1265 });
1266
1267 }
1268
1269
1270 function latepoint_get_customer_name($wrapper) {
1271 var customer_name = '';
1272 var first_name = $wrapper.find('input[name="customer[first_name]"]').val();
1273 var last_name = $wrapper.find('input[name="customer[last_name]"]').val();
1274 if (first_name) customer_name += first_name;
1275 if (last_name) customer_name += ' ' + last_name;
1276 return customer_name.trim();
1277 }
1278
1279 function latepoint_init_customer_otp_code_verify_form($booking_form_element) {
1280 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1281 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1282
1283 if ($verify_otp_btn.length && $verify_otp_input.length) {
1284 $verify_otp_input.trigger('focus');
1285
1286 // trigger on enter/space to emulate a button
1287 $verify_otp_btn.on('keydown', function (e) {
1288 if (e.key === 'Enter' || e.key === ' ') {
1289 e.preventDefault();
1290 jQuery(this).trigger('click'); // Triggers the click handler above
1291 }
1292 });
1293 // close
1294 $booking_form_element.find('.latepoint-customer-otp-resend').on('click', function (e) {
1295 e.preventDefault();
1296 latepoint_request_customer_otp_code($booking_form_element, jQuery(this));
1297 });
1298
1299 $booking_form_element.find('.latepoint-customer-otp-close').on('click', function () {
1300 $booking_form_element.find('.latepoint-customer-otp-input-container').html('');
1301 $booking_form_element.find('.hide-when-entering-otp').removeClass('os-hidden');
1302 latepoint_show_booking_form_footer($booking_form_element);
1303 return false;
1304 });
1305
1306 // input in code field
1307 $verify_otp_input.on('input', function () {
1308 // Remove non-numeric characters
1309 const cleanValue = jQuery(this).val().replace(/[^0-9]/g, '');
1310 jQuery(this).val(cleanValue);
1311 if (cleanValue.length === 6) {
1312 $verify_otp_btn.trigger('click');
1313 }
1314 });
1315 $verify_otp_input.on('keydown', function (e) {
1316 if (e.key === 'Enter') {
1317 e.preventDefault();
1318 $verify_otp_btn.trigger('click');
1319 }
1320 });
1321
1322 $verify_otp_btn.on('click', function (e) {
1323 return latepoint_verify_customer_otp_code($booking_form_element);
1324 });
1325 }
1326
1327 }
1328
1329 async function latepoint_verify_customer_otp_code($booking_form_element) {
1330 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1331 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1332
1333 $verify_otp_input.removeClass('os-invalid');
1334 if ($verify_otp_input.val().length !== 6) {
1335 $verify_otp_input.addClass('os-invalid').addClass('os-shake');
1336 return false;
1337 }
1338
1339 $verify_otp_btn.addClass('os-loading');
1340
1341 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1342
1343 let data = {
1344 action: 'latepoint_route_call',
1345 route_name: $verify_otp_btn.data('route'),
1346 params: latepoint_formdata_to_url_encoded_string(form_data),
1347 layout: 'none',
1348 return_format: 'json'
1349 }
1350 try {
1351 let response = await jQuery.ajax({
1352 type: "post",
1353 dataType: "json",
1354 url: latepoint_timestamped_ajaxurl(),
1355 data: data
1356 });
1357 $verify_otp_btn.removeClass('os-loading');
1358 if (response.status === 'success') {
1359 if($booking_form_element.data('success-action') === 'reload'){
1360 location.reload();
1361 }else{
1362 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'));
1363 $booking_form_element.find('input[name="customer_contact_verification_token"]').val(response.message);
1364 latepoint_reload_step($booking_form_element);
1365 }
1366 } else {
1367 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1368 }
1369 return false;
1370 } catch (e) {
1371 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1372 throw e;
1373 }
1374 }
1375
1376 async function latepoint_show_verify_contact_form_with_otp_code($booking_form_element, form_html) {
1377 $booking_form_element.find('.latepoint-customer-otp-input-container').html(form_html);
1378 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1379 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1380 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1381 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1382 latepoint_hide_booking_form_footer($booking_form_element);
1383 }
1384
1385 function latepoint_hide_booking_form_footer($booking_form_element) {
1386 $booking_form_element.addClass('hidden-buttons');
1387 }
1388
1389 function latepoint_show_booking_form_footer($booking_form_element) {
1390 $booking_form_element.removeClass('hidden-buttons');
1391 }
1392
1393 async function latepoint_request_customer_otp_code($booking_form_element, $request_otp_button) {
1394 $request_otp_button.addClass('os-loading');
1395
1396 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1397
1398
1399 // get values from phone number fields
1400 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1401 $booking_form_element.find('input.os-mask-phone').each(function () {
1402 const phoneInputName = this.getAttribute('name');
1403 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1404 // override value generated automatically by formdata with a formatted value of a phone field with country code
1405 form_data.set(phoneInputName, phoneInputValue);
1406 });
1407 }
1408
1409 let data = {
1410 action: 'latepoint_route_call',
1411 route_name: $request_otp_button.data('otp-request-route'),
1412 params: latepoint_formdata_to_url_encoded_string(form_data),
1413 layout: 'none',
1414 return_format: 'json'
1415 }
1416 try {
1417 let response = await jQuery.ajax({
1418 type: "post",
1419 dataType: "json",
1420 url: latepoint_timestamped_ajaxurl(),
1421 data: data
1422 });
1423 $request_otp_button.removeClass('os-loading');
1424 if (response.status === 'success') {
1425 latepoint_hide_message_inside_element($booking_form_element.find('.hide-when-entering-otp'));
1426 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1427 $booking_form_element.find('.latepoint-customer-otp-input-container').html(response.message);
1428 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1429 } else {
1430 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.hide-when-entering-otp'), 'error');
1431 }
1432 return false;
1433 } catch (e) {
1434 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.hide-when-entering-otp'), 'error');
1435 throw e;
1436 }
1437 }
1438
1439 function latepoint_customer_auth_load_next_step($booking_form_element) {
1440
1441 }
1442
1443 function latepoint_init_customer_otp_code_request_form($booking_form_element) {
1444 let $request_otp_button = $booking_form_element.find('.latepoint-request-otp-button');
1445 if ($request_otp_button.length > 0) {
1446 $request_otp_button.on('click', function (e) {
1447 return latepoint_request_customer_otp_code($booking_form_element, jQuery(this));
1448 });
1449 // trigger on enter/space to emulate a button
1450 $request_otp_button.on('keydown', function (e) {
1451 if (e.key === 'Enter' || e.key === ' ') {
1452 e.preventDefault();
1453 jQuery(this).trigger('click'); // Triggers the click handler above
1454 }
1455 });
1456 $booking_form_element.find('.latepoint-customer-otp-request-wrapper').find('input, select').on('keydown', function (e) {
1457 if (e.key === 'Enter') {
1458 e.preventDefault();
1459 $request_otp_button.trigger('click');
1460 }
1461 });
1462 }
1463 }
1464
1465 async function latepoint_login_customer($booking_form_element, $request_otp_button) {
1466
1467 $request_otp_button.addClass('os-loading');
1468 let $form = $booking_form_element.find('.latepoint-form');
1469
1470 let form_data = new FormData($form[0]);
1471
1472 // get values from phone number fields
1473 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1474 $form.find('input.os-mask-phone').each(function () {
1475 const phoneInputName = this.getAttribute('name');
1476 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1477 // override value generated automatically by formdata with a formatted value of a phone field with country code
1478 form_data.set(phoneInputName, phoneInputValue);
1479 });
1480 }
1481
1482 let data = {
1483 action: 'latepoint_route_call',
1484 route_name: $request_otp_button.data('password-login-route'),
1485 params: latepoint_formdata_to_url_encoded_string(form_data),
1486 layout: 'none',
1487 return_format: 'json'
1488 }
1489 try {
1490 let response = await jQuery.ajax({
1491 type: "post",
1492 dataType: "json",
1493 url: latepoint_timestamped_ajaxurl(),
1494 data: data
1495 });
1496 $request_otp_button.removeClass('os-loading');
1497
1498 if (response.status === "success") {
1499 if($booking_form_element.data('success-action') === 'reload'){
1500 location.reload();
1501 return true;
1502 }else {
1503 return latepoint_reload_step($booking_form_element);
1504 }
1505 } else {
1506 throw new Error(response.message);
1507 }
1508 } catch (e) {
1509 latepoint_show_message_inside_element(e.message, $booking_form_element.find('.os-step-existing-customer-login-w'));
1510 }
1511
1512 }
1513
1514
1515 function latepoint_init_auth_form($wrapper){
1516
1517 latepoint_init_customer_otp_code_request_form($wrapper);
1518 latepoint_init_customer_otp_code_verify_form($wrapper);
1519
1520
1521 $wrapper.find('.login-with-password-toggle').on('change', function () {
1522 if (jQuery(this).hasClass('os-opposite')) {
1523 if (jQuery(this).is(':checked')) {
1524 $wrapper.find('.os-customer-otp-notice').hide();
1525 $wrapper.find('.os-customer-login-password-fields-w').show();
1526 } else {
1527 $wrapper.find('.os-customer-otp-notice').show();
1528 $wrapper.find('.os-customer-login-password-fields-w').hide();
1529 }
1530 } else {
1531 if (jQuery(this).is(':checked')) {
1532 $wrapper.find('.os-customer-otp-notice').show();
1533 $wrapper.find('.os-customer-login-password-fields-w').hide();
1534 } else {
1535 $wrapper.find('.os-customer-otp-notice').hide();
1536 $wrapper.find('.os-customer-login-password-fields-w').show();
1537 }
1538 }
1539 });
1540
1541 $wrapper.find('.alternative-login-option').on('click', function () {
1542 let login_method = jQuery(this).data('auth-via');
1543 let delivery_method = jQuery(this).data('otp-delivery-method');
1544 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1545 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1546 $wrapper.find('.customer-login-method-wrapper').addClass('os-hidden');
1547 $wrapper.find('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1548 $wrapper.find('.alternative-login-option').removeClass('os-hidden');
1549 jQuery(this).addClass('os-hidden');
1550 return false;
1551 });
1552
1553 $wrapper.find('.login-options-via-wrapper .login-option').on('click', function () {
1554 let $wrapper = jQuery(this).closest('.latepoint-customer-auth-options-wrapper');
1555 let login_method = jQuery(this).data('login-method');
1556 let delivery_method = jQuery(this).data('otp-delivery-method');
1557
1558 let otp_enabled = jQuery(this).data('is-otp-enabled');
1559 if(otp_enabled === 'no'){
1560 if($wrapper.find('.login-with-password-toggle.os-opposite:not(:checked)').length){
1561 $wrapper.find('.login-with-password-toggle.os-opposite').trigger('click');
1562 }
1563 $wrapper.find('.latepoint-customer-otp-option').hide();
1564 $wrapper.find('.step-login-existing-customer-btn').addClass('latepoint-btn-block');
1565 }else{
1566 if($wrapper.find('.latepoint-customer-otp-option').length){
1567 $wrapper.find('.latepoint-customer-otp-option').show();
1568 $wrapper.find('.step-login-existing-customer-btn').removeClass('latepoint-btn-block');
1569 }
1570 }
1571 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1572 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1573 jQuery(this).closest('.login-options-via-wrapper').find('.login-option.os-selected').removeClass('os-selected')
1574 jQuery(this).addClass('os-selected');
1575 jQuery('.customer-login-method-wrapper').addClass('os-hidden');
1576 jQuery('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1577
1578 return false;
1579 });
1580
1581 // Init Login Existing Customer Button
1582 $wrapper.find('.os-customer-login-w input').on('keyup', function (e) {
1583 if (e.keyCode === 13) {
1584 e.preventDefault();
1585 $wrapper.find('.step-login-existing-customer-btn').trigger('click');
1586 return false;
1587 }
1588 });
1589
1590 $wrapper.find('.step-login-existing-customer-btn').on('click', function (e) {
1591 e.preventDefault();
1592 let via = $wrapper.find('input[name="auth[via]"]').val();
1593 if ($wrapper.find('input[name="auth[via]"]').is(':checkbox')) {
1594 let is_checked = $wrapper.find('input[name="auth[via]"]').is(':checked');
1595 if (via === 'otp' && !is_checked) {
1596 via = 'password';
1597 } else if (via === 'password' && !is_checked) {
1598 via = 'otp';
1599 }
1600 }
1601 if (via === 'otp') {
1602 latepoint_request_customer_otp_code($wrapper, jQuery(this));
1603 } else if (via === 'password') {
1604 latepoint_login_customer($wrapper, jQuery(this));
1605 }
1606
1607 });
1608 }
1609
1610 function latepoint_init_step_customer($booking_form_element) {
1611 latepoint_init_form_masks();
1612
1613 latepoint_init_auth_form($booking_form_element);
1614
1615 // Init Logout button
1616 $booking_form_element.find('.step-customer-logout-btn').on('click', function () {
1617 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1618 $booking_form_element.find('input[name="customer_contact_verification_token"]').val('');
1619 let data = {
1620 action: latepoint_helper.route_action,
1621 route_name: jQuery(this).data('btn-action'),
1622 layout: 'none',
1623 return_format: 'json'
1624 }
1625 latepoint_step_content_change_start($booking_form_element);
1626 jQuery.ajax({
1627 type: "post",
1628 dataType: "json",
1629 url: latepoint_timestamped_ajaxurl(),
1630 data: data,
1631 success: function (data) {
1632 $booking_form_element.find('input[name="auth[action]"]').val('logout');
1633 latepoint_reload_step($booking_form_element);
1634 }
1635 });
1636 return false;
1637 });
1638
1639
1640 }
1641
1642 function latepoint_step_content_change_start($booking_form_element) {
1643 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1644 }
1645
1646 // TODO
1647 function latepoint_step_content_change_end(new_content, $booking_form_element) {
1648 if (new_content) $booking_form_element.find('.latepoint-body .latepoint-step-content').replaceWith(new_content);
1649 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1650 setTimeout(function () {
1651 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1652 }, 50);
1653 }
1654
1655
1656 function latepoint_change_step_desc($booking_form_element, step_code) {
1657 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1658 setTimeout(function () {
1659 // Progress bar
1660 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1661 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1662 $step_progress.nextAll().removeClass('complete').removeClass('active');
1663 // Side panel
1664 var side_panel_desc = $booking_form_element.find('.latepoint-step-desc-library[data-step-code="' + step_code + '"]').html();
1665 $booking_form_element.find('.latepoint-step-desc').html(side_panel_desc);
1666
1667 // Top header
1668 var top_header_desc = $booking_form_element.find('.os-heading-text-library[data-step-code="' + step_code + '"]').html();
1669 $booking_form_element.find('.os-heading-text').html(top_header_desc);
1670 setTimeout(function () {
1671 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1672 }, 50);
1673 }, 500);
1674 }
1675
1676
1677 function latepoint_progress_prev($booking_form_element, step_code) {
1678 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1679 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1680 $step_progress.nextAll().removeClass('complete').removeClass('active');
1681 }
1682
1683
1684 function latepoint_progress_next($booking_form_element, step_code) {
1685 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1686 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1687 $step_progress.nextAll().removeClass('complete').removeClass('active');
1688 }
1689
1690
1691 function latepoint_next_step_description($booking_form_element, step_code) {
1692 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1693 setTimeout(function () {
1694 $booking_form_element.find('.latepoint-step-desc').html($booking_form_element.find('.latepoint-step-desc-library.active').removeClass('active').next('.latepoint-step-desc-library').addClass('active').html());
1695 $booking_form_element.find('.os-heading-text').html($booking_form_element.find('.os-heading-text-library.active').removeClass('active').next('.os-heading-text-library').addClass('active').html());
1696 setTimeout(function () {
1697 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1698 }, 50);
1699 }, 500);
1700 }
1701
1702 function latepoint_prev_step_description($booking_form_element, step_code) {
1703 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1704 setTimeout(function () {
1705 $booking_form_element.find('.latepoint-step-desc').html($booking_form_element.find('.latepoint-step-desc-library.active').removeClass('active').prev('.latepoint-step-desc-library').addClass('active').html());
1706 $booking_form_element.find('.os-heading-text').html($booking_form_element.find('.os-heading-text-library.active').removeClass('active').prev('.os-heading-text-library').addClass('active').html());
1707 setTimeout(function () {
1708 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1709 }, 50);
1710 }, 500);
1711 }
1712
1713
1714 function latepoint_validate_fields($fields) {
1715 var is_valid = true;
1716 $fields.each(function (index) {
1717 if (jQuery(this).val() == '') {
1718 is_valid = false;
1719 return false;
1720 }
1721 });
1722 return is_valid;
1723 }
1724
1725
1726 async function latepoint_submit_booking_form($booking_form) {
1727 let $booking_form_element = $booking_form.closest('.latepoint-booking-form-element');
1728
1729 let current_step = $booking_form_element.find('.latepoint_current_step_code').val();
1730 let callbacks_list = [];
1731 if (latepoint_check_if_booking_form_is_final_submit($booking_form_element)) {
1732 // check if order intent is still bookable
1733 latepoint_add_action(callbacks_list, async () => {
1734 return await latepoint_check_if_order_intent_still_bookable($booking_form_element);
1735 }, 1);
1736 }
1737 $booking_form_element.trigger('latepoint:submitBookingForm', [{
1738 current_step: current_step,
1739 callbacks_list: callbacks_list,
1740 is_final_submit: latepoint_check_if_booking_form_is_final_submit($booking_form_element),
1741 direction: $booking_form_element.find('.latepoint_step_direction').val()
1742 }]);
1743 try {
1744 latepoint_hide_prev_btn($booking_form_element);
1745 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
1746 } catch (error) {
1747 latepoint_show_prev_btn($booking_form_element);
1748 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
1749 return false;
1750 }
1751
1752
1753 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1754 latepoint_hide_prev_btn($booking_form_element);
1755 try {
1756 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
1757 let response = await jQuery.ajax({
1758 type: "post",
1759 dataType: "json",
1760 processData: false,
1761 contentType: false,
1762 url: latepoint_timestamped_ajaxurl(),
1763 data: latepoint_create_form_data($booking_form)
1764 });
1765
1766 $booking_form.find('.latepoint_step_direction').val('next');
1767 if (response.status === 'success') {
1768 if (response.fields_to_update) {
1769 for (const [key, value] of Object.entries(response.fields_to_update)) {
1770 $booking_form_element.find('input[name="' + key + '"]').val(value)
1771 }
1772 }
1773 if ($booking_form_element.data('flash-error')) {
1774 latepoint_show_message_inside_element($booking_form_element.data('flash-error'), $booking_form_element.find('.latepoint-body'));
1775 $booking_form_element.data('flash-error', '');
1776 }
1777 $booking_form_element.find('.latepoint_current_step_code').val(response.step_code);
1778 $booking_form_element.removeClass(function (index, className) {
1779 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
1780 }).addClass('current-step-' + response.step_code);
1781 setTimeout(function () {
1782 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1783 $booking_form_element.find('.latepoint-body').find('.latepoint-step-content').addClass('is-hidden');
1784 if ($booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]')) {
1785 $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]').remove();
1786 }
1787 $booking_form_element.find('.latepoint-body').append(response.message);
1788
1789
1790 latepoint_update_next_btn_label($booking_form_element);
1791 latepoint_init_step(response.step_code, $booking_form_element);
1792 setTimeout(function () {
1793 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1794 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1795 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1796 }, 50);
1797 }, 500);
1798
1799 if (response.is_pre_last_step) {
1800 $booking_form_element.data('next-submit-is-last', 'yes');
1801 } else {
1802 $booking_form_element.data('next-submit-is-last', 'no');
1803 }
1804 if (response.is_last_step) {
1805 $booking_form_element.addClass('hidden-buttons').find('.latepoint-footer').remove();
1806 $booking_form_element.find('.latepoint-progress').css('opacity', 0);
1807 $booking_form_element.closest('.latepoint-summary-is-open').removeClass('latepoint-summary-is-open');
1808 $booking_form_element.closest('.latepoint-show-side-panel').removeClass('latepoint-show-side-panel').addClass('latepoint-hide-side-panel');
1809 $booking_form_element.addClass('is-final-step');
1810 } else {
1811 if (response.show_next_btn === true) {
1812 latepoint_show_next_btn($booking_form_element);
1813 } else {
1814 latepoint_hide_next_btn($booking_form_element);
1815 }
1816 if (response.show_prev_btn === true) {
1817 latepoint_show_prev_btn($booking_form_element);
1818 } else {
1819 latepoint_hide_prev_btn($booking_form_element);
1820 }
1821 }
1822 latepoint_change_step_desc($booking_form_element, response.step_code);
1823 latepoint_reload_summary($booking_form_element);
1824 } else {
1825 if (response.fields_to_update) {
1826 for (const [key, value] of Object.entries(response.fields_to_update)) {
1827 $booking_form_element.find('input[name="' + key + '"]').val(value)
1828 }
1829 }
1830 if (response.callback) {
1831 let func_name = response.callback;
1832 if (func_name.includes('.')) {
1833 let func_arr = func_name.split('.');
1834 if (typeof window[func_arr[0]][func_arr[1]] !== 'function') {
1835 console.log(func_name + ' is undefined');
1836 }
1837 if (response.callback_data) {
1838 window[func_arr[0]][func_arr[1]]($booking_form_element, response.callback_data);
1839 } else {
1840 window[func_arr[0]][func_arr[1]]($booking_form_element);
1841 }
1842 } else {
1843 if (typeof window[func_name] !== 'function') {
1844 console.log(func_name + ' is undefined');
1845 }
1846 if (response.callback_data) {
1847 window[func_name]($booking_form_element, response.callback_data);
1848 } else {
1849 window[func_name]($booking_form_element);
1850 }
1851 }
1852 } else {
1853 if (response.send_to_step && response.send_to_step === 'resubmit') {
1854 let current_resubmit_count = parseInt($booking_form.data('resubmit-count')) ? parseInt($booking_form.data('resubmit-count')) : 1;
1855 $booking_form.data('resubmit-count', current_resubmit_count + 1);
1856 if (current_resubmit_count > 6) {
1857 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1858 } else {
1859 // resubmission probably caused by order intent still being processed, since
1860 // order intent is still processing, give it a little more time and try again
1861 await latepoint_sleep(2000);
1862 return latepoint_submit_booking_form($booking_form);
1863 }
1864 } else {
1865 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1866 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1867 if (response.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.send_to_step + '"]').length) {
1868 $booking_form_element.data('flash-error', response.message);
1869 latepoint_reload_step($booking_form_element, response.send_to_step);
1870 } else {
1871 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1872 latepoint_show_prev_btn($booking_form_element);
1873 }
1874 }
1875 }
1876 }
1877 } catch (e) {
1878 console.log(e);
1879 alert('Error:' + e);
1880 }
1881 }
1882
1883 function latepoint_sleep(ms) {
1884 return new Promise(resolve => setTimeout(resolve, ms));
1885 }
1886
1887 function latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element) {
1888 if (error.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + error.send_to_step + '"]').length) {
1889 latepoint_reload_step($booking_form_element, error.send_to_step);
1890 $booking_form_element.data('flash-error', error.message);
1891 } else {
1892 latepoint_show_message_inside_element(error.message, $booking_form_element.find('.latepoint-body'), 'error');
1893
1894 if ($booking_form_element.hasClass('step-content-loading')) $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1895 $booking_form_element.find('.latepoint-next-btn').removeClass('os-loading');
1896
1897 // if previous step exists - show prev button
1898 if ($booking_form_element.find('.latepoint-step-content:last-child').prev('.latepoint-step-content').length) latepoint_show_prev_btn($booking_form_element);
1899 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1900 }
1901 }
1902
1903 function latepoint_reset_active_cart_item($booking_form_element) {
1904 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
1905 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
1906 $booking_form_element.find('input[name="active_cart_item[item_data]"]').val('');
1907 }
1908
1909 function latepoint_check_if_booking_form_is_final_submit($booking_form_element) {
1910 return ($booking_form_element.data('next-submit-is-last') == 'yes');
1911 }
1912
1913
1914 async function latepoint_check_if_order_intent_still_bookable($booking_form_element) {
1915 let response = await jQuery.ajax({
1916 type: "post",
1917 dataType: "json",
1918 processData: false,
1919 contentType: false,
1920 url: latepoint_timestamped_ajaxurl(),
1921 data: latepoint_create_form_data($booking_form_element.find('.latepoint-form'), latepoint_helper.check_order_intent_bookable_route)
1922 });
1923 if (response.status === 'success') {
1924 return true;
1925 } else {
1926 throw new Error(response.message);
1927 }
1928 }
1929
1930 async function latepoint_process_list_of_callbacks(callbacks, $booking_form_element, $booking_form) {
1931 for (const callback of callbacks) {
1932 await callback.action();
1933 }
1934 }
1935
1936 function latepoint_clear_presets($booking_form_element) {
1937 $booking_form_element.find('.clear_for_new_item').val('');
1938 }
1939
1940 function latepoint_init_booking_form($booking_form_element) {
1941 $booking_form_element.on('click keydown', '.checkout-from-summary-panel-btn', function (event) {
1942 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1943 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
1944 jQuery(this).closest('.latepoint-w').removeClass('show-summary-on-mobile');
1945 return false;
1946 });
1947
1948 $booking_form_element.on('click keydown', '.latepoint-add-another-item-trigger', function (event) {
1949 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1950
1951 if (latepoint_helper.reset_presets_when_adding_new_item) {
1952 latepoint_clear_presets($booking_form_element);
1953 }
1954 latepoint_reset_active_cart_item($booking_form_element);
1955 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
1956 return false;
1957 });
1958 $booking_form_element.find('.latepoint-form').on('submit', function (e) {
1959 e.preventDefault();
1960 let $booking_form = jQuery(this);
1961 latepoint_submit_booking_form($booking_form);
1962 });
1963
1964 latepoint_init_booking_summary_panel($booking_form_element);
1965
1966 $booking_form_element.on('click keydown', '.latepoint-lightbox-summary-trigger', function (event) {
1967 event.preventDefault();
1968 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1969 let $wrapper = jQuery(this).closest('.latepoint-w');
1970 $wrapper.toggleClass('show-summary-on-mobile');
1971 return false;
1972 });
1973
1974 $booking_form_element.find('.latepoint-lightbox-close').on('click', function () {
1975
1976 let params = new URLSearchParams(location.search);
1977 if (params.has('latepoint_order_intent_key')) {
1978 params.delete('latepoint_order_intent_key');
1979 history.replaceState(null, '', '?' + params + location.hash);
1980 }
1981
1982 jQuery('body').removeClass('latepoint-lightbox-active');
1983 jQuery('.latepoint-lightbox-w').remove();
1984 return false;
1985 });
1986
1987
1988 $booking_form_element.on('click keydown', '.lp-option', function (event) {
1989 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1990 jQuery(this).closest('.lp-options').find('.lp-option.selected').removeClass('selected');
1991 jQuery(this).addClass('selected');
1992 });
1993
1994
1995 // Next Step button Click
1996 $booking_form_element.find('.latepoint-next-btn').on('click', async function (e) {
1997 e.preventDefault();
1998 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
1999 var $next_btn = jQuery(this);
2000 $next_btn.addClass('os-loading');
2001 var $booking_form = jQuery(this).closest('.latepoint-form');
2002
2003 var current_step = $booking_form_element.find('.latepoint_current_step_code').val();
2004
2005 $booking_form.find('.latepoint_step_direction').val('next');
2006 var callbacks_list = [];
2007
2008 $booking_form_element.trigger('latepoint:nextStepClicked', [{
2009 current_step: current_step,
2010 callbacks_list: callbacks_list
2011 }]);
2012 latepoint_hide_prev_btn($booking_form_element);
2013
2014 try {
2015 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
2016 await latepoint_submit_booking_form($booking_form);
2017 } catch (error) {
2018 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
2019 }
2020 return false;
2021 });
2022
2023
2024 // Previous Step button Click
2025 $booking_form_element.find('.latepoint-prev-btn').on('click', function (e) {
2026 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
2027
2028 let $current_step = $booking_form_element.find('.latepoint-step-content:last-child');
2029
2030
2031 // handle categories
2032 if ($current_step.hasClass('selecting-item-category')) {
2033 if ($current_step.find('.os-item-category-w .os-item-category-w.selected').length) {
2034 $current_step.find('.os-item-category-w .os-item-category-w.selected').parents('.os-item-category-w').addClass('selected').find('.os-item-category-w.selected').removeClass('selected');
2035 } else {
2036 $current_step.removeClass('selecting-item-category').find('.os-item-category-w.selected').removeClass('selected');
2037 $current_step.removeClass('selecting-item-category').find('.os-item-categories-holder.show-selected-only').removeClass('show-selected-only');
2038 }
2039 if (($booking_form_element.find('.latepoint-step-content').length <= 1) && !$current_step.hasClass('selecting-item-category')) {
2040 latepoint_hide_prev_btn($booking_form_element);
2041 }
2042 latepoint_reload_summary($booking_form_element);
2043 return false;
2044 }
2045
2046 if ($current_step.data('clear-action')) {
2047 window[$current_step.data('clear-action')]($booking_form_element);
2048 }
2049
2050 let $back_btn = jQuery(this);
2051 $back_btn.addClass('os-loading');
2052 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
2053 let $new_current_step = $booking_form_element.find('.latepoint-step-content.is-hidden').last();
2054 let new_current_step_code = $new_current_step.data('step-code');
2055 let current_step_code = $current_step.data('step-code');
2056
2057
2058 let current_parent_code_name = current_step_code.split('__')[0];
2059 let new_parent_code_name = new_current_step_code.split('__')[0];
2060
2061 let active_cart_item_id = $booking_form_element.find('input[name="active_cart_item[id]"]').val();
2062
2063 latepoint_change_step_desc($booking_form_element, new_current_step_code);
2064 setTimeout(function () {
2065 $new_current_step.removeClass('is-hidden');
2066 $current_step.remove();
2067 $booking_form_element.find('.latepoint_current_step_code').val(new_current_step_code);
2068 $booking_form_element.removeClass(function (index, className) {
2069 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
2070 }).addClass('current-step-' + new_current_step_code);
2071 $booking_form_element.find('.latepoint-next-btn span').text($booking_form_element.find('.latepoint-next-btn').data('label'));
2072 $booking_form_element.data('next-submit-is-last', 'no');
2073
2074 latepoint_update_next_btn_label($booking_form_element);
2075 latepoint_show_next_btn($booking_form_element);
2076 $back_btn.removeClass('os-loading');
2077 if ($booking_form_element.find('.latepoint-step-content').length <= 1) {
2078 if ($new_current_step.hasClass('selecting-item-category')) {
2079
2080 }
2081 if (new_current_step_code == 'booking__services') {
2082 var $services_step = $booking_form_element.find('.step-services-w');
2083 if ($services_step.hasClass('selecting-item-category')) {
2084 if ($services_step.find('.os-services > .os-item.selected').hasClass('is-preselected')) {
2085 // if service is preselected check if there are both multiple durations and quantity selector and only then show prev button
2086 } else {
2087 latepoint_show_prev_btn($booking_form_element);
2088 }
2089 } else {
2090 latepoint_hide_prev_btn($booking_form_element);
2091 }
2092 } else {
2093 if (!$new_current_step.hasClass('selecting-item-category')) {
2094 latepoint_hide_prev_btn($booking_form_element);
2095 }
2096 }
2097 }
2098 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
2099
2100
2101 if (new_parent_code_name == 'booking' && current_parent_code_name != 'booking' && active_cart_item_id) {
2102
2103 // we are going back to one of the steps of a booking process, we need to remove the item that was just added to the cart and start over
2104 $booking_form_element.find('.latepoint-summary-w').addClass('os-loading');
2105 let data = {
2106 action: latepoint_helper.route_action,
2107 route_name: latepoint_helper.remove_cart_item_route,
2108 params: jQuery.param({cart_item_id: active_cart_item_id}),
2109 layout: 'none',
2110 return_format: 'json'
2111 }
2112 jQuery.ajax({
2113 type: "post",
2114 dataType: "json",
2115 url: latepoint_timestamped_ajaxurl(),
2116 data: data,
2117 success: function (data) {
2118 if (data.status === "success") {
2119 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
2120 if ($booking_form_element.find('input[name="active_cart_item[variant]"]').val() == 'bundle') {
2121 latepoint_update_active_cart_item_item_data($booking_form_element, 'bundle_id', '');
2122 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
2123 }
2124 latepoint_reload_summary($booking_form_element);
2125 } else {
2126 $booking_form_element.find('.latepoint-summary-w').removeClass('os-loading');
2127 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'error');
2128 }
2129 }
2130 });
2131 } else {
2132 latepoint_reload_summary($booking_form_element);
2133 }
2134 setTimeout(function () {
2135 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
2136 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
2137 latepoint_scroll_to_top_of_booking_form($booking_form_element);
2138
2139 let callbacks_list = [];
2140 $booking_form_element.trigger('latepoint:prevStepReInit', [{
2141 current_step: new_current_step_code,
2142 callbacks_list: callbacks_list
2143 }]);
2144 }, 150);
2145 }, 700);
2146 return false;
2147 });
2148
2149 latepoint_init_agent_details_link($booking_form_element);
2150 $booking_form_element.trigger('latepoint:initBookingForm');
2151 }
2152
2153
2154 function latepoint_init_booking_form_by_trigger($trigger) {
2155 let route = latepoint_helper.booking_button_route;
2156 let params = {};
2157 let restrictions = {};
2158 let presets = {};
2159 let booking_element_styles = {};
2160 if ($trigger.data('show-service-categories')) restrictions.show_service_categories = $trigger.data('show-service-categories');
2161 if ($trigger.data('show-locations')) restrictions.show_locations = $trigger.data('show-locations');
2162 if ($trigger.data('show-services')) restrictions.show_services = $trigger.data('show-services');
2163 if ($trigger.data('show-agents')) restrictions.show_agents = $trigger.data('show-agents');
2164 if ($trigger.data('calendar-start-date')) restrictions.calendar_start_date = $trigger.data('calendar-start-date');
2165
2166 if ($trigger.data('selected-location')) presets.selected_location = $trigger.data('selected-location');
2167 if ($trigger.data('selected-agent')) presets.selected_agent = $trigger.data('selected-agent');
2168 if ($trigger.data('selected-service')) presets.selected_service = $trigger.data('selected-service');
2169 if ($trigger.data('selected-bundle')) presets.selected_bundle = $trigger.data('selected-bundle');
2170 if ($trigger.data('selected-duration')) presets.selected_duration = $trigger.data('selected-duration');
2171 if ($trigger.data('selected-total-attendees')) presets.selected_total_attendees = $trigger.data('selected-total-attendees');
2172 if ($trigger.data('selected-service-category')) presets.selected_service_category = $trigger.data('selected-service-category');
2173 if ($trigger.data('selected-start-date')) presets.selected_start_date = $trigger.data('selected-start-date');
2174 if ($trigger.data('selected-start-time')) presets.selected_start_time = $trigger.data('selected-start-time');
2175 if ($trigger.data('order-item-id')) presets.order_item_id = $trigger.data('order-item-id');
2176 if ($trigger.data('source-id')) presets.source_id = $trigger.data('source-id');
2177
2178 if ($trigger.data('hide-summary') == 'yes') booking_element_styles.hide_summary = true;
2179 if ($trigger.data('hide-side-panel') == 'yes') booking_element_styles.hide_side_panel = true;
2180
2181
2182 if (jQuery.isEmptyObject(restrictions) == false) params.restrictions = restrictions;
2183 if (jQuery.isEmptyObject(presets) == false) params.presets = presets;
2184 if (jQuery.isEmptyObject(booking_element_styles) == false) params.booking_element_styles = booking_element_styles;
2185
2186 let data = {
2187 action: latepoint_helper.route_action,
2188 route_name: route,
2189 params: params,
2190 layout: 'none',
2191 return_format: 'json'
2192 }
2193
2194 let is_inline_form = $trigger.hasClass('latepoint-book-form-wrapper');
2195 if (is_inline_form) {
2196 data.params.booking_element_type = 'inline_form';
2197 }
2198
2199 $trigger.addClass('os-loading');
2200 jQuery.ajax({
2201 type: "post",
2202 dataType: "json",
2203 url: latepoint_timestamped_ajaxurl(),
2204 data: data,
2205 success: (data) => {
2206 if (data.status === "success") {
2207 let $booking_form_element = false;
2208 if (is_inline_form) {
2209 $trigger.html(data.message);
2210 $booking_form_element = $trigger.find('.latepoint-booking-form-element');
2211 } else {
2212 let lightbox_class = 'booking-form-in-lightbox';
2213 latepoint_show_data_in_lightbox(data.message, lightbox_class, false);
2214 $booking_form_element = jQuery('.latepoint-lightbox-w .latepoint-booking-form-element');
2215 jQuery('body').addClass('latepoint-lightbox-active');
2216 }
2217 latepoint_init_booking_form($booking_form_element);
2218 latepoint_init_step(data.step, $booking_form_element);
2219 $trigger.removeClass('os-loading');
2220 } else {
2221 $trigger.removeClass('os-loading');
2222 // console.log(data.message);
2223 }
2224 }
2225 });
2226 }
2227