PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.2.9
LatePoint – Calendar Booking Plugin for Appointments and Events v5.2.9
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
2279 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 jQuery('.latepoint-login-form-w').each(function() {
1202 if(jQuery(this).data('success-action') == 'auto-redirect'){
1203 window.location.replace(jQuery(this).data('redirect-url'))
1204 }else{
1205 latepoint_init_auth_form(jQuery(this));
1206 }
1207 });
1208 }
1209 }
1210
1211 function latepoint_init_customer_dashboard() {
1212 latepoint_init_form_masks();
1213 jQuery('.latepoint-customer-timezone-selector-w select').on('change', function (e) {
1214 var $select_box = jQuery(this);
1215 $select_box.closest('.latepoint-customer-timezone-selector-w').addClass('os-loading');
1216 var data = {
1217 action: latepoint_helper.route_action,
1218 route_name: jQuery(this).closest('.latepoint-customer-timezone-selector-w').data('route-name'),
1219 params: {timezone_name: jQuery(this).val()},
1220 layout: 'none',
1221 return_format: 'json'
1222 }
1223 jQuery.ajax({
1224 type: "post",
1225 dataType: "json",
1226 url: latepoint_timestamped_ajaxurl(),
1227 data: data,
1228 success: function (data) {
1229 $select_box.closest('.latepoint-customer-timezone-selector-w').removeClass('os-loading');
1230 if (data.status === "success") {
1231 location.reload();
1232 } else {
1233
1234 }
1235 }
1236 });
1237 });
1238
1239
1240 jQuery('.latepoint-request-booking-cancellation').on('click', function () {
1241 if (!confirm(latepoint_helper.cancel_booking_prompt)) return false;
1242 var $this = jQuery(this);
1243 var $booking_box = $this.closest('.customer-booking');
1244
1245 var route = jQuery(this).data('route');
1246 var params = {id: $booking_box.data('id')};
1247
1248 var data = {
1249 action: latepoint_helper.route_action,
1250 route_name: route,
1251 params: params,
1252 layout: 'none',
1253 return_format: 'json'
1254 }
1255 $this.addClass('os-loading');
1256 jQuery.ajax({
1257 type: "post",
1258 dataType: "json",
1259 url: latepoint_timestamped_ajaxurl(),
1260 data: data,
1261 success: function (data) {
1262 if (data.status === "success") {
1263 $this.remove();
1264 location.reload();
1265 } else {
1266 $this.removeClass('os-loading');
1267 }
1268 }
1269 });
1270 return false;
1271 });
1272
1273 }
1274
1275
1276 function latepoint_get_customer_name($wrapper) {
1277 var customer_name = '';
1278 var first_name = $wrapper.find('input[name="customer[first_name]"]').val();
1279 var last_name = $wrapper.find('input[name="customer[last_name]"]').val();
1280 if (first_name) customer_name += first_name;
1281 if (last_name) customer_name += ' ' + last_name;
1282 return customer_name.trim();
1283 }
1284
1285 function latepoint_init_customer_otp_code_verify_form($booking_form_element) {
1286 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1287 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1288
1289 if ($verify_otp_btn.length && $verify_otp_input.length) {
1290 $verify_otp_input.trigger('focus');
1291
1292 // trigger on enter/space to emulate a button
1293 $verify_otp_btn.on('keydown', function (e) {
1294 if (e.key === 'Enter' || e.key === ' ') {
1295 e.preventDefault();
1296 jQuery(this).trigger('click'); // Triggers the click handler above
1297 }
1298 });
1299 // close
1300 $booking_form_element.find('.latepoint-customer-otp-resend').on('click', function (e) {
1301 e.preventDefault();
1302 latepoint_resend_customer_otp_code($booking_form_element, jQuery(this));
1303 });
1304
1305 $booking_form_element.find('.latepoint-customer-otp-close').on('click', function () {
1306 $booking_form_element.find('.latepoint-customer-otp-input-container').html('');
1307 $booking_form_element.find('.hide-when-entering-otp').removeClass('os-hidden');
1308 latepoint_show_booking_form_footer($booking_form_element);
1309 return false;
1310 });
1311
1312 // input in code field
1313 $verify_otp_input.on('input', function () {
1314 // Remove non-numeric characters
1315 const cleanValue = jQuery(this).val().replace(/[^0-9]/g, '');
1316 jQuery(this).val(cleanValue);
1317 if (cleanValue.length === 6) {
1318 $verify_otp_btn.trigger('click');
1319 }
1320 });
1321 $verify_otp_input.on('keydown', function (e) {
1322 if (e.key === 'Enter') {
1323 e.preventDefault();
1324 $verify_otp_btn.trigger('click');
1325 }
1326 });
1327
1328 $verify_otp_btn.on('click', function (e) {
1329 return latepoint_verify_customer_otp_code($booking_form_element);
1330 });
1331 }
1332
1333 }
1334
1335 async function latepoint_verify_customer_otp_code($booking_form_element) {
1336 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1337 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1338
1339 $verify_otp_input.removeClass('os-invalid');
1340 if ($verify_otp_input.val().length !== 6) {
1341 $verify_otp_input.addClass('os-invalid').addClass('os-shake');
1342 return false;
1343 }
1344
1345 $verify_otp_btn.addClass('os-loading');
1346
1347 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1348
1349 let data = {
1350 action: 'latepoint_route_call',
1351 route_name: $verify_otp_btn.data('route'),
1352 params: latepoint_formdata_to_url_encoded_string(form_data),
1353 layout: 'none',
1354 return_format: 'json'
1355 }
1356 try {
1357 let response = await jQuery.ajax({
1358 type: "post",
1359 dataType: "json",
1360 url: latepoint_timestamped_ajaxurl(),
1361 data: data
1362 });
1363 $verify_otp_btn.removeClass('os-loading');
1364 if (response.status === 'success') {
1365 if($booking_form_element.data('success-action') === 'redirect'){
1366 window.location.replace($booking_form_element.data('redirect-url'));
1367 return true;
1368 }else{
1369 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'));
1370 $booking_form_element.find('input[name="customer_contact_verification_token"]').val(response.message);
1371 latepoint_reload_step($booking_form_element);
1372 }
1373 } else {
1374 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1375 }
1376 return false;
1377 } catch (e) {
1378 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1379 throw e;
1380 }
1381 }
1382
1383 async function latepoint_show_verify_contact_form_with_otp_code($booking_form_element, form_html) {
1384 $booking_form_element.find('.latepoint-customer-otp-input-container').html(form_html);
1385 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1386 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1387 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1388 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1389 latepoint_hide_booking_form_footer($booking_form_element);
1390 }
1391
1392 function latepoint_hide_booking_form_footer($booking_form_element) {
1393 $booking_form_element.addClass('hidden-buttons');
1394 }
1395
1396 function latepoint_show_booking_form_footer($booking_form_element) {
1397 $booking_form_element.removeClass('hidden-buttons');
1398 }
1399
1400 async function latepoint_resend_customer_otp_code($booking_form_element, $resend_otp_button) {
1401 $resend_otp_button.addClass('os-loading');
1402
1403 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1404
1405 // get values from phone number fields
1406 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1407 $booking_form_element.find('input.os-mask-phone').each(function () {
1408 const phoneInputName = this.getAttribute('name');
1409 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1410 // override value generated automatically by formdata with a formatted value of a phone field with country code
1411 form_data.set(phoneInputName, phoneInputValue);
1412 });
1413 }
1414
1415 let data = {
1416 action: 'latepoint_route_call',
1417 route_name: $resend_otp_button.data('otp-resend-route'),
1418 params: latepoint_formdata_to_url_encoded_string(form_data),
1419 layout: 'none',
1420 return_format: 'json'
1421 }
1422 try {
1423 let response = await jQuery.ajax({
1424 type: "post",
1425 dataType: "json",
1426 url: latepoint_timestamped_ajaxurl(),
1427 data: data
1428 });
1429 $resend_otp_button.removeClass('os-loading');
1430 if (response.status === 'success') {
1431 latepoint_hide_message_inside_element($booking_form_element.find('.hide-when-entering-otp'));
1432 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1433 $booking_form_element.find('.latepoint-customer-otp-input-container').html(response.message);
1434 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1435 } else {
1436 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-customer-otp-input-wrapper'), 'error');
1437 }
1438 return false;
1439 } catch (e) {
1440 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.latepoint-customer-otp-input-wrapper'), 'error');
1441 throw e;
1442 }
1443 }
1444
1445 async function latepoint_request_customer_otp_code($booking_form_element, $request_otp_button) {
1446 $request_otp_button.addClass('os-loading');
1447
1448 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1449
1450
1451 // get values from phone number fields
1452 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1453 $booking_form_element.find('input.os-mask-phone').each(function () {
1454 const phoneInputName = this.getAttribute('name');
1455 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1456 // override value generated automatically by formdata with a formatted value of a phone field with country code
1457 form_data.set(phoneInputName, phoneInputValue);
1458 });
1459 }
1460
1461 let data = {
1462 action: 'latepoint_route_call',
1463 route_name: $request_otp_button.data('otp-request-route'),
1464 params: latepoint_formdata_to_url_encoded_string(form_data),
1465 layout: 'none',
1466 return_format: 'json'
1467 }
1468 try {
1469 let response = await jQuery.ajax({
1470 type: "post",
1471 dataType: "json",
1472 url: latepoint_timestamped_ajaxurl(),
1473 data: data
1474 });
1475 $request_otp_button.removeClass('os-loading');
1476 if (response.status === 'success') {
1477 latepoint_hide_message_inside_element($booking_form_element.find('.hide-when-entering-otp'));
1478 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1479 $booking_form_element.find('.latepoint-customer-otp-input-container').html(response.message);
1480 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1481 } else {
1482 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.hide-when-entering-otp'), 'error');
1483 }
1484 return false;
1485 } catch (e) {
1486 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.hide-when-entering-otp'), 'error');
1487 throw e;
1488 }
1489 }
1490
1491 function latepoint_customer_auth_load_next_step($booking_form_element) {
1492
1493 }
1494
1495 function latepoint_init_customer_otp_code_request_form($booking_form_element) {
1496 let $request_otp_button = $booking_form_element.find('.latepoint-request-otp-button');
1497 if ($request_otp_button.length > 0) {
1498 $request_otp_button.on('click', function (e) {
1499 return latepoint_request_customer_otp_code($booking_form_element, jQuery(this));
1500 });
1501 // trigger on enter/space to emulate a button
1502 $request_otp_button.on('keydown', function (e) {
1503 if (e.key === 'Enter' || e.key === ' ') {
1504 e.preventDefault();
1505 jQuery(this).trigger('click'); // Triggers the click handler above
1506 }
1507 });
1508 $booking_form_element.find('.latepoint-customer-otp-request-wrapper').find('input, select').on('keydown', function (e) {
1509 if (e.key === 'Enter') {
1510 e.preventDefault();
1511 $request_otp_button.trigger('click');
1512 }
1513 });
1514 }
1515 }
1516
1517 async function latepoint_login_customer($booking_form_element, $request_otp_button) {
1518
1519 $request_otp_button.addClass('os-loading');
1520 let $form = $booking_form_element.find('.latepoint-form');
1521
1522 let form_data = new FormData($form[0]);
1523
1524 // get values from phone number fields
1525 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1526 $form.find('input.os-mask-phone').each(function () {
1527 const phoneInputName = this.getAttribute('name');
1528 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1529 // override value generated automatically by formdata with a formatted value of a phone field with country code
1530 form_data.set(phoneInputName, phoneInputValue);
1531 });
1532 }
1533
1534 let data = {
1535 action: 'latepoint_route_call',
1536 route_name: $request_otp_button.data('password-login-route'),
1537 params: latepoint_formdata_to_url_encoded_string(form_data),
1538 layout: 'none',
1539 return_format: 'json'
1540 }
1541 try {
1542 let response = await jQuery.ajax({
1543 type: "post",
1544 dataType: "json",
1545 url: latepoint_timestamped_ajaxurl(),
1546 data: data
1547 });
1548 $request_otp_button.removeClass('os-loading');
1549
1550 if (response.status === "success") {
1551 if($booking_form_element.data('success-action') === 'redirect'){
1552 window.location.replace($booking_form_element.data('redirect-url'));
1553 return true;
1554 }else {
1555 return latepoint_reload_step($booking_form_element);
1556 }
1557 } else {
1558 throw new Error(response.message);
1559 }
1560 } catch (e) {
1561 latepoint_show_message_inside_element(e.message, $booking_form_element.find('.os-step-existing-customer-login-w'));
1562 }
1563
1564 }
1565
1566
1567 function latepoint_init_auth_form($wrapper){
1568
1569 latepoint_init_customer_otp_code_request_form($wrapper);
1570 latepoint_init_customer_otp_code_verify_form($wrapper);
1571
1572
1573 $wrapper.find('.login-with-password-toggle').on('change', function () {
1574 if (jQuery(this).hasClass('os-opposite')) {
1575 if (jQuery(this).is(':checked')) {
1576 $wrapper.find('.os-customer-otp-notice').hide();
1577 $wrapper.find('.os-customer-login-password-fields-w').show();
1578 } else {
1579 $wrapper.find('.os-customer-otp-notice').show();
1580 $wrapper.find('.os-customer-login-password-fields-w').hide();
1581 }
1582 } else {
1583 if (jQuery(this).is(':checked')) {
1584 $wrapper.find('.os-customer-otp-notice').show();
1585 $wrapper.find('.os-customer-login-password-fields-w').hide();
1586 } else {
1587 $wrapper.find('.os-customer-otp-notice').hide();
1588 $wrapper.find('.os-customer-login-password-fields-w').show();
1589 }
1590 }
1591 });
1592
1593 $wrapper.find('.alternative-login-option').on('click', function () {
1594 let login_method = jQuery(this).data('auth-via');
1595 let delivery_method = jQuery(this).data('otp-delivery-method');
1596 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1597 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1598 $wrapper.find('.customer-login-method-wrapper').addClass('os-hidden');
1599 $wrapper.find('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1600 $wrapper.find('.alternative-login-option').removeClass('os-hidden');
1601 jQuery(this).addClass('os-hidden');
1602 return false;
1603 });
1604
1605 $wrapper.find('.login-options-via-wrapper .login-option').on('click', function () {
1606 let $wrapper = jQuery(this).closest('.latepoint-customer-auth-options-wrapper');
1607 let login_method = jQuery(this).data('login-method');
1608 let delivery_method = jQuery(this).data('otp-delivery-method');
1609
1610 let otp_enabled = jQuery(this).data('is-otp-enabled');
1611 if(otp_enabled === 'no'){
1612 if($wrapper.find('.login-with-password-toggle.os-opposite:not(:checked)').length){
1613 $wrapper.find('.login-with-password-toggle.os-opposite').trigger('click');
1614 }
1615 $wrapper.find('.latepoint-customer-otp-option').hide();
1616 $wrapper.find('.step-login-existing-customer-btn').addClass('latepoint-btn-block');
1617 }else{
1618 if($wrapper.find('.latepoint-customer-otp-option').length){
1619 $wrapper.find('.latepoint-customer-otp-option').show();
1620 $wrapper.find('.step-login-existing-customer-btn').removeClass('latepoint-btn-block');
1621 }
1622 }
1623 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1624 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1625 jQuery(this).closest('.login-options-via-wrapper').find('.login-option.os-selected').removeClass('os-selected')
1626 jQuery(this).addClass('os-selected');
1627 jQuery('.customer-login-method-wrapper').addClass('os-hidden');
1628 jQuery('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1629
1630 return false;
1631 });
1632
1633 // Init Login Existing Customer Button
1634 $wrapper.find('.os-customer-login-w input').on('keyup', function (e) {
1635 if (e.keyCode === 13) {
1636 e.preventDefault();
1637 $wrapper.find('.step-login-existing-customer-btn').trigger('click');
1638 return false;
1639 }
1640 });
1641
1642 $wrapper.find('.step-login-existing-customer-btn').on('click', function (e) {
1643 e.preventDefault();
1644 let via = $wrapper.find('input[name="auth[via]"]').val();
1645 if ($wrapper.find('input[name="auth[via]"]').is(':checkbox')) {
1646 let is_checked = $wrapper.find('input[name="auth[via]"]').is(':checked');
1647 if (via === 'otp' && !is_checked) {
1648 via = 'password';
1649 } else if (via === 'password' && !is_checked) {
1650 via = 'otp';
1651 }
1652 }
1653 if (via === 'otp') {
1654 latepoint_request_customer_otp_code($wrapper, jQuery(this));
1655 } else if (via === 'password') {
1656 latepoint_login_customer($wrapper, jQuery(this));
1657 }
1658
1659 });
1660 }
1661
1662 function latepoint_init_step_customer($booking_form_element) {
1663 latepoint_init_form_masks();
1664
1665 latepoint_init_auth_form($booking_form_element);
1666
1667 // Init Logout button
1668 $booking_form_element.find('.step-customer-logout-btn').on('click', function () {
1669 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1670 $booking_form_element.find('input[name="customer_contact_verification_token"]').val('');
1671 let data = {
1672 action: latepoint_helper.route_action,
1673 route_name: jQuery(this).data('btn-action'),
1674 layout: 'none',
1675 return_format: 'json'
1676 }
1677 latepoint_step_content_change_start($booking_form_element);
1678 jQuery.ajax({
1679 type: "post",
1680 dataType: "json",
1681 url: latepoint_timestamped_ajaxurl(),
1682 data: data,
1683 success: function (data) {
1684 $booking_form_element.find('input[name="auth[action]"]').val('logout');
1685 latepoint_reload_step($booking_form_element);
1686 }
1687 });
1688 return false;
1689 });
1690
1691
1692 }
1693
1694 function latepoint_step_content_change_start($booking_form_element) {
1695 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1696 }
1697
1698 // TODO
1699 function latepoint_step_content_change_end(new_content, $booking_form_element) {
1700 if (new_content) $booking_form_element.find('.latepoint-body .latepoint-step-content').replaceWith(new_content);
1701 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1702 setTimeout(function () {
1703 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1704 }, 50);
1705 }
1706
1707
1708 function latepoint_change_step_desc($booking_form_element, step_code) {
1709 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1710 setTimeout(function () {
1711 // Progress bar
1712 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1713 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1714 $step_progress.nextAll().removeClass('complete').removeClass('active');
1715 // Side panel
1716 var side_panel_desc = $booking_form_element.find('.latepoint-step-desc-library[data-step-code="' + step_code + '"]').html();
1717 $booking_form_element.find('.latepoint-step-desc').html(side_panel_desc);
1718
1719 // Top header
1720 var top_header_desc = $booking_form_element.find('.os-heading-text-library[data-step-code="' + step_code + '"]').html();
1721 $booking_form_element.find('.os-heading-text').html(top_header_desc);
1722 setTimeout(function () {
1723 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1724 }, 50);
1725 }, 500);
1726 }
1727
1728
1729 function latepoint_progress_prev($booking_form_element, step_code) {
1730 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1731 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1732 $step_progress.nextAll().removeClass('complete').removeClass('active');
1733 }
1734
1735
1736 function latepoint_progress_next($booking_form_element, step_code) {
1737 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1738 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1739 $step_progress.nextAll().removeClass('complete').removeClass('active');
1740 }
1741
1742
1743 function latepoint_next_step_description($booking_form_element, step_code) {
1744 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1745 setTimeout(function () {
1746 $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());
1747 $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());
1748 setTimeout(function () {
1749 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1750 }, 50);
1751 }, 500);
1752 }
1753
1754 function latepoint_prev_step_description($booking_form_element, step_code) {
1755 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1756 setTimeout(function () {
1757 $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());
1758 $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());
1759 setTimeout(function () {
1760 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1761 }, 50);
1762 }, 500);
1763 }
1764
1765
1766 function latepoint_validate_fields($fields) {
1767 var is_valid = true;
1768 $fields.each(function (index) {
1769 if (jQuery(this).val() == '') {
1770 is_valid = false;
1771 return false;
1772 }
1773 });
1774 return is_valid;
1775 }
1776
1777
1778 async function latepoint_submit_booking_form($booking_form) {
1779 let $booking_form_element = $booking_form.closest('.latepoint-booking-form-element');
1780
1781 let current_step = $booking_form_element.find('.latepoint_current_step_code').val();
1782 let callbacks_list = [];
1783 if (latepoint_check_if_booking_form_is_final_submit($booking_form_element)) {
1784 // check if order intent is still bookable
1785 latepoint_add_action(callbacks_list, async () => {
1786 return await latepoint_check_if_order_intent_still_bookable($booking_form_element);
1787 }, 1);
1788 }
1789 $booking_form_element.trigger('latepoint:submitBookingForm', [{
1790 current_step: current_step,
1791 callbacks_list: callbacks_list,
1792 is_final_submit: latepoint_check_if_booking_form_is_final_submit($booking_form_element),
1793 direction: $booking_form_element.find('.latepoint_step_direction').val()
1794 }]);
1795 try {
1796 latepoint_hide_prev_btn($booking_form_element);
1797 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
1798 } catch (error) {
1799 latepoint_show_prev_btn($booking_form_element);
1800 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
1801 return false;
1802 }
1803
1804
1805 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1806 latepoint_hide_prev_btn($booking_form_element);
1807 try {
1808 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
1809 let response = await jQuery.ajax({
1810 type: "post",
1811 dataType: "json",
1812 processData: false,
1813 contentType: false,
1814 url: latepoint_timestamped_ajaxurl(),
1815 data: latepoint_create_form_data($booking_form)
1816 });
1817
1818 $booking_form.find('.latepoint_step_direction').val('next');
1819 if (response.status === 'success') {
1820 if (response.fields_to_update) {
1821 for (const [key, value] of Object.entries(response.fields_to_update)) {
1822 $booking_form_element.find('input[name="' + key + '"]').val(value)
1823 }
1824 }
1825 if ($booking_form_element.data('flash-error')) {
1826 latepoint_show_message_inside_element($booking_form_element.data('flash-error'), $booking_form_element.find('.latepoint-body'));
1827 $booking_form_element.data('flash-error', '');
1828 }
1829 $booking_form_element.find('.latepoint_current_step_code').val(response.step_code);
1830 $booking_form_element.removeClass(function (index, className) {
1831 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
1832 }).addClass('current-step-' + response.step_code);
1833 setTimeout(function () {
1834 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1835 $booking_form_element.find('.latepoint-body').find('.latepoint-step-content').addClass('is-hidden');
1836 if ($booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]')) {
1837 $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]').remove();
1838 }
1839 $booking_form_element.find('.latepoint-body').append(response.message);
1840
1841
1842 latepoint_update_next_btn_label($booking_form_element);
1843 latepoint_init_step(response.step_code, $booking_form_element);
1844 setTimeout(function () {
1845 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1846 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1847 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1848 }, 50);
1849 }, 500);
1850
1851 if (response.is_pre_last_step) {
1852 $booking_form_element.data('next-submit-is-last', 'yes');
1853 } else {
1854 $booking_form_element.data('next-submit-is-last', 'no');
1855 }
1856 if (response.is_last_step) {
1857 $booking_form_element.addClass('hidden-buttons').find('.latepoint-footer').remove();
1858 $booking_form_element.find('.latepoint-progress').css('opacity', 0);
1859 $booking_form_element.closest('.latepoint-summary-is-open').removeClass('latepoint-summary-is-open');
1860 $booking_form_element.closest('.latepoint-show-side-panel').removeClass('latepoint-show-side-panel').addClass('latepoint-hide-side-panel');
1861 $booking_form_element.addClass('is-final-step');
1862 } else {
1863 if (response.show_next_btn === true) {
1864 latepoint_show_next_btn($booking_form_element);
1865 } else {
1866 latepoint_hide_next_btn($booking_form_element);
1867 }
1868 if (response.show_prev_btn === true) {
1869 latepoint_show_prev_btn($booking_form_element);
1870 } else {
1871 latepoint_hide_prev_btn($booking_form_element);
1872 }
1873 }
1874 latepoint_change_step_desc($booking_form_element, response.step_code);
1875 latepoint_reload_summary($booking_form_element);
1876 } else {
1877 if (response.fields_to_update) {
1878 for (const [key, value] of Object.entries(response.fields_to_update)) {
1879 $booking_form_element.find('input[name="' + key + '"]').val(value)
1880 }
1881 }
1882 if (response.callback) {
1883 let func_name = response.callback;
1884 if (func_name.includes('.')) {
1885 let func_arr = func_name.split('.');
1886 if (typeof window[func_arr[0]][func_arr[1]] !== 'function') {
1887 console.log(func_name + ' is undefined');
1888 }
1889 if (response.callback_data) {
1890 window[func_arr[0]][func_arr[1]]($booking_form_element, response.callback_data);
1891 } else {
1892 window[func_arr[0]][func_arr[1]]($booking_form_element);
1893 }
1894 } else {
1895 if (typeof window[func_name] !== 'function') {
1896 console.log(func_name + ' is undefined');
1897 }
1898 if (response.callback_data) {
1899 window[func_name]($booking_form_element, response.callback_data);
1900 } else {
1901 window[func_name]($booking_form_element);
1902 }
1903 }
1904 } else {
1905 if (response.send_to_step && response.send_to_step === 'resubmit') {
1906 let current_resubmit_count = parseInt($booking_form.data('resubmit-count')) ? parseInt($booking_form.data('resubmit-count')) : 1;
1907 $booking_form.data('resubmit-count', current_resubmit_count + 1);
1908 if (current_resubmit_count > 6) {
1909 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1910 } else {
1911 // resubmission probably caused by order intent still being processed, since
1912 // order intent is still processing, give it a little more time and try again
1913 await latepoint_sleep(2000);
1914 return latepoint_submit_booking_form($booking_form);
1915 }
1916 } else {
1917 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1918 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1919 if (response.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.send_to_step + '"]').length) {
1920 $booking_form_element.data('flash-error', response.message);
1921 latepoint_reload_step($booking_form_element, response.send_to_step);
1922 } else {
1923 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1924 latepoint_show_prev_btn($booking_form_element);
1925 }
1926 }
1927 }
1928 }
1929 } catch (e) {
1930 console.log(e);
1931 alert('Error:' + e);
1932 }
1933 }
1934
1935 function latepoint_sleep(ms) {
1936 return new Promise(resolve => setTimeout(resolve, ms));
1937 }
1938
1939 function latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element) {
1940 if (error.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + error.send_to_step + '"]').length) {
1941 latepoint_reload_step($booking_form_element, error.send_to_step);
1942 $booking_form_element.data('flash-error', error.message);
1943 } else {
1944 latepoint_show_message_inside_element(error.message, $booking_form_element.find('.latepoint-body'), 'error');
1945
1946 if ($booking_form_element.hasClass('step-content-loading')) $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1947 $booking_form_element.find('.latepoint-next-btn').removeClass('os-loading');
1948
1949 // if previous step exists - show prev button
1950 if ($booking_form_element.find('.latepoint-step-content:last-child').prev('.latepoint-step-content').length) latepoint_show_prev_btn($booking_form_element);
1951 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1952 }
1953 }
1954
1955 function latepoint_reset_active_cart_item($booking_form_element) {
1956 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
1957 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
1958 $booking_form_element.find('input[name="active_cart_item[item_data]"]').val('');
1959 }
1960
1961 function latepoint_check_if_booking_form_is_final_submit($booking_form_element) {
1962 return ($booking_form_element.data('next-submit-is-last') == 'yes');
1963 }
1964
1965
1966 async function latepoint_check_if_order_intent_still_bookable($booking_form_element) {
1967 let response = await jQuery.ajax({
1968 type: "post",
1969 dataType: "json",
1970 processData: false,
1971 contentType: false,
1972 url: latepoint_timestamped_ajaxurl(),
1973 data: latepoint_create_form_data($booking_form_element.find('.latepoint-form'), latepoint_helper.check_order_intent_bookable_route)
1974 });
1975 if (response.status === 'success') {
1976 return true;
1977 } else {
1978 throw new Error(response.message);
1979 }
1980 }
1981
1982 async function latepoint_process_list_of_callbacks(callbacks, $booking_form_element, $booking_form) {
1983 for (const callback of callbacks) {
1984 await callback.action();
1985 }
1986 }
1987
1988 function latepoint_clear_presets($booking_form_element) {
1989 $booking_form_element.find('.clear_for_new_item').val('');
1990 }
1991
1992 function latepoint_init_booking_form($booking_form_element) {
1993 $booking_form_element.on('click keydown', '.checkout-from-summary-panel-btn', function (event) {
1994 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1995 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
1996 jQuery(this).closest('.latepoint-w').removeClass('show-summary-on-mobile');
1997 return false;
1998 });
1999
2000 $booking_form_element.on('click keydown', '.latepoint-add-another-item-trigger', function (event) {
2001 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2002
2003 if (latepoint_helper.reset_presets_when_adding_new_item) {
2004 latepoint_clear_presets($booking_form_element);
2005 }
2006 latepoint_reset_active_cart_item($booking_form_element);
2007 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
2008 return false;
2009 });
2010 $booking_form_element.find('.latepoint-form').on('submit', function (e) {
2011 e.preventDefault();
2012 let $booking_form = jQuery(this);
2013 latepoint_submit_booking_form($booking_form);
2014 });
2015
2016 latepoint_init_booking_summary_panel($booking_form_element);
2017
2018 $booking_form_element.on('click keydown', '.latepoint-lightbox-summary-trigger', function (event) {
2019 event.preventDefault();
2020 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2021 let $wrapper = jQuery(this).closest('.latepoint-w');
2022 $wrapper.toggleClass('show-summary-on-mobile');
2023 return false;
2024 });
2025
2026 $booking_form_element.find('.latepoint-lightbox-close').on('click', function () {
2027
2028 let params = new URLSearchParams(location.search);
2029 if (params.has('latepoint_order_intent_key')) {
2030 params.delete('latepoint_order_intent_key');
2031 history.replaceState(null, '', '?' + params + location.hash);
2032 }
2033
2034 jQuery('body').removeClass('latepoint-lightbox-active');
2035 jQuery('.latepoint-lightbox-w').remove();
2036 return false;
2037 });
2038
2039
2040 $booking_form_element.on('click keydown', '.lp-option', function (event) {
2041 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2042 jQuery(this).closest('.lp-options').find('.lp-option.selected').removeClass('selected');
2043 jQuery(this).addClass('selected');
2044 });
2045
2046
2047 // Next Step button Click
2048 $booking_form_element.find('.latepoint-next-btn').on('click', async function (e) {
2049 e.preventDefault();
2050 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
2051 var $next_btn = jQuery(this);
2052 $next_btn.addClass('os-loading');
2053 var $booking_form = jQuery(this).closest('.latepoint-form');
2054
2055 var current_step = $booking_form_element.find('.latepoint_current_step_code').val();
2056
2057 $booking_form.find('.latepoint_step_direction').val('next');
2058 var callbacks_list = [];
2059
2060 $booking_form_element.trigger('latepoint:nextStepClicked', [{
2061 current_step: current_step,
2062 callbacks_list: callbacks_list
2063 }]);
2064 latepoint_hide_prev_btn($booking_form_element);
2065
2066 try {
2067 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
2068 await latepoint_submit_booking_form($booking_form);
2069 } catch (error) {
2070 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
2071 }
2072 return false;
2073 });
2074
2075
2076 // Previous Step button Click
2077 $booking_form_element.find('.latepoint-prev-btn').on('click', function (e) {
2078 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
2079
2080 let $current_step = $booking_form_element.find('.latepoint-step-content:last-child');
2081
2082
2083 // handle categories
2084 if ($current_step.hasClass('selecting-item-category')) {
2085 if ($current_step.find('.os-item-category-w .os-item-category-w.selected').length) {
2086 $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');
2087 } else {
2088 $current_step.removeClass('selecting-item-category').find('.os-item-category-w.selected').removeClass('selected');
2089 $current_step.removeClass('selecting-item-category').find('.os-item-categories-holder.show-selected-only').removeClass('show-selected-only');
2090 }
2091 if (($booking_form_element.find('.latepoint-step-content').length <= 1) && !$current_step.hasClass('selecting-item-category')) {
2092 latepoint_hide_prev_btn($booking_form_element);
2093 }
2094 latepoint_reload_summary($booking_form_element);
2095 return false;
2096 }
2097
2098 if ($current_step.data('clear-action')) {
2099 window[$current_step.data('clear-action')]($booking_form_element);
2100 }
2101
2102 let $back_btn = jQuery(this);
2103 $back_btn.addClass('os-loading');
2104 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
2105 let $new_current_step = $booking_form_element.find('.latepoint-step-content.is-hidden').last();
2106 let new_current_step_code = $new_current_step.data('step-code');
2107 let current_step_code = $current_step.data('step-code');
2108
2109
2110 let current_parent_code_name = current_step_code.split('__')[0];
2111 let new_parent_code_name = new_current_step_code.split('__')[0];
2112
2113 let active_cart_item_id = $booking_form_element.find('input[name="active_cart_item[id]"]').val();
2114
2115 latepoint_change_step_desc($booking_form_element, new_current_step_code);
2116 setTimeout(function () {
2117 $new_current_step.removeClass('is-hidden');
2118 $current_step.remove();
2119 $booking_form_element.find('.latepoint_current_step_code').val(new_current_step_code);
2120 $booking_form_element.removeClass(function (index, className) {
2121 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
2122 }).addClass('current-step-' + new_current_step_code);
2123 $booking_form_element.find('.latepoint-next-btn span').text($booking_form_element.find('.latepoint-next-btn').data('label'));
2124 $booking_form_element.data('next-submit-is-last', 'no');
2125
2126 latepoint_update_next_btn_label($booking_form_element);
2127 latepoint_show_next_btn($booking_form_element);
2128 $back_btn.removeClass('os-loading');
2129 if ($booking_form_element.find('.latepoint-step-content').length <= 1) {
2130 if ($new_current_step.hasClass('selecting-item-category')) {
2131
2132 }
2133 if (new_current_step_code == 'booking__services') {
2134 var $services_step = $booking_form_element.find('.step-services-w');
2135 if ($services_step.hasClass('selecting-item-category')) {
2136 if ($services_step.find('.os-services > .os-item.selected').hasClass('is-preselected')) {
2137 // if service is preselected check if there are both multiple durations and quantity selector and only then show prev button
2138 } else {
2139 latepoint_show_prev_btn($booking_form_element);
2140 }
2141 } else {
2142 latepoint_hide_prev_btn($booking_form_element);
2143 }
2144 } else {
2145 if (!$new_current_step.hasClass('selecting-item-category')) {
2146 latepoint_hide_prev_btn($booking_form_element);
2147 }
2148 }
2149 }
2150 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
2151
2152
2153 if (new_parent_code_name == 'booking' && current_parent_code_name != 'booking' && active_cart_item_id) {
2154
2155 // 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
2156 $booking_form_element.find('.latepoint-summary-w').addClass('os-loading');
2157 let data = {
2158 action: latepoint_helper.route_action,
2159 route_name: latepoint_helper.remove_cart_item_route,
2160 params: jQuery.param({cart_item_id: active_cart_item_id}),
2161 layout: 'none',
2162 return_format: 'json'
2163 }
2164 jQuery.ajax({
2165 type: "post",
2166 dataType: "json",
2167 url: latepoint_timestamped_ajaxurl(),
2168 data: data,
2169 success: function (data) {
2170 if (data.status === "success") {
2171 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
2172 if ($booking_form_element.find('input[name="active_cart_item[variant]"]').val() == 'bundle') {
2173 latepoint_update_active_cart_item_item_data($booking_form_element, 'bundle_id', '');
2174 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
2175 }
2176 latepoint_reload_summary($booking_form_element);
2177 } else {
2178 $booking_form_element.find('.latepoint-summary-w').removeClass('os-loading');
2179 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'error');
2180 }
2181 }
2182 });
2183 } else {
2184 latepoint_reload_summary($booking_form_element);
2185 }
2186 setTimeout(function () {
2187 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
2188 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
2189 latepoint_scroll_to_top_of_booking_form($booking_form_element);
2190
2191 let callbacks_list = [];
2192 $booking_form_element.trigger('latepoint:prevStepReInit', [{
2193 current_step: new_current_step_code,
2194 callbacks_list: callbacks_list
2195 }]);
2196 }, 150);
2197 }, 700);
2198 return false;
2199 });
2200
2201 latepoint_init_agent_details_link($booking_form_element);
2202 $booking_form_element.trigger('latepoint:initBookingForm');
2203 }
2204
2205
2206 function latepoint_init_booking_form_by_trigger($trigger) {
2207 let route = latepoint_helper.booking_button_route;
2208 let params = {};
2209 let restrictions = {};
2210 let presets = {};
2211 let booking_element_styles = {};
2212 if ($trigger.data('show-service-categories')) restrictions.show_service_categories = $trigger.data('show-service-categories');
2213 if ($trigger.data('show-locations')) restrictions.show_locations = $trigger.data('show-locations');
2214 if ($trigger.data('show-services')) restrictions.show_services = $trigger.data('show-services');
2215 if ($trigger.data('show-agents')) restrictions.show_agents = $trigger.data('show-agents');
2216 if ($trigger.data('calendar-start-date')) restrictions.calendar_start_date = $trigger.data('calendar-start-date');
2217
2218 if ($trigger.data('selected-location')) presets.selected_location = $trigger.data('selected-location');
2219 if ($trigger.data('selected-agent')) presets.selected_agent = $trigger.data('selected-agent');
2220 if ($trigger.data('selected-service')) presets.selected_service = $trigger.data('selected-service');
2221 if ($trigger.data('selected-bundle')) presets.selected_bundle = $trigger.data('selected-bundle');
2222 if ($trigger.data('selected-duration')) presets.selected_duration = $trigger.data('selected-duration');
2223 if ($trigger.data('selected-total-attendees')) presets.selected_total_attendees = $trigger.data('selected-total-attendees');
2224 if ($trigger.data('selected-service-category')) presets.selected_service_category = $trigger.data('selected-service-category');
2225 if ($trigger.data('selected-start-date')) presets.selected_start_date = $trigger.data('selected-start-date');
2226 if ($trigger.data('selected-start-time')) presets.selected_start_time = $trigger.data('selected-start-time');
2227 if ($trigger.data('order-item-id')) presets.order_item_id = $trigger.data('order-item-id');
2228 if ($trigger.data('source-id')) presets.source_id = $trigger.data('source-id');
2229
2230 if ($trigger.data('hide-summary') == 'yes') booking_element_styles.hide_summary = true;
2231 if ($trigger.data('hide-side-panel') == 'yes') booking_element_styles.hide_side_panel = true;
2232
2233
2234 if (jQuery.isEmptyObject(restrictions) == false) params.restrictions = restrictions;
2235 if (jQuery.isEmptyObject(presets) == false) params.presets = presets;
2236 if (jQuery.isEmptyObject(booking_element_styles) == false) params.booking_element_styles = booking_element_styles;
2237
2238 let data = {
2239 action: latepoint_helper.route_action,
2240 route_name: route,
2241 params: params,
2242 layout: 'none',
2243 return_format: 'json'
2244 }
2245
2246 let is_inline_form = $trigger.hasClass('latepoint-book-form-wrapper');
2247 if (is_inline_form) {
2248 data.params.booking_element_type = 'inline_form';
2249 }
2250
2251 $trigger.addClass('os-loading');
2252 jQuery.ajax({
2253 type: "post",
2254 dataType: "json",
2255 url: latepoint_timestamped_ajaxurl(),
2256 data: data,
2257 success: (data) => {
2258 if (data.status === "success") {
2259 let $booking_form_element = false;
2260 if (is_inline_form) {
2261 $trigger.html(data.message);
2262 $booking_form_element = $trigger.find('.latepoint-booking-form-element');
2263 } else {
2264 let lightbox_class = 'booking-form-in-lightbox';
2265 latepoint_show_data_in_lightbox(data.message, lightbox_class, false);
2266 $booking_form_element = jQuery('.latepoint-lightbox-w .latepoint-booking-form-element');
2267 jQuery('body').addClass('latepoint-lightbox-active');
2268 }
2269 latepoint_init_booking_form($booking_form_element);
2270 latepoint_init_step(data.step, $booking_form_element);
2271 $trigger.removeClass('os-loading');
2272 } else {
2273 $trigger.removeClass('os-loading');
2274 // console.log(data.message);
2275 }
2276 }
2277 });
2278 }
2279