PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.6.3
LatePoint – Calendar Booking Plugin for Appointments and Events v5.6.3
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 _razorpay_connect.js 1 month ago _stripe_connect.js 1 year ago main.js 1 week ago
main.js
2300 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 let result = await latepoint_monthly_calendar_load_next_month($booking_form_element);
726 latepoint_datepicker_toggle_no_availability_message($booking_form_element);
727 return result;
728 });
729 $booking_form_element.find('.os-month-prev-btn').on('click', function () {
730 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
731 if ($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length) {
732 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active');
733 latepoint_calendar_set_month_label($booking_form_element);
734 }
735 latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element);
736 latepoint_datepicker_toggle_no_availability_message($booking_form_element);
737 return false;
738 });
739 }
740
741 function latepoint_calendar_set_month_label($booking_form_element) {
742 $booking_form_element.find('.os-current-month-label .current-year').text($booking_form_element.find('.os-monthly-calendar-days-w.active').data('calendar-year'));
743 $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'));
744 }
745
746
747 function latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element) {
748 $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'));
749 $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'));
750
751 if ($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length) {
752 $booking_form_element.find('.os-month-prev-btn').removeClass('disabled');
753 } else {
754 $booking_form_element.find('.os-month-prev-btn').addClass('disabled');
755 }
756 }
757
758 function latepoint_format_minutes_to_time(minutes, service_duration) {
759 var ampm = latepoint_am_or_pm(minutes);
760 var formatted_time = latepoint_minutes_to_hours_and_minutes(minutes) + ' ' + ampm;
761 if (latepoint_show_booking_end_time()) {
762 var end_minutes = minutes + service_duration;
763 var end_minutes_ampm = latepoint_am_or_pm(end_minutes);
764 formatted_time += ' - ' + latepoint_minutes_to_hours_and_minutes(end_minutes) + ' ' + end_minutes_ampm;
765 }
766 formatted_time = formatted_time.trim();
767 return formatted_time;
768 }
769
770 function latepoint_monthly_calendar_day_clicked(event) {
771 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
772 let $day = jQuery(this);
773 if ($day.hasClass('os-day-passed')) return false;
774 if ($day.hasClass('os-not-in-allowed-period')) return false;
775 if ($day.closest('.os-dates-and-times-w').hasClass('calendar-style-modern')) {
776 if ($day.hasClass('os-month-prev')) return false;
777 if ($day.hasClass('os-month-next')) return false;
778 }
779 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
780 if ($day.closest('.os-recurrence-datepicker-wrapper').length) {
781 // recurrent datepicker
782 $day.closest('.os-recurrence-datepicker-wrapper').find('.os-day.selected').removeClass('selected');
783 $day.addClass('selected');
784 if ($day.closest('.os-dates-and-times-w').hasClass('days-only')) {
785 $day.closest('.step-recurring-bookings-w').find('input[name="recurrence[rules][repeat_end_date]"]').val($day.data('date'));
786 window.latepointRecurringBookingsFrontFeature.reload_recurrence_rules($booking_form_element, true);
787 } else {
788 latepoint_generate_day_timeslots($day);
789 $day.closest('.os-recurrence-datepicker-wrapper').find('.time-selector-w')[0].scrollIntoView({block: "nearest", behavior: 'smooth'});
790 }
791 } else {
792 // regular datepicker
793 if ($day.closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')) {
794 // HIDE TIMESLOT IF ONLY ONE TIMEPOINT
795 if ($day.hasClass('os-not-available')) {
796 // clicked on a day that has no available timeslots
797 // do nothing
798 } else {
799 $booking_form_element.find('.os-day.selected').removeClass('selected');
800 $day.addClass('selected');
801 // set date
802 $booking_form_element.find('.latepoint_start_date').val($day.data('date'));
803 if ($day.hasClass('os-one-slot-only')) {
804 // clicked on a day that has only one slot available
805 var bookable_minutes = $day.data('bookable-minutes').toString().split(':')[0];
806 var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number($day.data('service-duration')));
807 $booking_form_element.find('.latepoint_start_time').val($day.data('bookable-minutes'));
808 latepoint_show_next_btn($booking_form_element);
809 $booking_form_element.find('.time-selector-w').slideUp(200);
810 } else {
811 // regular day with more than 1 timeslots available
812 // build timeslots
813 latepoint_generate_day_timeslots($day);
814 // clear time and hide next btn
815 $booking_form_element.find('.latepoint_start_time').val('');
816 latepoint_hide_next_btn($booking_form_element);
817 }
818 latepoint_reload_summary($booking_form_element);
819 }
820 } else {
821
822 // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT
823 $booking_form_element.find('.latepoint_start_date').val($day.data('date'));
824 $booking_form_element.find('.os-day.selected').removeClass('selected');
825 $day.addClass('selected');
826
827 // build timeslots
828 latepoint_generate_day_timeslots($day);
829 // clear time and hide next btn
830 latepoint_reload_summary($booking_form_element);
831 $booking_form_element.find('.latepoint_start_time').val('');
832 latepoint_hide_next_btn($booking_form_element);
833 }
834 }
835
836
837 return false;
838 }
839
840 // shows the "no availability" message when no loaded month has a day available for booking, hides it otherwise
841 function latepoint_datepicker_toggle_no_availability_message($booking_form_element) {
842 let has_available = $booking_form_element.find('.os-day.os-month-current').not('.os-not-available').length > 0;
843 $booking_form_element.find('.os-no-availability-message').toggle(!has_available);
844 }
845
846 async function latepoint_init_step_datepicker($booking_form_element = false) {
847 if (!$booking_form_element) return true;
848 latepoint_init_timeslots($booking_form_element);
849 latepoint_init_monthly_calendar_navigation($booking_form_element);
850 $booking_form_element.off('click', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
851 $booking_form_element.on('click', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
852 $booking_form_element.off('keydown', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
853 $booking_form_element.on('keydown', '.os-months .os-day', latepoint_monthly_calendar_day_clicked);
854
855 if ($booking_form_element.find('input[name="booking[start_date]"]').val()) {
856 $booking_form_element.find('.os-day[data-date="' + $booking_form_element.find('input[name="booking[start_date]"]').val() + '"]').trigger('click');
857 } else {
858 if ($booking_form_element.find('.os-dates-and-times-w').hasClass('auto-search')) {
859 let max_number_of_months_to_check = 24;
860 let current_year = new Date().getFullYear();
861 for (let i = 0; i < max_number_of_months_to_check; i++) {
862 let $active_month = $booking_form_element.find('.os-monthly-calendar-days-w.active');
863 let searching_month_label = $active_month.data('calendar-month-label');
864 if ($active_month.data('calendar-year') != current_year) searching_month_label += ' ' + $active_month.data('calendar-year');
865 $booking_form_element.find('.os-calendar-searching-info span').text(searching_month_label);
866 // check if active month has any days available for booking
867 let $first_available = $active_month.find('.os-day.os-month-current').not('.os-not-available').first();
868 if ($first_available.length) {
869 break;
870 } else {
871 await latepoint_monthly_calendar_load_next_month($booking_form_element);
872 }
873 }
874 }
875 latepoint_datepicker_toggle_no_availability_message($booking_form_element);
876 }
877 $booking_form_element.find('.os-dates-and-times-w').removeClass('is-searching');
878 return true;
879 }
880
881
882 function latepoint_init_step_verify($booking_form_element = false) {
883 if (!$booking_form_element) return;
884 $booking_form_element.closest('.latepoint-summary-is-open').removeClass('latepoint-summary-is-open');
885
886 $booking_form_element.find('.latepoint-body .load-customer-step-trigger').on('click', function () {
887 jQuery(this).addClass('os-loading');
888 latepoint_reload_step($booking_form_element, 'customer');
889 return false;
890 });
891
892 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-trigger-on-verify-w a').on('click', function (e) {
893 jQuery(this).closest('.coupon-code-wrapper-on-verify').addClass('entering-coupon').find('.coupon-code-input').trigger('focus');
894 return false;
895 });
896 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-input-cancel').on('click', function (e) {
897 jQuery(this).closest('.coupon-code-wrapper-on-verify').removeClass('entering-coupon');
898 return false;
899 });
900
901 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-input-submit').on('click', function (e) {
902 latepoint_apply_coupon(jQuery(this).closest('.coupon-code-input-w').find('.coupon-code-input'));
903 return false;
904 });
905
906 $booking_form_element.find('.os-remove-item-from-cart').on('click keydown', function (event) {
907 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
908 //make sure to clear active cart item so it doesn't add it again on reload!
909 if (confirm(jQuery(this).data('confirm-text'))) {
910 latepoint_remove_cart_item(jQuery(this));
911 }
912 return false;
913 });
914
915 $booking_form_element.find('.coupon-code-wrapper-on-verify .coupon-code-clear').on('click', function (e) {
916 latepoint_remove_coupon(jQuery(this));
917 return false;
918 });
919
920 $booking_form_element.find('.coupon-code-wrapper-on-verify input.coupon-code-input').on('keyup', function (e) {
921 if (e.which === 13) {
922 latepoint_apply_coupon(jQuery(this));
923 return false;
924 }
925 });
926 }
927
928
929 function latepoint_init_step_payment__pay($booking_form_element = false) {
930 var selected_payment_method = $booking_form_element.find('input[name="cart[payment_method]"]').val();
931 latepoint_init_payment_method_actions($booking_form_element, selected_payment_method);
932 }
933
934 function latepoint_init_step_payment__portions($booking_form_element = false) {
935 // Selecting Payment Time
936 $booking_form_element.find('.lp-payment-trigger-payment-portion-selector').on('click keydown', function (event) {
937 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
938 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
939 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
940 latepoint_show_prev_btn($booking_form_element);
941 latepoint_trigger_next_btn($booking_form_element);
942 return false;
943 });
944 }
945
946 function latepoint_init_step_payment__times($booking_form_element = false) {
947 // Selecting Payment Time
948 $booking_form_element.find('.lp-payment-trigger-payment-time-selector').on('click keydown', function (event) {
949 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
950 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
951 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
952 latepoint_show_prev_btn($booking_form_element);
953 latepoint_trigger_next_btn($booking_form_element);
954 return false;
955 });
956 }
957
958
959 function latepoint_init_step_payment__methods($booking_form_element = false) {
960 // Selecting Payment Time
961 $booking_form_element.find('.lp-payment-trigger-payment-method-selector').on('click', function (e) {
962 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
963 $booking_form_element.find('input[name="' + jQuery(this).data('holder') + '"]').val(jQuery(this).data('value'));
964 latepoint_show_prev_btn($booking_form_element);
965 latepoint_trigger_next_btn($booking_form_element);
966 return false;
967 });
968 }
969
970 function latepoint_category_item_clicked(event) {
971 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
972 let $item = jQuery(event.target);
973
974 let $booking_form_element = $item.closest('.latepoint-booking-form-element');
975 latepoint_show_prev_btn($booking_form_element);
976 $item.closest('.latepoint-step-content').addClass('selecting-item-category');
977 let $category_wrapper = $item.closest('.os-item-category-w');
978 let $main_parent = $item.closest('.os-item-categories-main-parent');
979 if ($category_wrapper.hasClass('selected')) {
980 $category_wrapper.removeClass('selected');
981 if ($category_wrapper.parent().closest('.os-item-category-w').length) {
982 $category_wrapper.parent().closest('.os-item-category-w').addClass('selected');
983 } else {
984 $main_parent.removeClass('show-selected-only');
985 }
986 } else {
987 $main_parent.find('.os-item-category-w.selected').removeClass('selected');
988 $main_parent.addClass('show-selected-only');
989 $category_wrapper.addClass('selected');
990 }
991 return false;
992 }
993
994 function latepoint_init_step_category_items(step_code) {
995 let $category_items = jQuery('.latepoint-step-content[data-step-code="' + step_code + '"] .os-item-category-info');
996 $category_items.on('click', latepoint_category_item_clicked);
997 $category_items.on('keydown', latepoint_category_item_clicked);
998 }
999
1000
1001 function latepoint_init_step_selectable_items($booking_form_element) {
1002 $booking_form_element.off('click', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
1003 $booking_form_element.on('click', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
1004
1005 $booking_form_element.off('click', '.os-selectable-items .os-selectable-item .item-quantity-selector-input', latepoint_selectable_item_quantity_keyup);
1006 $booking_form_element.on('click', '.os-selectable-items .os-selectable-item .item-quantity-selector-input', latepoint_selectable_item_quantity_keyup);
1007
1008
1009 $booking_form_element.off('keydown', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
1010 $booking_form_element.on('keydown', '.os-selectable-items .os-selectable-item', latepoint_selectable_item_clicked);
1011 }
1012
1013
1014 function latepoint_update_quantity_for_selectable_items($item) {
1015 var ids = $item.closest('.os-selectable-items')
1016 .find('.os-selectable-item.selected')
1017 .map(function () {
1018 if (jQuery(this).hasClass('has-quantity')) {
1019 return jQuery(this).data('item-id') + ':' + jQuery(this).find('input.item-quantity-selector-input').val();
1020 } else {
1021 return jQuery(this).data('item-id');
1022 }
1023 }).get();
1024 $item.closest('.latepoint-booking-form-element').find($item.data('id-holder')).val(ids);
1025 }
1026
1027 function latepoint_selectable_item_quantity_keyup(event) {
1028 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1029 var $item = jQuery(this).closest('.os-selectable-item');
1030 var new_value = jQuery(this).val();
1031 if (new_value && new_value.match(/^\d+$/)) {
1032 var max_quantity = $item.data('max-quantity');
1033 if (max_quantity && (new_value > max_quantity)) new_value = max_quantity;
1034 } else {
1035 new_value = 0;
1036 }
1037 jQuery(this).val(new_value);
1038
1039 if (($item.hasClass('selected') && (new_value > 0)) || (!$item.hasClass('selected') && (new_value == 0))) {
1040 latepoint_update_quantity_for_selectable_items($item);
1041 latepoint_reload_summary($booking_form_element);
1042 return false;
1043 } else {
1044 $item.trigger('click');
1045 }
1046 }
1047
1048 function latepoint_selectable_item_clicked(event) {
1049 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
1050 event.stopPropagation();
1051 event.stopImmediatePropagation();
1052 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1053 if (jQuery(this).hasClass('has-quantity')) {
1054 if (jQuery(event.target).hasClass('item-quantity-selector')) {
1055 var current_value = parseInt(jQuery(this).find('input.item-quantity-selector-input').val());
1056 var new_value = (jQuery(event.target).data('sign') == 'minus') ? current_value - 1 : current_value + 1;
1057 var max_quantity = jQuery(this).data('max-quantity');
1058 if (new_value < 0) new_value = 0;
1059 if (max_quantity && (new_value > max_quantity)) new_value = max_quantity;
1060 jQuery(this).find('input.item-quantity-selector-input').val(new_value);
1061 if ((jQuery(this).hasClass('selected') && (new_value > 0)) || (!jQuery(this).hasClass('selected') && (new_value == 0))) {
1062 latepoint_update_quantity_for_selectable_items(jQuery(this));
1063 latepoint_reload_summary($booking_form_element);
1064 return false;
1065 }
1066 }
1067 if (jQuery(event.target).hasClass('item-quantity-selector-input')) {
1068 latepoint_update_quantity_for_selectable_items(jQuery(this));
1069 latepoint_reload_summary($booking_form_element);
1070 return false;
1071 }
1072 }
1073 var summary_value = '';
1074 if (jQuery(this).hasClass('os-allow-multiselect')) {
1075 if (jQuery(this).hasClass('selected')) {
1076 jQuery(this).removeClass('selected');
1077 if (jQuery(this).hasClass('has-quantity')) jQuery(this).find('input.item-quantity-selector-input').val(0);
1078 } else {
1079 jQuery(this).addClass('selected');
1080 if (jQuery(this).hasClass('has-quantity') && !(jQuery(this).find('input.item-quantity-selector-input').val() > 0)) {
1081 jQuery(this).find('input.item-quantity-selector-input').val(1);
1082 }
1083 }
1084 latepoint_update_quantity_for_selectable_items(jQuery(this));
1085 latepoint_reload_summary($booking_form_element);
1086 latepoint_show_next_btn($booking_form_element);
1087 } else {
1088 if (!jQuery(this).hasClass('os-duration-item')) jQuery(this).closest('.os-item-categories-main-parent').find('.os-selectable-item.selected').removeClass('selected');
1089 jQuery(this).closest('.os-selectable-items').find('.os-selectable-item.selected').removeClass('selected');
1090 jQuery(this).addClass('selected');
1091 $booking_form_element.find(jQuery(this).data('id-holder')).val(jQuery(this).data('item-id'));
1092 if (jQuery(this).data('cart-item-item-data-key')) {
1093 latepoint_update_active_cart_item_item_data($booking_form_element, jQuery(this).data('cart-item-item-data-key'), jQuery(this).data('item-id'));
1094 }
1095 if (jQuery(this).data('os-call-func')) {
1096 window[jQuery(this).data('os-call-func')](jQuery(this));
1097 }
1098 if (jQuery(this).data('activate-sub-step')) {
1099 window[jQuery(this).data('activate-sub-step')](jQuery(this));
1100 } else {
1101 latepoint_trigger_next_btn($booking_form_element);
1102 }
1103 }
1104 return false;
1105 }
1106
1107 function latepoint_update_active_cart_item_item_data($booking_form_element, key, value) {
1108 let item_data_json = $booking_form_element.find('input[name="active_cart_item[item_data]"]').val();
1109 let item_data = item_data_json ? JSON.parse($booking_form_element.find('input[name="active_cart_item[item_data]"]').val()) : {};
1110 item_data[key] = value;
1111 $booking_form_element.find('input[name="active_cart_item[item_data]"]').val(JSON.stringify(item_data));
1112 }
1113
1114 function latepoint_format_price(price) {
1115 // replace default decimal separator dot with comma if it's in settings
1116 if (latepoint_helper.decimal_separator == ',') price = String(price).replace('.', ',');
1117 return latepoint_helper.currency_symbol_before + String(price) + latepoint_helper.currency_symbol_after;
1118 }
1119
1120
1121 function latepoint_init_step_services() {
1122 }
1123
1124
1125 function latepoint_trigger_next_btn($booking_form_element) {
1126 $booking_form_element.find('.latepoint_step_direction').val('next');
1127 latepoint_submit_booking_form($booking_form_element.find('.latepoint-form'));
1128 }
1129
1130 function latepoint_init_step_locations() {
1131 }
1132
1133 function latepoint_init_agent_details_link($booking_form_element) {
1134 $booking_form_element.on('click', '.os-trigger-item-details-popup', function () {
1135 $booking_form_element.find('.os-item-details-popup.open').remove();
1136 var $popup = $booking_form_element.find('#' + jQuery(this).data('item-details-popup-id')).first().clone().attr('id', '');
1137 $booking_form_element.find('.latepoint-form-w').addClass('showing-item-details-popup');
1138 $popup.addClass('open').appendTo($booking_form_element.find('.latepoint-body'));
1139 return false;
1140 });
1141 $booking_form_element.on('click', '.os-item-details-popup.open .os-item-details-popup-close', function () {
1142 $booking_form_element.find('.latepoint-form-w').removeClass('showing-item-details-popup');
1143 jQuery(this).closest('.os-item-details-popup.open').remove();
1144 return false;
1145 });
1146 }
1147
1148 function latepoint_init_step_agents() {
1149 }
1150
1151
1152 function latepoint_init_booking_summary_lightbox() {
1153 let $lightbox = jQuery('.customer-dashboard-booking-summary-lightbox');
1154 latepoint_init_qr_trigger($lightbox);
1155 latepoint_init_item_details_popup($lightbox);
1156 }
1157
1158 function latepoint_init_step_confirmation($booking_form_element = false) {
1159 if (!$booking_form_element) return;
1160 $booking_form_element.on('click', '.set-customer-password-btn', function () {
1161 let $btn = jQuery(this);
1162 let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1163
1164 $btn.addClass('os-loading');
1165 let params = {
1166 password_nonce: jQuery('input[name="new_password_nonce"]').val(),
1167 password: jQuery('input[name="customer[password]"]').val()
1168 }
1169 let data = {
1170 action: latepoint_helper.route_action,
1171 route_name: jQuery(this).data('btn-action'),
1172 params: jQuery.param(params),
1173 layout: 'none',
1174 return_format: 'json'
1175 }
1176 jQuery.ajax({
1177 type: "post",
1178 dataType: "json",
1179 url: latepoint_timestamped_ajaxurl(),
1180 data: data,
1181 success: function (data) {
1182 $btn.removeClass('os-loading');
1183 if (data.status === "success") {
1184 $booking_form_element.find('.step-confirmation-set-password').html('').hide();
1185 $booking_form_element.find('.confirmation-cabinet-info').show();
1186 } else {
1187 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.step-confirmation-set-password'), 'error');
1188 }
1189 }
1190 });
1191 return false;
1192 });
1193
1194 $booking_form_element.on('click', '.qr-show-trigger', function () {
1195 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1196 $booking_form_element.find('.qr-code-on-full-summary').addClass('show-vevent-qr-code');
1197 return false;
1198 });
1199
1200 $booking_form_element.on('click', '.show-set-password-fields', function () {
1201 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
1202
1203 $booking_form_element.find('.step-confirmation-set-password').show();
1204 $booking_form_element.find('#customer_password').trigger('focus');
1205 jQuery(this).closest('.info-box').hide();
1206 return false;
1207 });
1208 }
1209
1210 function latepoint_init_customer_login_form(){
1211 if(jQuery('.latepoint-login-form-w').length){
1212 jQuery('.latepoint-login-form-w').each(function() {
1213 if(jQuery(this).data('success-action') == 'auto-redirect'){
1214 window.location.replace(jQuery(this).data('redirect-url'))
1215 }else{
1216 latepoint_init_auth_form(jQuery(this));
1217 }
1218 });
1219 }
1220 }
1221
1222 function latepoint_init_customer_dashboard() {
1223 latepoint_init_form_masks();
1224 jQuery('.latepoint-customer-timezone-selector-w select').on('change', function (e) {
1225 var $select_box = jQuery(this);
1226 $select_box.closest('.latepoint-customer-timezone-selector-w').addClass('os-loading');
1227 var data = {
1228 action: latepoint_helper.route_action,
1229 route_name: jQuery(this).closest('.latepoint-customer-timezone-selector-w').data('route-name'),
1230 params: {timezone_name: jQuery(this).val()},
1231 layout: 'none',
1232 return_format: 'json'
1233 }
1234 jQuery.ajax({
1235 type: "post",
1236 dataType: "json",
1237 url: latepoint_timestamped_ajaxurl(),
1238 data: data,
1239 success: function (data) {
1240 $select_box.closest('.latepoint-customer-timezone-selector-w').removeClass('os-loading');
1241 if (data.status === "success") {
1242 location.reload();
1243 } else {
1244
1245 }
1246 }
1247 });
1248 });
1249
1250
1251 jQuery('.latepoint-request-booking-cancellation').on('click', function () {
1252 if (!confirm(latepoint_helper.cancel_booking_prompt)) return false;
1253 var $this = jQuery(this);
1254 var $booking_box = $this.closest('.customer-booking');
1255
1256 var route = jQuery(this).data('route');
1257 var params = {id: $booking_box.data('id')};
1258
1259 var data = {
1260 action: latepoint_helper.route_action,
1261 route_name: route,
1262 params: params,
1263 layout: 'none',
1264 return_format: 'json'
1265 }
1266 $this.addClass('os-loading');
1267 jQuery.ajax({
1268 type: "post",
1269 dataType: "json",
1270 url: latepoint_timestamped_ajaxurl(),
1271 data: data,
1272 success: function (data) {
1273 if (data.status === "success") {
1274 $this.remove();
1275 location.reload();
1276 } else {
1277 $this.removeClass('os-loading');
1278 }
1279 }
1280 });
1281 return false;
1282 });
1283
1284 }
1285
1286
1287 function latepoint_get_customer_name($wrapper) {
1288 var customer_name = '';
1289 var first_name = $wrapper.find('input[name="customer[first_name]"]').val();
1290 var last_name = $wrapper.find('input[name="customer[last_name]"]').val();
1291 if (first_name) customer_name += first_name;
1292 if (last_name) customer_name += ' ' + last_name;
1293 return customer_name.trim();
1294 }
1295
1296 function latepoint_init_customer_otp_code_verify_form($booking_form_element) {
1297 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1298 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1299
1300 if ($verify_otp_btn.length && $verify_otp_input.length) {
1301 $verify_otp_input.trigger('focus');
1302
1303 // trigger on enter/space to emulate a button
1304 $verify_otp_btn.on('keydown', function (e) {
1305 if (e.key === 'Enter' || e.key === ' ') {
1306 e.preventDefault();
1307 jQuery(this).trigger('click'); // Triggers the click handler above
1308 }
1309 });
1310 // close
1311 $booking_form_element.find('.latepoint-customer-otp-resend').on('click', function (e) {
1312 e.preventDefault();
1313 latepoint_resend_customer_otp_code($booking_form_element, jQuery(this));
1314 });
1315
1316 $booking_form_element.find('.latepoint-customer-otp-close').on('click', function () {
1317 $booking_form_element.find('.latepoint-customer-otp-input-container').html('');
1318 $booking_form_element.find('.hide-when-entering-otp').removeClass('os-hidden');
1319 latepoint_show_booking_form_footer($booking_form_element);
1320 return false;
1321 });
1322
1323 // input in code field
1324 $verify_otp_input.on('input', function () {
1325 // Remove non-numeric characters
1326 const cleanValue = jQuery(this).val().replace(/[^0-9]/g, '');
1327 jQuery(this).val(cleanValue);
1328 if (cleanValue.length === 6) {
1329 $verify_otp_btn.trigger('click');
1330 }
1331 });
1332 $verify_otp_input.on('keydown', function (e) {
1333 if (e.key === 'Enter') {
1334 e.preventDefault();
1335 $verify_otp_btn.trigger('click');
1336 }
1337 });
1338
1339 $verify_otp_btn.on('click', function (e) {
1340 return latepoint_verify_customer_otp_code($booking_form_element);
1341 });
1342 }
1343
1344 }
1345
1346 async function latepoint_verify_customer_otp_code($booking_form_element) {
1347 let $verify_otp_btn = $booking_form_element.find('.latepoint-verify-otp-button');
1348 let $verify_otp_input = $booking_form_element.find('.os-otp-code-field');
1349
1350 $verify_otp_input.removeClass('os-invalid');
1351 if ($verify_otp_input.val().length !== 6) {
1352 $verify_otp_input.addClass('os-invalid').addClass('os-shake');
1353 return false;
1354 }
1355
1356 $verify_otp_btn.addClass('os-loading');
1357
1358 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1359
1360 let data = {
1361 action: 'latepoint_route_call',
1362 route_name: $verify_otp_btn.data('route'),
1363 params: latepoint_formdata_to_url_encoded_string(form_data),
1364 layout: 'none',
1365 return_format: 'json'
1366 }
1367 try {
1368 let response = await jQuery.ajax({
1369 type: "post",
1370 dataType: "json",
1371 url: latepoint_timestamped_ajaxurl(),
1372 data: data
1373 });
1374 $verify_otp_btn.removeClass('os-loading');
1375 if (response.status === 'success') {
1376 if($booking_form_element.data('success-action') === 'redirect'){
1377 window.location.replace($booking_form_element.data('redirect-url'));
1378 return true;
1379 }else{
1380 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'));
1381 $booking_form_element.find('input[name="customer_contact_verification_token"]').val(response.message);
1382 latepoint_reload_step($booking_form_element);
1383 }
1384 } else {
1385 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1386 }
1387 return false;
1388 } catch (e) {
1389 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.latepoint-customer-otp-input-code-wrapper'), 'error');
1390 throw e;
1391 }
1392 }
1393
1394 async function latepoint_show_verify_contact_form_with_otp_code($booking_form_element, form_html) {
1395 $booking_form_element.find('.latepoint-customer-otp-input-container').html(form_html);
1396 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1397 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1398 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1399 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1400 latepoint_hide_booking_form_footer($booking_form_element);
1401 }
1402
1403 function latepoint_hide_booking_form_footer($booking_form_element) {
1404 $booking_form_element.addClass('hidden-buttons');
1405 }
1406
1407 function latepoint_show_booking_form_footer($booking_form_element) {
1408 $booking_form_element.removeClass('hidden-buttons');
1409 }
1410
1411 async function latepoint_resend_customer_otp_code($booking_form_element, $resend_otp_button) {
1412 $resend_otp_button.addClass('os-loading');
1413
1414 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1415
1416 // get values from phone number fields
1417 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1418 $booking_form_element.find('input.os-mask-phone').each(function () {
1419 const phoneInputName = this.getAttribute('name');
1420 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1421 // override value generated automatically by formdata with a formatted value of a phone field with country code
1422 form_data.set(phoneInputName, phoneInputValue);
1423 });
1424 }
1425
1426 let data = {
1427 action: 'latepoint_route_call',
1428 route_name: $resend_otp_button.data('otp-resend-route'),
1429 params: latepoint_formdata_to_url_encoded_string(form_data),
1430 layout: 'none',
1431 return_format: 'json'
1432 }
1433 try {
1434 let response = await jQuery.ajax({
1435 type: "post",
1436 dataType: "json",
1437 url: latepoint_timestamped_ajaxurl(),
1438 data: data
1439 });
1440 $resend_otp_button.removeClass('os-loading');
1441 if (response.status === 'success') {
1442 latepoint_hide_message_inside_element($booking_form_element.find('.hide-when-entering-otp'));
1443 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1444 $booking_form_element.find('.latepoint-customer-otp-input-container').html(response.message);
1445 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1446 } else {
1447 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-customer-otp-input-wrapper'), 'error');
1448 }
1449 return false;
1450 } catch (e) {
1451 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.latepoint-customer-otp-input-wrapper'), 'error');
1452 throw e;
1453 }
1454 }
1455
1456 async function latepoint_request_customer_otp_code($booking_form_element, $request_otp_button) {
1457 $request_otp_button.addClass('os-loading');
1458
1459 let form_data = new FormData($booking_form_element.find('.latepoint-form')[0]);
1460
1461
1462 // get values from phone number fields
1463 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1464 $booking_form_element.find('input.os-mask-phone').each(function () {
1465 const phoneInputName = this.getAttribute('name');
1466 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1467 // override value generated automatically by formdata with a formatted value of a phone field with country code
1468 form_data.set(phoneInputName, phoneInputValue);
1469 });
1470 }
1471
1472 let data = {
1473 action: 'latepoint_route_call',
1474 route_name: $request_otp_button.data('otp-request-route'),
1475 params: latepoint_formdata_to_url_encoded_string(form_data),
1476 layout: 'none',
1477 return_format: 'json'
1478 }
1479 try {
1480 let response = await jQuery.ajax({
1481 type: "post",
1482 dataType: "json",
1483 url: latepoint_timestamped_ajaxurl(),
1484 data: data
1485 });
1486 $request_otp_button.removeClass('os-loading');
1487 if (response.status === 'success') {
1488 latepoint_hide_message_inside_element($booking_form_element.find('.hide-when-entering-otp'));
1489 $booking_form_element.find('.hide-when-entering-otp').addClass('os-hidden');
1490 $booking_form_element.find('.latepoint-customer-otp-input-container').html(response.message);
1491 latepoint_init_customer_otp_code_verify_form($booking_form_element);
1492 } else {
1493 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.hide-when-entering-otp'), 'error');
1494 }
1495 return false;
1496 } catch (e) {
1497 latepoint_show_message_inside_element('Error generating OTP', $booking_form_element.find('.hide-when-entering-otp'), 'error');
1498 throw e;
1499 }
1500 }
1501
1502 function latepoint_customer_auth_load_next_step($booking_form_element) {
1503
1504 }
1505
1506 function latepoint_init_customer_otp_code_request_form($booking_form_element) {
1507 let $request_otp_button = $booking_form_element.find('.latepoint-request-otp-button');
1508 if ($request_otp_button.length > 0) {
1509 $request_otp_button.on('click', function (e) {
1510 return latepoint_request_customer_otp_code($booking_form_element, jQuery(this));
1511 });
1512 // trigger on enter/space to emulate a button
1513 $request_otp_button.on('keydown', function (e) {
1514 if (e.key === 'Enter' || e.key === ' ') {
1515 e.preventDefault();
1516 jQuery(this).trigger('click'); // Triggers the click handler above
1517 }
1518 });
1519 $booking_form_element.find('.latepoint-customer-otp-request-wrapper').find('input, select').on('keydown', function (e) {
1520 if (e.key === 'Enter') {
1521 e.preventDefault();
1522 $request_otp_button.trigger('click');
1523 }
1524 });
1525 }
1526 }
1527
1528 async function latepoint_login_customer($booking_form_element, $request_otp_button) {
1529
1530 $request_otp_button.addClass('os-loading');
1531 let $form = $booking_form_element.find('.latepoint-form');
1532
1533 let form_data = new FormData($form[0]);
1534
1535 // get values from phone number fields
1536 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
1537 $form.find('input.os-mask-phone').each(function () {
1538 const phoneInputName = this.getAttribute('name');
1539 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
1540 // override value generated automatically by formdata with a formatted value of a phone field with country code
1541 form_data.set(phoneInputName, phoneInputValue);
1542 });
1543 }
1544
1545 let data = {
1546 action: 'latepoint_route_call',
1547 route_name: $request_otp_button.data('password-login-route'),
1548 params: latepoint_formdata_to_url_encoded_string(form_data),
1549 layout: 'none',
1550 return_format: 'json'
1551 }
1552 try {
1553 let response = await jQuery.ajax({
1554 type: "post",
1555 dataType: "json",
1556 url: latepoint_timestamped_ajaxurl(),
1557 data: data
1558 });
1559 $request_otp_button.removeClass('os-loading');
1560
1561 if (response.status === "success") {
1562 if($booking_form_element.data('success-action') === 'redirect'){
1563 window.location.replace($booking_form_element.data('redirect-url'));
1564 return true;
1565 }else {
1566 return latepoint_reload_step($booking_form_element);
1567 }
1568 } else {
1569 throw new Error(response.message);
1570 }
1571 } catch (e) {
1572 latepoint_show_message_inside_element(e.message, $booking_form_element.find('.os-step-existing-customer-login-w'));
1573 }
1574
1575 }
1576
1577
1578 function latepoint_init_auth_form($wrapper){
1579
1580 latepoint_init_customer_otp_code_request_form($wrapper);
1581 latepoint_init_customer_otp_code_verify_form($wrapper);
1582
1583
1584 $wrapper.find('.login-with-password-toggle').on('change', function () {
1585 if (jQuery(this).hasClass('os-opposite')) {
1586 if (jQuery(this).is(':checked')) {
1587 $wrapper.find('.os-customer-otp-notice').hide();
1588 $wrapper.find('.os-customer-login-password-fields-w').show();
1589 } else {
1590 $wrapper.find('.os-customer-otp-notice').show();
1591 $wrapper.find('.os-customer-login-password-fields-w').hide();
1592 }
1593 } else {
1594 if (jQuery(this).is(':checked')) {
1595 $wrapper.find('.os-customer-otp-notice').show();
1596 $wrapper.find('.os-customer-login-password-fields-w').hide();
1597 } else {
1598 $wrapper.find('.os-customer-otp-notice').hide();
1599 $wrapper.find('.os-customer-login-password-fields-w').show();
1600 }
1601 }
1602 });
1603
1604 $wrapper.find('.alternative-login-option').on('click', function () {
1605 let login_method = jQuery(this).data('auth-via');
1606 let delivery_method = jQuery(this).data('otp-delivery-method');
1607 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1608 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1609 $wrapper.find('.customer-login-method-wrapper').addClass('os-hidden');
1610 $wrapper.find('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1611 $wrapper.find('.alternative-login-option').removeClass('os-hidden');
1612 jQuery(this).addClass('os-hidden');
1613 return false;
1614 });
1615
1616 $wrapper.find('.login-options-via-wrapper .login-option').on('click', function () {
1617 let $wrapper = jQuery(this).closest('.latepoint-customer-auth-options-wrapper');
1618 let login_method = jQuery(this).data('login-method');
1619 let delivery_method = jQuery(this).data('otp-delivery-method');
1620
1621 let otp_enabled = jQuery(this).data('is-otp-enabled');
1622 if(otp_enabled === 'no'){
1623 if($wrapper.find('.login-with-password-toggle.os-opposite:not(:checked)').length){
1624 $wrapper.find('.login-with-password-toggle.os-opposite').trigger('click');
1625 }
1626 $wrapper.find('.latepoint-customer-otp-option').hide();
1627 $wrapper.find('.step-login-existing-customer-btn').addClass('latepoint-btn-block');
1628 }else{
1629 if($wrapper.find('.latepoint-customer-otp-option').length){
1630 $wrapper.find('.latepoint-customer-otp-option').show();
1631 $wrapper.find('.step-login-existing-customer-btn').removeClass('latepoint-btn-block');
1632 }
1633 }
1634 $wrapper.find('input[name="auth[contact_type]"]').val(login_method);
1635 $wrapper.find('input[name="auth[delivery_method]"]').val(delivery_method);
1636 jQuery(this).closest('.login-options-via-wrapper').find('.login-option.os-selected').removeClass('os-selected')
1637 jQuery(this).addClass('os-selected');
1638 jQuery('.customer-login-method-wrapper').addClass('os-hidden');
1639 jQuery('.customer-login-method-wrapper[data-login-method="' + login_method + '"]').removeClass('os-hidden');
1640
1641 return false;
1642 });
1643
1644 // Init Login Existing Customer Button
1645 $wrapper.find('.os-customer-login-w input').on('keyup', function (e) {
1646 if (e.keyCode === 13) {
1647 e.preventDefault();
1648 $wrapper.find('.step-login-existing-customer-btn').trigger('click');
1649 return false;
1650 }
1651 });
1652
1653 $wrapper.find('.step-login-existing-customer-btn').on('click', function (e) {
1654 e.preventDefault();
1655 let via = $wrapper.find('input[name="auth[via]"]').val();
1656 if ($wrapper.find('input[name="auth[via]"]').is(':checkbox')) {
1657 let is_checked = $wrapper.find('input[name="auth[via]"]').is(':checked');
1658 if (via === 'otp' && !is_checked) {
1659 via = 'password';
1660 } else if (via === 'password' && !is_checked) {
1661 via = 'otp';
1662 }
1663 }
1664 if (via === 'otp') {
1665 latepoint_request_customer_otp_code($wrapper, jQuery(this));
1666 } else if (via === 'password') {
1667 latepoint_login_customer($wrapper, jQuery(this));
1668 }
1669
1670 });
1671 }
1672
1673 function latepoint_init_step_customer($booking_form_element) {
1674 latepoint_init_form_masks();
1675
1676 latepoint_init_auth_form($booking_form_element);
1677
1678 // Init Logout button
1679 $booking_form_element.find('.step-customer-logout-btn').on('click', function () {
1680 let $logout_btn = jQuery(this);
1681 let $booking_form_element = $logout_btn.closest('.latepoint-booking-form-element');
1682 $booking_form_element.find('input[name="customer_contact_verification_token"]').val('');
1683 let data = {
1684 action: latepoint_helper.route_action,
1685 route_name: $logout_btn.data('btn-action'),
1686 layout: 'none',
1687 return_format: 'json',
1688 params: {auth: {nonce: $logout_btn.data('nonce')}}
1689 }
1690 latepoint_step_content_change_start($booking_form_element);
1691 jQuery.ajax({
1692 type: "post",
1693 dataType: "json",
1694 url: latepoint_timestamped_ajaxurl(),
1695 data: data,
1696 success: function (data) {
1697 $booking_form_element.find('input[name="auth[action]"]').val('logout');
1698 latepoint_reload_step($booking_form_element);
1699 }
1700 });
1701 return false;
1702 });
1703
1704
1705 }
1706
1707 function latepoint_step_content_change_start($booking_form_element) {
1708 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1709 }
1710
1711 // TODO
1712 function latepoint_step_content_change_end(new_content, $booking_form_element) {
1713 if (new_content) $booking_form_element.find('.latepoint-body .latepoint-step-content').replaceWith(new_content);
1714 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1715 setTimeout(function () {
1716 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1717 }, 50);
1718 }
1719
1720
1721 function latepoint_change_step_desc($booking_form_element, step_code) {
1722 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1723 setTimeout(function () {
1724 // Progress bar
1725 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1726 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1727 $step_progress.nextAll().removeClass('complete').removeClass('active');
1728 // Side panel
1729 var side_panel_desc = $booking_form_element.find('.latepoint-step-desc-library[data-step-code="' + step_code + '"]').html();
1730 $booking_form_element.find('.latepoint-step-desc').html(side_panel_desc);
1731
1732 // Top header
1733 var top_header_desc = $booking_form_element.find('.os-heading-text-library[data-step-code="' + step_code + '"]').html();
1734 $booking_form_element.find('.os-heading-text').html(top_header_desc);
1735 setTimeout(function () {
1736 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1737 }, 50);
1738 }, 500);
1739 }
1740
1741
1742 function latepoint_progress_prev($booking_form_element, step_code) {
1743 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1744 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1745 $step_progress.nextAll().removeClass('complete').removeClass('active');
1746 }
1747
1748
1749 function latepoint_progress_next($booking_form_element, step_code) {
1750 var $step_progress = $booking_form_element.find('.latepoint-progress li[data-step-code="' + step_code + '"]');
1751 $step_progress.addClass('active').addClass('complete').prevAll().addClass('complete').removeClass('active');
1752 $step_progress.nextAll().removeClass('complete').removeClass('active');
1753 }
1754
1755
1756 function latepoint_next_step_description($booking_form_element, step_code) {
1757 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1758 setTimeout(function () {
1759 $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());
1760 $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());
1761 setTimeout(function () {
1762 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1763 }, 50);
1764 }, 500);
1765 }
1766
1767 function latepoint_prev_step_description($booking_form_element, step_code) {
1768 $booking_form_element.removeClass('step-changed').addClass('step-changing');
1769 setTimeout(function () {
1770 $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());
1771 $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());
1772 setTimeout(function () {
1773 $booking_form_element.removeClass('step-changing').addClass('step-changed');
1774 }, 50);
1775 }, 500);
1776 }
1777
1778
1779 function latepoint_validate_fields($fields) {
1780 var is_valid = true;
1781 $fields.each(function (index) {
1782 if (jQuery(this).val() == '') {
1783 is_valid = false;
1784 return false;
1785 }
1786 });
1787 return is_valid;
1788 }
1789
1790
1791 async function latepoint_submit_booking_form($booking_form) {
1792 let $booking_form_element = $booking_form.closest('.latepoint-booking-form-element');
1793
1794 let current_step = $booking_form_element.find('.latepoint_current_step_code').val();
1795 let callbacks_list = [];
1796 if (latepoint_check_if_booking_form_is_final_submit($booking_form_element)) {
1797 // check if order intent is still bookable
1798 latepoint_add_action(callbacks_list, async () => {
1799 return await latepoint_check_if_order_intent_still_bookable($booking_form_element);
1800 }, 1);
1801 }
1802 $booking_form_element.trigger('latepoint:submitBookingForm', [{
1803 current_step: current_step,
1804 callbacks_list: callbacks_list,
1805 is_final_submit: latepoint_check_if_booking_form_is_final_submit($booking_form_element),
1806 direction: $booking_form_element.find('.latepoint_step_direction').val()
1807 }]);
1808 try {
1809 latepoint_hide_prev_btn($booking_form_element);
1810 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
1811 } catch (error) {
1812 latepoint_show_prev_btn($booking_form_element);
1813 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
1814 return false;
1815 }
1816
1817
1818 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
1819 latepoint_hide_prev_btn($booking_form_element);
1820 try {
1821 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
1822 let response = await jQuery.ajax({
1823 type: "post",
1824 dataType: "json",
1825 processData: false,
1826 contentType: false,
1827 url: latepoint_timestamped_ajaxurl(),
1828 data: latepoint_create_form_data($booking_form)
1829 });
1830
1831 $booking_form.find('.latepoint_step_direction').val('next');
1832 if (response.status === 'success') {
1833 if (response.fields_to_update) {
1834 for (const [key, value] of Object.entries(response.fields_to_update)) {
1835 $booking_form_element.find('input[name="' + key + '"]').val(value)
1836 }
1837 }
1838 if ($booking_form_element.data('flash-error')) {
1839 latepoint_show_message_inside_element($booking_form_element.data('flash-error'), $booking_form_element.find('.latepoint-body'));
1840 $booking_form_element.data('flash-error', '');
1841 }
1842 $booking_form_element.find('.latepoint_current_step_code').val(response.step_code);
1843 $booking_form_element.removeClass(function (index, className) {
1844 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
1845 }).addClass('current-step-' + response.step_code);
1846 setTimeout(function () {
1847 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
1848 $booking_form_element.find('.latepoint-body').find('.latepoint-step-content').addClass('is-hidden');
1849 if ($booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]')) {
1850 $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.step_code + '"]').remove();
1851 }
1852 $booking_form_element.find('.latepoint-body').append(response.message);
1853
1854
1855 latepoint_update_next_btn_label($booking_form_element);
1856 latepoint_init_step(response.step_code, $booking_form_element);
1857 setTimeout(function () {
1858 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
1859 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1860 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1861 }, 50);
1862 }, 500);
1863
1864 if (response.is_pre_last_step) {
1865 $booking_form_element.data('next-submit-is-last', 'yes');
1866 } else {
1867 $booking_form_element.data('next-submit-is-last', 'no');
1868 }
1869 if (response.is_last_step) {
1870 $booking_form_element.addClass('hidden-buttons').find('.latepoint-footer').remove();
1871 $booking_form_element.find('.latepoint-progress').css('opacity', 0);
1872 $booking_form_element.closest('.latepoint-summary-is-open').removeClass('latepoint-summary-is-open');
1873 $booking_form_element.closest('.latepoint-show-side-panel').removeClass('latepoint-show-side-panel').addClass('latepoint-hide-side-panel');
1874 $booking_form_element.addClass('is-final-step');
1875 } else {
1876 if (response.show_next_btn === true) {
1877 latepoint_show_next_btn($booking_form_element);
1878 } else {
1879 latepoint_hide_next_btn($booking_form_element);
1880 }
1881 if (response.show_prev_btn === true) {
1882 latepoint_show_prev_btn($booking_form_element);
1883 } else {
1884 latepoint_hide_prev_btn($booking_form_element);
1885 }
1886 }
1887 latepoint_change_step_desc($booking_form_element, response.step_code);
1888 latepoint_reload_summary($booking_form_element);
1889 } else {
1890 if (response.fields_to_update) {
1891 for (const [key, value] of Object.entries(response.fields_to_update)) {
1892 $booking_form_element.find('input[name="' + key + '"]').val(value)
1893 }
1894 }
1895 if (response.callback) {
1896 let func_name = response.callback;
1897 if (func_name.includes('.')) {
1898 let func_arr = func_name.split('.');
1899 if (typeof window[func_arr[0]][func_arr[1]] !== 'function') {
1900 console.log(func_name + ' is undefined');
1901 }
1902 if (response.callback_data) {
1903 window[func_arr[0]][func_arr[1]]($booking_form_element, response.callback_data);
1904 } else {
1905 window[func_arr[0]][func_arr[1]]($booking_form_element);
1906 }
1907 } else {
1908 if (typeof window[func_name] !== 'function') {
1909 console.log(func_name + ' is undefined');
1910 }
1911 if (response.callback_data) {
1912 window[func_name]($booking_form_element, response.callback_data);
1913 } else {
1914 window[func_name]($booking_form_element);
1915 }
1916 }
1917 } else {
1918 if (response.send_to_step && response.send_to_step === 'resubmit') {
1919 let current_resubmit_count = parseInt($booking_form.data('resubmit-count')) ? parseInt($booking_form.data('resubmit-count')) : 1;
1920 $booking_form.data('resubmit-count', current_resubmit_count + 1);
1921 if (current_resubmit_count > 6) {
1922 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1923 } else {
1924 // resubmission probably caused by order intent still being processed, since
1925 // order intent is still processing, give it a little more time and try again
1926 await latepoint_sleep(2000);
1927 return latepoint_submit_booking_form($booking_form);
1928 }
1929 } else {
1930 $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1931 $booking_form_element.find('.latepoint-next-btn, .latepoint-prev-btn').removeClass('os-loading');
1932 if (response.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + response.send_to_step + '"]').length) {
1933 $booking_form_element.data('flash-error', response.message);
1934 latepoint_reload_step($booking_form_element, response.send_to_step);
1935 } else {
1936 latepoint_show_message_inside_element(response.message, $booking_form_element.find('.latepoint-body'));
1937 latepoint_show_prev_btn($booking_form_element);
1938 }
1939 }
1940 }
1941 }
1942 } catch (e) {
1943 console.log(e);
1944 alert('Error:' + e);
1945 }
1946 }
1947
1948 function latepoint_sleep(ms) {
1949 return new Promise(resolve => setTimeout(resolve, ms));
1950 }
1951
1952 function latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element) {
1953 if (error.send_to_step && $booking_form_element.find('.latepoint-step-content[data-step-code="' + error.send_to_step + '"]').length) {
1954 latepoint_reload_step($booking_form_element, error.send_to_step);
1955 $booking_form_element.data('flash-error', error.message);
1956 } else {
1957 latepoint_show_message_inside_element(error.message, $booking_form_element.find('.latepoint-body'), 'error');
1958
1959 if ($booking_form_element.hasClass('step-content-loading')) $booking_form_element.removeClass('step-content-loading').addClass('step-content-loaded');
1960 $booking_form_element.find('.latepoint-next-btn').removeClass('os-loading');
1961
1962 // if previous step exists - show prev button
1963 if ($booking_form_element.find('.latepoint-step-content:last-child').prev('.latepoint-step-content').length) latepoint_show_prev_btn($booking_form_element);
1964 latepoint_scroll_to_top_of_booking_form($booking_form_element);
1965 }
1966 }
1967
1968 function latepoint_reset_active_cart_item($booking_form_element) {
1969 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
1970 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
1971 $booking_form_element.find('input[name="active_cart_item[item_data]"]').val('');
1972 }
1973
1974 function latepoint_check_if_booking_form_is_final_submit($booking_form_element) {
1975 return ($booking_form_element.data('next-submit-is-last') == 'yes');
1976 }
1977
1978
1979 async function latepoint_check_if_order_intent_still_bookable($booking_form_element) {
1980 let response = await jQuery.ajax({
1981 type: "post",
1982 dataType: "json",
1983 processData: false,
1984 contentType: false,
1985 url: latepoint_timestamped_ajaxurl(),
1986 data: latepoint_create_form_data($booking_form_element.find('.latepoint-form'), latepoint_helper.check_order_intent_bookable_route)
1987 });
1988 if (response.status === 'success') {
1989 return true;
1990 } else {
1991 throw new Error(response.message);
1992 }
1993 }
1994
1995 async function latepoint_process_list_of_callbacks(callbacks, $booking_form_element, $booking_form) {
1996 for (const callback of callbacks) {
1997 await callback.action();
1998 }
1999 }
2000
2001 function latepoint_clear_presets($booking_form_element) {
2002 $booking_form_element.find('.clear_for_new_item').val('');
2003 }
2004
2005 function latepoint_init_booking_form($booking_form_element) {
2006 $booking_form_element.on('click keydown', '.checkout-from-summary-panel-btn', function (event) {
2007 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2008 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
2009 jQuery(this).closest('.latepoint-w').removeClass('show-summary-on-mobile');
2010 return false;
2011 });
2012
2013 $booking_form_element.on('click keydown', '.latepoint-add-another-item-trigger', function (event) {
2014 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2015
2016 if (latepoint_helper.reset_presets_when_adding_new_item) {
2017 latepoint_clear_presets($booking_form_element);
2018 }
2019 latepoint_reset_active_cart_item($booking_form_element);
2020 latepoint_reload_step($booking_form_element, jQuery(this).data('step'));
2021 return false;
2022 });
2023 $booking_form_element.find('.latepoint-form').on('submit', function (e) {
2024 e.preventDefault();
2025 let $booking_form = jQuery(this);
2026 latepoint_submit_booking_form($booking_form);
2027 });
2028
2029 latepoint_init_booking_summary_panel($booking_form_element);
2030
2031 $booking_form_element.on('click keydown', '.latepoint-lightbox-summary-trigger', function (event) {
2032 event.preventDefault();
2033 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2034 let $wrapper = jQuery(this).closest('.latepoint-w');
2035 $wrapper.toggleClass('show-summary-on-mobile');
2036 return false;
2037 });
2038
2039 $booking_form_element.find('.latepoint-lightbox-close').on('click', function () {
2040
2041 let params = new URLSearchParams(location.search);
2042 if (params.has('latepoint_order_intent_key')) {
2043 params.delete('latepoint_order_intent_key');
2044 history.replaceState(null, '', '?' + params + location.hash);
2045 }
2046
2047 jQuery('body').removeClass('latepoint-lightbox-active');
2048 jQuery('.latepoint-lightbox-w').remove();
2049 return false;
2050 });
2051
2052
2053 $booking_form_element.on('click keydown', '.lp-option', function (event) {
2054 if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return;
2055 jQuery(this).closest('.lp-options').find('.lp-option.selected').removeClass('selected');
2056 jQuery(this).addClass('selected');
2057 });
2058
2059
2060 // Next Step button Click
2061 $booking_form_element.find('.latepoint-next-btn').on('click', async function (e) {
2062 e.preventDefault();
2063 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
2064 var $next_btn = jQuery(this);
2065 $next_btn.addClass('os-loading');
2066 var $booking_form = jQuery(this).closest('.latepoint-form');
2067
2068 var current_step = $booking_form_element.find('.latepoint_current_step_code').val();
2069
2070 $booking_form.find('.latepoint_step_direction').val('next');
2071 var callbacks_list = [];
2072
2073 $booking_form_element.trigger('latepoint:nextStepClicked', [{
2074 current_step: current_step,
2075 callbacks_list: callbacks_list
2076 }]);
2077 latepoint_hide_prev_btn($booking_form_element);
2078
2079 try {
2080 await latepoint_process_list_of_callbacks(callbacks_list, $booking_form_element, $booking_form);
2081 await latepoint_submit_booking_form($booking_form);
2082 } catch (error) {
2083 latepoint_show_error_and_stop_loading_booking_form(error, $booking_form_element);
2084 }
2085 return false;
2086 });
2087
2088
2089 // Previous Step button Click
2090 $booking_form_element.find('.latepoint-prev-btn').on('click', function (e) {
2091 if (jQuery(this).hasClass('disabled') || jQuery(this).hasClass('os-loading')) return false;
2092
2093 let $current_step = $booking_form_element.find('.latepoint-step-content:last-child');
2094
2095
2096 // handle categories
2097 if ($current_step.hasClass('selecting-item-category')) {
2098 if ($current_step.find('.os-item-category-w .os-item-category-w.selected').length) {
2099 $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');
2100 } else {
2101 $current_step.removeClass('selecting-item-category').find('.os-item-category-w.selected').removeClass('selected');
2102 $current_step.removeClass('selecting-item-category').find('.os-item-categories-holder.show-selected-only').removeClass('show-selected-only');
2103 }
2104 if (($booking_form_element.find('.latepoint-step-content').length <= 1) && !$current_step.hasClass('selecting-item-category')) {
2105 latepoint_hide_prev_btn($booking_form_element);
2106 }
2107 latepoint_reload_summary($booking_form_element);
2108 return false;
2109 }
2110
2111 if ($current_step.data('clear-action')) {
2112 window[$current_step.data('clear-action')]($booking_form_element);
2113 }
2114
2115 let $back_btn = jQuery(this);
2116 $back_btn.addClass('os-loading');
2117 $booking_form_element.removeClass('step-content-loaded').addClass('step-content-loading');
2118 let $new_current_step = $booking_form_element.find('.latepoint-step-content.is-hidden').last();
2119 let new_current_step_code = $new_current_step.data('step-code');
2120 let current_step_code = $current_step.data('step-code');
2121
2122
2123 let current_parent_code_name = current_step_code.split('__')[0];
2124 let new_parent_code_name = new_current_step_code.split('__')[0];
2125
2126 let active_cart_item_id = $booking_form_element.find('input[name="active_cart_item[id]"]').val();
2127
2128 latepoint_change_step_desc($booking_form_element, new_current_step_code);
2129 setTimeout(function () {
2130 $new_current_step.removeClass('is-hidden');
2131 $current_step.remove();
2132 $booking_form_element.find('.latepoint_current_step_code').val(new_current_step_code);
2133 $booking_form_element.removeClass(function (index, className) {
2134 return (className.match(/(^|\s)current-step-\S+/g) || []).join(' ');
2135 }).addClass('current-step-' + new_current_step_code);
2136 $booking_form_element.find('.latepoint-next-btn span').text($booking_form_element.find('.latepoint-next-btn').data('label'));
2137 $booking_form_element.data('next-submit-is-last', 'no');
2138
2139 latepoint_update_next_btn_label($booking_form_element);
2140 latepoint_show_next_btn($booking_form_element);
2141 $back_btn.removeClass('os-loading');
2142 if ($booking_form_element.find('.latepoint-step-content').length <= 1) {
2143 if ($new_current_step.hasClass('selecting-item-category')) {
2144
2145 }
2146 if (new_current_step_code == 'booking__services') {
2147 var $services_step = $booking_form_element.find('.step-services-w');
2148 if ($services_step.hasClass('selecting-item-category')) {
2149 if ($services_step.find('.os-services > .os-item.selected').hasClass('is-preselected')) {
2150 // if service is preselected check if there are both multiple durations and quantity selector and only then show prev button
2151 } else {
2152 latepoint_show_prev_btn($booking_form_element);
2153 }
2154 } else {
2155 latepoint_hide_prev_btn($booking_form_element);
2156 }
2157 } else {
2158 if (!$new_current_step.hasClass('selecting-item-category')) {
2159 latepoint_hide_prev_btn($booking_form_element);
2160 }
2161 }
2162 }
2163 $booking_form_element.removeClass('step-content-loading').addClass('step-content-mid-loading');
2164
2165
2166 if (new_parent_code_name == 'booking' && current_parent_code_name != 'booking' && active_cart_item_id) {
2167
2168 // 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
2169 $booking_form_element.find('.latepoint-summary-w').addClass('os-loading');
2170 let data = {
2171 action: latepoint_helper.route_action,
2172 route_name: latepoint_helper.remove_cart_item_route,
2173 params: jQuery.param({cart_item_id: active_cart_item_id}),
2174 layout: 'none',
2175 return_format: 'json'
2176 }
2177 jQuery.ajax({
2178 type: "post",
2179 dataType: "json",
2180 url: latepoint_timestamped_ajaxurl(),
2181 data: data,
2182 success: function (data) {
2183 if (data.status === "success") {
2184 $booking_form_element.find('input[name="active_cart_item[id]"]').val('');
2185 if ($booking_form_element.find('input[name="active_cart_item[variant]"]').val() == 'bundle') {
2186 latepoint_update_active_cart_item_item_data($booking_form_element, 'bundle_id', '');
2187 $booking_form_element.find('input[name="active_cart_item[variant]"]').val('');
2188 }
2189 latepoint_reload_summary($booking_form_element);
2190 } else {
2191 $booking_form_element.find('.latepoint-summary-w').removeClass('os-loading');
2192 latepoint_show_message_inside_element(data.message, $booking_form_element.find('.latepoint-body'), 'error');
2193 }
2194 }
2195 });
2196 } else {
2197 latepoint_reload_summary($booking_form_element);
2198 }
2199 setTimeout(function () {
2200 $booking_form_element.removeClass('step-content-mid-loading').addClass('step-content-loaded');
2201 latepoint_hide_message_inside_element($booking_form_element.find('.latepoint-body'));
2202 latepoint_scroll_to_top_of_booking_form($booking_form_element);
2203
2204 let callbacks_list = [];
2205 $booking_form_element.trigger('latepoint:prevStepReInit', [{
2206 current_step: new_current_step_code,
2207 callbacks_list: callbacks_list
2208 }]);
2209 }, 150);
2210 }, 700);
2211 return false;
2212 });
2213
2214 latepoint_init_agent_details_link($booking_form_element);
2215 $booking_form_element.trigger('latepoint:initBookingForm');
2216 }
2217
2218
2219 function latepoint_init_booking_form_by_trigger($trigger) {
2220 let route = latepoint_helper.booking_button_route;
2221 let params = {};
2222 let restrictions = {};
2223 let presets = {};
2224 let booking_element_styles = {};
2225 if ($trigger.data('show-service-categories')) restrictions.show_service_categories = $trigger.data('show-service-categories');
2226 if ($trigger.data('show-locations')) restrictions.show_locations = $trigger.data('show-locations');
2227 if ($trigger.data('show-services')) restrictions.show_services = $trigger.data('show-services');
2228 if ($trigger.data('show-agents')) restrictions.show_agents = $trigger.data('show-agents');
2229 if ($trigger.data('calendar-start-date')) restrictions.calendar_start_date = $trigger.data('calendar-start-date');
2230 if ($trigger.data('service-display-mode')) restrictions.service_display_mode = $trigger.data('service-display-mode');
2231
2232 if ($trigger.data('selected-location')) presets.selected_location = $trigger.data('selected-location');
2233 if ($trigger.data('selected-agent')) presets.selected_agent = $trigger.data('selected-agent');
2234 if ($trigger.data('selected-service')) presets.selected_service = $trigger.data('selected-service');
2235 if ($trigger.data('selected-bundle')) presets.selected_bundle = $trigger.data('selected-bundle');
2236 if ($trigger.data('selected-duration')) presets.selected_duration = $trigger.data('selected-duration');
2237 if ($trigger.data('selected-total-attendees')) presets.selected_total_attendees = $trigger.data('selected-total-attendees');
2238 if ($trigger.data('selected-service-category')) presets.selected_service_category = $trigger.data('selected-service-category');
2239 if ($trigger.data('selected-start-date')) presets.selected_start_date = $trigger.data('selected-start-date');
2240 if ($trigger.data('selected-start-time')) presets.selected_start_time = $trigger.data('selected-start-time');
2241 if ($trigger.data('order-item-id')) presets.order_item_id = $trigger.data('order-item-id');
2242 if ($trigger.data('source-id')) presets.source_id = $trigger.data('source-id');
2243
2244 // Pass raw URL query parameters as a generic transport for addons (e.g. contact field pre-fill).
2245 if (window.location.search) {
2246 let url_params = {};
2247 new URLSearchParams(window.location.search).forEach(function(value, key) { url_params[key] = value; });
2248 if (Object.keys(url_params).length) presets.url_params = url_params;
2249 }
2250
2251 if ($trigger.data('hide-summary') == 'yes') booking_element_styles.hide_summary = true;
2252 if ($trigger.data('hide-side-panel') == 'yes') booking_element_styles.hide_side_panel = true;
2253
2254
2255 if (jQuery.isEmptyObject(restrictions) == false) params.restrictions = restrictions;
2256 if (jQuery.isEmptyObject(presets) == false) params.presets = presets;
2257 if (jQuery.isEmptyObject(booking_element_styles) == false) params.booking_element_styles = booking_element_styles;
2258
2259 let data = {
2260 action: latepoint_helper.route_action,
2261 route_name: route,
2262 params: params,
2263 layout: 'none',
2264 return_format: 'json'
2265 }
2266
2267 let is_inline_form = $trigger.hasClass('latepoint-book-form-wrapper');
2268 if (is_inline_form) {
2269 data.params.booking_element_type = 'inline_form';
2270 }
2271
2272 $trigger.addClass('os-loading');
2273 jQuery.ajax({
2274 type: "post",
2275 dataType: "json",
2276 url: latepoint_timestamped_ajaxurl(),
2277 data: data,
2278 success: (data) => {
2279 if (data.status === "success") {
2280 let $booking_form_element = false;
2281 if (is_inline_form) {
2282 $trigger.html(data.message);
2283 $booking_form_element = $trigger.find('.latepoint-booking-form-element');
2284 } else {
2285 let lightbox_class = 'booking-form-in-lightbox';
2286 latepoint_show_data_in_lightbox(data.message, lightbox_class, false);
2287 $booking_form_element = jQuery('.latepoint-lightbox-w .latepoint-booking-form-element');
2288 jQuery('body').addClass('latepoint-lightbox-active');
2289 }
2290 latepoint_init_booking_form($booking_form_element);
2291 latepoint_init_step(data.step, $booking_form_element);
2292 $trigger.removeClass('os-loading');
2293 } else {
2294 $trigger.removeClass('os-loading');
2295 // console.log(data.message);
2296 }
2297 }
2298 });
2299 }
2300