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