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