PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.3
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.3
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 / public / javascripts / admin.js
latepoint / public / javascripts Last commit date
vendor 1 year ago admin.js 1 year ago admin.js.map 1 year ago front.js 1 year ago front.js.map 1 year ago vendor-admin.js 1 year ago vendor-front.js 1 year ago
admin.js
5350 lines
1 function latepoint_is_timeframe_in_periods(timeframe_start, timeframe_end, periods_arr) {
2 var is_inside = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
3
4 for (var i = 0; i < periods_arr.length; i++) {
5
6 var period_start = 0;
7 var period_end = 0;
8 var buffer_before = 0;
9 var buffer_after = 0;
10
11 var period_info = periods_arr[i].split(':');
12 if (period_info.length == 2) {
13 period_start = period_info[0];
14 period_end = period_info[1];
15 } else {
16 buffer_before = period_info[2];
17 buffer_after = period_info[3];
18 period_start = parseFloat(period_info[0]) - parseFloat(buffer_before);
19 period_end = parseFloat(period_info[1]) + parseFloat(buffer_after);
20 }
21 if (is_inside) {
22 if (latepoint_is_period_inside_another(timeframe_start, timeframe_end, period_start, period_end)) {
23 return true;
24 }
25 } else {
26 if (latepoint_is_period_overlapping(timeframe_start, timeframe_end, period_start, period_end)) {
27 return true;
28 }
29 }
30 }
31 return false;
32 }
33
34 function latepoint_is_period_overlapping(period_one_start, period_one_end, period_two_start, period_two_end) {
35 // https://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap/
36 return period_one_start < period_two_end && period_two_start < period_one_end;
37 }
38
39 function latepoint_is_period_inside_another(period_one_start, period_one_end, period_two_start, period_two_end) {
40 return period_one_start >= period_two_start && period_one_end <= period_two_end;
41 }
42
43
44 // Converts time in minutes to hours if possible, if minutes also exists - shows minutes too
45 function latepoint_minutes_to_hours_preferably(time) {
46 var army_clock = latepoint_is_army_clock();
47
48 var hours = Math.floor(time / 60);
49 if (!army_clock && hours > 12) hours = hours - 12;
50
51 var minutes = time % 60;
52 if (minutes > 0) hours = hours + ':' + minutes;
53 return hours;
54 }
55
56
57 function latepoint_minutes_to_hours(time) {
58 var army_clock = latepoint_is_army_clock();
59
60 var hours = Math.floor(time / 60);
61 if (!army_clock && hours > 12) hours = hours - 12;
62 return hours;
63 }
64
65
66 function latepoint_am_or_pm(minutes) {
67 if (latepoint_is_army_clock()) return '';
68 return (minutes < 720 || minutes == 1440) ? 'am' : 'pm';
69 }
70
71 function latepoint_hours_and_minutes_to_minutes(hours_and_minutes, ampm) {
72 var hours_and_minutes_arr = hours_and_minutes.split(':');
73 var hours = hours_and_minutes_arr[0];
74 var minutes = hours_and_minutes_arr[1];
75 if (ampm == "pm" && hours < 12) hours = parseInt(hours) + 12;
76 if (ampm == "am" && hours == 12) hours = 0;
77 minutes = parseInt(minutes) + (hours * 60);
78 return minutes;
79 }
80
81 function latepoint_get_time_system() {
82 return latepoint_helper.time_system;
83 }
84
85 function latepoint_is_army_clock() {
86 return (latepoint_get_time_system() == '24');
87 }
88
89 function latepoint_minutes_to_hours_and_minutes(minutes) {
90 var army_clock = latepoint_is_army_clock();
91 var format = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '%02d:%02d';
92
93 var hours = Math.floor(minutes / 60);
94 if (!army_clock && (hours > 12)) hours = hours - 12;
95 if (!army_clock && hours == 0) hours = 12;
96 minutes = minutes % 60;
97 return sprintf(format, hours, minutes);
98 }
99
100
101 (function($) {
102
103 jQuery.fn.lateSelect = function() {
104
105 function os_build_selected_item($option){
106 var quantity_html = '';
107 if($option.data('quantity')) quantity_html = '<span class="os-late-quantity-selector-w"><span class="os-late-quantity-selector minus" data-sign="minus"></span><input class="os-late-quantity-selector-input" type="text" data-max-quantity="'+ $option.data('max-quantity') +'" value="' + $option.data('quantity') + '"/><span class="os-late-quantity-selector plus" data-sign="plus"></span></span>';
108 return '<div class="ls-item" data-value="' + $option.val() + '"><span class="latepoint-icon latepoint-icon-cross ls-item-remover"></span><span>' + $option.text() + '</span>' + quantity_html + '</div>'
109 }
110
111 this.each( function() {
112 var lateselect_html = '';
113 var all_items = '';
114 var selected_items = '';
115 var is_selected = '';
116 if(jQuery(this).hasClass('os-late-select-active')) return;
117 jQuery(this).hide().addClass('os-late-select-active');
118 jQuery(this).find('option').each(function(){
119 if(jQuery(this).is(':selected')) selected_items+= os_build_selected_item(jQuery(this));
120 is_selected = jQuery(this).is(':selected') ? 'selected' : '';
121 all_items+= '<div class="ls-item '+ is_selected +'" data-value="' + jQuery(this).val() + '">' + jQuery(this).text() + '</div>';
122 });
123 var placeholder = '<div class="ls-placeholder">' + jQuery(this).data('placeholder') + '</div>';
124 lateselect_html = jQuery('<div class="lateselect-w"></div>');
125 jQuery(this).wrap(lateselect_html);
126 var $lateselect_wrapper = jQuery(this).closest('.lateselect-w');
127 $lateselect_wrapper.append('<div class="ls-selected-items-w">' + placeholder + selected_items + '</div>');
128 $lateselect_wrapper.append('<div class="ls-all-items-w">' + all_items + '</div>');
129
130
131 // ADD ITEM
132 $lateselect_wrapper.on('click', '.ls-all-items-w .ls-item:not(.selected)', function(){
133 var selected_value = jQuery(this).data('value');
134 $lateselect_wrapper.find('.ls-selected-items-w').append(os_build_selected_item($lateselect_wrapper.find('select option[value="'+ selected_value +'"]')));
135 jQuery(this).addClass('selected');
136 $lateselect_wrapper.removeClass('ls-selecting');
137 $lateselect_wrapper.find('select option[value="'+ selected_value +'"]').prop('selected', true);
138 $lateselect_wrapper.find('select').trigger('change');
139 return false;
140 });
141
142 // REMOVE ITEM
143 $lateselect_wrapper.on('click', '.ls-selected-items-w .ls-item-remover', function(){
144 var selected_value = jQuery(this).closest('.ls-item').data('value');
145 jQuery(this).closest('.ls-item').remove();
146 $lateselect_wrapper.find('.ls-all-items-w .ls-item.selected[data-value="' + selected_value + '"]').removeClass('selected');
147 $lateselect_wrapper.find('select option[value="'+ selected_value +'"]').prop('selected', false);
148 $lateselect_wrapper.find('select').trigger('change');
149 return false;
150 });
151
152 $lateselect_wrapper.on('click', '.ls-selected-items-w', function(){
153 $lateselect_wrapper.toggleClass('ls-selecting');
154 return false;
155 });
156
157 $lateselect_wrapper.on('click', '.os-late-quantity-selector', function(){
158 var $input = jQuery(this).closest('.ls-item').find('input.os-late-quantity-selector-input');
159 var current_value = parseInt($input.val());
160 var new_quantity = (jQuery(this).data('sign') == 'minus') ? current_value - 1 : current_value + 1;
161 var max_quantity = $input.data('max-quantity');
162 if(new_quantity <= 0) new_quantity = 1;
163 if(max_quantity && (new_quantity > max_quantity)) new_quantity = max_quantity;
164 var selected_value = jQuery(this).closest('.ls-item').data('value');
165 $lateselect_wrapper.find('select option[value="'+ selected_value +'"]').data('quantity', new_quantity);
166 $input.val(new_quantity);
167 $lateselect_wrapper.find('select').trigger('change');
168 return false;
169 });
170
171 jQuery(this).on('change', function(){
172 var $hidden_connection = false;
173 if(jQuery(this).data('hidden-connection')){
174 $hidden_connection = jQuery(jQuery(this).data('hidden-connection'));
175 }else{
176 $hidden_connection = jQuery(this).closest('.lateselect-w').next('input[type="hidden"]');
177 }
178 var formatted_ids = '';
179 if(jQuery(this).find('option:selected').length){
180 jQuery(this).find('option:selected').each(function(){
181 if(jQuery(this).data('quantity')){
182 var quantity = jQuery(this).data('quantity') ? jQuery(this).data('quantity') : 1;
183 formatted_ids+= jQuery(this).val() + ':' + quantity + ',';
184 }else{
185 formatted_ids+= jQuery(this).val() + ',';
186 }
187 });
188 }else{
189 formatted_ids = '';
190 }
191 if(formatted_ids != '') formatted_ids = formatted_ids.slice(0, -1);
192 $hidden_connection.val(formatted_ids);
193 });
194 });
195 }
196 }(jQuery));
197
198 /*
199 * Copyright (c) 2023 LatePoint LLC. All rights reserved.
200 */
201
202 (function($) {
203
204 jQuery.fn.lateCheckbox = function() {
205
206 function applyChanges(id){
207 let $wrapper = jQuery('.latecheckbox-w[data-latecheckbox-id="' + id + '"]');
208 $wrapper.find('.latecheckbox-options-w').html(jQuery('.latecheckbox-options-w[data-latecheckbox-id="' + id + '"]').html());
209
210 let $options = $wrapper.find('.latecheckbox-options');
211 let total_checked = $options.find('.latecheckbox-option input[type="checkbox"]:checked').length;
212 let total_available = $options.find('.latecheckbox-option input[type="checkbox"]').length;
213 if(total_checked < total_available){
214 $wrapper.find('.latecheckbox .filter-value').text(total_checked);
215 }else{
216 $wrapper.find('.latecheckbox .filter-value').text('All');
217 }
218 // set indeterminate, since it can only be set via JS
219 $wrapper.find('input[type="checkbox"][indeterminate="indeterminate"]').prop('indeterminate', true).removeAttr('indeterminate');
220
221 $wrapper.find('.latecheckbox').trigger('change');
222 }
223
224 this.each( function() {
225 var $latecheckbox_wrapper = jQuery(this).closest('.latecheckbox-w');
226 $latecheckbox_wrapper.attr('data-latecheckbox-id', 'latecheckbox-' + latepoint_random_generator());
227
228 $latecheckbox_wrapper.on('click', '.latecheckbox', function(){
229 let $latecheckbox = jQuery(this);
230 jQuery('body > .latecheckbox-options-w').remove();
231 if(jQuery(this).hasClass('is-active')){
232 jQuery(this).removeClass('is-active');
233 }else{
234 jQuery('.latecheckbox.is-active').removeClass('is-active');
235 jQuery(this).addClass('is-active');
236 let position = jQuery(this).position();
237 let left = position.left;
238 let $options_wrapper = $latecheckbox_wrapper.find('.latecheckbox-options-w');
239 let $options_wrapper_clone = $options_wrapper.clone();
240 $options_wrapper_clone.attr('data-latecheckbox-id', jQuery(this).closest('.latecheckbox-w').attr('data-latecheckbox-id')).appendTo('body');
241 if(true){
242 // todo add ability to change position
243 left = left + jQuery(this).outerWidth() - $options_wrapper_clone.outerWidth();
244 }
245 $options_wrapper_clone.css({"top": position.top + jQuery(this).outerHeight() +5 , "left": left});
246 if($options_wrapper_clone.find('.latecheckbox-filter-input').length) $options_wrapper_clone.find('.latecheckbox-filter-input').trigger('focus');
247
248 $options_wrapper_clone.on('change', '.latecheckbox-all-check', function(){
249 if(jQuery(this).is(':checked')){
250 jQuery(this).attr('checked', 'checked').removeAttr('indeterminate');
251 jQuery(this).closest('.latecheckbox-options-w').find('.latecheckbox-options input[type="checkbox"]').prop('checked', true).prop('indeterminate', false).attr('checked', 'checked');
252 }else{
253 jQuery(this).removeAttr('checked').removeAttr('indeterminate');
254 jQuery(this).closest('.latecheckbox-options-w').find('.latecheckbox-options input[type="checkbox"]').prop('checked', false).prop('indeterminate', false).removeAttr('checked');
255 }
256 applyChanges(jQuery(this).closest('.latecheckbox-options-w').attr('data-latecheckbox-id'));
257 });
258 $options_wrapper_clone.on('change', '.latecheckbox-group-check', function(){
259 if(jQuery(this).is(':checked')){
260 jQuery(this).attr('checked', 'checked').removeAttr('indeterminate');
261 jQuery(this).closest('.latecheckbox-group').find('.latecheckbox-group-options input[type="checkbox"]').prop('checked', true).attr('checked', 'checked');
262 }else{
263 jQuery(this).removeAttr('checked').removeAttr('indeterminate');
264 jQuery(this).closest('.latecheckbox-group').find('.latecheckbox-group-options input[type="checkbox"]').prop('checked', false).removeAttr('checked');
265 }
266 applyChanges(jQuery(this).closest('.latecheckbox-options-w').attr('data-latecheckbox-id'));
267 });
268
269 $options_wrapper_clone.on('keyup', '.latecheckbox-filter-input', function(){
270 let q = jQuery(this).val().toLowerCase();
271 if(q == ''){
272 jQuery(this).closest('.latecheckbox-options-w').find('.latecheckbox-option.hidden').removeClass('hidden');
273 }else{
274 jQuery(this).closest('.latecheckbox-options-w').find('.latecheckbox-option').each(function(){
275 let text = jQuery(this).text().toLowerCase();
276 (text.indexOf(q) >= 0) ? jQuery(this).removeClass('hidden') : jQuery(this).addClass('hidden');
277 });
278 }
279 });
280
281 $options_wrapper_clone.on('change', '.latecheckbox-option input[type="checkbox"]', function(){
282 if(jQuery(this).is(':checked')){
283 jQuery(this).attr('checked', 'checked');
284 }else{
285 jQuery(this).removeAttr('checked');
286 }
287
288 // group checkbox
289 if(jQuery(this).closest('.latecheckbox-group-options').length){
290 let $group = jQuery(this).closest('.latecheckbox-group');
291 let checked_count = $group.find('.latecheckbox-option input:checked').length;
292 let unchecked_count = $group.find('.latecheckbox-option input:not(:checked)').length;
293
294 if(checked_count && unchecked_count){
295 $group.find('.latecheckbox-group-check').prop('indeterminate', true).attr('indeterminate', 'indeterminate');
296 $group.find('.latecheckbox-group-check').prop('checked', false).removeAttr('checked');
297 }else{
298 $group.find('.latecheckbox-group-check').prop('indeterminate', false).removeAttr('indeterminate');
299 if(!checked_count){
300 $group.find('.latecheckbox-group-check').prop('checked', false).removeAttr('checked');
301 }
302 if(!unchecked_count){
303 $group.find('.latecheckbox-group-check').prop('checked', true).attr('checked', 'checked');
304 }
305 }
306 }
307 let checked_count = $options_wrapper_clone.find('.latecheckbox-option input:checked').length;
308 let unchecked_count = $options_wrapper_clone.find('.latecheckbox-option input:not(:checked)').length;
309
310 if(checked_count && unchecked_count){
311 $options_wrapper_clone.find('.latecheckbox-all-check').prop('indeterminate', true).attr('indeterminate', 'indeterminate');
312 $options_wrapper_clone.find('.latecheckbox-all-check').prop('checked', false).removeAttr('checked');
313 }else{
314 $options_wrapper_clone.find('.latecheckbox-all-check').prop('indeterminate', false).removeAttr('indeterminate');
315 if(!checked_count){
316 $options_wrapper_clone.find('.latecheckbox-all-check').prop('checked', false).removeAttr('checked');
317 }
318 if(!unchecked_count){
319 $options_wrapper_clone.find('.latecheckbox-all-check').prop('checked', true).attr('checked', 'checked');
320 }
321 }
322 applyChanges(jQuery(this).closest('.latecheckbox-options-w').attr('data-latecheckbox-id'));
323 });
324 }
325 return false;
326 });
327
328 });
329 }
330 }(jQuery));
331
332 function latepoint_generate_form_message_html(messages, status){
333 var message_html = '<div class="os-form-message-w status-' + status + '"><ul>';
334 if(Array.isArray(messages)){
335 messages.forEach(function(message){
336 message_html+= '<li>' + message + '</li>';
337 });
338 }else{
339 message_html+= '<li>' + messages + '</li>';
340 }
341 message_html+= '</ul></div>';
342 return message_html;
343 }
344
345 function latepoint_display_in_side_sub_panel(html){
346 if(!jQuery('.latepoint-side-panel-w').length) latepoint_show_data_in_side_panel('');
347 jQuery('.latepoint-side-panel-w .latepoint-side-panels .side-sub-panel-wrapper').remove();
348 jQuery('.latepoint-side-panel-w .latepoint-side-panels').append(html);
349 }
350
351 function latepoint_clear_form_messages($form){
352 $form.find('.os-form-message-w').remove();
353 }
354
355 function latepoint_show_data_in_side_panel(message, extra_classes = '', close_btn = true){
356 jQuery('.latepoint-side-panel-w').remove();
357 jQuery('body').append('<div class="latepoint-side-panel-w ' + extra_classes + ' os-loading"><div class="latepoint-side-panel-shadow"></div><div class="latepoint-side-panels"><div class="latepoint-side-panel-i"></div></div></div>');
358 jQuery('.latepoint-side-panel-i').html(message);
359 if(close_btn){
360 jQuery('.latepoint-side-panel-i').find('.os-form-header .latepoint-side-panel-close').remove();
361 jQuery('.latepoint-side-panel-i').find('.os-form-header').append('<a href="#" class="latepoint-side-panel-close latepoint-side-panel-close-trigger"><i class="latepoint-icon latepoint-icon-x"></i></a>');
362 }
363 setTimeout(function(){
364 jQuery('.latepoint-side-panel-w').removeClass('os-loading');
365 }, 100);
366 }
367
368 function latepoint_show_data_in_lightbox(message, extra_classes = '', close_btn = true, tag = 'div', inner_extra_classes = '', inner_tag = 'div'){
369 jQuery('.latepoint-lightbox-w').remove();
370 let lightbox_css_classes = 'latepoint-lightbox-w latepoint-w latepoint-border-radius-' + latepoint_helper.style_border_radius+ ' ';
371 if(extra_classes) lightbox_css_classes+= extra_classes;
372 let lightbox_css_inner_classes = 'latepoint-lightbox-i ';
373 if(inner_extra_classes) lightbox_css_inner_classes += inner_extra_classes;
374
375 let close_btn_html = close_btn ? '<a href="#" class="latepoint-lightbox-close" tabindex="0"><i class="latepoint-icon latepoint-icon-x"></i></a>' : '';
376 jQuery('body').append('<'+tag+' class="'+ lightbox_css_classes +'"><'+inner_tag+' class="'+ lightbox_css_inner_classes +'">' + message + close_btn_html + '</'+inner_tag+'><div class="latepoint-lightbox-shadow"></div></'+tag+'>');
377
378 jQuery('body').addClass('latepoint-lightbox-active');
379 }
380
381
382
383 // DOCUMENT READY
384 jQuery(function( $ ) {
385
386 if($('.latepoint').find('[data-os-action-onload]').length){
387 $('.latepoint').find('[data-os-action-onload]').each(function(){
388 var $this = jQuery(this);
389 $this.addClass('os-loading');
390 var params = $this.data('os-params');
391 var return_format = $this.data('os-return-format') ? $this.data('os-return-format') : 'json'
392 var data = { action: 'latepoint_route_call', route_name: $this.data('os-action-onload'), params: params, return_format: return_format }
393 jQuery.ajax({
394 type : "post",
395 dataType : "json",
396 url : latepoint_timestamped_ajaxurl(),
397 data : data,
398 success: function(response) {
399 $this.removeClass('os-loading');
400 if (response.status === "success") {
401 if($this.data('os-output-target') == 'self'){
402 $this.html(response.message);
403 }
404 }
405 }
406 });
407 });
408 }
409
410 /*
411 Ajax buttons action
412 */
413 $('.latepoint').on('click', 'button[data-os-action], a[data-os-action], div[data-os-action], span[data-os-action], tr[data-os-action]', function(e){
414 var $this = jQuery(this);
415 if($this.data('os-prompt') && !confirm($this.data('os-prompt'))) return false;
416 var params = $this.data('os-params');
417 if($this.data('os-source-of-params')){
418 var form_data = latepoint_create_form_data_from_non_form_element($($this.data('os-source-of-params')));
419 params = latepoint_formdata_to_url_encoded_string(form_data);
420 }
421 var return_format = $this.data('os-return-format') ? $this.data('os-return-format') : 'json'
422 var data = { action: 'latepoint_route_call', route_name: $this.data('os-action'), params: params, return_format: return_format }
423 $this.addClass('os-loading');
424 if($this.data('os-output-target') == 'side-panel'){
425 $('.latepoint-side-panel-w').remove();
426 let css_classes = $this.data('os-lightbox-classes') ? $this.data('os-lightbox-classes') : '';
427 $('body').append('<div class="latepoint-side-panel-w ' + css_classes + ' os-loading"><div class="latepoint-side-panel-shadow"></div><div class="latepoint-side-panels"><div class="latepoint-side-panel-i"></div></div></div>');
428 }
429 $.ajax({
430 type : "post",
431 dataType : "json",
432 url : latepoint_timestamped_ajaxurl(),
433 data : data,
434 success: function(response){
435 if(response.status === "success"){
436 if($this.data('os-output-target') == 'lightbox'){
437 latepoint_show_data_in_lightbox(response.message, $this.data('os-lightbox-classes'), ($this.data('os-lightbox-no-close-button') !== 'yes'), $this.data('os-lightbox-tag'), $this.data('os-lightbox-inner-classes'), $this.data('os-lightbox-inner-tag'));
438 }else if($this.data('os-output-target') == 'side-panel'){
439 $('.latepoint-side-panel-i').html(response.message);
440 jQuery('.latepoint-side-panel-i').find('.os-form-header .latepoint-side-panel-close').remove();
441 jQuery('.latepoint-side-panel-i').find('.os-form-header').append('<a href="#" class="latepoint-side-panel-close latepoint-side-panel-close-trigger"><i class="latepoint-icon latepoint-icon-x"></i></a>');
442 setTimeout(function(){
443 $('.latepoint-side-panel-w').removeClass('os-loading');
444 }, 100);
445 }else if($this.data('os-success-action') == 'reload'){
446 latepoint_add_notification(response.message);
447 location.reload();
448 return;
449 }else if($this.data('os-success-action') == 'redirect'){
450 if($this.data('os-redirect-to')){
451 latepoint_add_notification(response.message);
452 window.location.replace($this.data('os-redirect-to'));
453 }else{
454 window.location.replace(response.message);
455 }
456 return;
457 }else if($this.data('os-output-target') && $($this.data('os-output-target')).length){
458 if($this.data('os-output-target-do') == 'append') {
459 $($this.data('os-output-target')).append(response.message);
460 }else if($this.data('os-output-target-do') == 'prepend'){
461 $($this.data('os-output-target')).prepend(response.message);
462 }else{
463 $($this.data('os-output-target')).html(response.message);
464 }
465 }else{
466 switch($this.data('os-before-after')){
467 case 'before':
468 $this.before(response.message);
469 break;
470 case 'after':
471 $this.after(response.message);
472 break;
473 case 'replace':
474 $this.replaceWith(response.message);
475 break;
476 case 'none':
477 break;
478 default:
479 latepoint_add_notification(response.message);
480 }
481 }
482 if($this.data('os-after-call')){
483 var func_name = $this.data('os-after-call');
484 var callback = false;
485 if(func_name.includes('.')){
486 var func_arr = func_name.split('.');
487 if(typeof window[func_arr[0]][func_arr[1]] !== 'function'){
488 console.log(func_name + ' is undefined');
489 }
490 if($this.data('os-pass-this') && $this.data('os-pass-response')){
491 window[func_arr[0]][func_arr[1]]($this, response);
492 }else if($this.data('os-pass-this')){
493 window[func_arr[0]][func_arr[1]]($this);
494 }else if($this.data('os-pass-response')){
495 window[func_arr[0]][func_arr[1]](response);
496 }else{
497 window[func_arr[0]][func_arr[1]]();
498 }
499 }else{
500 if(typeof window[func_name] !== 'function'){
501 console.log(func_name + ' is undefined');
502 }
503 if($this.data('os-pass-this') && $this.data('os-pass-response')){
504 window[func_name]($this, response);
505 }else if($this.data('os-pass-this')){
506 window[func_name]($this);
507 }else if($this.data('os-pass-response')){
508 window[func_name](response);
509 }else{
510 window[func_name]();
511 }
512 }
513 }
514 $this.removeClass('os-loading');
515 }else{
516 $this.removeClass('os-loading');
517 if($this.data('os-output-target') && $($this.data('os-output-target')).length){
518 $($this.data('os-output-target')).prepend(latepoint_generate_form_message_html(response.message, 'error'));
519 }else{
520 alert(response.message);
521 }
522 if($this.data('os-after-call-error')){
523 var func_name = $this.data('os-after-call-error');
524 var callback = false;
525 if(func_name.includes('.')){
526 var func_arr = func_name.split('.');
527 if(typeof window[func_arr[0]][func_arr[1]] !== 'function'){
528 console.log(func_name + ' is undefined');
529 }
530 if($this.data('os-pass-this') && $this.data('os-pass-response')){
531 window[func_arr[0]][func_arr[1]]($this, response);
532 }else if($this.data('os-pass-this')){
533 window[func_arr[0]][func_arr[1]]($this);
534 }else if($this.data('os-pass-response')){
535 window[func_arr[0]][func_arr[1]](response);
536 }else{
537 window[func_arr[0]][func_arr[1]]();
538 }
539 }else{
540 if(typeof window[func_name] !== 'function'){
541 console.log(func_name + ' is undefined');
542 }
543 if($this.data('os-pass-this') && $this.data('os-pass-response')){
544 window[func_name]($this, response);
545 }else if($this.data('os-pass-this')){
546 window[func_name]($this);
547 }else if($this.data('os-pass-response')){
548 window[func_name](response);
549 }else{
550 window[func_name]();
551 }
552 }
553 }
554 }
555 }
556 });
557 return false;
558 });
559
560
561 $('.latepoint').on('click', 'form[data-os-action] button[type="submit"]', function(e){
562 $(this).addClass('os-loading');
563 });
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581 /*
582 Form ajax submit action
583 */
584 $('.latepoint').on('submit', 'form[data-os-action]', function(e){
585 e.preventDefault(); // prevent native submit
586 var $form = $(this);
587 var form_data = new FormData($form[0]);
588
589 if (('intlTelInputGlobals' in window) && ('intlTelInputUtils' in window)) {
590 // Get e164 formatted number from phone fields when form is submitted
591 $form.find('input.os-mask-phone').each(function () {
592 let telInstance = window.intlTelInputGlobals.getInstance(this);
593 if(telInstance){
594 const phoneInputName = this.getAttribute('name');
595 const phoneInputValue = window.intlTelInputGlobals.getInstance(this).getNumber(window.intlTelInputUtils.numberFormat.E164);
596 form_data.set(phoneInputName, phoneInputValue);
597 }
598 });
599 }
600
601 let data = latepoint_create_form_data($form, $(this).data('os-action'));
602
603 // var data = { action: 'latepoint_route_call', route_name: $(this).data('os-action'), params: latepoint_formdata_to_url_encoded_string(form_data), return_format: 'json' }
604 $form.find('button[type="submit"]').addClass('os-loading');
605 $.ajax({
606 type : "post",
607 dataType : "json",
608 processData: false,
609 contentType: false,
610 url : latepoint_timestamped_ajaxurl(),
611 data : data,
612 success: function(response){
613 $form.find('button[type="submit"].os-loading').removeClass('os-loading');
614 latepoint_clear_form_messages($form);
615 if(response.status === "success"){
616 if($form.data('os-success-action') == 'reload'){
617 latepoint_add_notification(response.message);
618 location.reload();
619 return;
620 }else if($form.data('os-success-action') == 'redirect'){
621 if($form.data('os-redirect-to')){
622 latepoint_add_notification(response.message);
623 window.location.replace($form.data('os-redirect-to'));
624 }else{
625 window.location.replace(response.message);
626 }
627 return;
628 }else if($form.data('os-output-target') && $($form.data('os-output-target')).length){
629 $($form.data('os-output-target')).html(response.message);
630 }else{
631 if(response.message == 'redirect'){
632 window.location.replace(response.url);
633 }else{
634 latepoint_add_notification(response.message);
635 }
636 }
637 if($form.data('os-record-id-holder') && response.record_id){
638 $form.find('[name="' + $form.data('os-record-id-holder') + '"]').val(response.record_id)
639 }
640 if($form.data('os-after-call')){
641
642 var func_name = $form.data('os-after-call');
643 var callback = false;
644 if(func_name.includes('.')){
645 var func_arr = func_name.split('.');
646 if(typeof window[func_arr[0]][func_arr[1]] !== 'function'){
647 console.log(func_name + ' is undefined');
648 }
649 if($form.data('os-pass-this') && $form.data('os-pass-response')){
650 window[func_arr[0]][func_arr[1]]($form, response);
651 }else if($form.data('os-pass-this')){
652 window[func_arr[0]][func_arr[1]]($form);
653 }else if($form.data('os-pass-response')){
654 window[func_arr[0]][func_arr[1]](response);
655 }else{
656 window[func_arr[0]][func_arr[1]]();
657 }
658 }else{
659 if(typeof window[func_name] !== 'function'){
660 console.log(func_name + ' is undefined');
661 }
662 if($form.data('os-pass-this') && $form.data('os-pass-response')){
663 window[func_name]($form, response);
664 }else if($form.data('os-pass-this')){
665 window[func_name]($form);
666 }else if($form.data('os-pass-response')){
667 window[func_name](response);
668 }else{
669 window[func_name]();
670 }
671 }
672 }
673 $('button.os-loading').removeClass('os-loading');
674 }else{
675 $('button.os-loading').removeClass('os-loading');
676 if($form.data('os-show-errors-as-notification')){
677 latepoint_add_notification(response.message, 'error');
678 }else{
679 latepoint_add_notification(response.message, 'error');
680 $([document.documentElement, document.body]).animate({
681 scrollTop: ($form.find(".os-form-message-w").offset().top - 30)
682 }, 200);
683 }
684 }
685 if(response.form_values_to_update){
686 $.each(response.form_values_to_update, function(name, value){
687 $form.find('[name="'+ name +'"]').val(value);
688 });
689 }
690 }
691 });
692 return false;
693 });
694 });
695
696 function latepoint_add_notification(message, message_type = 'success'){
697 var wrapper = jQuery('body').find('.os-notifications');
698 if(!wrapper.length){
699 jQuery('body').append('<div class="os-notifications"></div>');
700 wrapper = jQuery('body').find('.os-notifications');
701 }
702 if(wrapper.find('.item').length > 0) wrapper.find('.item:first-child').remove();
703 wrapper.append('<div class="item item-type-'+ message_type +'">' + message + '<span class="os-notification-close"><i class="latepoint-icon latepoint-icon-x"></i></span></div>');
704 }
705
706 function latepoint_add_lightbox_notification(message, message_type = 'success'){
707 var wrapper = jQuery('.latepoint-lightbox-content').find('.os-notifications');
708 if(!wrapper.length){
709 jQuery('.latepoint-lightbox-content').prepend('<div class="os-notifications"></div>');
710 wrapper = jQuery('.latepoint-lightbox-content').find('.os-notifications');
711 }
712 if(wrapper.find('.item').length > 0) wrapper.find('.item:first-child').remove();
713 wrapper.append('<div class="item item-type-'+ message_type +'">' + message + '<span class="os-notification-close"><i class="latepoint-icon latepoint-icon-x"></i></span></div>');
714 }
715
716 function latepoint_timestamped_ajaxurl(){
717 let url = latepoint_helper.ajaxurl;
718 let timestamp = Date.now();
719
720 // Check if the URL already has GET parameters
721 if (url.includes('?')) {
722 return `${url}&t=${timestamp}`;
723 } else {
724 return `${url}?t=${timestamp}`;
725 }
726 }
727
728 function latepoint_random_generator() {
729 var S4 = function () {
730 return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
731 };
732 return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
733 }
734
735 function latepoint_validate_form($form) {
736 let errors = [];
737 $form.find('select[data-os-validate], input[data-os-validate], textarea[data-os-validate]').each(function () {
738 let validations = jQuery(this).data('os-validate').split(' ');
739 let $input = jQuery(this);
740 let label = $input.closest('.os-form-group').find('label').text();
741 let field_has_errors = false;
742 if (validations) {
743 for (let i = 0; i < validations.length; i++) {
744 switch (validations[i]) {
745 case 'presence':
746 if($input.is(':checkbox')){
747 if (!$input.is(':checked')) {
748 errors.push({message: label + ' ' + latepoint_helper.msg_validation_presence_checkbox});
749 field_has_errors = true;
750 }
751 }else{
752 if (!$input.val()) {
753 errors.push({message: label + ' ' + latepoint_helper.msg_validation_presence});
754 field_has_errors = true;
755 }
756 }
757 break;
758 case 'phone':
759 if (!window.intlTelInputGlobals.getInstance($input[0]).isValidNumber()) {
760 errors.push({message: label + ' ' + latepoint_helper.msg_validation_invalid});
761 field_has_errors = true;
762 }
763 break;
764 }
765 }
766 }
767 if (field_has_errors) {
768 $input.closest('.os-form-group').addClass('os-invalid');
769 } else {
770 $input.closest('.os-form-group').removeClass('os-invalid');
771 }
772 });
773 return errors;
774 }
775
776 function latepoint_create_form_data_from_non_form_element($elem) {
777 let formData = new FormData();
778 // create objecte from all input fields that are inside of the element
779 let fields = $elem.find('select, input, textarea').serializeArray();
780 if (fields) {
781 fields.forEach(field => formData.append(field.name, field.value));
782 }
783 return formData;
784 }
785
786 function latepoint_create_form_data($form, route_name = false, extra_params = false) {
787 let form_data = new FormData();
788 let params = new FormData($form[0]);
789
790 if (extra_params) {
791 Object.keys(extra_params).forEach(key => {
792 params.set(key, extra_params[key]);
793 });
794 }
795
796 // get values from phone number fields
797 if (('intlTelInputGlobals' in window) && ('intlTelInputUtils' in window)) {
798 $form.find('input.os-mask-phone').each(function () {
799 const phoneInputName = this.getAttribute('name');
800 const phoneInputValue = window.intlTelInputGlobals.getInstance(this).getNumber(window.intlTelInputUtils.numberFormat.E164);
801 // override value generated automatically by formdata with a formatted value of a phone field with country code
802 params.set(phoneInputName, phoneInputValue);
803 });
804 }
805
806 form_data.append('params', latepoint_formdata_to_url_encoded_string(params));
807 form_data.append('action', latepoint_helper.route_action);
808 form_data.append('route_name', route_name ? route_name : $form.data('route-name'));
809 form_data.append('layout', 'none');
810 form_data.append('return_format', 'json');
811
812 let file_data;
813 // put file data into main form_data object, since we can't send them in "params" string
814 $form.find('input[type="file"]').each(function () {
815 file_data = this.files; // get multiple files from input file
816 let file_name = this.getAttribute("name");
817 for (let i = 0; i < file_data.length; i++) {
818 form_data.append(file_name + '[]', file_data[i]);
819 }
820 });
821 return form_data;
822 }
823
824 function latepoint_mask_timefield($elem) {
825 if (jQuery().inputmask) {
826 $elem.inputmask({
827 'mask': '99:99',
828 'placeholder': 'HH:MM'
829 });
830 }
831 }
832
833 function latepoint_formdata_to_url_encoded_string(form_data) {
834 let filtered_form_data = new FormData();
835 // remove file fields from params, so we can serialize it into string,
836 // !important, this will not include file fields into the form_data, so you have to include them manually, see latepoint_create_form_data() that does it
837 // note: we don't use form_data.remove(key) on original object because we might want to preserve it
838 for (const [key, value] of form_data) {
839 if (value instanceof File) continue;
840 if (key.slice(-2) === '[]') {
841 // expecting array, append
842 filtered_form_data.append(key, value);
843 } else {
844 filtered_form_data.set(key, value);
845 }
846 }
847 return new URLSearchParams(filtered_form_data).toString();
848 }
849
850 function latepoint_mask_percent($elem) {
851 if (jQuery().inputmask) {
852 $elem.inputmask({
853 'alias': 'decimal',
854 'radixPoint': latepoint_helper.decimal_separator,
855 'digits': 4,
856 'digitsOptional': false,
857 'suffix': '%',
858 'placeholder': '0',
859 'rightAlign': false
860 });
861 }
862 }
863
864 function latepoint_mask_minutes($elem) {
865 if (jQuery().inputmask) {
866 $elem.inputmask({
867 'removeMaskOnSubmit': true,
868 'alias': 'numeric',
869 'digits': 0,
870 'suffix': latepoint_helper.msg_minutes_suffix,
871 'placeholder': '0',
872 'rightAlign': false
873 });
874 }
875 }
876
877
878 function latepoint_mask_money($elem) {
879 if (jQuery().inputmask) {
880 $elem.inputmask({
881 'alias': 'currency',
882 'groupSeparator': latepoint_helper.thousand_separator,
883 'radixPoint': latepoint_helper.decimal_separator,
884 'digits': latepoint_helper.number_of_decimals,
885 'digitsOptional': false,
886 'prefix': latepoint_helper.currency_symbol_before ? latepoint_helper.currency_symbol_before + ' ' : '',
887 'suffix': latepoint_helper.currency_symbol_after ? ' ' + latepoint_helper.currency_symbol_after : '',
888 'placeholder': '0',
889 'rightAlign': false
890 });
891 }
892 }
893
894 function latepoint_mask_date($elem) {
895 if (jQuery().inputmask) {
896 $elem.inputmask({
897 'alias': 'datetime',
898 'inputFormat': latepoint_helper.date_format_for_js
899 });
900 }
901 }
902
903 function latepoint_init_phone_masking_from_placeholder($input) {
904 if (!latepoint_helper.mask_phone_number_fields) return;
905 let format = $input.attr('placeholder');
906 if (format && jQuery().inputmask) {
907 $input.inputmask(format.replace(/[0-9]/g, 9));
908 }
909 }
910
911 function latepoint_mask_phone($elem) {
912 let jsElem = $elem[0];
913
914 // First priority is to prevent duplicates (common in non-document.body contexts)
915 if (jsElem && !window.intlTelInputGlobals.getInstance(jsElem)) {
916 let dropdownContainer = document.body;
917
918 let onlyCountries = JSON.parse(latepoint_helper.included_phone_countries);
919 // Remedy a quirk with json_encode(EMPTY_ARRAY)
920 if (onlyCountries.length === 1 && onlyCountries[0] === "") {
921 onlyCountries = [];
922 }
923 const preferredCountries = onlyCountries.length ? [] : window.intlTelInputGlobals.defaults.preferredCountries;
924
925 // remove country name in english and only use names in country language
926 var countryData = window.intlTelInputGlobals.getCountryData();
927
928 for (var i = 0; i < countryData.length; i++) {
929 var country = countryData[i];
930 country.name = country.name.replace(/ *\([^)]*\) */g, "");
931 }
932
933 let defaultCountryCode = latepoint_helper.default_phone_country;
934 if (onlyCountries.length && !onlyCountries.includes(defaultCountryCode)) {
935 defaultCountryCode = onlyCountries[0];
936 }
937
938
939 let iti = window.intlTelInput(jsElem, {
940 dropdownContainer: dropdownContainer,
941 formatOnDisplay: true,
942 nationalMode: true,
943 autoPlaceholder: 'aggressive',
944 initialCountry: defaultCountryCode,
945 geoIpLookup: function (callback) {
946 const cookieName = 'latepoint_phone_country';
947
948 if (latepoint_has_cookie(cookieName)) {
949 callback(latepoint_get_cookie(cookieName));
950 } else {
951 jQuery.get('https://ipinfo.io', function () {
952 }, 'jsonp').always(function (response) {
953 // Sensible default
954 let countryCode = defaultCountryCode;
955
956 if (response && response.country) {
957 countryCode = response.country.toLowerCase();
958 latepoint_set_cookie(cookieName, countryCode);
959 }
960 callback(countryCode);
961 })
962 }
963 },
964 allowDropdown: onlyCountries.length != 1,
965 onlyCountries: onlyCountries,
966 preferredCountries: preferredCountries,
967 separateDialCode: latepoint_helper.is_enabled_show_dial_code_with_flag
968 });
969
970 iti.promise.then(function () {
971 latepoint_init_phone_masking_from_placeholder($elem);
972 });
973
974
975 $elem.on("countrychange", function (event) {
976 latepoint_init_phone_masking_from_placeholder(jQuery(this));
977 });
978 }
979 }
980
981 function latepoint_show_booking_end_time() {
982 return (latepoint_helper.show_booking_end_time == 'yes');
983 }
984
985 function latepoint_set_cookie(name, value, days) {
986 let date = new Date;
987 date.setTime(date.getTime() + 24 * 60 * 60 * 1000 * days);
988 document.cookie = name + "=" + value + ";path=/;expires=" + date.toGMTString();
989 }
990
991 function latepoint_get_cookie(name) {
992 let cookie = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
993 return cookie ? cookie[2] : null;
994 }
995
996 function latepoint_has_cookie(name) {
997 return latepoint_get_cookie(name) !== null;
998 }
999
1000 function latepoint_delete_cookie(name) {
1001 latepoint_set_cookie(name, '', -1);
1002 }
1003
1004 function latepoint_load_addons_info(){
1005 var $addons_info_wrapper = jQuery('.addons-info-holder');
1006 $addons_info_wrapper.addClass('os-loading');
1007 var route = $addons_info_wrapper.data('route');
1008
1009 var data = { action: 'latepoint_route_call', route_name: route, params: '', return_format: 'json' }
1010 jQuery.ajax({ type : "post", dataType : "json", url : latepoint_timestamped_ajaxurl(), data : data,
1011 success: function(response){
1012 $addons_info_wrapper.removeClass('os-loading');
1013 if(response.status === "success"){
1014 if(response.message){
1015 $addons_info_wrapper.html(response.message);
1016 }else{
1017 $addons_info_wrapper.html('Something is wrong. Try refreshing the page.')
1018 }
1019 }else{
1020 alert(response.message, 'error');
1021 }
1022 }
1023 });
1024 }
1025
1026
1027 function latepoint_dismiss_message($elem){
1028 $elem.closest('.addon-message').slideUp(300);
1029 return false;
1030 }
1031
1032 function latepoint_check_for_updates(){
1033 if(jQuery('.version-log-w').length){
1034 var $log_wrapper = jQuery('.version-log-w');
1035 $log_wrapper.addClass('os-loading');
1036 var route = $log_wrapper.data('route');
1037
1038 var data = { action: 'latepoint_route_call', route_name: route, params: '', return_format: 'json' }
1039 jQuery.ajax({ type : "post", dataType : "json", url : latepoint_timestamped_ajaxurl(), data : data,
1040 success: function(response){
1041 $log_wrapper.removeClass('os-loading');
1042 if(response.status === "success"){
1043 $log_wrapper.html(response.message);
1044 }else{
1045 alert(response.message, 'error');
1046 }
1047 }
1048 });
1049 }
1050 if(jQuery('.version-status-info').length){
1051
1052 var $version_info_wrapper = jQuery('.version-status-info');
1053 $version_info_wrapper.addClass('os-loading');
1054 var route = $version_info_wrapper.data('route');
1055
1056 var data = { action: 'latepoint_route_call', route_name: route, params: '', return_format: 'json' }
1057 jQuery.ajax({ type : "post", dataType : "json", url : latepoint_timestamped_ajaxurl(), data : data,
1058 success: function(response){
1059 $version_info_wrapper.removeClass('os-loading');
1060 if(response.status === "success"){
1061 $version_info_wrapper.html(response.message);
1062 }else{
1063 alert(response.message, 'error');
1064 }
1065 }
1066 });
1067 }
1068 if(jQuery('.addons-info-holder').length){
1069 latepoint_load_addons_info();
1070 }
1071 }
1072
1073
1074 // DOCUMENT READY
1075 jQuery(document).ready(function( $ ) {
1076 latepoint_check_for_updates();
1077
1078
1079 jQuery('body').on('click', '.addon-category-filter-trigger', function(){
1080 jQuery('.addons-categories-wrapper .addon-category-filter-trigger.is-selected').removeClass('is-selected');
1081 if(jQuery(this).data('category')){
1082 let category = jQuery(this).data('category').toString();
1083 jQuery('.addon-box').addClass('hidden');
1084 jQuery('.addon-box').each(function(){
1085 if(jQuery(this).data('category').toString().split(',').includes(category)) jQuery(this).removeClass('hidden');
1086 })
1087 }else{
1088 jQuery('.addon-box').removeClass('hidden');
1089 }
1090
1091 jQuery(this).addClass('is-selected');
1092 return false;
1093 })
1094
1095
1096 // Install addon button click
1097 jQuery('.addons-info-holder').on('click', '.os-addon-action-btn', function(){
1098 var $install_btn = jQuery(this);
1099 $install_btn.addClass('os-loading');
1100
1101 var data = { action: 'latepoint_route_call', route_name: $install_btn.data('route-name'), params: { addon_name: $install_btn.data('addon-name'), addon_path: $install_btn.data('addon-path') }, layout: 'none', return_format: 'json'};
1102 jQuery.ajax({
1103 type : "post",
1104 dataType : "json",
1105 url : latepoint_timestamped_ajaxurl(),
1106 data : data,
1107 success: function(response){
1108 $install_btn.removeClass('os-loading');
1109 if(response.status === "success"){
1110 latepoint_add_notification(response.message);
1111 latepoint_load_addons_info();
1112 }else{
1113 if(response.code == '404'){
1114 latepoint_show_data_in_lightbox(response.message);
1115 }else{
1116 alert(response.message);
1117 }
1118 }
1119 }
1120 });
1121 return false;
1122 });
1123 });
1124
1125 /*
1126 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
1127 */
1128
1129 function latepoint_init_version5_intro(){
1130 if(jQuery('.improvement-install-pro').length){
1131 let $install_btn = jQuery('.improvement-install-pro');
1132 var data = {
1133 action: latepoint_helper.route_action,
1134 route_name: $install_btn.data('route-name'),
1135 params: {},
1136 return_format: 'json'
1137 }
1138 jQuery.ajax({
1139 type : "post",
1140 dataType : "json",
1141 url : latepoint_timestamped_ajaxurl(),
1142 data : data,
1143 success: function(response){
1144 $install_btn.removeClass('os-loading');
1145 if(response.status == 'success'){
1146 $install_btn.addClass('is-installed').find('span').html(response.message);
1147 }else{
1148 $install_btn.addClass('is-not-installed').find('span').html(response.message);
1149 }
1150 }
1151 });
1152 }
1153 }
1154
1155 function latepoint_build_and_save_step_order(){
1156 var $steps_wrapper = jQuery('.os-ordered-steps');
1157 let steps_in_order = [];
1158 $steps_wrapper.find('.os-ordered-step').each(function(index){
1159 if(jQuery(this).find('.os-ordered-step-children').length){
1160 jQuery(this).find('.os-ordered-step-child').each(function(){
1161 steps_in_order.push(jQuery(this).data('step-code'));
1162 });
1163 }else{
1164 steps_in_order.push(jQuery(this).data('step-code'));
1165 }
1166 });
1167 var data = { action: latepoint_helper.route_action, route_name: $steps_wrapper.data('route-name'), params: {steps_order: steps_in_order.join(',')}, return_format: 'json' }
1168 jQuery('.latepoint-lightbox-heading').addClass('os-loading');
1169 jQuery.ajax({
1170 type : "post",
1171 dataType : "json",
1172 url : latepoint_timestamped_ajaxurl(),
1173 data : data,
1174 success: function(response){
1175 jQuery('.latepoint-lightbox-heading').removeClass('os-loading');
1176 latepoint_add_lightbox_notification(response.message, response.status);
1177 }
1178 });
1179 }
1180
1181 function latepoint_init_step_reordering(){
1182 jQuery('.os-ordered-step-expand').on('click', function(){
1183 jQuery(this).closest('.os-ordered-step').toggleClass('is-expanded');
1184 return false;
1185 });
1186
1187
1188 // Steps Order Dragging
1189 dragula([jQuery('.os-ordered-steps')[0]], {
1190 moves: function (el, container, handle) {
1191 return handle.classList.contains('os-ordered-step-drag-handle');
1192 },
1193 }).on('drop', function(el){
1194 latepoint_build_and_save_step_order();
1195 });
1196
1197 jQuery('.os-ordered-step-children').each(function(){
1198 let step_holder = jQuery(this)
1199 // Child steps Order Dragging
1200 dragula([step_holder[0]], {
1201 moves: function (el, container, handle) {
1202 return handle.classList.contains('os-ordered-step-child-drag-handle');
1203 },
1204 }).on('drop', function(el){
1205 latepoint_build_and_save_step_order();
1206 });
1207 });
1208 }
1209
1210
1211 function latepoint_init_json_view($pre_element = false){
1212 if(!$pre_element){
1213 // if pre is not provided -search for all unitialised ones
1214 $pre_element = jQuery('pre.format-json:not(.json-document)');
1215 }
1216 if($pre_element.length){
1217 $pre_element.each(function(){
1218 let json_data = JSON.parse(jQuery(this).html());
1219 jQuery(this).jsonViewer(json_data);
1220 });
1221 }
1222 }
1223
1224 function latepoint_init_accordions(){
1225 jQuery('.latepoint-admin').on('click', '.os-accordion-title', function(){
1226 jQuery(this).closest('.os-accordion-wrapper').toggleClass('is-open');
1227 return false;
1228 });
1229 }
1230
1231
1232 function latepoint_init_sticky_side_menu(){
1233 jQuery('.os-sticky-side-menu a').on('click', function(){
1234 jQuery('.os-sticky-side-menu li.os-active').removeClass('os-active');
1235 jQuery(this).closest('li').addClass('os-active');
1236 let section_anchor = jQuery(this).data('section-anchor');
1237 let position = jQuery('.section-anchor#'+section_anchor).offset();
1238 jQuery('html').animate({ scrollTop: position.top }, 300);
1239 return false;
1240 });
1241 }
1242
1243 function latepoint_init_template_library(){
1244 jQuery('.os-templates-wrapper .template-type-selector').on('click', function(){
1245 jQuery(this).toggleClass('is-selected');
1246 let user_type = jQuery(this).data('user-type');
1247 jQuery('.os-template-items[data-user-type="'+user_type+'"]').toggleClass('hidden');
1248 return false;
1249 });
1250
1251 jQuery('.os-templates-wrapper .os-template-item').on('click', function(){
1252 let $this = jQuery(this);
1253 $this.closest('.os-templates-list').find('.os-template-item.selected').removeClass('selected');
1254 $this.addClass('selected');
1255 let templateId = $this.data('id');
1256 jQuery('.os-template-preview').hide();
1257 jQuery('.os-template-preview[data-id="'+ templateId+'"]').show();
1258 jQuery('.os-no-template-selected-message').hide();
1259 jQuery('.os-template-use-button-wrapper').removeClass('hidden');
1260 return false;
1261 });
1262
1263 jQuery('.latepoint-select-template-btn').on('click', function(){
1264 let $btn = jQuery(this);
1265 let route_name = $btn.data('route');
1266 let action_id = $btn.data('action-id');
1267 let process_id = $btn.data('process-id');
1268 let action_type = $btn.data('action-type');
1269 $btn.addClass('os-loading');
1270
1271 let data = { action: latepoint_helper.route_action,
1272 route_name: route_name,
1273 params: {
1274 template_id: jQuery('.os-template-item.selected').data('id'),
1275 action_id: action_id,
1276 process_id: process_id,
1277 action_type: action_type
1278 },
1279 return_format: 'json' }
1280 jQuery.ajax({
1281 type: 'post',
1282 dataType : "json",
1283 url : latepoint_timestamped_ajaxurl(),
1284 data : data,
1285 success: (response) => {
1286 $btn.removeClass('os-loading');
1287 if(response.status === latepoint_helper.response_status.success){
1288 let $action_form = jQuery('.process-action-form[data-id="'+action_id+'"]');
1289 $action_form.find('.process-action-settings').html(response.message);
1290 latepoint_init_process_action_form($action_form);
1291 latepoint_close_side_panel();
1292 }else{
1293 alert("Error!");
1294 }
1295 }
1296 });
1297
1298 return false;
1299 });
1300 }
1301
1302 function latepoint_init_default_form_fields_settings(){
1303
1304 if(jQuery('.os-default-fields').length){
1305 jQuery('.os-default-field input[type="checkbox"], .os-default-field select').on('change', (event) => {
1306 latepoint_update_default_form_fields_settings();
1307 });
1308
1309 jQuery('.os-default-field .os-toggler').on('ostoggler:toggle', (event) => {
1310 if(jQuery(event.currentTarget).hasClass('off')){
1311 jQuery(event.currentTarget).closest('.os-default-field').addClass('is-disabled');
1312 }else{
1313 jQuery(event.currentTarget).closest('.os-default-field').removeClass('is-disabled');
1314 }
1315 latepoint_update_default_form_fields_settings();
1316 });
1317 }
1318 }
1319
1320 function latepoint_update_default_form_fields_settings(){
1321 var $wrapper = jQuery('.os-default-fields');
1322
1323 var form_data = new FormData($wrapper.find('form')[0]);
1324 var data = { action: latepoint_helper.route_action,
1325 route_name: $wrapper.data('route'),
1326 params: latepoint_formdata_to_url_encoded_string(form_data),
1327 return_format: 'json' }
1328
1329 jQuery.ajax({
1330 type : "post",
1331 dataType : "json",
1332 url : latepoint_timestamped_ajaxurl(),
1333 data : data,
1334 success: (response) => {
1335 latepoint_add_notification(response.message);
1336 }
1337 });
1338 }
1339
1340 function latepoint_init_side_menu(){
1341 jQuery('.menu-toggler').on('click', function(){
1342 var layout_style = 'full';
1343 if(jQuery('.latepoint-side-menu-w').hasClass('side-menu-full')){
1344 layout_style = 'compact';
1345 jQuery('.latepoint-side-menu-w').addClass('side-menu-compact').removeClass('side-menu-full');
1346 }else{
1347 jQuery('.latepoint-side-menu-w').addClass('side-menu-full').removeClass('side-menu-compact');
1348 }
1349 var route_name = jQuery(this).data('route');
1350 var data = { action: latepoint_helper.route_action, route_name: route_name, params: { menu_layout_style: layout_style }, layout: 'none', return_format: 'json' }
1351 jQuery.ajax({
1352 type : "post",
1353 dataType : "json",
1354 url : latepoint_timestamped_ajaxurl(),
1355 data : data,
1356 success: function(data){
1357 }
1358 });
1359 return false;
1360 });
1361 }
1362
1363 function latepoint_init_grouped_bookings_form(){
1364
1365 }
1366
1367 function latepoint_quick_order_customer_cleared(){
1368 latepoint_init_input_masks(jQuery('.quick-order-form-w .customer-quick-edit-form-w'));
1369 }
1370
1371 function latepoint_quick_order_customer_selected(){
1372 latepoint_init_input_masks(jQuery('.quick-order-form-w .customer-quick-edit-form-w'));
1373 jQuery('.customer-info-w').removeClass('selecting').addClass('selected');
1374 }
1375
1376 function latepoint_custom_day_removed($elem){
1377 $elem.closest('.custom-day-work-period').fadeOut(300, function(){ jQuery(this).remove()});
1378 }
1379
1380
1381 function latepoint_count_active_connections($connection_wrapper){
1382 var connected_services_count = $connection_wrapper.find('.connection-children-list li.active').length;
1383 var all_services_count = $connection_wrapper.find('.connection-children-list li').length;
1384 if(connected_services_count == all_services_count){
1385 connected_services_count = jQuery('.selected-connections').data('all-text');
1386 jQuery('.selected-connections').removeClass('not-all-selected');
1387 }else{
1388 connected_services_count = connected_services_count + '/' + all_services_count;
1389 jQuery('.selected-connections').addClass('not-all-selected');
1390 $connection_wrapper.closest('.white-box').find('.os-select-all-toggler').prop('checked', false);
1391 }
1392 $connection_wrapper.find('.selected-connections strong').text(connected_services_count);
1393 }
1394
1395 function latepoint_custom_field_removed($elem){
1396 $elem.closest('.os-form-block').remove();
1397 }
1398
1399 function latepoint_coupon_removed($elem){
1400 $elem.closest('.os-coupon-form').remove();
1401 }
1402
1403 function latepoint_reminder_removed($elem){
1404 $elem.closest('.os-reminder-form').remove();
1405 }
1406
1407 function latepoint_init_form_blocks(){
1408 jQuery('.latepoint-content-w').on('click', '.os-form-block-header', function(){
1409 jQuery(this).closest('.os-form-block').toggleClass('os-is-editing');
1410 return false;
1411 });
1412 jQuery('.latepoint-content-w').on('keyup', '.os-form-block-name-input', function(){
1413 jQuery(this).closest('.os-form-block').find('.os-form-block-name').text(jQuery(this).val());
1414 });
1415 }
1416
1417
1418 function latepoint_init_coupons_form(){
1419 jQuery('.latepoint-content-w').on('click', '.os-coupon-form-info', function(){
1420 jQuery(this).closest('.os-coupon-form').toggleClass('os-is-editing');
1421 return false;
1422 });
1423 jQuery('.latepoint-content-w').on('change', 'select.os-coupon-medium-select', function(){
1424 if(jQuery(this).val() == 'email'){
1425 jQuery(this).closest('.os-coupon-form').find('.os-coupon-email-subject').show();
1426 }else{
1427 jQuery(this).closest('.os-coupon-form').find('.os-coupon-email-subject').hide();
1428 }
1429 });
1430 jQuery('.latepoint-content-w').on('keyup', '.os-coupon-name-input', function(){
1431 jQuery(this).closest('.os-coupon-form').find('.os-coupon-name').text(jQuery(this).val());
1432 });
1433 jQuery('.latepoint-content-w').on('keyup', '.os-coupon-code-input', function(){
1434 jQuery(this).closest('.os-coupon-form').find('.os-coupon-code').text(jQuery(this).val());
1435 });
1436 }
1437
1438 function latepoint_init_reminders_form(){
1439 jQuery('.latepoint-content-w').on('click', '.os-reminder-form-info', function(){
1440 jQuery(this).closest('.os-reminder-form').toggleClass('os-is-editing');
1441 return false;
1442 });
1443 jQuery('.latepoint-content-w').on('change', 'select.os-reminder-medium-select', function(){
1444 if(jQuery(this).val() == 'email'){
1445 jQuery(this).closest('.os-reminder-form').find('.os-reminder-email-subject').show();
1446 }else{
1447 jQuery(this).closest('.os-reminder-form').find('.os-reminder-email-subject').hide();
1448 }
1449 });
1450 jQuery('.latepoint-content-w').on('keyup', '.os-reminder-name-input', function(){
1451 jQuery(this).closest('.os-reminder-form').find('.os-reminder-name').text(jQuery(this).val());
1452 });
1453 }
1454
1455 function latepoint_custom_field_saved($elem){
1456 }
1457
1458 function latepoint_init_custom_day_schedule(){
1459 latepoint_init_input_masks(jQuery('.latepoint-lightbox-w .custom-day-schedule-w'));
1460
1461 jQuery('.period-type-selector').on('change', function(){
1462 jQuery(this).closest('.custom-day-calendar').attr('data-period-type', jQuery(this).val());
1463 jQuery('.custom-day-calendar').attr('data-picking', 'start').data('picking', 'start');
1464 if(jQuery(this).val() == 'range'){
1465 jQuery('.custom-day-calendar-head .calendar-heading').text(jQuery('.custom-day-calendar-head .calendar-heading').data('label-start'));
1466 jQuery('.custom-day-calendar #start_custom_date').trigger('focus');
1467 }else{
1468 jQuery('.custom-day-calendar .os-day.selected').removeClass('selected');
1469 jQuery('.latepoint-lightbox-footer').hide();
1470 jQuery('.custom-day-calendar-head .calendar-heading').text(jQuery('.custom-day-calendar-head .calendar-heading').data('label-single'));
1471 }
1472 });
1473
1474
1475 jQuery('#custom_day_calendar_month, #custom_day_calendar_year').on('change', function(){
1476 var $calendar = jQuery('.custom-day-calendar-month');
1477 var route_name = $calendar.data('route');
1478 $calendar.addClass('os-loading');
1479 var target_date_string = jQuery('#custom_day_calendar_year').val() + '-' + jQuery('#custom_day_calendar_month').val() + '-01';
1480 var data = { action: latepoint_helper.route_action, route_name: route_name, params: { target_date_string: target_date_string }, layout: 'none', return_format: 'json' }
1481 jQuery.ajax({
1482 type : "post",
1483 dataType : "json",
1484 url : latepoint_timestamped_ajaxurl(),
1485 data : data,
1486 success: function(data){
1487 $calendar.removeClass('os-loading');
1488 if(data.status === "success"){
1489 $calendar.html(data.message);
1490 }else{
1491 // console.log(data.message);
1492 }
1493 }
1494 });
1495 });
1496
1497
1498
1499 jQuery('.custom-day-calendar').on('focus', '#start_custom_date', function(){
1500 jQuery('.custom-day-calendar-head .calendar-heading').text(jQuery('.custom-day-calendar-head .calendar-heading').data('label-start'));
1501 jQuery('.custom-day-calendar').attr('data-picking', 'start').data('picking', 'start');
1502 });
1503
1504 jQuery('.custom-day-calendar').on('focus', '#end_custom_date', function(){
1505 jQuery('.custom-day-calendar-head .calendar-heading').text(jQuery('.custom-day-calendar-head .calendar-heading').data('label-end'));
1506 jQuery('.custom-day-calendar').attr('data-picking', 'end').data('picking', 'end');
1507 });
1508
1509 jQuery('.custom-day-calendar').on('click', '.os-day', function(){
1510 var $this = jQuery(this);
1511 $this.closest('.custom-day-calendar').find('.os-day.selected').removeClass('selected');
1512 $this.addClass('selected');
1513
1514 if(jQuery('.custom-day-calendar').data('picking') == 'start'){
1515 jQuery('.custom-day-settings-w #start_custom_date').val($this.data('date')).trigger('keyup');
1516 if(jQuery('.period-type-selector').val() == 'range'){
1517 jQuery('.custom-day-calendar #end_custom_date').trigger('focus');
1518 if(!jQuery('.custom-day-calendar #end_custom_date').val()) return false;
1519 }
1520 }else{
1521 jQuery('.custom-day-settings-w #end_custom_date').val($this.data('date')).trigger('keyup');
1522 }
1523 jQuery('.latepoint-lightbox-footer').slideDown(200);
1524 if(jQuery('.custom-day-calendar').data('show-schedule') == 'yes') jQuery('.latepoint-lightbox-w').removeClass('hide-schedule');
1525 return false;
1526 });
1527 }
1528
1529 function latepoint_init_updates_page(){
1530
1531 }
1532
1533 function latepoint_calendar_set_month_label(){
1534 jQuery('.os-current-month-label .current-month').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-month-label'));
1535 jQuery('.os-current-month-label .current-year').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-year'));
1536 }
1537
1538
1539 function latepoint_init_element_togglers(){
1540 jQuery('[data-toggle-element]').on('click', function(){
1541 var $this = jQuery(this);
1542 $this.closest('.os-form-checkbox-group').toggleClass('is-checked');
1543 jQuery($this.data('toggle-element')).toggle();
1544 });
1545 }
1546
1547
1548 function latepoint_init_color_picker(){
1549 if(jQuery('.latepoint-color-picker').length){
1550 jQuery('.latepoint-color-picker').each(function(){
1551 var color = jQuery(this).data('color');
1552 var picker = jQuery(this)[0];
1553 var $picker_wrapper = jQuery(this).closest('.latepoint-color-picker-w');
1554 Pickr.create({
1555 el: picker,
1556 default: color,
1557 comparison: false,
1558 useAsButton: true,
1559 components: {
1560
1561 // Main components
1562 preview: false,
1563 opacity: false,
1564 hue: true,
1565
1566 // Input / output Options
1567 interaction: {
1568 input: false,
1569 clear: false,
1570 save: true
1571 }
1572 },
1573 onChange(hsva, instance) {
1574 $picker_wrapper.find('.os-form-control').val(hsva.toHEX().toString());
1575 },
1576 });
1577 });
1578 }
1579 }
1580
1581
1582 function latepoint_lightbox_close(){
1583 jQuery('body').removeClass('latepoint-lightbox-active');
1584 jQuery('.latepoint-lightbox-w').remove();
1585 }
1586
1587 function latepoint_reload_select_service_categories(){
1588 jQuery('.service-selector-adder-field-w').each(function(){
1589 var $trigger_elem = jQuery(this);
1590 var route = jQuery('.service-selector-adder-field-w').find('select').data('select-source');
1591 var data = { action: latepoint_helper.route_action, route_name: route, params: '', return_format: 'json' }
1592 jQuery.ajax({
1593 type : "post",
1594 dataType : "json",
1595 url : latepoint_timestamped_ajaxurl(),
1596 data : data,
1597 success: function(response){
1598 $trigger_elem.removeClass('os-loading');
1599 if(response.status === "success"){
1600 latepoint_lightbox_close();
1601 $trigger_elem.find('select').html(response.message);
1602 $trigger_elem.find('select option:last').attr('selected', 'selected');
1603 }else{
1604 alert(response.message, 'error');
1605 }
1606 }
1607 });
1608 });
1609 }
1610
1611 function latepoint_wizard_item_editing_cancelled(response){
1612 jQuery('.os-wizard-setup-w').removeClass('is-sub-editing');
1613 jQuery('.os-wizard-footer').show();
1614 jQuery('.os-wizard-footer .os-wizard-next-btn').show();
1615 if(response.show_prev_btn){
1616 jQuery('.os-wizard-footer .os-wizard-prev-btn').show();
1617 }
1618 }
1619
1620
1621 function latepoint_reload_week_view_calendar(start_date = false){
1622 var service_id = (jQuery('.cc-availability-toggler #overlay_service_availability').val() == 'on') ? jQuery('.calendar-service-selector').val() : false;
1623 var agent_id = jQuery('.calendar-agent-selector').val();
1624 var location_id = jQuery('.calendar-location-selector').val();
1625 var calendar_start_date = (start_date) ? start_date : jQuery('.calendar-start-date').val();
1626 latepoint_load_calendar(calendar_start_date, agent_id, location_id, service_id);
1627 }
1628
1629 function latepoint_init_work_period_form(){
1630 latepoint_mask_timefield(jQuery('.os-time-input-w .os-mask-time'));
1631 }
1632
1633 function latepoint_close_side_panel(){
1634 latepoint_close_quick_availability_form();
1635 jQuery('.latepoint-side-panel-w').remove();
1636 }
1637
1638 function reload_process_jobs_table(){
1639 if(jQuery('table.os-reload-on-booking-update').length) latepoint_filter_table(jQuery('table.os-reload-on-booking-update'), jQuery('table.os-reload-on-booking-update'));
1640 }
1641
1642
1643 function latepoint_transaction_removed($trigger){
1644 $trigger.closest('.quick-add-transaction-box-w').remove();
1645 latepoint_reload_balance_and_payments();
1646 }
1647
1648 function latepoint_reload_widget($widget_elem){
1649 var form_data = $widget_elem.find('select, input').serialize();
1650 var data = { action: latepoint_helper.route_action, route_name: $widget_elem.data('os-reload-action'), params: form_data, return_format: 'json' }
1651 $widget_elem.addClass('os-loading');
1652 jQuery.ajax({
1653 type : "post",
1654 dataType : "json",
1655 url : latepoint_timestamped_ajaxurl(),
1656 data : data,
1657 success: function(response){
1658 $widget_elem.removeClass('os-loading');
1659 if(response.status === "success"){
1660 var $updated_widget_elem = jQuery(response.message);
1661 $updated_widget_elem.removeClass('os-widget-animated');
1662 $widget_elem = $widget_elem.replaceWith($updated_widget_elem);
1663 latepoint_init_daterangepicker($updated_widget_elem.find('.os-date-range-picker'));
1664 if($widget_elem.hasClass('os-widget-top-agents')) latepoint_init_circles_charts();
1665 if($widget_elem.hasClass('os-widget-daily-bookings')){
1666 latepoint_init_daily_bookings_chart();
1667 latepoint_init_donut_charts();
1668 }
1669 }else{
1670 alert(response.message);
1671 }
1672 }
1673 });
1674 }
1675
1676 function latepoint_load_calendar(target_date, agent_id, location_id = false, service_id = false){
1677 var route_name = jQuery('.calendar-week-agent-w').data('calendar-action');
1678 jQuery('.calendar-week-agent-w').addClass('os-loading');
1679 var params_arr = {target_date: target_date, agent_id: agent_id};
1680 if(location_id) params_arr.location_id = location_id;
1681 if(service_id) params_arr.service_id = service_id;
1682 var data = { action: latepoint_helper.route_action, route_name: route_name, params: jQuery.param(params_arr), return_format: 'json' }
1683 jQuery.ajax({
1684 type : "post",
1685 dataType : "json",
1686 url : latepoint_timestamped_ajaxurl(),
1687 data : data,
1688 success: function(response){
1689 if(response.status === "success"){
1690 jQuery('.calendar-week-agent-w').html(response.message).removeClass('os-loading');
1691 jQuery('.calendar-load-target-date.os-loading').removeClass('os-loading');
1692 }else{
1693 alert(response.message);
1694 }
1695 }
1696 });
1697 }
1698
1699 function latepoint_init_quick_transaction_form(){
1700 latepoint_mask_money(jQuery('.quick-add-transaction-box-w .os-mask-money'));
1701 }
1702
1703 function latepoint_reload_price_breakdown(){
1704 var $trigger = jQuery('.reload-price-breakdown');
1705 $trigger.addClass('os-loading');
1706 var $quick_edit_form = $trigger.closest('form.order-quick-edit-form');
1707 var form_data = new FormData($quick_edit_form[0]);
1708 var route = $trigger.data('route');
1709
1710 var data = { action: latepoint_helper.route_action, route_name: route, params: latepoint_formdata_to_url_encoded_string(form_data), return_format: 'json' }
1711 jQuery.ajax({
1712 type : "post",
1713 dataType : "json",
1714 url : latepoint_timestamped_ajaxurl(),
1715 data : data,
1716 success: function(response){
1717 $trigger.removeClass('os-loading');
1718 if(response.status === "success"){
1719 jQuery('.price-breakdown-wrapper').html(response.message);
1720 latepoint_mask_money(jQuery('.price-breakdown-wrapper .os-mask-money'));
1721 latepoint_reload_balance_and_payments();
1722 }else{
1723 alert(response.message);
1724 }
1725 }
1726 });
1727 }
1728
1729 function latepoint_complex_selector_select($connection_wrappers, qty = 1){
1730 $connection_wrappers.each(function(){
1731 jQuery(this).addClass('active');
1732 jQuery(this).find('.connection-children-list li').addClass('active');
1733 jQuery(this).find('.connection-child-is-connected').val('yes');
1734 jQuery(this).find('.item-quantity-selector-input').val(qty);
1735 latepoint_count_active_connections(jQuery(this));
1736 });
1737 }
1738
1739 function latepoint_complex_selector_deselect($connection_wrappers){
1740 $connection_wrappers.each(function(){
1741 jQuery(this).removeClass('active');
1742 jQuery(this).removeClass('show-customize-box');
1743 jQuery(this).find('.connection-children-list li.active').removeClass('active');
1744 jQuery(this).find('.connection-child-is-connected').val('no');
1745 jQuery(this).find('.item-quantity-selector-input').val(0);
1746 latepoint_count_active_connections(jQuery(this));
1747 });
1748 }
1749
1750
1751
1752 function latepoint_is_next_day($form){
1753 let field_base_name = 'order_items[' + $form.data('order-item-id') +'][bookings][' + $form.data('booking-id') +']';
1754
1755 var start_time = $form.find('input[name="' + field_base_name + '[start_time][formatted_value]"]').val();
1756 var start_time_ampm = $form.find('input[name="' + field_base_name + '[start_time][ampm]"]').val();
1757 var start_time_minutes = latepoint_hours_and_minutes_to_minutes(start_time, start_time_ampm);
1758 var end_time = $form.find('input[name="' + field_base_name + '[end_time][formatted_value]"]').val();
1759 var end_time_ampm = $form.find('input[name="' + field_base_name + '[end_time][ampm]"]').val();
1760 var end_time_minutes = latepoint_hours_and_minutes_to_minutes(end_time, end_time_ampm);
1761
1762 if(end_time_minutes && (end_time_minutes <= start_time_minutes)){
1763 $form.find('.quick-end-time-w').addClass('ending-next-day');
1764 }else{
1765 $form.find('.quick-end-time-w').removeClass('ending-next-day');
1766 }
1767 }
1768
1769 function latepoint_set_booking_end_time($booking_data_form){
1770 var booking_duration = 0;
1771 var service_duration = Number($booking_data_form.find('.os-service-durations select').val());
1772
1773 let field_base_name = 'order_items[' + $booking_data_form.data('order-item-id') +'][bookings][' + $booking_data_form.data('booking-id') +']';
1774
1775 booking_duration = booking_duration + service_duration;
1776 if($booking_data_form.find('select[name="temp_service_extras_ids"] option:selected').length){
1777 $booking_data_form.find('select[name="temp_service_extras_ids"] option:selected').each(function(){
1778 var extra_duration = Number(jQuery(this).data('duration'));
1779 var $extra_quantity_input = jQuery(this).closest('.lateselect-w').find('.ls-item[data-value="' + jQuery(this).val() + '"]').find('.os-late-quantity-selector-input');
1780 if($extra_quantity_input.length) extra_duration = Number(extra_duration) * Number($extra_quantity_input.val());
1781 booking_duration = Number(booking_duration) + Number(extra_duration);
1782 });
1783 }
1784
1785 var start_time = $booking_data_form.find('input[name="'+field_base_name+'[start_time][formatted_value]"]').val();
1786
1787 if(start_time){
1788 var start_time_ampm = $booking_data_form.find('input[name="'+field_base_name+'[start_time][ampm]"]').val();
1789 var start_time_minutes = latepoint_hours_and_minutes_to_minutes(start_time, start_time_ampm);
1790 var end_time_minutes = parseInt(start_time_minutes) + parseInt(booking_duration);
1791 if(end_time_minutes >= (24 * 60)) end_time_minutes = (end_time_minutes - 24 * 60);
1792 var end_time_ampm = (end_time_minutes >= 720 && end_time_minutes < (24 * 60)) ? 'pm' : 'am';
1793 var end_hours_and_minutes = latepoint_minutes_to_hours_and_minutes(end_time_minutes);
1794
1795 $booking_data_form.find('input[name="'+field_base_name+'[end_time][formatted_value]"]').val(end_hours_and_minutes);
1796 $booking_data_form.find('.quick-end-time-w .time-ampm-select.time-' + end_time_ampm).trigger('click');
1797 $booking_data_form.find('input[name="'+field_base_name+'[end_time][formatted_value]"]').closest('.os-form-group').addClass('has-value');
1798 }
1799 latepoint_is_next_day($booking_data_form);
1800 }
1801
1802
1803
1804 function latepoint_init_sortable_columns(){
1805 jQuery('.os-sortable-column').on('click', function(){
1806 let current_direction = jQuery(this).hasClass('ordered-desc') ? 'desc' : 'asc';
1807 let new_direction = (current_direction == 'desc') ? 'asc' : 'desc';
1808 jQuery(this).closest('table').find('.os-sortable-column').removeClass('ordered-desc').removeClass('ordered-asc');
1809 jQuery(this).addClass('ordered-' + new_direction);
1810
1811 jQuery(this).closest('table').find('.records-ordered-by-key').val(jQuery(this).data('order-key'));
1812 jQuery(this).closest('table').find('.records-ordered-by-direction').val(new_direction);
1813 latepoint_filter_table(jQuery(this).closest('table'), jQuery(this).closest('.os-form-group'));
1814 return false;
1815 });
1816 }
1817 function latepoint_random_text(length){
1818 var result = '';
1819 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
1820 var charactersLength = characters.length;
1821 for ( var i = 0; i < length; i++ ) {
1822 result += characters.charAt(Math.floor(Math.random() * charactersLength));
1823 }
1824 return result;
1825 }
1826
1827 function latepoint_get_order_for_service_categories(){
1828
1829 }
1830
1831
1832 function latepoint_init_daterangepicker($elem){
1833 $elem.each(function(){
1834 // DATERANGEPICKER
1835 var picker_start_time = jQuery(this).find('input[name="date_from"], .os-datepicker-date-from').val();
1836 var picker_end_time = jQuery(this).find('input[name="date_to"], .os-datepicker-date-to').val();
1837 var locale = {};
1838 if(jQuery(this).data('can-be-cleared')) locale = { cancelLabel: jQuery(this).data('clear-btn-label')};
1839
1840
1841 moment.locale(latepoint_helper.wp_locale);
1842
1843 jQuery(this).daterangepicker({
1844 opens: 'center',
1845 singleDatePicker: (jQuery(this).data('single-date') == 'yes'),
1846 startDate: (picker_start_time) ? moment(picker_start_time) : moment(),
1847 endDate: (picker_end_time) ? moment(picker_end_time) : moment(),
1848 locale: locale
1849 });
1850 });
1851
1852 $elem.on('cancel.daterangepicker', function(ev, picker) {
1853 if(picker.element.data('can-be-cleared')){
1854 picker.element.find('input[name="date_from"], .os-datepicker-date-from').val('');
1855 picker.element.find('input[name="date_to"], .os-datepicker-date-to').val('');
1856 picker.element.find('span.range-picker-value').text(picker.element.data('no-value-label'));
1857 if(picker.element.hasClass('os-table-filter-datepicker')){
1858 latepoint_filter_table(picker.element.closest('table'), picker.element.closest('.os-form-group'));
1859 }
1860 }
1861 });
1862
1863 $elem.on('apply.daterangepicker', function(ev, picker) {
1864 if(picker.element.data('single-date') == 'yes'){
1865 picker.element.find('.range-picker-value').text(picker.startDate.format('ll'));
1866 }else{
1867 picker.element.find('.range-picker-value').text(picker.startDate.format('ll') + ' - ' + picker.endDate.format('ll'));
1868 }
1869 picker.element.find('input[name="date_from"], .os-datepicker-date-from').attr('value', picker.startDate.format('YYYY-MM-DD'));
1870 picker.element.find('input[name="date_to"], .os-datepicker-date-to').attr('value', picker.endDate.format('YYYY-MM-DD'));
1871 if(picker.element.closest('.os-widget').length){
1872 latepoint_reload_widget(picker.element.closest('.os-widget'));
1873 }
1874 if(picker.element.hasClass('os-table-filter-datepicker')){
1875 latepoint_filter_table(picker.element.closest('table'), picker.element.closest('.os-form-group'));
1876 }
1877 });
1878 }
1879
1880 function latepoint_recalculate_items_count_in_category(){
1881 jQuery('.os-category-items-count').each(function(){
1882 var number_of_items = jQuery(this).closest('.os-category-parent-w').find('.item-in-category-w').length;
1883 jQuery(this).find('span').text(number_of_items);
1884 });
1885 }
1886
1887 function latepoint_remove_agent_box($remove_btn){
1888 var $agent_box = $remove_btn.closest('.agent-box-w');
1889 $agent_box.fadeOut(300, function(){ jQuery(this).remove(); });
1890 }
1891
1892 function latepoint_remove_service_box($remove_btn){
1893 var $service_box = $remove_btn.closest('.service-box-w');
1894 $service_box.fadeOut(300, function(){ jQuery(this).remove(); });
1895 }
1896
1897 function latepoint_init_monthly_view(){
1898 if(!jQuery('.calendar-month-agents-w').length) return;
1899
1900 jQuery('.monthly-calendar-headers select').on('change', function(){
1901 var $calendar = jQuery('.calendar-month-agents-w');
1902 var route_name = $calendar.data('route');
1903 $calendar.addClass('os-loading');
1904 var params = { month: jQuery('#monthly_calendar_month_select').val(), year: jQuery('#monthly_calendar_year_select').val() };
1905 if(jQuery('#monthly_calendar_location_select').length && jQuery('#monthly_calendar_location_select').val()) params.location_id = jQuery('#monthly_calendar_location_select').val();
1906 if(jQuery('#monthly_calendar_service_select').length && jQuery('#monthly_calendar_service_select').val()) params.service_id = jQuery('#monthly_calendar_service_select').val();
1907 var data = { action: latepoint_helper.route_action, route_name: route_name, params: params, layout: 'none', return_format: 'json' }
1908 jQuery.ajax({
1909 type : "post",
1910 dataType : "json",
1911 url : latepoint_timestamped_ajaxurl(),
1912 data : data,
1913 success: function(data){
1914 $calendar.removeClass('os-loading');
1915 if(data.status === "success"){
1916 $calendar.html(data.message);
1917 }else{
1918 // console.log(data.message);
1919 }
1920 }
1921 });
1922 });
1923 }
1924
1925
1926 function latepoint_init_copy_on_click_elements(){
1927
1928 jQuery('.os-click-to-copy').on('mouseenter', function() {
1929 var $this = jQuery(this);
1930 var position_info = $this.offset();
1931 var width = jQuery(this).outerWidth();
1932 var position_left = position_info.left;
1933 var position_top = position_info.top - 20 - jQuery(window).scrollTop();
1934
1935 let color = ($this.data('copy-tooltip-color') == 'dark') ? 'dark' : 'light';
1936 if($this.data('copy-tooltip-position') == 'left'){
1937 position_left = position_left - width - 5;
1938 position_top = position_top + $this.outerHeight() - jQuery(window).scrollTop();
1939 }
1940 jQuery('body').append('<div class="os-click-to-copy-prompt color-'+color+'" style="top: '+position_top+'px; left: '+position_left+'px;">' + latepoint_helper.click_to_copy_prompt + '</div>');
1941 }).on('mouseleave', function() {
1942 jQuery('body').find('.os-click-to-copy-prompt').remove();
1943 });
1944 jQuery('.os-click-to-copy').on('click', function(){
1945 var $this = jQuery(this);
1946 let color = ($this.data('copy-tooltip-color') == 'dark') ? 'dark' : 'light';
1947 jQuery('body').find('.os-click-to-copy-prompt').hide();
1948 var text_to_copy = $this.is('input') ? $this.val() : $this.text();
1949 navigator.clipboard.writeText(text_to_copy);
1950
1951 var position_info = $this.offset();
1952 var width = $this.outerWidth();
1953 var position_left = position_info.left;
1954 var position_top = position_info.top - 20 - jQuery(window).scrollTop();
1955
1956 if($this.data('copy-tooltip-position') == 'left'){
1957 position_left = position_left - width - 5;
1958 position_top = position_top + $this.outerHeight() - jQuery(window).scrollTop();
1959 }
1960 var $done_prompt = jQuery('<div class="os-click-to-copy-done color-'+color+'" style="top: '+position_top+'px; left: '+position_left+'px;">' + latepoint_helper.click_to_copy_done + '</div>');
1961 $done_prompt.appendTo(jQuery('body')).animate({
1962 opacity: 0,
1963 left: (position_left + 20),
1964 }, 600);
1965 setTimeout(function(){
1966 jQuery('body').find('.os-click-to-copy-done').remove();
1967 jQuery('body').find('.os-click-to-copy-prompt').show();
1968 }, 800);
1969 });
1970 }
1971
1972 function latepoint_remove_floating_popup(){
1973 jQuery('.os-showing-popup').removeClass('os-showing-popup');
1974 jQuery('.os-floating-popup').remove();
1975 }
1976
1977 function latepoint_init_clickable_cells(){
1978 jQuery('.os-clickable-popup-trigger').on('click', function(){
1979 var $this = jQuery(this);
1980 var position = $this.offset();
1981 var width = $this.outerWidth();
1982 var $popup = jQuery('<div class="os-floating-popup os-loading"></div>');
1983 if($this.hasClass('os-showing-popup')){
1984 latepoint_remove_floating_popup();
1985 }else{
1986 latepoint_remove_floating_popup();
1987 $popup.offset({top: position.top, left: (position.left + width/2)});
1988 jQuery('body').append($popup);
1989 $this.addClass('os-showing-popup');
1990
1991 var route = $this.data('route');
1992 var params = $this.data('os-params');
1993 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
1994 jQuery.ajax({
1995 type : "post",
1996 dataType : "json",
1997 url : latepoint_timestamped_ajaxurl(),
1998 data : data,
1999 success: function(response){
2000 if(response.status === latepoint_helper.response_status.success){
2001 jQuery('body').find('.os-floating-popup').html(response.message).removeClass('os-loading');
2002 latepoint_init_customer_donut_chart();
2003 jQuery('.os-floating-popup .os-floating-popup-close').on('click', function(){
2004 latepoint_remove_floating_popup();
2005 return false;
2006 });
2007 }else{
2008
2009 }
2010 }
2011 });
2012 }
2013 return false;
2014 });
2015 }
2016
2017 function latepoint_init_tiny_mce(element_id){
2018 // TODO CHECK IF wp.editor is defined
2019 if(typeof wp !== 'undefined' && typeof wp.editor !== 'undefined' && jQuery('#'+ element_id).length){
2020 wp.editor.remove(element_id);
2021 wp.editor.initialize(element_id,
2022 {
2023 tinymce: {
2024 wpautop: false,
2025 toolbar1: 'formatselect alignjustify forecolor | bold italic underline strikethrough | bullist numlist | blockquote hr | alignleft aligncenter alignright | link unlink | pastetext removeformat | outdent indent | undo redo',
2026 height : "480",
2027 },
2028 quicktags: true,
2029 mediaButtons: true,
2030 }
2031 );
2032 }
2033 }
2034
2035 function latepoint_init_reminder_form(){
2036 latepoint_init_tiny_mce(jQuery('.os-reminder-form:last-child textarea').attr('id'));
2037 }
2038
2039
2040 function latepoint_filter_table($table, $filter_elem, reset_page = true){
2041 $filter_elem.addClass('os-loading');
2042 var filter_params = $table.find('.os-table-filter').serialize();
2043 var $table_w = $table.closest('.table-with-pagination-w');
2044 if(reset_page){
2045 $table_w.find('select.pagination-page-select').val(1);
2046 }else{
2047 filter_params+= '&page_number='+$table_w.find('select.pagination-page-select').val();
2048 }
2049 var route = $table.data('route');
2050 var data = { action: latepoint_helper.route_action, route_name: route, params: filter_params, layout: 'none', return_format: 'json' };
2051 jQuery.ajax({
2052 type : "post",
2053 dataType : "json",
2054 url : latepoint_timestamped_ajaxurl(),
2055 data : data,
2056 success: function(data){
2057 $filter_elem.removeClass('os-loading');
2058 if(data.status === "success"){
2059 $table.find('tbody').html(data.message);
2060 if(data.total_pages && reset_page){
2061 var options = '';
2062 for(var i = 1; i <= data.total_pages; i++){
2063 options+= '<option>'+ i +'</option>';
2064 }
2065 $table_w.find('select.pagination-page-select').html(options);
2066 }
2067 $table_w.find('.os-pagination-from').text(data.showing_from);
2068 $table_w.find('.os-pagination-to').text(data.showing_to);
2069 $table_w.find('.os-pagination-total').text(data.total_records);
2070 latepoint_init_clickable_cells();
2071 }else{
2072 // console.log(data.message);
2073 }
2074 }
2075 });
2076 }
2077
2078 function latepoint_init_wizard_content(){
2079 latepoint_init_input_masks(jQuery('.os-wizard-step-content'));
2080 }
2081
2082 function latepoint_init_input_masks($scoped_element = false){
2083 let $wrapper = $scoped_element ? $scoped_element : jQuery('body');
2084 latepoint_mask_timefield($wrapper.find('.os-mask-time'));
2085
2086 $wrapper.find('.os-mask-phone').each(function(){
2087 latepoint_mask_phone(jQuery(this));
2088 });
2089
2090 latepoint_mask_money($wrapper.find('.os-mask-money'));
2091 latepoint_mask_date($wrapper.find('.os-mask-date'));
2092 latepoint_mask_minutes($wrapper.find('.os-mask-minutes'));
2093
2094 $wrapper.trigger('latepoint:initInputMasks');
2095 }
2096
2097
2098
2099
2100 function latepoint_init_quick_agent_form(){
2101 let $agent_form_wrapper = jQuery('.quick-agent-form-w');
2102 latepoint_init_input_masks($agent_form_wrapper);
2103
2104
2105 $agent_form_wrapper.find('.agent-quick-edit-form').on('submit', function(e){
2106 if(jQuery(this).find('button[type="submit"]').hasClass('os-loading')) return false;
2107 e.preventDefault();
2108 latepoint_submit_quick_agent_form();
2109 });
2110
2111
2112 $agent_form_wrapper.find('.quick-agent-form-view-log-btn').on('click', function(){
2113 let $trigger_elem = jQuery(this);
2114 $trigger_elem.addClass('os-loading');
2115 let route = $trigger_elem.data('route');
2116 let data = { action: 'latepoint_route_call', route_name: route, params: {agent_id: $trigger_elem.data('agent-id')}, return_format: 'json' }
2117 jQuery.ajax({
2118 type : "post",
2119 dataType : "json",
2120 url : latepoint_timestamped_ajaxurl(),
2121 data : data,
2122 success: function(response){
2123 $trigger_elem.removeClass('os-loading');
2124 if(response.status === "success"){
2125 latepoint_display_in_side_sub_panel(response.message);
2126 jQuery('body').addClass('has-side-sub-panel');
2127 }else{
2128 alert(response.message, 'error');
2129 }
2130 }
2131 });
2132 return false;
2133 });
2134 }
2135
2136 /*
2137 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
2138 */
2139
2140 function latepoint_init_quick_customer_form(){
2141 let $customer_form_wrapper = jQuery('.quick-customer-form-w');
2142 latepoint_init_input_masks($customer_form_wrapper);
2143
2144
2145 $customer_form_wrapper.find('.customer-quick-edit-form').on('submit', function(e){
2146 if(jQuery(this).find('button[type="submit"]').hasClass('os-loading')) return false;
2147 e.preventDefault();
2148 latepoint_submit_quick_customer_form();
2149 });
2150
2151
2152 $customer_form_wrapper.find('.quick-customer-form-view-log-btn').on('click', function(){
2153 var $trigger_elem = jQuery(this);
2154 $trigger_elem.addClass('os-loading');
2155 var route = $trigger_elem.data('route');
2156 var data = { action: 'latepoint_route_call', route_name: route, params: {customer_id: $trigger_elem.data('customer-id')}, return_format: 'json' }
2157 jQuery.ajax({
2158 type : "post",
2159 dataType : "json",
2160 url : latepoint_timestamped_ajaxurl(),
2161 data : data,
2162 success: function(response){
2163 $trigger_elem.removeClass('os-loading');
2164 if(response.status === "success"){
2165 latepoint_display_in_side_sub_panel(response.message);
2166 jQuery('body').addClass('has-side-sub-panel');
2167 }else{
2168 alert(response.message, 'error');
2169 }
2170 }
2171 });
2172 return false;
2173 });
2174 }
2175
2176
2177 function latepoint_submit_quick_customer_form(){
2178 let $quick_edit_form = jQuery('form.customer-quick-edit-form');
2179
2180 let errors = latepoint_validate_form($quick_edit_form);
2181 if(errors.length){
2182 let error_messages = errors.map(error => error.message ).join(', ');
2183 latepoint_add_notification(error_messages, 'error');
2184 return false;
2185 }
2186
2187 $quick_edit_form.find('button[type="submit"]').addClass('os-loading');
2188 jQuery.ajax({
2189 type: "post",
2190 dataType: "json",
2191 processData: false,
2192 contentType: false,
2193 url: latepoint_timestamped_ajaxurl(),
2194 data: latepoint_create_form_data($quick_edit_form),
2195 success: function (response) {
2196 $quick_edit_form.find('button[type="submit"]').removeClass('os-loading');
2197 if(response.form_values_to_update){
2198 jQuery.each(response.form_values_to_update, function(name, value){
2199 $quick_edit_form.find('[name="'+ name +'"]').val(value);
2200 });
2201 }
2202 if (response.status === "success") {
2203 latepoint_add_notification(response.message);
2204 latepoint_reload_after_customer_save();
2205 }else{
2206 latepoint_add_notification(response.message, 'error');
2207 }
2208 }
2209 });
2210
2211 }
2212
2213
2214
2215 function latepoint_reload_after_customer_save(){
2216 latepoint_reload_calendar_view();
2217
2218 jQuery('.os-widget').each(function(){
2219 latepoint_reload_widget(jQuery(this));
2220 });
2221 if(jQuery('table.os-reload-on-booking-update').length) latepoint_filter_table(jQuery('table.os-reload-on-booking-update'), jQuery('table.os-reload-on-booking-update'));
2222 latepoint_close_side_panel();
2223 }
2224
2225 /*
2226 * Copyright (c) 2023 LatePoint LLC. All rights reserved.
2227 */
2228
2229
2230 function latepoint_init_daily_bookings_chart() {
2231 if (typeof Chart === 'undefined' || !jQuery('#chartDailyBookings').length) return
2232
2233 let $dailyBookingsChart = jQuery('#chartDailyBookings');
2234 let dailyBookingsLabels = $dailyBookingsChart.data('chart-labels').toString().split(',');
2235 let dailyBookingsValues = $dailyBookingsChart.data('chart-values').toString().split(',').map(Number);
2236 let dailyBookingsChartMax = Math.max.apply(Math, dailyBookingsValues);
2237 // calculate max Y to have space for a tooltip
2238 let canvasHeight = 200
2239 let spaceForTooltip = 160
2240 let maxValue = dailyBookingsChartMax + spaceForTooltip * dailyBookingsChartMax / canvasHeight + 1
2241
2242
2243 var fontFamily = latepoint_helper.body_font_family;
2244
2245 Chart.Tooltip.positioners.top = function (items) {
2246 const pos = Chart.Tooltip.positioners.average(items);
2247
2248 // Happens when nothing is found
2249 if (pos === false) {
2250 return false;
2251 }
2252
2253 const chart = this.chart;
2254
2255 return {
2256 x: pos.x,
2257 y: chart.chartArea.top,
2258 xAlign: 'center',
2259 yAlign: 'bottom',
2260 };
2261 };
2262
2263 Chart.defaults.defaultFontFamily = fontFamily;
2264 Chart.defaults.defaultFontSize = 18;
2265 Chart.defaults.defaultFontStyle = '400';
2266 Chart.defaults.plugins.tooltip.titleFont = {
2267 family: fontFamily,
2268 size: 14,
2269 color: 'rgba(255,255,255,0.6)',
2270 style: 'normal',
2271 weight: 400
2272 }
2273
2274 Chart.defaults.plugins.tooltip.titleFont = {family: fontFamily, size: 14, weight: 400};
2275 Chart.defaults.plugins.tooltip.titleColor = 'rgba(255,255,255,0.6)';
2276 Chart.defaults.plugins.tooltip.backgroundColor = '#000';
2277 Chart.defaults.plugins.tooltip.titleMarginBottom = 5;
2278 Chart.defaults.plugins.tooltip.bodyFont = {family: fontFamily, size: 24, weight: 700, lineHeight: 0.8};
2279 Chart.defaults.plugins.tooltip.displayColors = false;
2280 Chart.defaults.plugins.tooltip.padding = 10;
2281 Chart.defaults.plugins.tooltip.yAlign = 'bottom';
2282 Chart.defaults.plugins.tooltip.xAlign = 'center';
2283 Chart.defaults.plugins.tooltip.cornerRadius = 4;
2284 Chart.defaults.plugins.tooltip.caretSize = 5;
2285 Chart.defaults.plugins.tooltip.position = 'top';
2286
2287 var ctx = $dailyBookingsChart[0].getContext("2d");
2288 var gradientStroke = ctx.createLinearGradient(500, 0, 100, 0);
2289 gradientStroke.addColorStop(0, '#1d7bff');
2290 gradientStroke.addColorStop(1, '#1d7bff');
2291
2292
2293 let gradientFill = ctx.createLinearGradient(0, 0, 0, 140);
2294 gradientFill.addColorStop(0, 'rgb(206,224,255, 0.4)');
2295 gradientFill.addColorStop(1, 'rgba(206,224,255,0)');
2296
2297 // line chart data
2298 var chartDailyBookingsData = {
2299 labels: dailyBookingsLabels,
2300 datasets: [{
2301 backgroundColor: gradientFill,
2302 borderColor: gradientStroke,
2303 label: "",
2304 fill: true,
2305 lineTension: 0.1,
2306 borderWidth: 2,
2307 borderCapStyle: 'butt',
2308 borderDash: [],
2309 borderDashOffset: 0.0,
2310 borderJoinStyle: 'miter',
2311 pointBorderColor: "#fff",
2312 pointBackgroundColor: "#1D7BFF",
2313 pointRadius: 3,
2314 pointBorderWidth: 2,
2315 pointHoverRadius: 6,
2316 pointHoverBorderWidth: 4,
2317 pointHoverBackgroundColor: "#1D7BFF",
2318 pointHoverBorderColor: "#aecdff",
2319 pointHitRadius: 20,
2320 spanGaps: false,
2321 data: dailyBookingsValues,
2322 }]
2323 };
2324
2325
2326 let options = {
2327 animation: false,
2328 layout: {
2329 padding: {
2330 top: 0
2331 }
2332 },
2333 interaction: {
2334 mode: 'index',
2335 intersect: false,
2336 },
2337 maintainAspectRatio: false,
2338 plugins: {
2339 verticalLiner: {},
2340 legend: {
2341 display: false
2342 },
2343 },
2344 scales: {
2345 x: {
2346 display: true,
2347 ticks: {
2348 fontFamily: fontFamily,
2349 maxRotation: 0,
2350 color: '#1f222b',
2351 font: {
2352 size: 11,
2353 family: fontFamily
2354 },
2355 callback: function (value, index, ticks) {
2356 if(ticks.length){
2357 return ((index + 2) % Math.round(ticks.length/8)) ? '' : this.getLabelForValue(value)
2358 }else{
2359 return this.getLabelForValue(value)
2360 }
2361 }
2362 },
2363 grid: {
2364 borderDash: [1, 5],
2365 color: 'rgba(0,0,0,0.35)',
2366 zeroLineColor: 'rgba(0,0,0,0.15)',
2367 },
2368 },
2369 y: {
2370 max: maxValue,
2371 grid: {
2372 color: 'rgba(0,0,0,0.05)',
2373 zeroLineColor: 'rgba(0,0,0,0.05)',
2374 },
2375 display: false,
2376 ticks: {
2377 beginAtZero: true,
2378 fontSize: '10',
2379 fontColor: '#000'
2380 }
2381 }
2382
2383 }
2384 }
2385
2386 const plugin = {
2387 id: 'verticalLiner',
2388 afterInit: (chart, args, opts) => {
2389 chart.verticalLiner = {}
2390 },
2391 afterEvent: (chart, args, options) => {
2392 const {inChartArea} = args
2393 chart.verticalLiner = {draw: inChartArea}
2394 },
2395 beforeTooltipDraw: (chart, args, options) => {
2396 const {draw} = chart.verticalLiner
2397 if (!draw) return
2398
2399 const {ctx} = chart
2400 const {top, bottom} = chart.chartArea
2401 const {tooltip} = args
2402 const x = tooltip.caretX
2403 if (!x) return
2404
2405 ctx.save()
2406
2407 ctx.beginPath()
2408 ctx.moveTo(x, top)
2409 ctx.lineTo(x, bottom)
2410 ctx.stroke()
2411
2412 ctx.restore()
2413 }
2414 }
2415
2416 // line chart init
2417 let chartDailyBookings = new Chart($dailyBookingsChart, {
2418 type: 'line',
2419 data: chartDailyBookingsData,
2420 options: options,
2421 plugins: [plugin],
2422 });
2423 }
2424
2425
2426 function latepoint_init_customer_donut_chart() {
2427 if (typeof Chart !== 'undefined' && jQuery('.os-customer-donut-chart').length) {
2428 var fontFamily = latepoint_helper.body_font_family;
2429 // set defaults
2430 Chart.defaults.defaultFontFamily = fontFamily;
2431 Chart.defaults.defaultFontSize = 16;
2432 Chart.defaults.defaultFontStyle = '400';
2433
2434 Chart.defaults.plugins.tooltip.titleFont = {family: fontFamily, size: 14, weight: 400};
2435 Chart.defaults.plugins.tooltip.titleColor = 'rgba(255,255,255,0.6)';
2436 Chart.defaults.plugins.tooltip.backgroundColor = '#000';
2437 Chart.defaults.plugins.tooltip.titleMarginBottom = 1;
2438 Chart.defaults.plugins.tooltip.bodyFont = {family: fontFamily, size: 18, weight: 500};
2439 Chart.defaults.plugins.tooltip.displayColors = false;
2440 Chart.defaults.plugins.tooltip.padding = 5;
2441 Chart.defaults.plugins.tooltip.yAlign = 'bottom';
2442 Chart.defaults.plugins.tooltip.xAlign = 'center';
2443 Chart.defaults.plugins.tooltip.cornerRadius = 4;
2444 Chart.defaults.plugins.tooltip.intersect = false;
2445 jQuery('.os-customer-donut-chart').each(function (index) {
2446 var chart_colors = jQuery(this).data('chart-colors').toString().split(',');
2447 var chart_labels = jQuery(this).data('chart-labels').toString().split(',');
2448 var chart_values = jQuery(this).data('chart-values').toString().split(',').map(Number);
2449 var $chart_canvas = jQuery(this);
2450 var chartDonut = new Chart($chart_canvas, {
2451 type: 'doughnut',
2452 data: {
2453 labels: chart_labels,
2454 datasets: [{
2455 data: chart_values,
2456 backgroundColor: chart_colors,
2457 hoverBackgroundColor: chart_colors,
2458 borderWidth: 0,
2459 hoverBorderColor: 'transparent'
2460 }]
2461 },
2462 options: {
2463 layout: {
2464 padding: {
2465 top: 10,
2466 bottom: 10,
2467 left: 10,
2468 right: 10
2469 }
2470 },
2471 plugins: {
2472 legend: {
2473 display: false
2474 },
2475 tooltip: {
2476 callbacks: {
2477 title: function (tooltipItem) {
2478 return tooltipItem[0].label;
2479 },
2480 label: function (tooltipItem) {
2481 return tooltipItem.parsed;
2482 },
2483 }
2484 },
2485 },
2486 animation: {
2487 animateRotate: false
2488 },
2489 cutout: "90%",
2490 responsive: false,
2491 maintainAspectRatio: true,
2492 }
2493 });
2494 });
2495 }
2496 }
2497
2498 function latepoint_init_donut_charts() {
2499 if (typeof Chart !== 'undefined' && jQuery('.os-donut-chart').length) {
2500 var fontFamily = latepoint_helper.body_font_family;
2501 // set defaults
2502 Chart.defaults.defaultFontFamily = fontFamily;
2503 Chart.defaults.defaultFontSize = 18;
2504 Chart.defaults.defaultFontStyle = '400';
2505
2506 Chart.defaults.plugins.tooltip.titleFont.family = fontFamily;
2507 Chart.defaults.plugins.tooltip.titleFont.size = 14;
2508 Chart.defaults.plugins.tooltip.titleColor = 'rgba(255,255,255,0.6)';
2509 Chart.defaults.plugins.tooltip.backgroundColor = '#000';
2510 Chart.defaults.plugins.tooltip.titleFont.style = '400';
2511 Chart.defaults.plugins.tooltip.titleMarginBottom = 1;
2512 Chart.defaults.plugins.tooltip.bodyFont.family = fontFamily;
2513 Chart.defaults.plugins.tooltip.bodyFont.size = 24;
2514 Chart.defaults.plugins.tooltip.bodyFont.style = '500';
2515 Chart.defaults.plugins.tooltip.displayColors = false;
2516 Chart.defaults.plugins.tooltip.padding.x = 10;
2517 Chart.defaults.plugins.tooltip.padding.y = 8;
2518 Chart.defaults.plugins.tooltip.yAlign = 'bottom';
2519 Chart.defaults.plugins.tooltip.xAlign = 'center';
2520 Chart.defaults.plugins.tooltip.cornerRadius = 8;
2521 Chart.defaults.plugins.tooltip.intersect = false;
2522 jQuery('.os-donut-chart').each(function (index) {
2523 var chart_colors = jQuery(this).data('chart-colors').toString().split(',');
2524 var chart_labels = jQuery(this).data('chart-labels').toString().split(',');
2525 var chart_values = jQuery(this).data('chart-values').toString().split(',').map(Number);
2526 var $chart_canvas = jQuery(this);
2527 var chartDonut = new Chart($chart_canvas, {
2528 type: 'doughnut',
2529 data: {
2530 labels: chart_labels,
2531 datasets: [{
2532 data: chart_values,
2533 backgroundColor: chart_colors,
2534 hoverBackgroundColor: chart_colors,
2535 borderWidth: 0,
2536 hoverBorderColor: 'transparent'
2537 }]
2538 },
2539 options: {
2540 layout: {
2541 padding: {
2542 top: 40
2543 }
2544 },
2545 plugins: {
2546 legend: {
2547 display: false
2548 },
2549 tooltip: {
2550 callbacks: {
2551 title: function (tooltipItem, data) {
2552 return data['labels'][tooltipItem[0]['index']];
2553 },
2554 label: function (tooltipItem, data) {
2555 return data['datasets'][0]['data'][tooltipItem['index']];
2556 }
2557 }
2558 }
2559 },
2560 animation: {
2561 animateScale: true
2562 },
2563 cutoutPercentage: 96,
2564 responsive: false,
2565 maintainAspectRatio: true,
2566 }
2567 });
2568 });
2569 }
2570 }
2571
2572
2573 function latepoint_init_circles_charts() {
2574 jQuery('.circle-chart').each(function (index) {
2575 var chart_elem_id = jQuery(this).prop('id');
2576 var max_value = jQuery(this).data('max-value');
2577 var chart_value = jQuery(this).data('chart-value');
2578 var chart_color = jQuery(this).data('chart-color');
2579 var chart_color_fade = jQuery(this).data('chart-color-fade');
2580 var myCircle = Circles.create({
2581 id: chart_elem_id,
2582 radius: 25,
2583 value: chart_value,
2584 maxValue: max_value,
2585 width: 2,
2586 text: function (value) {
2587 return Math.round(value);
2588 },
2589 colors: [chart_color, chart_color_fade],
2590 duration: 200,
2591 wrpClass: 'circles-wrp',
2592 textClass: 'circles-text',
2593 valueStrokeClass: 'circles-valueStroke',
2594 maxValueStrokeClass: 'circles-maxValueStroke',
2595 styleWrapper: true,
2596 styleText: true
2597 });
2598
2599 });
2600
2601
2602 }
2603
2604
2605 /*
2606 * Copyright (c) 2023 LatePoint LLC. All rights reserved.
2607 */
2608
2609 function latepoint_check_horizontal_calendar_scroll(){
2610 if(jQuery('.daily-availability-calendar.horizontal-calendar').length){
2611 if(jQuery('.daily-availability-calendar.horizontal-calendar').width() < 700){
2612 jQuery('.daily-availability-calendar.horizontal-calendar').scrollLeft(jQuery('.os-day.selected').index() * jQuery('.os-day.selected').width());
2613 }
2614 }
2615 }
2616
2617 function latepoint_init_calendars(){
2618 latepoint_check_horizontal_calendar_scroll();
2619 jQuery('.os-calendar-settings-extra .latecheckbox').lateCheckbox();
2620
2621
2622 jQuery('.calendar-settings-toggler').on('click', function(){
2623 jQuery('.os-calendar-settings-form').toggleClass('show-extra-settings');
2624 return false;
2625 });
2626
2627 jQuery('.os-calendar-settings-form').on('change', 'select[name="calendar_settings[view]"]', function(){
2628 jQuery(this).closest('.calendar-wrapper').attr('data-view', jQuery(this).val());
2629 });
2630
2631 jQuery('.os-calendar-settings-form').on('change', 'select, input, .latecheckbox ', function(){
2632 latepoint_reload_calendar_view();
2633 });
2634
2635
2636 jQuery('.calendar-view-wrapper').on('click', '.weekly-calendar-agent-selector', function(){
2637 jQuery('.weekly-calendar-agent-selector.selected').removeClass('selected');
2638 jQuery(this).addClass('selected');
2639 jQuery('.os-calendar-settings-form input[name="calendar_settings[selected_agent_id]"]').val(jQuery(this).data('agent-id'));
2640 jQuery('.agent-weekly-calendar.selected').removeClass('selected');
2641 jQuery('.agent-weekly-calendar[data-agent-id="'+jQuery(this).data('agent-id')+'"]').addClass('selected');
2642 return false;
2643 });
2644
2645 jQuery('.calendar-view-wrapper').on('click', '.daily-calendar-action-navigation-btn', function(){
2646 jQuery(this).addClass('os-loading');
2647 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('target-date')).trigger('change');
2648 return false;
2649 });
2650
2651 jQuery('.calendar-view-wrapper').on('click', '.daily-availability-calendar .os-day', function(){
2652 jQuery('.os-monthly-calendar-days-w .os-day.selected').removeClass('selected');
2653 jQuery(this).addClass('selected');
2654 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('date')).trigger('change');
2655 return false;
2656 });
2657
2658
2659 jQuery('.os-calendar-today-btn').on('click', function(){
2660 jQuery(this).addClass('os-loading');
2661 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('target-date')).trigger('change');
2662 return false;
2663 });
2664
2665 jQuery('.os-calendar-prev-btn').on('click', function(){
2666 jQuery(this).addClass('os-loading');
2667 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery('input[name="prev_target_date"]').val()).trigger('change');
2668 return false;
2669 });
2670
2671 jQuery('.os-calendar-next-btn').on('click', function(){
2672 jQuery(this).addClass('os-loading');
2673 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery('input[name="next_target_date"]').val()).trigger('change');
2674 return false;
2675 });
2676 }
2677
2678 function latepoint_reload_calendar_view(){
2679 let $calendar_wrapper = jQuery('.calendar-view-wrapper');
2680 if(!$calendar_wrapper.length) return;
2681 $calendar_wrapper.addClass('os-loading');
2682
2683 let calendar_settings = new FormData(jQuery('form.os-calendar-settings-form')[0]);
2684
2685 let data = new FormData();
2686 data.append('params', latepoint_formdata_to_url_encoded_string(calendar_settings));
2687 data.append('action', latepoint_helper.route_action);
2688 data.append('route_name', $calendar_wrapper.data('route'));
2689 data.append('return_format', 'json');
2690
2691 jQuery.ajax({
2692 type: "post",
2693 dataType: "json",
2694 processData: false,
2695 contentType: false,
2696 url: latepoint_timestamped_ajaxurl(),
2697 data: data,
2698 success: function (response) {
2699 if (response.status === "success") {
2700 $calendar_wrapper.html(response.message).removeClass('os-loading');
2701 jQuery('.os-calendar-today-btn, .os-calendar-prev-btn, .os-calendar-next-btn').removeClass('os-loading');
2702 jQuery('.os-current-month-label .current-month').text(response.top_date_label);
2703 jQuery('.os-current-month-label .current-year').text(response.top_date_year);
2704 latepoint_check_horizontal_calendar_scroll();
2705 }
2706 }
2707 });
2708
2709 }
2710
2711 /*
2712 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
2713 */
2714
2715 function latepoint_process_updated() {
2716 location.reload();
2717 }
2718
2719 function latepoint_process_action_removed($elem) {
2720 $elem.closest('.os-form-block').remove();
2721 }
2722
2723 function latepoint_replace_process_condition_element($trigger, params, $target, callback = null) {
2724 $trigger.closest('.sub-section-content').addClass('os-loading');
2725 let route_name = $trigger.data('route');
2726 let data = {action: latepoint_helper.route_action, route_name: route_name, params: params, return_format: 'json'}
2727 jQuery.ajax({
2728 type: 'post',
2729 dataType: "json",
2730 url: latepoint_timestamped_ajaxurl(),
2731 data: data,
2732 success: (response) => {
2733 if (response.status === latepoint_helper.response_status.success) {
2734 $target.html(response.message);
2735 latepoint_init_process_conditions_form();
2736 $trigger.closest('.sub-section-content').removeClass('os-loading');
2737 if (typeof callback === 'function') {
2738 callback();
2739 }
2740 } else {
2741 alert("Error!");
2742 }
2743 }
2744 });
2745 }
2746
2747
2748 function latepoint_init_process_forms() {
2749 latepoint_init_process_conditions_form();
2750
2751 jQuery('.os-processes-w').on('latepoint:initProcessActionForm latepoint:initProcessActionTypeSettings', '.process-action-form', async function () {
2752 if (jQuery(this).find('.latepoint-whatsapp-templates-loader').length) {
2753 let $loader = jQuery(this).find('.latepoint-whatsapp-templates-loader');
2754 let $settings = jQuery(this).find('.process-action-settings');
2755 let $holder = jQuery(this).find('.latepoint-whatsapp-templates-holder');
2756 $settings.addClass('os-loading');
2757
2758 let data = {
2759 action: latepoint_helper.route_action,
2760 route_name: $loader.data('route'),
2761 params: {
2762 template_id: $loader.data('selected-template-id'),
2763 action_id: $loader.data('process-action-id'),
2764 process_id: $loader.data('process-id')
2765 },
2766 layout: 'none',
2767 return_format: 'json'
2768 }
2769 try {
2770 let response = await jQuery.ajax({
2771 type: "post",
2772 dataType: "json",
2773 url: latepoint_timestamped_ajaxurl(),
2774 data: data
2775 });
2776 $settings.removeClass('os-loading');
2777 if (response.status === 'success') {
2778 $loader.remove();
2779 $holder.html(response.message);
2780 } else {
2781 throw new Error(response.message);
2782 }
2783 } catch (e) {
2784 $settings.removeClass('os-loading');
2785 console.log(e);
2786 alert(e);
2787 }
2788 }
2789 });
2790
2791 jQuery('.os-processes-w').on('click', '.os-run-process', function () {
2792 let $btn = jQuery(this);
2793 $btn.addClass('os-loading');
2794 let $process_form = $btn.closest('.os-process-form');
2795 // remove previously assigned class on other forms
2796 jQuery('.os-process-form.prepared-to-run').removeClass('prepared-to-run');
2797 // add class so we know which form is about to be processed
2798 $process_form.addClass('prepared-to-run');
2799
2800
2801 let form_data = new FormData($process_form[0]);
2802 form_data.set('process_event_type', $process_form.closest('.os-process-form').find('.process-event-type-selector').val());
2803
2804
2805 let data = new FormData();
2806 data.append('params', latepoint_formdata_to_url_encoded_string(form_data));
2807 data.append('action', latepoint_helper.route_action);
2808 data.append('route_name', $btn.data('route'));
2809 data.append('return_format', 'json');
2810
2811 jQuery.ajax({
2812 type: "post",
2813 dataType: "json",
2814 processData: false,
2815 contentType: false,
2816 url: latepoint_timestamped_ajaxurl(),
2817 data: data,
2818 success: function (data) {
2819 latepoint_show_data_in_side_panel(data.message, 'width-600');
2820 latepoint_init_process_test_form();
2821 $btn.removeClass('os-loading');
2822 }
2823 });
2824 return false;
2825 });
2826
2827 jQuery('.os-processes-w').find('.process-action-form').each(function (index) {
2828 latepoint_init_process_action_form(jQuery(this));
2829 });
2830
2831 jQuery('.os-processes-w').on('click', '.pe-remove-condition', (event) => {
2832 if (jQuery(event.currentTarget).closest('.pe-conditions').find('.pe-condition').length > 1) {
2833 jQuery(event.currentTarget).closest('.pe-condition').remove();
2834 } else {
2835 alert('You need to have at least one condition if your custom field is set to be conditional.')
2836 }
2837 return false;
2838 });
2839
2840
2841 jQuery('.os-processes-w').on('change', 'select.process-condition-operator-selector', (event) => {
2842 let $select = jQuery(event.currentTarget);
2843 if ($select.val() == 'changed' || $select.val() == 'not_changed') {
2844 $select.closest('.pe-condition').find('.process-condition-values-w').hide();
2845 } else {
2846 $select.closest('.pe-condition').find('.process-condition-values-w').show();
2847 }
2848 });
2849
2850 jQuery('.os-processes-w').on('change', 'select.process-event-type-selector', (event) => {
2851 let $select = jQuery(event.currentTarget);
2852 latepoint_replace_process_condition_element($select, {event_type: $select.val()}, $select.closest('.os-form-block').find('.process-event-condition-wrapper'));
2853 });
2854
2855 jQuery('.os-processes-w').on('change', 'select.process-condition-object-selector', (event) => {
2856 let $select = jQuery(event.currentTarget);
2857 let $property_selector = $select.closest('.pe-condition').find('.process-condition-properties-w select');
2858 latepoint_replace_process_condition_element($select, {object_code: $select.val()}, $property_selector, () => {
2859 $property_selector.trigger('change');
2860 });
2861 });
2862
2863 jQuery('.os-processes-w').on('change', 'select.process-condition-property-selector', (event) => {
2864 let $select = jQuery(event.currentTarget);
2865 let $operator_selector = $select.closest('.pe-condition').find('.process-condition-operators-w select');
2866 latepoint_replace_process_condition_element($select, {property: $select.val()}, $operator_selector, () => {
2867 $operator_selector.trigger('change');
2868 });
2869 });
2870
2871 jQuery('.os-processes-w').on('change', 'select.process-condition-operator-selector', (event) => {
2872 let $select = jQuery(event.currentTarget);
2873 latepoint_replace_process_condition_element($select, {
2874 property: $select.closest('.pe-condition').find('select.process-condition-property-selector').val(),
2875 trigger_condition_id: $select.closest('.pe-condition').data('condition-id'),
2876 operator: $select.val()
2877 }, $select.closest('.pe-condition').find('.process-condition-values-w'));
2878 });
2879
2880 }
2881
2882 function latepoint_init_process_conditions_form() {
2883 jQuery('.os-late-select').lateSelect();
2884 }
2885
2886 function latepoint_add_process_condition($btn, response) {
2887 $btn.closest('.pe-condition').after(response.message);
2888 latepoint_init_process_conditions_form();
2889 }
2890
2891 function latepoint_init_added_process_action_form($trigger) {
2892 let $action_form = $trigger.prev('.process-action-form');
2893 $action_form.addClass('is-editing').trigger('latepoint:initProcessActionForm');
2894 latepoint_init_process_action_form($action_form);
2895 }
2896
2897 function latepoint_init_process_test_form() {
2898
2899 jQuery('.latepoint-run-process-btn').on('click', function () {
2900 let $btn = jQuery(this);
2901 if ($btn.hasClass('os-loading')) return false;
2902 $btn.addClass('os-loading');
2903 let $test_action_form = jQuery('.latepoint-side-panel-w .action-settings-wrapper');
2904
2905
2906 let form_data = new FormData(jQuery('.os-process-form.prepared-to-run')[0]);
2907
2908 // set data sources
2909 jQuery('.process-test-data-source-selector').each(function () {
2910 form_data.set(jQuery(this).prop('name'), jQuery(this).val());
2911 });
2912
2913 // set selected actions
2914 jQuery('.process-test-data-source-selector').each(function () {
2915 form_data.set(jQuery(this).prop('name'), jQuery(this).val());
2916 });
2917
2918 let action_ids_to_run = [];
2919 jQuery('.action-to-run input[type="hidden"]').each(function () {
2920 if (jQuery(this).val() == 'on') action_ids_to_run.push(jQuery(this).closest('.action-to-run').data('id'));
2921 });
2922 form_data.set('action_ids', action_ids_to_run.join(','));
2923
2924
2925 let data = new FormData();
2926 data.append('params', latepoint_formdata_to_url_encoded_string(form_data));
2927 data.append('action', latepoint_helper.route_action);
2928 data.append('route_name', $btn.data('route'));
2929 data.append('return_format', 'json');
2930
2931 jQuery.ajax({
2932 type: "post",
2933 dataType: "json",
2934 processData: false,
2935 contentType: false,
2936 url: latepoint_timestamped_ajaxurl(),
2937 data: data,
2938 success: function (data) {
2939 $btn.removeClass('os-loading');
2940 if (data.status == 'success') {
2941 latepoint_add_notification(data.message);
2942 } else {
2943 latepoint_add_notification(data.message, 'error');
2944 }
2945 }
2946 });
2947 });
2948
2949 jQuery('.process-action-test-data-source-selector').on('change', function () {
2950 // TODO add call to server to check if selected data sources matches conditions of this process
2951 });
2952 }
2953
2954
2955 function latepoint_init_process_action_test_form() {
2956
2957 latepoint_init_json_view(jQuery('.action-preview-wrapper.type-trigger_webhook pre'));
2958
2959 jQuery('.latepoint-run-action-btn').on('click', function () {
2960 let $btn = jQuery(this);
2961 if ($btn.hasClass('os-loading')) return false;
2962 $btn.addClass('os-loading');
2963 let $test_action_form = jQuery('.latepoint-side-panel-w .action-settings-wrapper');
2964
2965 let action_data = new FormData();
2966
2967
2968 action_data.append('params', $test_action_form.find('select, textarea, input').serialize());
2969 action_data.append('action', latepoint_helper.route_action);
2970 action_data.append('route_name', $btn.data('route'));
2971 action_data.append('return_format', 'json');
2972
2973 jQuery.ajax({
2974 type: "post",
2975 dataType: "json",
2976 processData: false,
2977 contentType: false,
2978 url: latepoint_timestamped_ajaxurl(),
2979 data: action_data,
2980 success: function (data) {
2981 $btn.removeClass('os-loading');
2982 if (data.status == 'success') {
2983 latepoint_add_notification(data.message);
2984 } else {
2985 latepoint_add_notification(data.message, 'error');
2986 }
2987 }
2988 });
2989 });
2990
2991 jQuery('.process-action-test-data-source-selector').on('change', function () {
2992 let $select = jQuery(this);
2993 jQuery('.action-preview-wrapper').addClass('os-loading');
2994 let $test_action_form = $select.closest('.action-settings-wrapper');
2995
2996 let action_data = new FormData();
2997
2998
2999 action_data.append('params', $test_action_form.find('select, textarea, input').serialize());
3000 action_data.append('action', latepoint_helper.route_action);
3001 action_data.append('route_name', $select.data('route'));
3002 action_data.append('return_format', 'json');
3003
3004 jQuery.ajax({
3005 type: "post",
3006 dataType: "json",
3007 processData: false,
3008 contentType: false,
3009 url: latepoint_timestamped_ajaxurl(),
3010 data: action_data,
3011 success: function (data) {
3012 jQuery('.action-preview-wrapper').html(data.message).removeClass('os-loading');
3013 latepoint_init_json_view(jQuery('.action-preview-wrapper.type-trigger_webhook pre'));
3014 }
3015 });
3016 });
3017 }
3018
3019 function latepoint_init_process_action_form($action_form) {
3020 $action_form.on('click', '.os-run-process-action', function () {
3021 let $btn = jQuery(this);
3022 $btn.addClass('os-loading');
3023 let $action_form = $btn.closest('.process-action-form');
3024
3025 if (window.tinyMCE !== undefined) window.tinyMCE.triggerSave();
3026
3027 let action_data = new FormData();
3028 let params = latepoint_create_form_data_from_non_form_element($action_form);
3029
3030 params.set('process_event_type', $action_form.closest('.os-process-form').find('.process-event-type-selector').val());
3031
3032 action_data.append('params', latepoint_formdata_to_url_encoded_string(params));
3033 action_data.append('action', latepoint_helper.route_action);
3034 action_data.append('route_name', $btn.data('route'));
3035 action_data.append('return_format', 'json');
3036
3037 jQuery.ajax({
3038 type: "post",
3039 dataType: "json",
3040 processData: false,
3041 contentType: false,
3042 url: latepoint_timestamped_ajaxurl(),
3043 data: action_data,
3044 success: function (data) {
3045 latepoint_show_data_in_side_panel(data.message, 'width-800');
3046 latepoint_init_process_action_test_form();
3047 $btn.removeClass('os-loading');
3048 }
3049 });
3050 return false;
3051 });
3052 $action_form.on('click', '.process-action-heading', function () {
3053 let $action_form = jQuery(this).closest('.process-action-form');
3054 if (!$action_form.hasClass('is-editing')) $action_form.trigger('latepoint:initProcessActionForm')
3055 $action_form.toggleClass('is-editing');
3056 return false;
3057 });
3058
3059 $action_form.find('textarea.os-wp-editor-textarea').each(function (index) {
3060 latepoint_init_tiny_mce(jQuery(this).attr('id'));
3061 });
3062 $action_form.on('click', '.os-remove-process-action', function () {
3063 if (confirm(jQuery(this).data('os-prompt'))) {
3064 jQuery(this).closest('.process-action-form').remove();
3065 }
3066 return false;
3067 });
3068
3069 $action_form.on('change', '.process-action-type-whatsapp-template-selector', async function () {
3070 let $select = jQuery(this);
3071 let $preview_holder = $select.closest('.process-action-settings').find('.latepoint-whatsapp-template-preview-holder');
3072 $preview_holder.addClass('os-loading');
3073
3074 let data = {
3075 action: latepoint_helper.route_action,
3076 route_name: $select.data('route'),
3077 params: {
3078 template_id: $select.val(),
3079 action_id: $select.data('action-id')
3080 },
3081 layout: 'none',
3082 return_format: 'json'
3083 }
3084 try {
3085 let response = await jQuery.ajax({
3086 type: "post",
3087 dataType: "json",
3088 url: latepoint_timestamped_ajaxurl(),
3089 data: data
3090 });
3091 $preview_holder.removeClass('os-loading');
3092 if (response.status === 'success') {
3093 $preview_holder.html(response.message);
3094 } else {
3095 throw new Error(response.message);
3096 }
3097 } catch (e) {
3098 $preview_holder.removeClass('os-loading');
3099 console.log(e);
3100 alert(e);
3101 }
3102 return false;
3103 });
3104
3105 $action_form.on('change', '.process-action-type', function () {
3106 let $select = jQuery(this);
3107 jQuery(this).closest('.process-action-form').find('.process-action-name').text($select.find('option:selected').text());
3108 let action_type = $select.val();
3109 let action_id = $select.data('action-id');
3110 let route_name = $select.data('route');
3111 let $action_settings = $select.closest('.process-action-content').find('.process-action-settings');
3112 $action_settings.addClass('os-loading');
3113 let data = {
3114 action: latepoint_helper.route_action,
3115 route_name: route_name,
3116 params: {
3117 action_type: action_type,
3118 action_id: action_id
3119 },
3120 layout: 'none',
3121 return_format: 'json'
3122 }
3123 jQuery.ajax({
3124 type: "post",
3125 dataType: "json",
3126 url: latepoint_timestamped_ajaxurl(),
3127 data: data,
3128 success: function (data) {
3129 $action_settings.html(data.message).removeClass('os-loading');
3130 let $action_form = $select.closest('.process-action-form');
3131 latepoint_init_input_masks($action_form);
3132 $action_form.trigger('latepoint:initProcessActionTypeSettings');
3133 }
3134 });
3135 return false;
3136 });
3137 }
3138
3139 /*
3140 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
3141 */
3142
3143
3144 function latepoint_preview_init_step_category_items(step_code){
3145 jQuery('.booking-form-preview .os-item-category-info').on('click', function(){
3146 var $booking_form_element = jQuery(this).closest('.booking-form-preview');
3147 jQuery(this).closest('.latepoint-step-content').addClass('selecting-item-category');
3148 var $category_wrapper = jQuery(this).closest('.os-item-category-w');
3149 var $main_parent = jQuery(this).closest('.os-item-categories-main-parent');
3150 if($category_wrapper.hasClass('selected')){
3151 $category_wrapper.removeClass('selected');
3152 if($category_wrapper.parent().closest('.os-item-category-w').length){
3153 $category_wrapper.parent().closest('.os-item-category-w').addClass('selected');
3154 }else{
3155 $main_parent.removeClass('show-selected-only');
3156 }
3157 }else{
3158 $main_parent.find('.os-item-category-w.selected').removeClass('selected');
3159 $main_parent.addClass('show-selected-only');
3160 $category_wrapper.addClass('selected');
3161 }
3162 return false;
3163 });
3164 }
3165
3166 function latepoint_booking_form_discard_changes(){
3167
3168 let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]);
3169
3170 var data = {
3171 action: latepoint_helper.route_action,
3172 route_name: jQuery('.booking-form-preview-settings').data('route-name'),
3173 params: latepoint_formdata_to_url_encoded_string(form_data),
3174 layout: 'none',
3175 return_format: 'json'
3176 }
3177
3178 jQuery.ajax({
3179 type : "post",
3180 dataType : "json",
3181 url : latepoint_timestamped_ajaxurl(),
3182 data : data,
3183 success: function(data){
3184 if(data.status === "success"){
3185 jQuery('.booking-form-preview-inner').html(data.booking_form_html);
3186 latepoint_init_booking_form_preview();
3187 }else{
3188 latepoint_add_notification(data.message, 'error');
3189 }
3190 }
3191 });
3192 }
3193
3194 function latepoint_booking_form_save_changes(){
3195
3196 let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]);
3197
3198 jQuery('.editable-setting').each(function(){
3199 form_data.set('steps_settings' + jQuery(this).data('setting-key'), jQuery(this).html());
3200 });
3201
3202
3203 form_data.set('steps_settings' + jQuery('.bf-side-media-picker-trigger').find('.os-image-id-holder').prop('name'), jQuery('.bf-side-media-picker-trigger').find('.os-image-id-holder').val());
3204
3205
3206 var data = {
3207 action: latepoint_helper.route_action,
3208 route_name: jQuery('.booking-form-preview-settings').data('route-name'),
3209 params: latepoint_formdata_to_url_encoded_string(form_data),
3210 layout: 'none',
3211 return_format: 'json'
3212 }
3213
3214 jQuery.ajax({
3215 type : "post",
3216 dataType : "json",
3217 url : latepoint_timestamped_ajaxurl(),
3218 data : data,
3219 success: function(data){
3220 jQuery('.booking-form-preview-settings').removeClass('os-loading');
3221 if(data.status === "success"){
3222 jQuery('.bf-preview-step-settings').html(data.step_settings_html);
3223 jQuery('.booking-form-preview-inner').html(data.booking_form_html);
3224 jQuery('#latepoint-main-admin-inline-css').html(data.css_variables);
3225 latepoint_init_booking_form_preview();
3226 }else{
3227 latepoint_add_notification(data.message, 'error');
3228 }
3229 }
3230 });
3231 }
3232
3233 function latepoint_init_booking_form_preview(){
3234
3235 latepoint_preview_init_step_category_items();
3236 latepoint_booking_form_preview_init_datepicker();
3237
3238
3239 jQuery('.booking-form-preview-wrapper').on('click', '.os-step-tab', function(){
3240 jQuery(this).closest('.os-step-tabs').find('.os-step-tab').removeClass('active');
3241 jQuery(this).addClass('active');
3242 var target = jQuery(this).data('target');
3243 jQuery(this).closest('.os-step-tabs-w').find('.os-step-tab-content').hide();
3244 jQuery(target).show();
3245 });
3246
3247
3248 jQuery('.bf-save-btn').on('click', function(){
3249 jQuery(this).addClass('os-loading');
3250 latepoint_booking_form_save_changes();
3251 return false;
3252 });
3253
3254 jQuery('.bf-cancel-save-btn').on('click', function(){
3255 jQuery(this).addClass('os-loading');
3256 latepoint_booking_form_discard_changes();
3257 return false;
3258 });
3259
3260
3261 jQuery('.booking-form-preview .bf-next-btn').on('click', function(){
3262 jQuery(this).addClass('os-loading');
3263 jQuery("#selected_step_code > option:selected")
3264 .prop("selected", false)
3265 .next()
3266 .prop("selected", true).trigger('change');
3267 });
3268
3269 jQuery('.booking-form-preview .bf-prev-btn').on('click', function(){
3270 jQuery(this).addClass('os-loading');
3271 jQuery("#selected_step_code > option:selected")
3272 .prop("selected", false)
3273 .prev()
3274 .prop("selected", true).trigger('change');
3275 });
3276
3277
3278 jQuery('.booking-form-preview .os-image-selector-trigger').on('click', function(){
3279 jQuery('.booking-form-preview').addClass('has-changes');
3280 });
3281
3282 jQuery('.booking-form-preview .editable-setting').on('focus', function(){
3283 jQuery('.booking-form-preview').addClass('has-changes');
3284 });
3285
3286
3287 let editor = new MediumEditor('.booking-form-preview .os-editable', {toolbar: {
3288 buttons: [
3289 {
3290 name: 'bold',
3291 classList: ['latepoint-icon', 'latepoint-icon-format_bold'],
3292 },
3293 {
3294 name: 'anchor',
3295 classList: ['latepoint-icon', 'latepoint-icon-format_link'],
3296 },
3297 {
3298 name: 'h3',
3299 classList: ['latepoint-icon', 'latepoint-icon-format_h3'],
3300 },
3301 {
3302 name: 'h4',
3303 classList: ['latepoint-icon', 'latepoint-icon-format_h4'],
3304 },
3305 {
3306 name: 'h5',
3307 classList: ['latepoint-icon', 'latepoint-icon-format_h5'],
3308 },
3309
3310 ]
3311 }
3312 });
3313 let editor_basic = new MediumEditor('.booking-form-preview .os-editable-basic', {toolbar: {
3314 buttons: [
3315 {
3316 name: 'bold',
3317 classList: ['latepoint-icon', 'latepoint-icon-format_bold'],
3318 },
3319 {
3320 name: 'italic',
3321 classList: ['latepoint-icon', 'latepoint-icon-format_italic'],
3322 },
3323 {
3324 name: 'underline',
3325 classList: ['latepoint-icon', 'latepoint-icon-format_underlined'],
3326 },
3327 {
3328 name: 'anchor',
3329 classList: ['latepoint-icon', 'latepoint-icon-format_link'],
3330 },
3331
3332 ]
3333 }
3334 });
3335 }
3336
3337 function latepoint_reload_booking_form_preview(){
3338 latepoint_booking_form_save_changes();
3339 }
3340
3341 function latepoint_init_steps_settings(){
3342
3343 jQuery('.booking-form-preview-settings').on('change', ' select, input[type="hidden"]', function(){
3344 jQuery('.booking-form-preview-settings').addClass('os-loading');
3345 latepoint_reload_booking_form_preview();
3346 });
3347
3348 jQuery('.trigger-custom-color-save').on('click', function(){
3349 jQuery('.booking-form-preview-settings').addClass('os-loading');
3350 latepoint_booking_form_save_changes();
3351 return false;
3352 });
3353
3354 jQuery('.bf-color-scheme-color-trigger').on('click', function(){
3355 jQuery('.bf-color-scheme-color-trigger.is-selected').removeClass('is-selected');
3356 jQuery(this).addClass('is-selected');
3357 let color_scheme = jQuery(this).data('color-code');
3358 jQuery('.os-color-scheme-selector-wrapper select').val(color_scheme).trigger('change');
3359 if(color_scheme == 'custom'){
3360 jQuery('.os-custom-color-selector-wrapper').removeClass('is-hidden');
3361 }else{
3362 jQuery('.os-custom-color-selector-wrapper').addClass('is-hidden');
3363 }
3364 return false;
3365 });
3366
3367 jQuery('.os-section-collapsible-trigger').on('click', function(){
3368 jQuery(this).closest('.os-section-collapsible-wrapper').toggleClass('is-open');
3369 return false;
3370 })
3371 }
3372
3373
3374 function latepoint_booking_form_preview_init_timeslots($booking_form_element = false){
3375 if(!$booking_form_element) return;
3376 $booking_form_element.on('click', '.dp-timepicker-trigger', function(){
3377 if(jQuery(this).hasClass('is-booked') || jQuery(this).hasClass('is-off')){
3378 // Show error message that you cant select a booked period
3379 }else{
3380 if(jQuery(this).hasClass('selected')){
3381 jQuery(this).removeClass('selected');
3382 jQuery(this).find('.dp-success-label').remove();
3383 }else{
3384 $booking_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove();
3385 var selected_timeslot_time = jQuery(this).find('.dp-label-time').html();
3386 jQuery(this).addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>');
3387
3388 var minutes = parseInt(jQuery(this).data('minutes'));
3389 var timeshift_minutes = parseInt($booking_form_element.find('.latepoint_timeshift_minutes').val());
3390 // 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
3391 if(timeshift_minutes) minutes = minutes - timeshift_minutes;
3392 var start_date = new Date($booking_form_element.find('.os-day.selected').data('date'));
3393 if(minutes < 0){
3394 // business minutes are in previous day
3395 minutes = 24*60 + minutes;
3396 // move start date back 1 day
3397 start_date.setDate(start_date.getDate() - 1);
3398 }else if(minutes >= 24*60){
3399 // business minutes are in next day
3400 minutes = minutes - 24*60;
3401 start_date.setDate(start_date.getDate() + 1);
3402 }
3403 $booking_form_element.find('.latepoint_start_date').val(start_date.toISOString().split('T')[0])
3404 latepoint_trigger_next_btn($booking_form_element);
3405 }
3406 }
3407 return false;
3408 });
3409 }
3410
3411
3412 function latepoint_booking_form_preview_day_timeslots($day){
3413 let $wrapper_element = jQuery('.booking-form-preview');
3414 $day.addClass('selected');
3415
3416 var service_duration = $day.data('service-duration');
3417 var interval = $day.data('interval');
3418 var work_start_minutes = $day.data('work-start-time');
3419 var work_end_minutes = $day.data('work-end-time');
3420 var total_work_minutes = $day.data('total-work-minutes');
3421 var bookable_minutes = [];
3422 var available_capacities_of_bookable_minute = [];
3423 if($day.attr('data-bookable-minutes')){
3424 if($day.data('bookable-minutes').toString().indexOf(':') > -1){
3425 // has capacity information embedded into bookable minutes string
3426 let bookable_minutes_with_capacity = $day.data('bookable-minutes').toString().split(',');
3427 for(let i = 0; i < bookable_minutes_with_capacity.length; i++){
3428 bookable_minutes.push(parseInt(bookable_minutes_with_capacity[i].split(':')[0]));
3429 available_capacities_of_bookable_minute.push(parseInt(bookable_minutes_with_capacity[i].split(':')[1]));
3430 }
3431 }else{
3432 bookable_minutes = $day.data('bookable-minutes').toString().split(',').map(Number);
3433 }
3434 }
3435 var work_minutes = $day.data('work-minutes').toString().split(',').map(Number);
3436
3437 var $timeslots = $wrapper_element.find('.timeslots');
3438 $timeslots.html('');
3439
3440 if(total_work_minutes > 0 && bookable_minutes.length && work_minutes.length){
3441 var prev_minutes = false;
3442 work_minutes.forEach(function(current_minutes){
3443 var ampm = latepoint_am_or_pm(current_minutes);
3444
3445 var timeslot_class = 'dp-timepicker-trigger';
3446 var timeslot_available_capacity = 0;
3447 if($wrapper_element.find('.os-dates-w').data('time-pick-style') == 'timeline'){
3448 timeslot_class+= ' dp-timeslot';
3449 }else{
3450 timeslot_class+= ' dp-timebox';
3451 }
3452
3453 if(prev_minutes !== false && ((current_minutes - prev_minutes) > service_duration)){
3454 // show interval that is off between two work periods
3455 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);
3456 var off_width = (((current_minutes - prev_minutes - service_duration) / total_work_minutes) * 100);
3457 $timeslots.append('<div class="'+ timeslot_class +' is-off" style="max-width:'+ off_width +'%; width:'+ off_width +'%"><span class="dp-label">' + off_label + '</span></div>');
3458 }
3459
3460 if(!bookable_minutes.includes(current_minutes)){
3461 timeslot_class+= ' is-booked';
3462 }else{
3463 if(available_capacities_of_bookable_minute.length) timeslot_available_capacity = available_capacities_of_bookable_minute[bookable_minutes.indexOf(current_minutes)];
3464 }
3465 var tick_html = '';
3466 var capacity_label = '';
3467 var capacity_label_html = '';
3468 var capacity_internal_label_html = '';
3469
3470 if(((current_minutes % 60) == 0) || (interval >= 60)){
3471 timeslot_class+= ' with-tick';
3472 tick_html = '<span class="dp-tick"><strong>'+latepoint_minutes_to_hours_preferably(current_minutes)+'</strong>'+' '+ampm+'</span>';
3473 }
3474 var timeslot_label = latepoint_minutes_to_hours_and_minutes(current_minutes)+' '+ampm;
3475 if(latepoint_show_booking_end_time()){
3476 var end_minutes = current_minutes + service_duration;
3477 if(end_minutes > 1440) end_minutes = end_minutes - 1440;
3478 var end_minutes_ampm = latepoint_am_or_pm(end_minutes);
3479 timeslot_label+= ' - <span class="dp-label-end-time">' + latepoint_minutes_to_hours_and_minutes(end_minutes)+' '+end_minutes_ampm + '</span>';
3480 }
3481 if(timeslot_available_capacity){
3482 var spaces_message = timeslot_available_capacity > 1 ? latepoint_helper.many_spaces_message : latepoint_helper.single_space_message;
3483 capacity_label = timeslot_available_capacity + ' ' + spaces_message;
3484 capacity_label_html = '<span class="dp-capacity">' + capacity_label + '</span>';
3485 capacity_internal_label_html = '<span class="dp-label-capacity">' + capacity_label + '</span>';
3486 }
3487 timeslot_label = timeslot_label.trim();
3488 $timeslots.removeClass('slots-not-available').append('<div 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>');
3489 prev_minutes = current_minutes;
3490 });
3491 }else{
3492 // No working hours this day
3493 $timeslots.addClass('slots-not-available').append('<div class="not-working-message">' + latepoint_helper.msg_not_available + "</div>");
3494 }
3495 jQuery('.times-header-label span').text($day.data('nice-date'));
3496 $wrapper_element.find('.time-selector-w').slideDown(200);
3497 }
3498
3499 function latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element){
3500
3501 if(!$booking_form_element) return;
3502 $booking_form_element.on('click', '.os-month-next-btn', function(){
3503 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
3504 var next_month_route_name = jQuery(this).data('route');
3505 if($booking_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length){
3506 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active');
3507 latepoint_booking_form_preview_calendar_set_month_label($booking_form_element);
3508 }else{
3509 alert('Disabled in preview');
3510 }
3511 latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element);
3512 return false;
3513 });
3514 $booking_form_element.on('click', '.os-month-prev-btn', function(){
3515 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
3516 if($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length){
3517 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active');
3518 latepoint_booking_form_preview_calendar_set_month_label($booking_form_element);
3519 }
3520 return false;
3521 });
3522 }
3523
3524
3525 function latepoint_booking_form_preview_calendar_set_month_label(){
3526 jQuery('.os-current-month-label .current-month').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-month-label'));
3527 jQuery('.os-current-month-label .current-year').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-year'));
3528 }
3529
3530
3531
3532 function latepoint_booking_form_preview_init_datepicker(){
3533 let $booking_form_element = jQuery('.latepoint-booking-form-element');
3534 latepoint_booking_form_preview_init_timeslots($booking_form_element);
3535 latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element);
3536 $booking_form_element.on('click', '.os-months .os-day', function(){
3537 if(jQuery(this).hasClass('os-day-passed')) return false;
3538 if(jQuery(this).hasClass('os-not-in-allowed-period')) return false;
3539 if(jQuery(this).closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')){
3540
3541 // HIDE TIMESLOT IF ONLY ONE TIMEPOINT
3542 if(jQuery(this).hasClass('os-not-available')){
3543 // clicked on a day that has no available timeslots
3544 // do nothing
3545 }else{
3546 $booking_form_element.find('.os-day.selected').removeClass('selected');
3547 jQuery(this).addClass('selected');
3548 // set date
3549 $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date'));
3550 if(jQuery(this).hasClass('os-one-slot-only')){
3551 // clicked on a day that has only one slot available
3552 var bookable_minutes = jQuery(this).data('bookable-minutes').toString().split(':')[0];
3553 var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number(jQuery(this).data('service-duration')));
3554 $booking_form_element.find('.time-selector-w').slideUp(200);
3555 }else{
3556 // regular day with more than 1 timeslots available
3557 // build timeslots
3558 latepoint_booking_form_preview_day_timeslots(jQuery(this));
3559 // clear time and hide next btn
3560 }
3561 }
3562 }else{
3563 // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT
3564 $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date'));
3565 $booking_form_element.find('.os-day.selected').removeClass('selected');
3566 jQuery(this).addClass('selected');
3567
3568 // build timeslots
3569 latepoint_booking_form_preview_day_timeslots(jQuery(this));
3570 // clear time and hide next btn
3571 }
3572
3573
3574 return false;
3575 });
3576 }
3577
3578
3579
3580 /*
3581 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
3582 */
3583
3584 function latepoint_submit_quick_order_form(){
3585 let $quick_edit_form = jQuery('form.order-quick-edit-form');
3586
3587 let errors = latepoint_validate_form($quick_edit_form);
3588 if(errors.length){
3589 let error_messages = errors.map(error => error.message ).join(', ');
3590 latepoint_add_notification(error_messages, 'error');
3591 return false;
3592 }
3593
3594 $quick_edit_form.find('button[type="submit"]').addClass('os-loading');
3595 jQuery.ajax({
3596 type: "post",
3597 dataType: "json",
3598 processData: false,
3599 contentType: false,
3600 url: latepoint_timestamped_ajaxurl(),
3601 data: latepoint_create_form_data($quick_edit_form),
3602 success: function (response) {
3603 if(response.fields_to_update){
3604 for (const [key, value] of Object.entries(response.fields_to_update)) {
3605 $quick_edit_form.find('input[name="' + key + '"]').val(value)
3606 }
3607 }
3608 $quick_edit_form.find('button[type="submit"]').removeClass('os-loading');
3609 if(response.form_values_to_update){
3610 jQuery.each(response.form_values_to_update, function(name, value){
3611 $quick_edit_form.find('[name="'+ name +'"]').val(value);
3612 });
3613 }
3614 if (response.status === "success") {
3615 latepoint_add_notification(response.message);
3616 latepoint_reload_after_order_save();
3617 }else{
3618 latepoint_add_notification(response.message, 'error');
3619 }
3620 }
3621 });
3622
3623 }
3624
3625 function latepoint_apply_agent_selector_change(){
3626 if(jQuery('.quick-availability-per-day-w').length){
3627
3628 let booking_form_id = jQuery('.quick-availability-per-day-w').data('trigger-form-booking-id');
3629 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
3630
3631 latepoint_load_quick_availability($trigger_btn);
3632 }
3633 }
3634
3635 function latepoint_apply_service_selector_change($form){
3636 let field_base_name = 'order_items[' + $form.data('order-item-id') +'][bookings][' + $form.data('booking-id') +']';
3637
3638 var $selected_service = $form.find('.os-services-select-field-w .service-option-selected');
3639 var service_id = $selected_service.data('id');
3640 var buffer_before = $selected_service.data('buffer-before');
3641 var buffer_after = $selected_service.data('buffer-after');
3642 var default_duration = $selected_service.data('duration');
3643 var default_duration_name = $selected_service.data('duration-name');
3644 var min_capacity = $selected_service.data('capacity-min');
3645 var max_capacity = $selected_service.data('capacity-max');
3646
3647 var extra_durations = $selected_service.data('extra-durations');
3648
3649 $form.find('input[name="'+field_base_name+'[buffer_before]"]').val(buffer_before).trigger('change').closest('.os-form-group').addClass('has-value');
3650 $form.find('input[name="'+field_base_name+'[buffer_after]"]').val(buffer_after).trigger('change').closest('.os-form-group').addClass('has-value');
3651 $form.find('input[name="'+field_base_name+'[service_id]"]').val(service_id).trigger('change').closest('.os-form-group').addClass('has-value');
3652
3653 var duration_name = default_duration_name ? default_duration_name : (default_duration + ' ' + latepoint_helper.string_minutes);
3654 var options = '<option value="'+ default_duration +'">' + duration_name + '</option>';
3655 if(extra_durations.length){
3656 jQuery.each(extra_durations, function(index, value){
3657 var duration_name = value.name ? value.name : value.duration + ' ' + latepoint_helper.string_minutes;
3658 options+= '<option value="'+ value.duration +'">' + duration_name + '</option>';
3659 });
3660 $form.find('.os-service-durations').show();
3661 }else{
3662 $form.find('.os-service-durations').hide();
3663 }
3664
3665 $form.find('.booking-total-attendees-selector-w .capacity-info strong').text(max_capacity);
3666 var attendees_options_html = '';
3667 for(var i=1;i<=max_capacity;i++){
3668 attendees_options_html+= '<option value="' + i + '">' + i + '</option>';
3669 }
3670 var selected_attendees = Math.min(jQuery('.booking-total-attendees-selector-w select').val(), max_capacity);
3671 $form.find('.booking-total-attendees-selector-w select').html(attendees_options_html).val(selected_attendees);
3672 if(max_capacity > 1){
3673 $form.find('.booking-total-attendees-selector-w').show();
3674 }else{
3675 $form.find('.booking-total-attendees-selector-w').hide();
3676 }
3677
3678 $form.find('.os-service-durations select').html(options);
3679
3680 latepoint_set_booking_end_time($form);
3681 if(jQuery('.quick-availability-per-day-w').length){
3682 latepoint_load_quick_availability($form.find('.trigger-quick-availability'));
3683 }
3684
3685 latepoint_init_input_masks($form);
3686 }
3687
3688 function latepoint_reload_balance_and_payments(){
3689 let $wrapper = jQuery('.balance-payment-info');
3690 $wrapper.closest('.balance-payment-wrapper').addClass('os-loading');
3691 let route_name = $wrapper.data('route');
3692 let $quick_edit_form = $wrapper.closest('form.order-quick-edit-form');
3693 let form_data = new FormData($quick_edit_form[0]);
3694
3695 let data = { action: latepoint_helper.route_action, route_name: route_name, params: latepoint_formdata_to_url_encoded_string(form_data), return_format: 'json' }
3696 jQuery.ajax({
3697 type : "post",
3698 dataType : "json",
3699 url : latepoint_timestamped_ajaxurl(),
3700 data : data,
3701 success: function(response){
3702 $wrapper.closest('.balance-payment-wrapper').removeClass('os-loading');
3703 if(response.status === "success"){
3704 jQuery('.balance-payment-wrapper').html(response.message);
3705 latepoint_init_input_masks(jQuery('.balance-payment-wrapper'));
3706 latepoint_init_daterangepicker(jQuery('.balance-payment-wrapper .os-date-range-picker'));
3707 latepoint_init_payment_request_form(jQuery('.quick-order-form-w'));
3708 }else{
3709 alert(response.message);
3710 }
3711 }
3712 });
3713 }
3714
3715
3716
3717 function latepoint_cancel_adding_new_order_item_to_quick_edit_form(){
3718 jQuery('.order-items-list').removeClass('is-blurred');
3719 jQuery('.new-order-item-list-bundles-wrapper').removeClass('is-open');
3720 jQuery('.new-order-item-variant-selector-wrapper').removeClass('is-open');
3721 jQuery('.order-form-add-item-btn').removeClass('is-cancelling').find('span').text(jQuery('.order-form-add-item-btn').data('add-label'));
3722 }
3723
3724 function latepoint_build_new_booking_order_item(){
3725 jQuery('.order-form-add-item-btn').addClass('os-loading');
3726 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3727 let params = {}
3728
3729 var data = {
3730 action: 'latepoint_route_call',
3731 route_name: jQuery('.order-form-add-item-btn').data('booking-form-route-name'),
3732 params: params,
3733 return_format: 'json'
3734 }
3735 jQuery.ajax({
3736 type : "post",
3737 dataType : "json",
3738 url : latepoint_timestamped_ajaxurl(),
3739 data : data,
3740 success: function(response){
3741 if(response.status === "success"){
3742 let $form = jQuery(response.message);
3743 jQuery('.order-items-list').prepend($form);
3744 jQuery('.order-form-add-item-btn').removeClass('os-loading');
3745 latepoint_init_booking_data_form(jQuery('.order-item-booking-data-form-wrapper[data-order-item-id="' + $form.data('order-item-id') + '"]'));
3746 // new item added, trigger change event
3747 latepoint_quick_order_items_changed();
3748 }else{
3749 alert(response.message, 'error');
3750 }
3751 }
3752 });
3753 }
3754
3755 function latepoint_build_booking_data_form_for_bundle($slot_for_booking){
3756 $slot_for_booking.addClass('os-loading');
3757 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3758 let params = {}
3759
3760 let is_booked = $slot_for_booking.hasClass('is-booked');
3761
3762 var data = {
3763 action: 'latepoint_route_call',
3764 route_name: jQuery('.order-form-add-item-btn').data('booking-form-route-name'),
3765 params: {
3766 order_item_id: $slot_for_booking.data('order-item-id'),
3767 order_item_variant: $slot_for_booking.data('order-item-variant'),
3768 booking_id: $slot_for_booking.data('booking-id'),
3769 booking_item_data: is_booked ? $slot_for_booking.find('.booking_item_data').val() : $slot_for_booking.find('.unscheduled_booking_item_data').val()
3770 },
3771 return_format: 'json'
3772 }
3773 jQuery.ajax({
3774 type : "post",
3775 dataType : "json",
3776 url : latepoint_timestamped_ajaxurl(),
3777 data : data,
3778 success: function(response){
3779 if(response.status === "success"){
3780 let $form = jQuery(response.message);
3781 $slot_for_booking.removeClass('os-loading');
3782 if($slot_for_booking){
3783 $slot_for_booking.find('.scheduled-bundle-booking').html($form).closest('.order-item-variant-bundle-booking ').addClass('is-booked');
3784 }else{
3785 jQuery('.order-items-list').prepend($form);
3786 }
3787 latepoint_init_booking_data_form(jQuery('.order-item-booking-data-form-wrapper[data-order-item-id="' + $form.data('order-item-id') + '"][data-booking-id="' + $form.data('booking-id') + '"]'));
3788 // new item added, trigger change event
3789 if(!$slot_for_booking) latepoint_quick_order_items_changed();
3790 }else{
3791 alert(response.message, 'error');
3792 }
3793 }
3794 });
3795 }
3796
3797 function latepoint_bundle_added_to_quick_order(){
3798 latepoint_quick_order_items_changed();
3799 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3800 }
3801
3802 function latepoint_quick_order_items_changed(){
3803 latepoint_reload_price_breakdown();
3804 }
3805
3806
3807 function latepoint_fold_booking_data_form_in_order_quick_edit($booking_data_form){
3808 if(!$booking_data_form.length) return false;
3809 latepoint_close_quick_availability_form();
3810 latepoint_show_all_order_items();
3811 let order_item_id = $booking_data_form.data('order-item-id');
3812 let booking_id = $booking_data_form.data('booking-id');
3813 let order_item_variant = $booking_data_form.data('order-item-variant');
3814
3815
3816 $booking_data_form.addClass('is-loading');
3817
3818 let form_data = new FormData(jQuery('.order-quick-edit-form')[0]);
3819 form_data.set('order_item_id', order_item_id);
3820 form_data.set('booking_id', booking_id);
3821 var data = {
3822 action: 'latepoint_route_call',
3823 route_name: jQuery('.order-form-add-item-btn').data('fold-booking-data-route-name'),
3824 params: latepoint_formdata_to_url_encoded_string(form_data),
3825 return_format: 'json'
3826 }
3827 jQuery.ajax({
3828 type : "post",
3829 dataType : "json",
3830 url : latepoint_timestamped_ajaxurl(),
3831 data : data,
3832 success: function(response){
3833 if(response.status === "success"){
3834 $booking_data_form.removeClass('is-loading').removeClass('is-unfolded').addClass('is-folded');
3835 if(order_item_variant == latepoint_helper.order_item_variant_bundle){
3836 $booking_data_form.closest('.order-item-variant-bundle-booking').addClass('is-booked');
3837 $booking_data_form.find('.bundle-booking-item-pill').replaceWith(response.message);
3838 }else{
3839 $booking_data_form.find('.order-item-pill').replaceWith(response.message);
3840 }
3841 }else{
3842 alert(response.message, 'error');
3843 }
3844 }
3845 });
3846 }
3847
3848
3849 function latepoint_init_booking_data_form($booking_data_form){
3850 latepoint_init_input_masks($booking_data_form);
3851
3852 $booking_data_form.find('.fold-order-item-booking-data-form-btn').on('click', function(){
3853 latepoint_fold_booking_data_form_in_order_quick_edit($booking_data_form);
3854 return false;
3855 });
3856
3857 $booking_data_form.find('.quick-booking-form-view-log-btn').on('click', function(){
3858 var $trigger_elem = jQuery(this);
3859 $trigger_elem.addClass('os-loading');
3860 var route = $trigger_elem.data('route');
3861 var data = { action: 'latepoint_route_call', route_name: route, params: {booking_id: $trigger_elem.data('booking-id')}, return_format: 'json' }
3862 jQuery.ajax({
3863 type : "post",
3864 dataType : "json",
3865 url : latepoint_timestamped_ajaxurl(),
3866 data : data,
3867 success: function(response){
3868 $trigger_elem.removeClass('os-loading');
3869 if(response.status === "success"){
3870 latepoint_display_in_side_sub_panel(response.message);
3871 jQuery('body').addClass('has-side-sub-panel');
3872 }else{
3873 alert(response.message, 'error');
3874 }
3875 }
3876 });
3877 return false;
3878 });
3879
3880
3881 $booking_data_form.find('.os-late-select').lateSelect();
3882
3883 $booking_data_form.find('.trigger-quick-availability').on('click', function(){
3884 latepoint_load_quick_availability(jQuery(this));
3885 return false;
3886 });
3887
3888 let field_base_name = 'order_items[' + $booking_data_form.data('order-item-id') +'][bookings][' + $booking_data_form.data('booking-id') +']';
3889
3890 $booking_data_form.find('input[name="' + field_base_name +'[start_time][formatted_value]"]').on('change', function(){
3891 latepoint_set_booking_end_time($booking_data_form);
3892 });
3893 $booking_data_form.find('input[name="' + field_base_name +'[end_time][formatted_value]"]').on('change', function(){
3894 latepoint_is_next_day($booking_data_form);
3895 });
3896
3897
3898
3899 $booking_data_form.on('change', '.agent-selector', function(){
3900 latepoint_apply_agent_selector_change($booking_data_form);
3901 });
3902 $booking_data_form.on('change', 'select[name="booking[location_id]"]', function(){
3903 latepoint_apply_agent_selector_change($booking_data_form);
3904 });
3905 $booking_data_form.on('change', 'select[name="booking[total_attendees]"]', function(){
3906 latepoint_apply_agent_selector_change($booking_data_form);
3907 });
3908
3909 $booking_data_form.on('change', '.os-affects-duration', function(){
3910 latepoint_set_booking_end_time($booking_data_form);
3911 if(jQuery('.quick-availability-per-day-w').length){
3912 latepoint_load_quick_availability($booking_data_form.find('.trigger-quick-availability'));
3913 }
3914 });
3915
3916 $booking_data_form.on('change', '.os-affects-price', function(){
3917 latepoint_reload_price_breakdown();
3918 });
3919
3920 $booking_data_form.on('change', '.os-affects-balance', function(){
3921 latepoint_reload_balance_and_payments();
3922 });
3923 $booking_data_form.on('keyup', '.os-affects-balance', function(event){
3924 if(event.keyCode == 13) {
3925 latepoint_reload_balance_and_payments();
3926 }
3927 });
3928
3929
3930 $booking_data_form.on('click', '.services-options-list .service-option', function(){
3931 var selected_option_html = jQuery(this).html();
3932 var $selected_option = jQuery(this).closest('.os-services-select-field-w').find('.service-option-selected');
3933 $selected_option.html(selected_option_html)
3934 .data('id', jQuery(this).data('id'))
3935 .data('duration', jQuery(this).data('duration'))
3936 .data('duration-name', jQuery(this).data('duration-name'))
3937 .data('buffer-before', jQuery(this).data('buffer-before'))
3938 .data('buffer-after', jQuery(this).data('buffer-after'))
3939 .data('capacity-min', jQuery(this).data('capacity-min'))
3940 .data('capacity-max', jQuery(this).data('capacity-max'))
3941 .data('extra-durations', jQuery(this).data('extra-durations'));
3942 jQuery(this).closest('.os-services-select-field-w').find('.service-option.selected').removeClass('selected');
3943 jQuery(this).addClass('selected').closest('.os-services-select-field-w').removeClass('active');
3944 latepoint_apply_service_selector_change($booking_data_form);
3945 return false;
3946 });
3947
3948 $booking_data_form.trigger('latepoint:initBookingDataForm');
3949
3950 }
3951
3952 function latepoint_init_payment_request_form($quick_order_form){
3953 $quick_order_form.find('select[name="payment_request[portion]"]').on('change', function(){
3954 if(jQuery(this).val() == 'custom'){
3955 $quick_order_form.find('.custom-charge-amount-wrapper').show();
3956 }else{
3957 $quick_order_form.find('.custom-charge-amount-wrapper').hide();
3958 }
3959 })
3960 }
3961
3962 function latepoint_show_all_order_items(){
3963 let $quick_order_form = jQuery('.quick-order-form-w');
3964 $quick_order_form.find('.order-items-info-w').removeClass('show-preselected-only');
3965 $quick_order_form.find('.holds-preselected-booking').removeClass('holds-preselected-booking');
3966 }
3967
3968 function latepoint_init_quick_order_form(){
3969 let $quick_order_form = jQuery('.quick-order-form-w');
3970 $quick_order_form.trigger('latepoint:initOrderEditForm');
3971
3972 $quick_order_form.on('change', '.os-affects-balance', function(){
3973 latepoint_reload_balance_and_payments();
3974 });
3975 $quick_order_form.on('keyup', '.os-affects-balance', function(event){
3976 if(event.keyCode == 13) {
3977 latepoint_reload_balance_and_payments();
3978 }
3979 });
3980
3981 latepoint_init_customer_inline_edit_form($quick_order_form.find('.customer-info-w'));
3982 $quick_order_form.find('.order-item-booking-data-form-wrapper').each(function(){
3983 latepoint_init_booking_data_form(jQuery(this));
3984 });
3985
3986 latepoint_lightbox_close();
3987 latepoint_remove_floating_popup();
3988 latepoint_init_input_masks($quick_order_form);
3989 latepoint_init_daterangepicker($quick_order_form.find('.os-date-range-picker'));
3990 latepoint_init_payment_request_form($quick_order_form);
3991
3992 // Transactions
3993
3994 $quick_order_form.on('click', '.transaction-refund-settings-button', function(){
3995 jQuery(this).closest('.quick-add-transaction-box-w').addClass('show-refund-settings');
3996 });
3997 $quick_order_form.on('click', '.transaction-refund-submit-button', function(){
3998 let $trigger_elem = jQuery(this);
3999 if(confirm(jQuery(this).data('os-prompt'))){
4000 $trigger_elem.addClass('os-loading');
4001 let route = $trigger_elem.data('route');
4002 let data = { action: 'latepoint_route_call', route_name: route, params: $trigger_elem.closest('.refund-settings-fields').find('input, textarea, select').serialize(), return_format: 'json' }
4003 jQuery.ajax({
4004 type : "post",
4005 dataType : "json",
4006 url : latepoint_timestamped_ajaxurl(),
4007 data : data,
4008 success: function(response){
4009 $trigger_elem.removeClass('os-loading');
4010 if(response.status === "success"){
4011 $trigger_elem.closest('.quick-add-transaction-box-w').replaceWith(response.message);
4012 latepoint_reload_balance_and_payments();
4013 }else{
4014 alert(response.message, 'error');
4015 }
4016 }
4017 });
4018 return false;
4019 }
4020 });
4021
4022 $quick_order_form.on('click', '.refund-settings-close', function(){
4023 jQuery(this).closest('.quick-add-transaction-box-w').removeClass('show-refund-settings');
4024 });
4025 $quick_order_form.on('change', '.refund-portion-selector', function(){
4026 if(jQuery(this).val() == 'full'){
4027 jQuery(this).closest('.refund-settings-fields').find('.custom-charge-amount-wrapper').hide();
4028 }else{
4029 jQuery(this).closest('.refund-settings-fields').find('.custom-charge-amount-wrapper').show();
4030 }
4031 });
4032
4033 // Log
4034
4035 $quick_order_form.find('.quick-order-form-view-log-btn').on('click', function(){
4036 var $trigger_elem = jQuery(this);
4037 $trigger_elem.addClass('os-loading');
4038 var route = $trigger_elem.data('route');
4039 var data = { action: 'latepoint_route_call', route_name: route, params: {order_id: $trigger_elem.data('order-id')}, return_format: 'json' }
4040 jQuery.ajax({
4041 type : "post",
4042 dataType : "json",
4043 url : latepoint_timestamped_ajaxurl(),
4044 data : data,
4045 success: function(response){
4046 $trigger_elem.removeClass('os-loading');
4047 if(response.status === "success"){
4048 latepoint_display_in_side_sub_panel(response.message);
4049 jQuery('body').addClass('has-side-sub-panel');
4050 }else{
4051 alert(response.message, 'error');
4052 }
4053 }
4054 });
4055 return false;
4056 });
4057
4058
4059 $quick_order_form.find('.new-order-item-variant-bundle').on('click', function(){
4060 $quick_order_form.find('.new-order-item-list-bundles-wrapper').toggleClass('is-open');
4061 $quick_order_form.find('.new-order-item-variant-selector-wrapper').toggleClass('is-open');
4062 return false;
4063 });
4064
4065
4066
4067
4068 $quick_order_form.find('.hidden-order-items-notice-link, .hidden-bundle-items-notice-link').on('click', function(e){
4069 latepoint_show_all_order_items();
4070 return false;
4071 });
4072
4073 $quick_order_form.find('.order-quick-edit-form').on('submit', function(e){
4074 if(jQuery(this).find('button[type="submit"]').hasClass('os-loading')) return false;
4075 e.preventDefault();
4076 latepoint_submit_quick_order_form();
4077 });
4078
4079 $quick_order_form.on("keydown", ":input:not(textarea):not(:submit)", function(event) {
4080 if (event.key == "Enter") {
4081 event.preventDefault();
4082 }
4083 });
4084
4085 $quick_order_form.find('.order-items-list').on('click', '.remove-order-item-btn', function(){
4086 latepoint_close_quick_availability_form();
4087 if(confirm(jQuery(this).data('os-prompt'))){
4088 if(jQuery(this).closest('.order-item-variant-bundle-booking-wrapper').length){
4089 // it's a bundle booking
4090 // need to figure out how to remove it when bundle
4091 jQuery(this).closest('.order-item-variant-bundle-booking').removeClass('is-booked').find('.scheduled-bundle-booking').html('');
4092 }else{
4093 jQuery(this).closest('.order-item').remove();
4094 jQuery(this).closest('.order-item-booking-data-form-wrapper').remove();
4095
4096 }
4097 latepoint_quick_order_items_changed();
4098 }
4099 return false;
4100 });
4101
4102 $quick_order_form.find('.new-order-item-variant-booking').on('click', function(){
4103 latepoint_fold_all_open_booking_data_forms();
4104 latepoint_build_new_booking_order_item();
4105 });
4106
4107 $quick_order_form.on('click', '.order-item-pill.order-item-pill-variant-booking', function(){
4108 jQuery(this).closest('.order-item-booking-data-form-wrapper').removeClass('is-folded').addClass('is-unfolded');
4109 return false;
4110 });
4111
4112 $quick_order_form.on('click', '.bundle-booking-item-pill', function(){
4113 jQuery(this).closest('.order-item-booking-data-form-wrapper').removeClass('is-folded').addClass('is-unfolded');
4114 return false;
4115 });
4116
4117 $quick_order_form.on('click', '.unscheduled-bundle-booking', function(){
4118 latepoint_build_booking_data_form_for_bundle(jQuery(this).closest('.order-item-variant-bundle-booking'));
4119 });
4120
4121
4122 $quick_order_form.find('.order-form-add-item-btn').on('click', function(){
4123 let $booking_data_forms = jQuery('.order-item-booking-data-form-wrapper');
4124 $booking_data_forms.each(function(){
4125 latepoint_fold_booking_data_form_in_order_quick_edit(jQuery(this));
4126 });
4127 if(jQuery(this).hasClass('is-cancelling')){
4128 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
4129 }else{
4130 if(jQuery('.new-order-item-variant-selector-wrapper').length){
4131 jQuery('.order-items-list').addClass('is-blurred');
4132 jQuery('.new-order-item-variant-selector-wrapper').addClass('is-open');
4133 jQuery(this).addClass('is-cancelling').find('span').text(jQuery(this).data('cancel-label'));
4134 }else{
4135 // no bundles exist, create booking form
4136 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
4137 latepoint_build_new_booking_order_item();
4138 }
4139 }
4140 return false;
4141 });
4142
4143
4144 $quick_order_form.on('click', '.order-item-variant-bundle .bundle-icon', function(){
4145 jQuery(this).closest('.order-item-variant-bundle').toggleClass('is-open');
4146 return false;
4147 });
4148
4149 $quick_order_form.find('.reload-price-breakdown').on('click', function(){
4150 latepoint_reload_price_breakdown();
4151 return false;
4152 });
4153
4154 $quick_order_form.on('click', '.trigger-remove-transaction-btn', function(){
4155 jQuery(this).closest('.quick-add-transaction-box-w').remove();
4156 return false;
4157 });
4158
4159
4160 $quick_order_form.trigger('latepoint:initQuickOrderForm');
4161 }
4162
4163 function latepoint_fold_all_open_booking_data_forms(){
4164 let $booking_data_forms = jQuery('.order-item-booking-data-form-wrapper');
4165 $booking_data_forms.each(function(){
4166 latepoint_fold_booking_data_form_in_order_quick_edit(jQuery(this));
4167 });
4168 }
4169
4170 function latepoint_init_customer_inline_edit_form($customer_form){
4171
4172 latepoint_init_input_masks($customer_form);
4173
4174 $customer_form.find('.customers-selector-search-input').on('keyup',function(){
4175 var $queryInput = jQuery(this);
4176 var query = $queryInput.val().toLowerCase();
4177 if(query == $queryInput.data('current-query')) return;
4178
4179 // Search
4180 $queryInput.closest('.customers-selector-search-w').addClass('os-loading');
4181 $queryInput.data('searching-query', query);
4182 setTimeout(function(){
4183 if(query != jQuery('.customers-selector-search-input').data('searching-query')) return;
4184 var data = { action: latepoint_helper.route_action, route_name: $queryInput.data('route'), params: {query: query}, return_format: 'json' }
4185 jQuery.ajax({
4186 type : "post",
4187 dataType : "json",
4188 url : latepoint_timestamped_ajaxurl(),
4189 data : data,
4190 success: function(response){
4191 if($queryInput.data('searching-query') != query) return;
4192 $queryInput.closest('.customers-selector-search-w').removeClass('os-loading');
4193 if(response.status === "success"){
4194 $queryInput.data('current-query', query);
4195 jQuery('.quick-order-form-w .customers-options-list').html(response.message);
4196 }else{
4197 // console.log(response.message);
4198 }
4199 }
4200 });
4201 }, 300, query, $queryInput);
4202 });
4203
4204 }
4205
4206
4207 function latepoint_load_quick_availability($trigger_elem, custom_agent_id = false, start_date = false, load_more_days = false, load_prev_days = false){
4208 $trigger_elem.addClass('os-loading');
4209
4210 let $booking_form = $trigger_elem.closest('.order-item-booking-data-form-wrapper');
4211 var route = $booking_form.find('.trigger-quick-availability').data('route');
4212 var $quick_order_form = jQuery('.quick-order-form-w');
4213
4214 if(custom_agent_id) $quick_order_form.find('.agent-selector').val(custom_agent_id);
4215 if(!$quick_order_form.find('.service-selector').val() || $quick_order_form.find('.service-selector').val() == '0'){
4216 $quick_order_form.find('.os-services-select-field-w .service-option:first').trigger('click');
4217 }
4218
4219 let form_data = new FormData($quick_order_form.find('form')[0]);
4220
4221
4222 form_data.set('trigger_form_booking_id', $booking_form.data('booking-id'));
4223 form_data.set('trigger_form_order_item_id', $booking_form.data('order-item-id'));
4224
4225 if(start_date) form_data.set('start_date', start_date);
4226 if(load_more_days || load_prev_days) form_data.set('show_days_only', true);
4227 if(load_prev_days) form_data.set('previous_days', true);
4228
4229 var data = {
4230 action: latepoint_helper.route_action,
4231 route_name: route,
4232 params: latepoint_formdata_to_url_encoded_string(form_data),
4233 return_format: 'json'
4234 }
4235
4236 jQuery.ajax({
4237 type : "post",
4238 dataType : "json",
4239 url : latepoint_timestamped_ajaxurl(),
4240 data : data,
4241 success: function(response){
4242 $trigger_elem.removeClass('os-loading');
4243 if(response.status === "success"){
4244 if(load_more_days){
4245 jQuery('.latepoint-side-panel-w .quick-availability-per-day-w').html(response.message);
4246 }else if(load_prev_days){
4247 jQuery('.latepoint-side-panel-w .quick-availability-per-day-w').html(response.message);
4248 jQuery('.latepoint-side-panel-w .os-availability-days').scrollTop(30);
4249 }else{
4250 latepoint_display_in_side_sub_panel(response.message);
4251 jQuery('.latepoint-side-panel-w .os-availability-days').scrollTop(30);
4252 jQuery('body').addClass('has-side-sub-panel');
4253 latepoint_init_quick_availability_form();
4254 }
4255 }else{
4256 alert(response.message, 'error');
4257 }
4258 }
4259 });
4260 }
4261
4262 function latepoint_create_field_base_name(order_item_id, booking_id){
4263 return 'order_items['+order_item_id+'][bookings]['+booking_id+']';
4264 }
4265
4266 function latepoint_close_quick_availability_form(){
4267 jQuery('.quick-availability-per-day-w').remove();
4268 jQuery('body').removeClass('has-side-sub-panel');
4269 }
4270
4271 function latepoint_init_quick_availability_form(){
4272 // TODO set booking ID
4273 let $quick_availability_wrapper = jQuery('.quick-availability-per-day-w');
4274
4275 let trigger_form_order_item_id = $quick_availability_wrapper.data('trigger-form-order-item-id');
4276 let trigger_form_booking_id = $quick_availability_wrapper.data('trigger-form-booking-id');
4277
4278 let field_base_name = latepoint_create_field_base_name(trigger_form_order_item_id, trigger_form_booking_id);
4279
4280 let $booking_data_form = jQuery('.quick-order-form-w .order-item-booking-data-form-wrapper[data-booking-id="'+trigger_form_booking_id+'"]');
4281
4282 var selected_start_date = $booking_data_form.find('input[name="'+field_base_name+'[start_date_formatted]"').val();
4283 var selected_start_time = $booking_data_form.find('input[name="'+field_base_name+'[start_time][formatted_value]"]').val();
4284 var selected_start_time_ampm = $booking_data_form.find('input[name="'+field_base_name+'[start_time][ampm]"]').val();
4285
4286
4287 var selected_start_time_minutes = latepoint_hours_and_minutes_to_minutes(selected_start_time, selected_start_time_ampm);
4288 $quick_availability_wrapper.find('.os-availability-days').find('.agent-timeslot[data-formatted-date="'+ selected_start_date +'"][data-minutes="' + selected_start_time_minutes + '"]').addClass('selected');
4289 $quick_availability_wrapper.on('click', '.load-more-quick-availability', function(){
4290 jQuery(this).addClass('os-loading');
4291 let booking_form_id = jQuery(this).closest('.quick-availability-per-day-w').data('trigger-form-booking-id');
4292 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
4293 latepoint_load_quick_availability($trigger_btn, false, jQuery(this).data('start-date'), true);
4294 return false;
4295 });
4296 $quick_availability_wrapper.on('click', '.load-prev-quick-availability', function(){
4297 jQuery(this).addClass('os-loading');
4298 let booking_form_id = jQuery(this).closest('.quick-availability-per-day-w').data('trigger-form-booking-id');
4299 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
4300 latepoint_load_quick_availability($trigger_btn, false, jQuery(this).data('start-date'), false, true);
4301 return false;
4302 });
4303 $quick_availability_wrapper.find('select[name="booking[agent_id]"]').on('change', function(){
4304 latepoint_load_quick_availability(jQuery('.trigger-quick-availability'), jQuery(this).val());
4305 });
4306 jQuery('.os-time-group label').on('click', function(){
4307 jQuery(this).closest('.os-time-group').find('.os-form-control').trigger('focus');
4308 });
4309 $quick_availability_wrapper.on('click', '.fill-booking-time', function(){
4310 jQuery('.os-availability-days .agent-timeslot.selected').removeClass('selected');
4311 jQuery(this).addClass('selected');
4312 var formatted_date = jQuery(this).data('formatted-date');
4313 var minutes = jQuery(this).data('minutes');
4314 $booking_data_form.find('input[name="'+field_base_name+'[start_date_formatted]"]').val(formatted_date);
4315 var start_minutes = minutes;
4316 var start_hours_and_minutes = latepoint_minutes_to_hours_and_minutes(start_minutes);
4317
4318 if(start_minutes >= 720){
4319 $booking_data_form.find('.quick-start-time-w .time-pm').trigger('click');
4320 }else{
4321 $booking_data_form.find('.quick-start-time-w .time-am').trigger('click');
4322 }
4323
4324 $booking_data_form.find('input[name="'+field_base_name+'[start_time][formatted_value]"]').val(start_hours_and_minutes);
4325 latepoint_set_booking_end_time($booking_data_form);
4326 $booking_data_form.find('.ws-period, .as-period').addClass('animate-filled-in');
4327 setTimeout(function(){
4328 $booking_data_form.find('.ws-period, .as-period').removeClass('animate-filled-in');
4329 }, 500)
4330 });
4331 }
4332
4333
4334 function latepoint_reload_after_order_save(){
4335 latepoint_reload_calendar_view();
4336
4337 jQuery('.os-widget').each(function(){
4338 latepoint_reload_widget(jQuery(this));
4339 });
4340 if(jQuery('table.os-reload-on-booking-update').length) latepoint_filter_table(jQuery('table.os-reload-on-booking-update'), jQuery('table.os-reload-on-booking-update'));
4341 latepoint_close_side_panel();
4342 }
4343
4344 /*
4345 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
4346 */
4347
4348 class LatepointStripeConnectAdmin {
4349
4350 // Init
4351 constructor(){
4352 this.ready();
4353 }
4354
4355 ready() {
4356 jQuery(document).ready(() => {
4357 jQuery('.stripe-connect-status-wrapper').on('click', '.payment-start-connecting', function(){
4358 let $link = jQuery(this);
4359 $link.addClass('os-loading');
4360 var data = {
4361 action: 'latepoint_route_call',
4362 route_name: $link.data('route-name'),
4363 params: { env: $link.data('env') },
4364 layout: 'none',
4365 return_format: 'json'
4366 }
4367 jQuery.ajax({
4368 type : "post",
4369 dataType : "json",
4370 url : latepoint_timestamped_ajaxurl(),
4371 data : data,
4372 success: (data) => {
4373 window.location.href = data.url;
4374 }
4375 });
4376 return false;
4377 });
4378
4379 if(jQuery('.stripe-connect-status-wrapper').length){
4380 jQuery('.stripe-connect-status-wrapper').each((index, elem) => {
4381 let $wrapper = jQuery(elem);
4382 var data = {
4383 action: 'latepoint_route_call',
4384 route_name: $wrapper.data('route-name'),
4385 params: { env: $wrapper.data('env') },
4386 layout: 'none',
4387 return_format: 'json'
4388 }
4389 jQuery.ajax({
4390 type : "post",
4391 dataType : "json",
4392 url : latepoint_timestamped_ajaxurl(),
4393 data : data,
4394 success: (data) => {
4395 this.reload_connect_status_wrapper($wrapper, data);
4396 }
4397 });
4398 })
4399 }
4400 });
4401 }
4402
4403
4404 reload_connect_status_wrapper($elem, data){
4405 if(data.status === 'success'){
4406 if($elem.hasClass('.stripe-connect-status-wrapper')){
4407 $elem.html(data.message);
4408 }else{
4409 $elem.closest('.stripe-connect-status-wrapper').html(data.message);
4410 }
4411 }else{
4412 alert(data.message);
4413 }
4414 }
4415
4416
4417 }
4418
4419
4420 window.latepointStripeConnectAdmin = new LatepointStripeConnectAdmin();
4421
4422 /*
4423 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
4424 */
4425
4426 // @codekit-prepend "bin/time.js";
4427 // @codekit-prepend "bin/lateselect.js";
4428 // @codekit-prepend "bin/latecheckbox.js";
4429 // @codekit-prepend "bin/actions.js";
4430 // @codekit-prepend "bin/notifications.js";
4431 // @codekit-prepend "bin/shared.js";
4432 // @codekit-prepend "bin/admin/updates.js";
4433 // @codekit-prepend "bin/admin/main.js";
4434 // @codekit-prepend "bin/admin/_agents.js";
4435 // @codekit-prepend "bin/admin/_customers.js";
4436 // @codekit-prepend "bin/admin/_chart.js";
4437 // @codekit-prepend "bin/admin/_calendar.js";
4438 // @codekit-prepend "bin/admin/_processes.js";
4439 // @codekit-prepend "bin/admin/_steps.js";
4440 // @codekit-prepend "bin/admin/_orders.js";
4441 // @codekit-prepend "bin/admin/_stripe_connect.js";
4442
4443
4444
4445 // DOCUMENT READY
4446 jQuery(document).ready(function( $ ) {
4447
4448
4449 // DASHBOARD
4450 latepoint_init_calendars();
4451 latepoint_init_circles_charts();
4452 latepoint_init_donut_charts();
4453 latepoint_init_daily_bookings_chart();
4454 latepoint_init_element_togglers();
4455 latepoint_init_daterangepicker(jQuery('.os-date-range-picker'));
4456 latepoint_init_monthly_view();
4457 latepoint_init_form_blocks();
4458 latepoint_init_reminders_form();
4459 latepoint_init_coupons_form();
4460 latepoint_init_copy_on_click_elements();
4461 latepoint_init_side_menu();
4462 latepoint_init_color_picker();
4463 latepoint_init_clickable_cells();
4464 latepoint_init_input_masks();
4465 latepoint_init_process_forms();
4466 latepoint_init_sticky_side_menu();
4467 latepoint_init_sortable_columns();
4468 latepoint_init_accordions();
4469 latepoint_init_default_form_fields_settings();
4470 latepoint_init_steps_settings();
4471 latepoint_init_booking_form_preview();
4472
4473 latepoint_init_version5_intro();
4474
4475 jQuery(document).on({
4476 mouseenter: function () {
4477 let $elem = jQuery(this);
4478 let offset = $elem.offset();
4479 jQuery('body > .late-tooltip').remove();
4480 let $popup = jQuery('<div/>').addClass('late-tooltip').text($elem.data('late-tooltip')).appendTo(jQuery('body'));
4481 $popup.css('top', offset.top - 2);
4482 $popup.css('left', offset.left + $elem.outerWidth() / 2);
4483 return false;
4484 },
4485 mouseleave: function () {
4486 jQuery('body > .late-tooltip').remove();
4487 }
4488 }, "[data-late-tooltip]");
4489
4490 jQuery('body').on('click', '.disabled-items-open-trigger', function(){
4491 jQuery('.disabled-items-wrapper').toggleClass('is-open');
4492 return false;
4493 });
4494
4495 jQuery('body').on('click', '.latepoint-side-panel-close', function(){
4496 jQuery('.side-sub-panel-wrapper').remove();
4497 return false;
4498 });
4499
4500 jQuery('#settings_list_of_phone_countries').on('change', function(){
4501 if(jQuery(this).val() == latepoint_helper.value_all){
4502 jQuery('.select-phone-countries-wrapper').hide();
4503 }else{
4504 jQuery('.select-phone-countries-wrapper').show();
4505 }
4506 });
4507
4508 jQuery('.os-select-all-toggler').on('change', function(){
4509 var $connection_wrappers = jQuery(this).closest('.white-box').find('.os-complex-connections-selector .connection');
4510 if(jQuery(this).is(':checked')){
4511 latepoint_complex_selector_select($connection_wrappers);
4512 }else{
4513 latepoint_complex_selector_deselect($connection_wrappers);
4514 }
4515 return false;
4516 });
4517
4518
4519 jQuery('.os-main-location-selector').on('change', function(){
4520 var route = jQuery(this).data('route');
4521 var params = 'id=' + jQuery(this).val();
4522 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4523 jQuery('.latepoint-content-w').addClass('os-loading');
4524 jQuery.ajax({
4525 type : "post",
4526 dataType : "json",
4527 url : latepoint_timestamped_ajaxurl(),
4528 data : data,
4529 success: function(data){
4530 location.reload();
4531 }
4532 });
4533 });
4534
4535 jQuery('.os-service-durations-w').on('click', '.os-remove-duration', function(){
4536 jQuery(this).closest('.duration-box').slideUp(300, function(){
4537 jQuery(this).remove();
4538 });
4539 return false;
4540 });
4541
4542
4543 jQuery('.menu-color-toggler').on('click', function(){
4544 jQuery('.latepoint-side-menu-w').toggleClass('dark');
4545 return false;
4546 });
4547
4548
4549 jQuery('.latepoint-mobile-top-menu-trigger').on('click', function(){
4550 jQuery(this).closest('.latepoint-all-wrapper').toggleClass('os-show-mobile-menu');
4551 if(jQuery(this).closest('.latepoint-all-wrapper').hasClass('os-show-mobile-menu')){
4552 jQuery('.latepoint-side-menu-w ul.side-menu > li.has-children > a').on('click', function(){
4553 jQuery(this).closest('li').toggleClass('menu-item-sub-open-mobile');
4554 return false;
4555 });
4556 }else{
4557 jQuery('.latepoint-side-menu-w ul.side-menu > li.has-children > a').off('click');
4558 }
4559 return false;
4560 });
4561
4562 jQuery('.latepoint-mobile-top-search-trigger-cancel').on('click', function(){
4563 jQuery(this).closest('.latepoint-all-wrapper').removeClass('os-show-mobile-search');
4564 return false;
4565 });
4566
4567 jQuery('.latepoint-mobile-top-search-trigger').on('click', function(){
4568 jQuery(this).closest('.latepoint-all-wrapper').toggleClass('os-show-mobile-search');
4569 if(jQuery(this).closest('.latepoint-all-wrapper').hasClass('os-show-mobile-search')){
4570 jQuery('.latepoint-top-search').trigger('focus');
4571 }
4572 return false;
4573 });
4574
4575
4576 jQuery('.latepoint-side-menu-w').on('click', '.top-user-info-toggler', function(){
4577 jQuery('.latepoint-user-info-dropdown').toggleClass('os-visible');
4578 return false;
4579 });
4580
4581 jQuery('.latepoint-content').on('click', '.mobile-calendar-actions-trigger', function(){
4582 jQuery(this).closest('.calendar-mobile-controls').toggleClass('os-show-actions');
4583 return false;
4584 });
4585
4586 jQuery('.latepoint-content').on('click', '.os-widget-header-actions-trigger', function(){
4587 jQuery(this).closest('.os-widget-header').toggleClass('os-show-actions');
4588 return false;
4589 });
4590
4591 jQuery('.latepoint-content').on('click', '.mobile-table-actions-trigger', function(){
4592 jQuery(this).closest('.os-pagination-w').toggleClass('os-show-actions');
4593 return false;
4594 });
4595
4596
4597
4598
4599
4600
4601 jQuery('.download-csv-with-filters').on('click', function(){
4602 var filter_params = jQuery(this).closest('.table-with-pagination-w').find('.os-table-filter').serialize();
4603 filter_params+= '&download=csv';
4604 jQuery(this).attr('href', this.href + '&' + filter_params);
4605 });
4606
4607 jQuery('select.pagination-page-select').on('change', function(){
4608 latepoint_filter_table(jQuery(this).closest('.table-with-pagination-w').find('table'), jQuery(this).closest('.pagination-page-select-w'), false);
4609 });
4610
4611 jQuery('select.os-table-filter').on('change', function(){
4612 latepoint_filter_table(jQuery(this).closest('table'), jQuery(this).closest('.os-form-group'));
4613 });
4614
4615 jQuery('input.os-table-filter').on('keyup', function(){
4616 latepoint_filter_table(jQuery(this).closest('table'), jQuery(this).closest('.os-form-group'));
4617 });
4618
4619
4620 jQuery('.customize-connection-btn').on('click', function(){
4621 jQuery(this).closest('.connection').toggleClass('show-customize-box');
4622 return false;
4623 });
4624
4625 jQuery('.connection-children-list').on('click', 'li', function(){
4626 if(jQuery(this).hasClass('active')){
4627 jQuery(this).removeClass('active');
4628 jQuery(this).find('input.connection-child-is-connected').val('no');
4629 }else{
4630 jQuery(this).addClass('active');
4631 jQuery(this).find('input.connection-child-is-connected').val('yes');
4632 }
4633 latepoint_count_active_connections(jQuery(this).closest('.connection'));
4634 return false;
4635 });
4636
4637 jQuery('.display-toggler-control').on('change', function(){
4638 let group = jQuery(this).data('toggler-group');
4639 let key = jQuery(this).val();
4640 jQuery('.display-toggler-target[data-toggler-group="' + group + '"]').hide();
4641 jQuery('.display-toggler-target[data-toggler-group="' + group + '"][data-toggler-key="'+ key +'"]').show();
4642 return false;
4643 });
4644
4645 jQuery('.add-item-category-trigger').on('click', function(){
4646 jQuery('.add-item-category-box').toggle();
4647 jQuery('.os-new-item-category-form-w').toggle();
4648 return false;
4649 });
4650
4651 jQuery('.latepoint-top-search').on('keyup', function(event){
4652 var $wrapper = jQuery(this).closest('.latepoint-top-search-w');
4653 $wrapper.addClass('os-loading');
4654 var query = jQuery(this).val();
4655 if(event.keyCode == 27){
4656 $wrapper.removeClass('typing');
4657 jQuery('.latepoint-top-search-results-w').html('');
4658 jQuery(this).val('');
4659 $wrapper.removeClass('os-loading');
4660 return;
4661 }
4662 if(query == ''){
4663 $wrapper.removeClass('typing');
4664 jQuery('.latepoint-top-search-results-w').html('');
4665 $wrapper.removeClass('os-loading');
4666 return;
4667 }
4668 var route = jQuery(this).data('route');
4669 var params = 'query=' + query;
4670 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4671 $wrapper.addClass('typing');
4672 jQuery.ajax({
4673 type : "post",
4674 dataType : "json",
4675 url : latepoint_timestamped_ajaxurl(),
4676 data : data,
4677 success: function(data){
4678 if(!$wrapper.hasClass('typing')) return;
4679 $wrapper.removeClass('os-loading');
4680 if(data.status === "success"){
4681 jQuery('.latepoint-top-search-results-w').html(data.message);
4682 }else{
4683 // console.log(data.message);
4684 }
4685 }
4686 });
4687 });
4688
4689
4690 jQuery('.appointment-status-selector').on('click', function(e){
4691 e.stopPropagation();
4692 });
4693
4694 jQuery('.latepoint-show-license-details').on('click', function(e){
4695 jQuery(this).closest('.active-license-info').find('.license-info-w').slideToggle(200);
4696 return false;
4697 });
4698
4699 jQuery('.aba-button-w').on('click', function(e){
4700 e.stopPropagation();
4701 var confirm_message = (jQuery(this).hasClass('aba-approve')) ? latepoint_helper.approve_confirm : latepoint_helper.reject_confirm;
4702 if(confirm(confirm_message)){
4703 var $box = jQuery(this).closest('.appointment-box-large');
4704 $box.find('.appointment-status-selector select').val(jQuery(this).data('status')).trigger('change');
4705 }
4706 return false;
4707 });
4708
4709
4710
4711 jQuery('.appointment-status-selector select').on('change', function(e){
4712 var $wrapper = jQuery(this).closest('.appointment-status-selector');
4713 var route = $wrapper.data('route');
4714 var nonce = $wrapper.data('wp-nonce');
4715 var booking_id = $wrapper.data('booking-id');
4716 var status = jQuery(this).val();
4717 jQuery(this).closest('.appointment-box-large').attr('class', 'appointment-box-large status-' + status);
4718 var params = 'id=' + booking_id + '&status=' + status + '&_wpnonce=' + nonce;
4719 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4720 jQuery.ajax({
4721 type : "post",
4722 dataType : "json",
4723 url : latepoint_timestamped_ajaxurl(),
4724 data : data,
4725 success: function(data){
4726 if(data.status === "success"){
4727 latepoint_add_notification(data.message);
4728 }else{
4729 latepoint_add_notification(data.message, 'error');
4730 // console.log(data.message);
4731 }
4732 }
4733 });
4734 });
4735
4736 jQuery('body').on('click', '.open-template-variables-panel', function(){
4737 jQuery('.latepoint-template-variables').toggleClass('is-visible');
4738 return false;
4739 });
4740
4741 jQuery('body').on('click', '.close-template-variables-panel', function(){
4742 jQuery('.latepoint-template-variables').removeClass('is-visible');
4743 return false;
4744 });
4745
4746 jQuery('body').on('click', '.open-layout-template-variables-panel', function(){
4747 jQuery('.latepoint-layout-template-variables').toggleClass('is-visible');
4748 return false;
4749 });
4750
4751 jQuery('body').on('click', '.close-layout-template-variables-panel', function(){
4752 jQuery('.latepoint-layout-template-variables').removeClass('is-visible');
4753 return false;
4754 });
4755
4756 jQuery('body').on('click', '.os-notifications .os-notification-close', function(){
4757 jQuery(this).closest('.item').remove();
4758 return false;
4759 });
4760
4761
4762 jQuery('body').on('keyup', '.os-form-group .os-form-control', function(){
4763 if(jQuery(this).val()){
4764 jQuery(this).closest('.os-form-group').addClass('has-value');
4765 }else{
4766 jQuery(this).closest('.os-form-group').removeClass('has-value');
4767 }
4768 });
4769
4770
4771
4772 jQuery('.os-wizard-setup-w, .latepoint-settings-w, .custom-schedule-wrapper').on('click', '.ws-head', function(){
4773 var $schedule_wrapper = jQuery(this).closest('.weekday-schedule-w');
4774 $schedule_wrapper.toggleClass('is-editing').removeClass('day-off');
4775 $schedule_wrapper.find('.os-toggler').removeClass('off');
4776 $schedule_wrapper.find('input.is-active').val(1);
4777 });
4778
4779
4780 jQuery('.latepoint').on('click', '.wizard-add-edit-item-trigger', function(e){
4781 jQuery(this).addClass('os-loading');
4782 var add_item_route_name = jQuery(this).data('route');
4783 var item_info = { };
4784 if(jQuery(this).data('id')){
4785 item_info.id = jQuery(this).data('id');
4786 }
4787 var data = { action: latepoint_helper.route_action, route_name: add_item_route_name, params: item_info, layout: 'none', return_format: 'json' };
4788 jQuery.ajax({
4789 type : "post",
4790 dataType : "json",
4791 url : latepoint_timestamped_ajaxurl(),
4792 data : data,
4793 success: function(data){
4794 jQuery('.wizard-add-edit-item-trigger.os-loading').removeClass('os-loading');
4795 if(data.status === "success"){
4796 jQuery('.os-wizard-step-content-i').html(data.message);
4797 jQuery('.os-wizard-setup-w').addClass('is-sub-editing');
4798 jQuery('.os-wizard-footer').hide();
4799 latepoint_init_wizard_content();
4800 }else{
4801 // console.log(data.message);
4802 }
4803 }
4804 });
4805 });
4806
4807
4808
4809
4810 // WIZARD NEXT BUTTON CLICK LOGIC
4811 jQuery('.latepoint').on('click', '.latepoint-pro-link-subtle', function(){
4812 jQuery('.pro-premium-features-list-wrapper').slideDown(200);
4813 jQuery('.pro-feature-banner').addClass('is-open');
4814 jQuery(this).hide();
4815 return false;
4816 });
4817
4818 jQuery('.latepoint').on('click', '.os-wizard-trigger-next-btn', function(){
4819 var $next_btn = jQuery(this);
4820 $next_btn.addClass('os-loading');
4821 var current_step_code = jQuery('#wizard_current_step_code').val();
4822 var params = 'current_step_code='+current_step_code;
4823
4824 // work periods step
4825 if(jQuery('.os-wizard-setup-w form.weekday-schedules-w').length){
4826 params+= '&'+ jQuery('.os-wizard-setup-w form.weekday-schedules-w .weekday-schedule-w:not(.day-off) input').serialize();
4827 }
4828 // agent/notifications step
4829 if(jQuery('.os-wizard-default-agent-form').length){
4830 params+= '&'+ jQuery('.os-wizard-default-agent-form input').serialize();
4831
4832 var $form = $('.os-wizard-default-agent-form');
4833 var form_data = new FormData($form[0]);
4834 form_data.set('current_step_code', current_step_code);
4835
4836 if (('intlTelInputGlobals' in window) && ('intlTelInputUtils' in window)) {
4837 // Get e164 formatted number from phone fields when form is submitted
4838 $form.find('input.os-mask-phone').each(function () {
4839 let telInstance = window.intlTelInputGlobals.getInstance(this);
4840 if(telInstance){
4841 const phoneInputName = this.getAttribute('name');
4842 const phoneInputValue = window.intlTelInputGlobals.getInstance(this).getNumber(window.intlTelInputUtils.numberFormat.E164);
4843 form_data.set(phoneInputName, phoneInputValue);
4844 }
4845 });
4846 }
4847 params = latepoint_formdata_to_url_encoded_string(form_data);
4848 }
4849
4850 var data = {
4851 action: latepoint_helper.route_action,
4852 route_name: jQuery(this).data('route-name'),
4853 params: params,
4854 layout: 'none',
4855 return_format: 'json'};
4856 jQuery.ajax({
4857 type : "post",
4858 dataType : "json",
4859 url : latepoint_timestamped_ajaxurl(),
4860 data : data,
4861 success: function(data){
4862 $next_btn.removeClass('os-loading');
4863 if(data.status === "success"){
4864 jQuery('#wizard_current_step_code').val(data.step_code);
4865 jQuery('.os-wizard-setup-w').attr('class', 'os-wizard-setup-w step-' + data.step_code);
4866 jQuery('.os-wizard-step-content').html(data.message);
4867 latepoint_init_wizard_content();
4868 if(data.show_prev_btn){
4869 jQuery('.os-wizard-prev-btn').show();
4870 }else{
4871 jQuery('.os-wizard-prev-btn').hide();
4872 }
4873 if(data.show_next_btn){
4874 jQuery('.os-wizard-next-btn').show();
4875 }else{
4876 jQuery('.os-wizard-next-btn').hide();
4877 }
4878 if(!data.show_next_btn && !data.show_prev_btn){
4879 jQuery('.os-wizard-footer').hide();
4880 }else{
4881 jQuery('.os-wizard-footer').show();
4882 }
4883 }
4884 }
4885 });
4886 return false;
4887 });
4888
4889 // WIZARD PREV BUTTON CLICK LOGIC
4890 jQuery('.latepoint').on('click', '.os-wizard-trigger-prev-btn', function(){
4891 var $prev_btn = jQuery(this);
4892 $prev_btn.addClass('os-loading');
4893 var current_step_code = jQuery('#wizard_current_step_code').val();
4894 var params = 'current_step_code='+current_step_code;
4895 var data = { action: latepoint_helper.route_action, route_name: jQuery(this).data('route-name'), params: params, layout: 'none', return_format: 'json'};
4896 jQuery.ajax({
4897 type : "post",
4898 dataType : "json",
4899 url : latepoint_timestamped_ajaxurl(),
4900 data : data,
4901 success: function(data){
4902 $prev_btn.removeClass('os-loading');
4903 if(data.status === "success"){
4904 jQuery('#wizard_current_step_code').val(data.step_code);
4905 jQuery('.os-wizard-setup-w').attr('class', 'os-wizard-setup-w step-' + data.step_code);
4906 jQuery('.os-wizard-step-content').html(data.message);
4907 latepoint_init_wizard_content();
4908 if(data.show_prev_btn){
4909 jQuery('.os-wizard-prev-btn').show();
4910 }else{
4911 jQuery('.os-wizard-prev-btn').hide();
4912 }
4913 if(data.show_next_btn){
4914 jQuery('.os-wizard-next-btn').show();
4915 }else{
4916 jQuery('.os-wizard-next-btn').hide();
4917 }
4918 if(!data.show_next_btn && !data.show_prev_btn){
4919 jQuery('.os-wizard-footer').hide();
4920 }else{
4921 jQuery('.os-wizard-footer').show();
4922 }
4923 }
4924 }
4925 });
4926 return false;
4927 });
4928
4929 jQuery('.latepoint-content-w').on('change', '.os-widget .os-trigger-reload-widget', function(){
4930 latepoint_reload_widget(jQuery(this).closest('.os-widget'));
4931 });
4932
4933 jQuery('.latepoint-content-w').on('click', '.os-widget .timeline-type-toggle .timeline-type-option', function(){
4934 jQuery(this).closest('.timeline-type-toggle').find('.timeline-type-option.active').removeClass('active');
4935 jQuery(this).addClass('active');
4936 jQuery('.timeline-and-availability-contents').removeClass('shows-appointments shows-availability').addClass('shows-' + jQuery(this).data('value'));
4937 jQuery('#' + jQuery(this).closest('.timeline-type-toggle').data('value-holder-id')).val(jQuery(this).data('value'));
4938 });
4939
4940
4941 dragula([].slice.apply(document.querySelectorAll('.os-categories-ordering-w .os-category-children')), {
4942 moves: function (el, container, handle) {
4943 return (handle.classList.contains('os-category-drag') || handle.classList.contains('os-category-item-drag'));
4944 },
4945 }).on('drop', function(el){
4946 var $categories_wrapper = jQuery('.os-categories-ordering-w');
4947 var category_datas = [];
4948 var item_datas = [];
4949
4950 $categories_wrapper.find('.os-category-parent-w').each(function(index){
4951 var order_number = jQuery(this).index() + 1;
4952 var parent_id = jQuery(this).parent().closest('.os-category-parent-w').data('id') || 0;
4953 category_datas.push({id: jQuery(this).data('id'), order_number: order_number, parent_id: parent_id});
4954 });
4955 $categories_wrapper.find('.item-in-category-w').each(function(index){
4956 var item_order_number = jQuery(this).index() + 1;
4957 var category_id = jQuery(this).closest('.os-category-parent-w').data('id') || 0;
4958 item_datas.push({id: jQuery(this).data('id'), order_number: item_order_number, category_id: category_id});
4959 });
4960 latepoint_recalculate_items_count_in_category();
4961 var data = { action: latepoint_helper.route_action, route_name: $categories_wrapper.data('category-order-update-route'), params: {category_datas: category_datas, item_datas: item_datas}, return_format: 'json' }
4962 $categories_wrapper.addClass('os-loading');
4963 jQuery.ajax({
4964 type : "post",
4965 dataType : "json",
4966 url : latepoint_timestamped_ajaxurl(),
4967 data : data,
4968 success: function(response){
4969 $categories_wrapper.removeClass('os-loading');
4970 if(response.status === "success"){
4971 // latepoint_add_notification(response.message);
4972 }else{
4973 alert(response.message);
4974 }
4975 }
4976 });
4977 });
4978
4979
4980 // Universal re-ordering dragging for form blocks
4981 dragula([jQuery('.os-draggable-form-blocks')[0]], {
4982 moves: function (el, container, handle) {
4983 return handle.classList.contains('os-form-block-drag');
4984 },
4985 }).on('drop', function(el){
4986 var blocks_order_data = {};
4987 var $draggable_form_blocks_wrapper = jQuery('.os-draggable-form-blocks');
4988 $draggable_form_blocks_wrapper.find('.os-form-block').each(function(index){
4989 var new_order_number = jQuery(this).index() + 1;
4990 var $block_model_id = jQuery(this).find('.os-form-block-id');
4991 if($block_model_id.length && $block_model_id.val()) blocks_order_data[$block_model_id.val()] = new_order_number;
4992 });
4993 var data = { action: latepoint_helper.route_action,
4994 route_name: $draggable_form_blocks_wrapper.data('order-update-route'),
4995 params: {ordered_fields: blocks_order_data,
4996 fields_for: $draggable_form_blocks_wrapper.data('fields-for')},
4997 return_format: 'json' }
4998 $draggable_form_blocks_wrapper.addClass('os-loading');
4999 jQuery.ajax({
5000 type : "post",
5001 dataType : "json",
5002 url : latepoint_timestamped_ajaxurl(),
5003 data : data,
5004 success: function(response){
5005 $draggable_form_blocks_wrapper.removeClass('os-loading');
5006 }
5007 });
5008 });
5009
5010
5011 jQuery('body.latepoint-admin').on('click', '.os-category-edit-btn, .os-category-edit-cancel-btn, .os-category-w .os-category-name', function(){
5012 jQuery(this).closest('.os-category-w').toggleClass('editing');
5013 return false;
5014 });
5015
5016 jQuery('body.latepoint-admin').on('click', '.step-edit-btn, .step-edit-cancel-btn, .step-w .step-head', function(){
5017 jQuery(this).closest('.step-w').toggleClass('editing');
5018 return false;
5019 });
5020
5021 jQuery('body.latepoint-admin').on('click', '.agent-info-change-agent-btn', function(){
5022 jQuery(this).closest('.agent-info-w').removeClass('selected').addClass('selecting');
5023 return false;
5024 });
5025
5026 jQuery('body.latepoint-admin').on('click', '.agent-info-change-agent-btn', function(){
5027 jQuery(this).closest('.agent-info-w').removeClass('selected').addClass('selecting');
5028 return false;
5029 });
5030
5031
5032 jQuery('body.latepoint-admin').on('click', '.customer-info-create-btn', function(){
5033 jQuery(this).closest('.customer-info-w').removeClass('selecting').addClass('selected');
5034 return false;
5035 });
5036
5037 jQuery('body.latepoint-admin').on('click', '.customer-info-load-btn', function(){
5038 jQuery(this).closest('.customer-info-w').removeClass('selected').addClass('selecting').find('.customers-selector-search-input').trigger('focus');
5039 return false;
5040 });
5041
5042 jQuery('body.latepoint-admin').on('click', '.customers-selector-cancel', function(){
5043 jQuery(this).closest('.customer-info-w').removeClass('selecting').addClass('selected ');
5044 jQuery('.customers-options-list .customer-option').show();
5045 jQuery('.customers-selector-search-input').val('');
5046 return false;
5047 });
5048
5049 // CUSTOMER SELECTOR
5050
5051 // SERVICES SELECTOR
5052 jQuery('body.latepoint-admin').on('click', '.service-option-selected', function(){
5053 var $select = jQuery(this).closest('.os-services-select-field-w');
5054 if($select.hasClass('active')){
5055 $select.removeClass('active');
5056 }else{
5057 $select.addClass('active').find('input').trigger('focus');
5058 }
5059 return false;
5060 });
5061
5062
5063 jQuery('body.latepoint-admin').on('keyup', '.service-options-filter-input', function(){
5064 var $list = jQuery(this).closest('.services-options-list');
5065 var text = jQuery(this).val().toLowerCase();
5066 $list.find('.service-option').hide();
5067
5068 // Search
5069 $list.find('.service-option').each(function(){
5070
5071 if(jQuery(this).text().toLowerCase().indexOf(""+text+"") != -1 ){
5072 jQuery(this).show();
5073 }
5074 });
5075 return false;
5076 });
5077
5078
5079 jQuery('.calendar-week-agent-w').on('click', '.calendar-load-target-date', function(event){
5080 jQuery(this).addClass('os-loading');
5081 latepoint_reload_week_view_calendar(jQuery(this).data('target-date'));
5082 return false;
5083 });
5084
5085 jQuery('.calendar-week-agent-w').on('change', '.cc-availability-toggler #overlay_service_availability', function(event){
5086 if(jQuery(this).val() == 'on'){
5087 jQuery('.calendar-week-agent-w .cc-service-selector').show();
5088 }else{
5089 jQuery('.calendar-week-agent-w .cc-service-selector').hide();
5090 }
5091 latepoint_reload_week_view_calendar();
5092 });
5093
5094
5095 jQuery('.calendar-week-agent-w').on('change', '.trigger-weekly-calendar-reload', function(event){
5096 latepoint_reload_week_view_calendar();
5097 return false;
5098 });
5099
5100 jQuery('.latepoint-admin').on('click', '.os-complex-connections-selector .selector-trigger', function(e){
5101 var $connection_wrapper = jQuery(this).closest('.connection');
5102 if($connection_wrapper.hasClass('active')){
5103 latepoint_complex_selector_deselect($connection_wrapper);
5104 jQuery(this).closest('.white-box').find('.os-select-all-toggler').prop('checked', false);
5105 }else{
5106 latepoint_complex_selector_select($connection_wrapper);
5107 }
5108 return false;
5109 });
5110
5111 jQuery('.latepoint-admin').on('click', '.os-complex-connections-selector .item-quantity-selector', function(e){
5112 let val = parseInt(jQuery(this).closest('.item-quantity-selector-w').find('.item-quantity-selector-input').val());
5113 if(jQuery(this).data('sign') == 'plus'){
5114 val = val + 1;
5115 }else{
5116 val = val - 1;
5117 }
5118 val = (val > 0) ? val : 0;
5119 jQuery(this).closest('.item-quantity-selector-w').find('.item-quantity-selector-input').val(val).trigger('change');
5120 return false;
5121 });
5122
5123 jQuery('.latepoint-admin').on('change', '.os-complex-connections-selector .item-quantity-selector-input', function(e){
5124 let $this = jQuery(this);
5125 let $connection_wrapper = jQuery(this).closest('.connection');
5126 if($this.val() > 0){
5127 latepoint_complex_selector_select($connection_wrapper, $this.val());
5128 }else{
5129 latepoint_complex_selector_deselect($connection_wrapper);
5130 }
5131 return false;
5132 });
5133
5134 jQuery('.latepoint-admin').on('click', '.os-agents-selector .agent', function(){
5135 if(jQuery(this).hasClass('active')){
5136 jQuery(this).removeClass('active');
5137 jQuery(this).find('.connection-child-is-connected').val('no');
5138 }else{
5139 jQuery(this).addClass('active');
5140 jQuery(this).find('.connection-child-is-connected').val('yes');
5141 }
5142 return false;
5143 });
5144
5145 jQuery('.latepoint-admin').on('click', '.os-services-selector .service', function(){
5146 if(jQuery(this).hasClass('active')){
5147 jQuery(this).removeClass('active');
5148 jQuery(this).find('.connection-child-is-connected').val('no');
5149 }else{
5150 jQuery(this).addClass('active');
5151 jQuery(this).find('.connection-child-is-connected').val('yes');
5152 }
5153 return false;
5154 });
5155
5156 jQuery('.latepoint-admin').on( 'click', '.os-form-toggler-group', function( event ){
5157 jQuery(this).find('.os-toggler').trigger('click');
5158 return false;
5159 });
5160
5161 jQuery('.latepoint-admin').on( 'click', '.os-toggler', function( event ){
5162 let $toggler = jQuery(this);
5163 if($toggler.data('confirm')){
5164 if(!confirm($toggler.data('confirm'))) return false;
5165 }
5166 if($toggler.hasClass('on')){
5167 $toggler.removeClass('on').addClass('off');
5168 }else{
5169 $toggler.removeClass('off').addClass('on');
5170 }
5171 if($toggler.data('for')){
5172 if($toggler.hasClass('os-toggler-radio')){
5173 // radio
5174 // uncheck all radio buttons with the same name
5175 let $radio = jQuery('#' + $toggler.data('for'));
5176 jQuery('input[type="radio"][name="'+ $radio.prop('name') + '"]:checked').each(function(index){
5177 let toggle_content_id = jQuery(this).prop('checked', false).closest('.os-toggler-w').find('.os-toggler.on').removeClass('on').addClass('off').data('controlled-toggle-id');
5178 jQuery('#'+ toggle_content_id).hide();
5179 });
5180 $radio.prop('checked', !$toggler.hasClass('off'));
5181 }else{
5182 var $hiddenInput = jQuery('input[type="hidden"]#' + $toggler.data('for'));
5183 if($hiddenInput.length){
5184 // hidden input
5185 if($toggler.data('is-string-value')){
5186 $hiddenInput.val($toggler.hasClass('off') ? 'off' : 'on').trigger('change');
5187 }else{
5188 $hiddenInput.val($toggler.hasClass('off') ? 0 : 1).trigger('change');
5189 }
5190
5191 if($toggler.data('os-instant-update')){
5192 let data = new FormData();
5193
5194 let params = $hiddenInput.serialize();
5195 if($toggler.data('nonce')) params+= '&_wpnonce='+$toggler.data('nonce');
5196 data.append('params', params);
5197 data.append('action', latepoint_helper.route_action);
5198 data.append('route_name', $toggler.data('os-instant-update'));
5199 data.append('return_format', 'json');
5200
5201 jQuery.ajax({
5202 type: "post",
5203 dataType: "json",
5204 processData: false,
5205 contentType: false,
5206 url: latepoint_timestamped_ajaxurl(),
5207 data: data,
5208 success: function (response) {
5209
5210 }
5211 });
5212 }
5213 }else{
5214 // checkbox
5215 jQuery('#' + $toggler.data('for')).prop('checked', !$toggler.hasClass('off'));
5216 }
5217 }
5218 }
5219 if($toggler.data('controlled-toggle-id')){
5220 if($toggler.hasClass('off')){
5221 jQuery('#' + $toggler.data('controlled-toggle-id')).hide();
5222 }else{
5223 jQuery('#' + $toggler.data('controlled-toggle-id')).show();
5224 }
5225 }
5226 $toggler.trigger('ostoggler:toggle');
5227 return false;
5228 });
5229
5230
5231
5232 // UPLOAD/REMOVE IMAGE LINK LOGIC
5233 jQuery('.latepoint-admin').on( 'click', '.os-image-selector-trigger', function( event ){
5234 var frame;
5235
5236 event.preventDefault();
5237
5238 var $image_uploader_trigger = jQuery(this);
5239 var $image_selector_w = jQuery(this).closest('.os-image-selector-w');
5240 var $image_container = $image_selector_w.find('.os-image-container');
5241 var $image_id_holder = $image_selector_w.find('.os-image-id-holder');
5242
5243 let is_avatar = $image_selector_w.hasClass('is-avatar');
5244
5245 var image_exists = is_avatar ? $image_container.find('.image-self').length : $image_container.find('img').length;
5246
5247 if(image_exists){
5248 $image_id_holder.val('');
5249 $image_selector_w.removeClass('has-image');
5250 $image_container.html('');
5251 $image_uploader_trigger.find('.os-text-holder').text($image_uploader_trigger.data('label-set-str'));
5252 }else{
5253 // If the media frame already exists, reopen it.
5254 if ( frame ) {
5255 frame.open();
5256 return false;
5257 }
5258
5259 // Create a new media frame
5260 frame = wp.media({
5261 title: 'Select or Upload Media',
5262 button: { text: 'Use this media' },
5263 multiple: false
5264 });
5265
5266 frame.on( 'select', function() {
5267 var attachment = frame.state().get('selection').first().toJSON();
5268 if(is_avatar){
5269 $image_container.html( '<div class="image-self" style="background-image: url('+attachment.url+')"></div>' );
5270 }else{
5271 $image_container.html( '<img src="'+attachment.url+'" alt=""/>' );
5272 }
5273 $image_id_holder.val( attachment.id );
5274 $image_selector_w.addClass('has-image');
5275 $image_uploader_trigger.find('.os-text-holder').text($image_uploader_trigger.data('label-remove-str'));
5276 });
5277
5278 frame.open();
5279 }
5280
5281 return false;
5282 });
5283
5284
5285
5286 jQuery('body').on('click', '.latepoint-lightbox-close', function(){
5287 latepoint_lightbox_close();
5288 return false;
5289 });
5290
5291
5292 jQuery('body').on('click', '.latepoint-side-panel-close-trigger', function(){
5293 latepoint_close_side_panel();
5294 return false;
5295 });
5296 jQuery('body').on('click', '.latepoint-side-sub-panel-close-trigger', function(){
5297 jQuery(this).closest('.side-sub-panel-wrapper').remove();
5298 return false;
5299 });
5300
5301
5302
5303 jQuery('body.latepoint-admin').on('click', '.time-ampm-select', function(){
5304 let $form = jQuery(this).closest('.order-item-booking-data-form-wrapper');
5305 jQuery(this).closest('.time-ampm-w').find('.active').removeClass('active');
5306 jQuery(this).addClass('active');
5307 var ampm_value = jQuery(this).data('ampm-value');
5308 jQuery(this).closest('.os-time-group').find('.ampm-value-hidden-holder').val(ampm_value);
5309 if(jQuery(this).closest('.quick-start-time-w').length){
5310 // if called from quick edit form - we need to make sure it accurately changes time to next day if end time is earlier than start time
5311 latepoint_set_booking_end_time($form);
5312 latepoint_is_next_day($form);
5313 }
5314 if(jQuery(this).closest('.quick-end-time-w').length){
5315 latepoint_is_next_day($form);
5316 }
5317 return false;
5318 });
5319
5320
5321 jQuery('body.latepoint-admin').on('click', '.latepoint-lightbox-shadow', function(){
5322 latepoint_lightbox_close();
5323 return false;
5324 });
5325
5326 jQuery('body.latepoint-admin').on('click', '.latepoint-side-panel-shadow', function(){
5327 jQuery('.latepoint-side-panel-w').remove();
5328 return false;
5329 });
5330
5331 // SCHEDULE
5332
5333 jQuery('body.latepoint-admin').on('click', '.ws-period-remove', function(e){
5334 jQuery(this).closest('.ws-period').remove();
5335 return false;
5336 });
5337
5338
5339 jQuery('.latepoint-admin').on( 'click', '.weekday-schedule-w .os-toggler', function( event ){
5340 if(jQuery(this).hasClass('off')){
5341 jQuery(this).closest('.weekday-schedule-w').addClass('day-off').removeClass('is-editing').find('input.is-active').val(0);
5342 }else{
5343 jQuery(this).closest('.weekday-schedule-w').removeClass('day-off').addClass('is-editing').find('input.is-active').val(1);
5344 }
5345 return false;
5346 });
5347
5348
5349
5350 });