PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.91
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.91
5.6.7 5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / 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
5374 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 (('lp_intlTelInputGlobals' in window) && ('lp_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.lp_intlTelInputGlobals.getInstance(this);
593 if(telInstance){
594 const phoneInputName = this.getAttribute('name');
595 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_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.lp_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 (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
798 $form.find('input.os-mask-phone').each(function () {
799 const phoneInputName = this.getAttribute('name');
800 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_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.lp_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.lp_intlTelInputGlobals.defaults.preferredCountries;
924
925 // remove country name in english and only use names in country language
926 var countryData = window.lp_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.lp_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_calendar_custom_period_created(){
2618 latepoint_reload_calendar_view();
2619 latepoint_lightbox_close();
2620 }
2621
2622 function latepoint_init_calendar_quick_actions(){
2623 latepoint_init_input_masks(jQuery('.quick-calendar-action-settings'));
2624
2625 jQuery('.quick-calendar-action-day-off').on('click', function(){
2626 jQuery('.quick-calendar-actions-wrapper').addClass('showing-settings');
2627 jQuery('.quick-calendar-actions').hide();
2628 jQuery('.quick-calendar-action-settings').removeClass('setting-slot-off').addClass('setting-day-off');
2629 jQuery('.quick-calendar-action-settings input[name="blocked_period_settings[full_day_off]"]').val('yes');
2630 jQuery('.quick-calendar-action-toggle.selected').removeClass('selected');
2631 jQuery('.quick-calendar-action-toggle[data-period-type="full"]').addClass('selected');
2632
2633 return false;
2634 });
2635 jQuery('.quick-calendar-action-slot-off').on('click', function(){
2636 jQuery('.quick-calendar-actions-wrapper').addClass('showing-settings');
2637 jQuery('.quick-calendar-actions').hide();
2638 jQuery('.quick-calendar-action-settings').removeClass('setting-day-off').addClass('setting-slot-off');
2639 jQuery('.quick-calendar-action-settings input[name="blocked_period_settings[full_day_off]"]').val('no');
2640 jQuery('.quick-calendar-action-toggle.selected').removeClass('selected');
2641 jQuery('.quick-calendar-action-toggle[data-period-type="partial"]').addClass('selected');
2642 return false;
2643 });
2644
2645 jQuery('.quick-calendar-action-toggle').on('click', function(){
2646 if(jQuery(this).data('period-type') === 'full'){
2647 jQuery('.quick-calendar-action-day-off').trigger('click');
2648 }else{
2649 jQuery('.quick-calendar-action-slot-off').trigger('click');
2650 }
2651 return false;
2652 });
2653 }
2654
2655 function latepoint_init_calendars(){
2656 latepoint_check_horizontal_calendar_scroll();
2657 jQuery('.os-calendar-settings-extra .latecheckbox').lateCheckbox();
2658
2659
2660 jQuery('.calendar-settings-toggler').on('click', function(){
2661 jQuery('.os-calendar-settings-form').toggleClass('show-extra-settings');
2662 return false;
2663 });
2664
2665 jQuery('.os-calendar-settings-form').on('change', 'select[name="calendar_settings[view]"]', function(){
2666 jQuery(this).closest('.calendar-wrapper').attr('data-view', jQuery(this).val());
2667 });
2668
2669 jQuery('.os-calendar-settings-form').on('change', 'select, input, .latecheckbox ', function(){
2670 latepoint_reload_calendar_view();
2671 });
2672
2673
2674 jQuery('.calendar-view-wrapper').on('click', '.weekly-calendar-agent-selector', function(){
2675 jQuery('.weekly-calendar-agent-selector.selected').removeClass('selected');
2676 jQuery(this).addClass('selected');
2677 jQuery('.os-calendar-settings-form input[name="calendar_settings[selected_agent_id]"]').val(jQuery(this).data('agent-id'));
2678 jQuery('.agent-weekly-calendar.selected').removeClass('selected');
2679 jQuery('.agent-weekly-calendar[data-agent-id="'+jQuery(this).data('agent-id')+'"]').addClass('selected');
2680 return false;
2681 });
2682
2683 jQuery('.calendar-view-wrapper').on('click', '.daily-calendar-action-navigation-btn', function(){
2684 jQuery(this).addClass('os-loading');
2685 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('target-date')).trigger('change');
2686 return false;
2687 });
2688
2689 jQuery('.calendar-view-wrapper').on('click', '.daily-availability-calendar .os-day', function(){
2690 jQuery('.os-monthly-calendar-days-w .os-day.selected').removeClass('selected');
2691 jQuery(this).addClass('selected');
2692 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('date')).trigger('change');
2693 return false;
2694 });
2695
2696
2697 jQuery('.os-calendar-today-btn').on('click', function(){
2698 jQuery(this).addClass('os-loading');
2699 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery(this).data('target-date')).trigger('change');
2700 return false;
2701 });
2702
2703 jQuery('.os-calendar-prev-btn').on('click', function(){
2704 jQuery(this).addClass('os-loading');
2705 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery('input[name="prev_target_date"]').val()).trigger('change');
2706 return false;
2707 });
2708
2709 jQuery('.os-calendar-next-btn').on('click', function(){
2710 jQuery(this).addClass('os-loading');
2711 jQuery('input[name="calendar_settings[target_date_string]"]').val(jQuery('input[name="next_target_date"]').val()).trigger('change');
2712 return false;
2713 });
2714 }
2715
2716 function latepoint_reload_calendar_view(){
2717 let $calendar_wrapper = jQuery('.calendar-view-wrapper');
2718 if(!$calendar_wrapper.length) return;
2719 $calendar_wrapper.addClass('os-loading');
2720
2721 let calendar_settings = new FormData(jQuery('form.os-calendar-settings-form')[0]);
2722
2723 let data = new FormData();
2724 data.append('params', latepoint_formdata_to_url_encoded_string(calendar_settings));
2725 data.append('action', latepoint_helper.route_action);
2726 data.append('route_name', $calendar_wrapper.data('route'));
2727 data.append('return_format', 'json');
2728
2729 jQuery.ajax({
2730 type: "post",
2731 dataType: "json",
2732 processData: false,
2733 contentType: false,
2734 url: latepoint_timestamped_ajaxurl(),
2735 data: data,
2736 success: function (response) {
2737 if (response.status === "success") {
2738 $calendar_wrapper.html(response.message).removeClass('os-loading');
2739 jQuery('.os-calendar-today-btn, .os-calendar-prev-btn, .os-calendar-next-btn').removeClass('os-loading');
2740 jQuery('.os-current-month-label .current-month').text(response.top_date_label);
2741 jQuery('.os-current-month-label .current-year').text(response.top_date_year);
2742 latepoint_check_horizontal_calendar_scroll();
2743 }
2744 }
2745 });
2746
2747 }
2748
2749 /*
2750 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
2751 */
2752
2753 function latepoint_process_updated() {
2754 location.reload();
2755 }
2756
2757 function latepoint_process_action_removed($elem) {
2758 $elem.closest('.os-form-block').remove();
2759 }
2760
2761 function latepoint_replace_process_condition_element($trigger, params, $target, callback = null) {
2762 $trigger.closest('.sub-section-content').addClass('os-loading');
2763 let route_name = $trigger.data('route');
2764 let data = {action: latepoint_helper.route_action, route_name: route_name, params: params, return_format: 'json'}
2765 jQuery.ajax({
2766 type: 'post',
2767 dataType: "json",
2768 url: latepoint_timestamped_ajaxurl(),
2769 data: data,
2770 success: (response) => {
2771 if (response.status === latepoint_helper.response_status.success) {
2772 $target.html(response.message);
2773 latepoint_init_process_conditions_form();
2774 $trigger.closest('.sub-section-content').removeClass('os-loading');
2775 if (typeof callback === 'function') {
2776 callback();
2777 }
2778 } else {
2779 alert("Error!");
2780 }
2781 }
2782 });
2783 }
2784
2785
2786 function latepoint_init_process_forms() {
2787 latepoint_init_process_conditions_form();
2788
2789 jQuery('.os-processes-w').on('latepoint:initProcessActionForm latepoint:initProcessActionTypeSettings', '.process-action-form', async function () {
2790 if (jQuery(this).find('.latepoint-whatsapp-templates-loader').length) {
2791 let $loader = jQuery(this).find('.latepoint-whatsapp-templates-loader');
2792 let $settings = jQuery(this).find('.process-action-settings');
2793 let $holder = jQuery(this).find('.latepoint-whatsapp-templates-holder');
2794 $settings.addClass('os-loading');
2795
2796 let data = {
2797 action: latepoint_helper.route_action,
2798 route_name: $loader.data('route'),
2799 params: {
2800 template_id: $loader.data('selected-template-id'),
2801 action_id: $loader.data('process-action-id'),
2802 process_id: $loader.data('process-id')
2803 },
2804 layout: 'none',
2805 return_format: 'json'
2806 }
2807 try {
2808 let response = await jQuery.ajax({
2809 type: "post",
2810 dataType: "json",
2811 url: latepoint_timestamped_ajaxurl(),
2812 data: data
2813 });
2814 $settings.removeClass('os-loading');
2815 if (response.status === 'success') {
2816 $loader.remove();
2817 $holder.html(response.message);
2818 } else {
2819 throw new Error(response.message);
2820 }
2821 } catch (e) {
2822 $settings.removeClass('os-loading');
2823 console.log(e);
2824 alert(e);
2825 }
2826 }
2827 });
2828
2829 jQuery('.os-processes-w').on('click', '.os-run-process', function () {
2830 let $btn = jQuery(this);
2831 $btn.addClass('os-loading');
2832 let $process_form = $btn.closest('.os-process-form');
2833 // remove previously assigned class on other forms
2834 jQuery('.os-process-form.prepared-to-run').removeClass('prepared-to-run');
2835 // add class so we know which form is about to be processed
2836 $process_form.addClass('prepared-to-run');
2837
2838
2839 let form_data = new FormData($process_form[0]);
2840 form_data.set('process_event_type', $process_form.closest('.os-process-form').find('.process-event-type-selector').val());
2841
2842
2843 let data = new FormData();
2844 data.append('params', latepoint_formdata_to_url_encoded_string(form_data));
2845 data.append('action', latepoint_helper.route_action);
2846 data.append('route_name', $btn.data('route'));
2847 data.append('return_format', 'json');
2848
2849 jQuery.ajax({
2850 type: "post",
2851 dataType: "json",
2852 processData: false,
2853 contentType: false,
2854 url: latepoint_timestamped_ajaxurl(),
2855 data: data,
2856 success: function (data) {
2857 latepoint_show_data_in_side_panel(data.message, 'width-600');
2858 latepoint_init_process_test_form();
2859 $btn.removeClass('os-loading');
2860 }
2861 });
2862 return false;
2863 });
2864
2865 jQuery('.os-processes-w').find('.process-action-form').each(function (index) {
2866 latepoint_init_process_action_form(jQuery(this));
2867 });
2868
2869 jQuery('.os-processes-w').on('click', '.pe-remove-condition', (event) => {
2870 if (jQuery(event.currentTarget).closest('.pe-conditions').find('.pe-condition').length > 1) {
2871 jQuery(event.currentTarget).closest('.pe-condition').remove();
2872 } else {
2873 alert('You need to have at least one condition if your custom field is set to be conditional.')
2874 }
2875 return false;
2876 });
2877
2878
2879 jQuery('.os-processes-w').on('change', 'select.process-condition-operator-selector', (event) => {
2880 let $select = jQuery(event.currentTarget);
2881 if ($select.val() == 'changed' || $select.val() == 'not_changed') {
2882 $select.closest('.pe-condition').find('.process-condition-values-w').hide();
2883 } else {
2884 $select.closest('.pe-condition').find('.process-condition-values-w').show();
2885 }
2886 });
2887
2888 jQuery('.os-processes-w').on('change', 'select.process-event-type-selector', (event) => {
2889 let $select = jQuery(event.currentTarget);
2890 latepoint_replace_process_condition_element($select, {event_type: $select.val()}, $select.closest('.os-form-block').find('.process-event-condition-wrapper'));
2891 });
2892
2893 jQuery('.os-processes-w').on('change', 'select.process-condition-object-selector', (event) => {
2894 let $select = jQuery(event.currentTarget);
2895 let $property_selector = $select.closest('.pe-condition').find('.process-condition-properties-w select');
2896 latepoint_replace_process_condition_element($select, {object_code: $select.val()}, $property_selector, () => {
2897 $property_selector.trigger('change');
2898 });
2899 });
2900
2901 jQuery('.os-processes-w').on('change', 'select.process-condition-property-selector', (event) => {
2902 let $select = jQuery(event.currentTarget);
2903 let $operator_selector = $select.closest('.pe-condition').find('.process-condition-operators-w select');
2904 latepoint_replace_process_condition_element($select, {property: $select.val()}, $operator_selector, () => {
2905 $operator_selector.trigger('change');
2906 });
2907 });
2908
2909 jQuery('.os-processes-w').on('change', 'select.process-condition-operator-selector', (event) => {
2910 let $select = jQuery(event.currentTarget);
2911 latepoint_replace_process_condition_element($select, {
2912 property: $select.closest('.pe-condition').find('select.process-condition-property-selector').val(),
2913 trigger_condition_id: $select.closest('.pe-condition').data('condition-id'),
2914 operator: $select.val()
2915 }, $select.closest('.pe-condition').find('.process-condition-values-w'));
2916 });
2917
2918 }
2919
2920 function latepoint_init_process_conditions_form() {
2921 jQuery('.os-late-select').lateSelect();
2922 }
2923
2924 function latepoint_add_process_condition($btn, response) {
2925 $btn.closest('.pe-condition').after(response.message);
2926 latepoint_init_process_conditions_form();
2927 }
2928
2929 function latepoint_init_added_process_action_form($trigger) {
2930 let $action_form = $trigger.prev('.process-action-form');
2931 $action_form.addClass('is-editing').trigger('latepoint:initProcessActionForm');
2932 latepoint_init_process_action_form($action_form);
2933 }
2934
2935 function latepoint_init_process_test_form() {
2936
2937 jQuery('.latepoint-run-process-btn').on('click', function () {
2938 let $btn = jQuery(this);
2939 if ($btn.hasClass('os-loading')) return false;
2940 $btn.addClass('os-loading');
2941 let $test_action_form = jQuery('.latepoint-side-panel-w .action-settings-wrapper');
2942
2943
2944 let form_data = new FormData(jQuery('.os-process-form.prepared-to-run')[0]);
2945
2946 // set data sources
2947 jQuery('.process-test-data-source-selector').each(function () {
2948 form_data.set(jQuery(this).prop('name'), jQuery(this).val());
2949 });
2950
2951 // set selected actions
2952 jQuery('.process-test-data-source-selector').each(function () {
2953 form_data.set(jQuery(this).prop('name'), jQuery(this).val());
2954 });
2955
2956 let action_ids_to_run = [];
2957 jQuery('.action-to-run input[type="hidden"]').each(function () {
2958 if (jQuery(this).val() == 'on') action_ids_to_run.push(jQuery(this).closest('.action-to-run').data('id'));
2959 });
2960 form_data.set('action_ids', action_ids_to_run.join(','));
2961
2962
2963 let data = new FormData();
2964 data.append('params', latepoint_formdata_to_url_encoded_string(form_data));
2965 data.append('action', latepoint_helper.route_action);
2966 data.append('route_name', $btn.data('route'));
2967 data.append('return_format', 'json');
2968
2969 jQuery.ajax({
2970 type: "post",
2971 dataType: "json",
2972 processData: false,
2973 contentType: false,
2974 url: latepoint_timestamped_ajaxurl(),
2975 data: data,
2976 success: function (data) {
2977 $btn.removeClass('os-loading');
2978 if (data.status == 'success') {
2979 latepoint_add_notification(data.message);
2980 } else {
2981 latepoint_add_notification(data.message, 'error');
2982 }
2983 }
2984 });
2985 });
2986
2987 jQuery('.process-action-test-data-source-selector').on('change', function () {
2988 // TODO add call to server to check if selected data sources matches conditions of this process
2989 });
2990 }
2991
2992
2993 function latepoint_init_process_action_test_form() {
2994
2995 latepoint_init_json_view(jQuery('.action-preview-wrapper.type-trigger_webhook pre'));
2996
2997 jQuery('.latepoint-run-action-btn').on('click', function () {
2998 let $btn = jQuery(this);
2999 if ($btn.hasClass('os-loading')) return false;
3000 $btn.addClass('os-loading');
3001 let $test_action_form = jQuery('.latepoint-side-panel-w .action-settings-wrapper');
3002
3003 let action_data = new FormData();
3004
3005
3006 action_data.append('params', $test_action_form.find('select, textarea, input').serialize());
3007 action_data.append('action', latepoint_helper.route_action);
3008 action_data.append('route_name', $btn.data('route'));
3009 action_data.append('return_format', 'json');
3010
3011 jQuery.ajax({
3012 type: "post",
3013 dataType: "json",
3014 processData: false,
3015 contentType: false,
3016 url: latepoint_timestamped_ajaxurl(),
3017 data: action_data,
3018 success: function (data) {
3019 $btn.removeClass('os-loading');
3020 if (data.status == 'success') {
3021 latepoint_add_notification(data.message);
3022 } else {
3023 latepoint_add_notification(data.message, 'error');
3024 }
3025 }
3026 });
3027 });
3028
3029 jQuery('.process-action-test-data-source-selector').on('change', function () {
3030 let $select = jQuery(this);
3031 jQuery('.action-preview-wrapper').addClass('os-loading');
3032 let $test_action_form = $select.closest('.action-settings-wrapper');
3033
3034 let action_data = new FormData();
3035
3036
3037 action_data.append('params', $test_action_form.find('select, textarea, input').serialize());
3038 action_data.append('action', latepoint_helper.route_action);
3039 action_data.append('route_name', $select.data('route'));
3040 action_data.append('return_format', 'json');
3041
3042 jQuery.ajax({
3043 type: "post",
3044 dataType: "json",
3045 processData: false,
3046 contentType: false,
3047 url: latepoint_timestamped_ajaxurl(),
3048 data: action_data,
3049 success: function (data) {
3050 jQuery('.action-preview-wrapper').html(data.message).removeClass('os-loading');
3051 latepoint_init_json_view(jQuery('.action-preview-wrapper.type-trigger_webhook pre'));
3052 }
3053 });
3054 });
3055 }
3056
3057 function latepoint_init_process_action_form($action_form) {
3058 $action_form.on('click', '.os-run-process-action', function () {
3059 let $btn = jQuery(this);
3060 $btn.addClass('os-loading');
3061 let $action_form = $btn.closest('.process-action-form');
3062
3063 if (window.tinyMCE !== undefined) window.tinyMCE.triggerSave();
3064
3065 let action_data = new FormData();
3066 let params = latepoint_create_form_data_from_non_form_element($action_form);
3067
3068 params.set('process_event_type', $action_form.closest('.os-process-form').find('.process-event-type-selector').val());
3069
3070 action_data.append('params', latepoint_formdata_to_url_encoded_string(params));
3071 action_data.append('action', latepoint_helper.route_action);
3072 action_data.append('route_name', $btn.data('route'));
3073 action_data.append('return_format', 'json');
3074
3075 jQuery.ajax({
3076 type: "post",
3077 dataType: "json",
3078 processData: false,
3079 contentType: false,
3080 url: latepoint_timestamped_ajaxurl(),
3081 data: action_data,
3082 success: function (data) {
3083 latepoint_show_data_in_side_panel(data.message, 'width-800');
3084 latepoint_init_process_action_test_form();
3085 $btn.removeClass('os-loading');
3086 }
3087 });
3088 return false;
3089 });
3090 $action_form.on('click', '.process-action-heading', function () {
3091 let $action_form = jQuery(this).closest('.process-action-form');
3092 if (!$action_form.hasClass('is-editing')) $action_form.trigger('latepoint:initProcessActionForm')
3093 $action_form.toggleClass('is-editing');
3094 return false;
3095 });
3096
3097 $action_form.find('textarea.os-wp-editor-textarea').each(function (index) {
3098 latepoint_init_tiny_mce(jQuery(this).attr('id'));
3099 });
3100 $action_form.on('click', '.os-remove-process-action', function () {
3101 if (confirm(jQuery(this).data('os-prompt'))) {
3102 jQuery(this).closest('.process-action-form').remove();
3103 }
3104 return false;
3105 });
3106
3107 $action_form.on('change', '.process-action-type-whatsapp-template-selector', async function () {
3108 let $select = jQuery(this);
3109 let $preview_holder = $select.closest('.process-action-settings').find('.latepoint-whatsapp-template-preview-holder');
3110 $preview_holder.addClass('os-loading');
3111
3112 let data = {
3113 action: latepoint_helper.route_action,
3114 route_name: $select.data('route'),
3115 params: {
3116 template_id: $select.val(),
3117 action_id: $select.data('action-id')
3118 },
3119 layout: 'none',
3120 return_format: 'json'
3121 }
3122 try {
3123 let response = await jQuery.ajax({
3124 type: "post",
3125 dataType: "json",
3126 url: latepoint_timestamped_ajaxurl(),
3127 data: data
3128 });
3129 $preview_holder.removeClass('os-loading');
3130 if (response.status === 'success') {
3131 $preview_holder.html(response.message);
3132 } else {
3133 throw new Error(response.message);
3134 }
3135 } catch (e) {
3136 $preview_holder.removeClass('os-loading');
3137 console.log(e);
3138 alert(e);
3139 }
3140 return false;
3141 });
3142
3143 $action_form.on('change', '.process-action-type', function () {
3144 let $select = jQuery(this);
3145 jQuery(this).closest('.process-action-form').find('.process-action-name').text($select.find('option:selected').text());
3146 let action_type = $select.val();
3147 let action_id = $select.data('action-id');
3148 let route_name = $select.data('route');
3149 let $action_settings = $select.closest('.process-action-content').find('.process-action-settings');
3150 $action_settings.addClass('os-loading');
3151 let data = {
3152 action: latepoint_helper.route_action,
3153 route_name: route_name,
3154 params: {
3155 action_type: action_type,
3156 action_id: action_id
3157 },
3158 layout: 'none',
3159 return_format: 'json'
3160 }
3161 jQuery.ajax({
3162 type: "post",
3163 dataType: "json",
3164 url: latepoint_timestamped_ajaxurl(),
3165 data: data,
3166 success: function (data) {
3167 $action_settings.html(data.message).removeClass('os-loading');
3168 let $action_form = $select.closest('.process-action-form');
3169 latepoint_init_input_masks($action_form);
3170 $action_form.trigger('latepoint:initProcessActionTypeSettings');
3171 }
3172 });
3173 return false;
3174 });
3175 }
3176
3177 /*
3178 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
3179 */
3180
3181
3182 function latepoint_preview_init_step_category_items(step_code){
3183 jQuery('.booking-form-preview .os-item-category-info').on('click', function(){
3184 var $booking_form_element = jQuery(this).closest('.booking-form-preview');
3185 jQuery(this).closest('.latepoint-step-content').addClass('selecting-item-category');
3186 var $category_wrapper = jQuery(this).closest('.os-item-category-w');
3187 var $main_parent = jQuery(this).closest('.os-item-categories-main-parent');
3188 if($category_wrapper.hasClass('selected')){
3189 $category_wrapper.removeClass('selected');
3190 if($category_wrapper.parent().closest('.os-item-category-w').length){
3191 $category_wrapper.parent().closest('.os-item-category-w').addClass('selected');
3192 }else{
3193 $main_parent.removeClass('show-selected-only');
3194 }
3195 }else{
3196 $main_parent.find('.os-item-category-w.selected').removeClass('selected');
3197 $main_parent.addClass('show-selected-only');
3198 $category_wrapper.addClass('selected');
3199 }
3200 return false;
3201 });
3202 }
3203
3204 function latepoint_booking_form_discard_changes(){
3205
3206 let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]);
3207
3208 var data = {
3209 action: latepoint_helper.route_action,
3210 route_name: jQuery('.booking-form-preview-settings').data('route-name'),
3211 params: latepoint_formdata_to_url_encoded_string(form_data),
3212 layout: 'none',
3213 return_format: 'json'
3214 }
3215
3216 jQuery.ajax({
3217 type : "post",
3218 dataType : "json",
3219 url : latepoint_timestamped_ajaxurl(),
3220 data : data,
3221 success: function(data){
3222 if(data.status === "success"){
3223 jQuery('.booking-form-preview-inner').html(data.booking_form_html);
3224 latepoint_init_booking_form_preview();
3225 }else{
3226 latepoint_add_notification(data.message, 'error');
3227 }
3228 }
3229 });
3230 }
3231
3232 function latepoint_booking_form_save_changes(){
3233
3234 let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]);
3235
3236 jQuery('.editable-setting').each(function(){
3237 form_data.set('steps_settings' + jQuery(this).data('setting-key'), jQuery(this).html());
3238 });
3239
3240
3241 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());
3242
3243
3244 var data = {
3245 action: latepoint_helper.route_action,
3246 route_name: jQuery('.booking-form-preview-settings').data('route-name'),
3247 params: latepoint_formdata_to_url_encoded_string(form_data),
3248 layout: 'none',
3249 return_format: 'json'
3250 }
3251
3252 jQuery.ajax({
3253 type : "post",
3254 dataType : "json",
3255 url : latepoint_timestamped_ajaxurl(),
3256 data : data,
3257 success: function(data){
3258 jQuery('.booking-form-preview-settings').removeClass('os-loading');
3259 if(data.status === "success"){
3260 jQuery('.bf-preview-step-settings').html(data.step_settings_html);
3261 jQuery('.booking-form-preview-inner').html(data.booking_form_html);
3262 jQuery('#latepoint-main-admin-inline-css').html(data.css_variables);
3263 latepoint_init_booking_form_preview();
3264 }else{
3265 latepoint_add_notification(data.message, 'error');
3266 }
3267 }
3268 });
3269 }
3270
3271 function latepoint_init_booking_form_preview(){
3272
3273 latepoint_preview_init_step_category_items();
3274 latepoint_booking_form_preview_init_datepicker();
3275
3276
3277 jQuery('.booking-form-preview-wrapper').on('click', '.os-step-tab', function(){
3278 jQuery(this).closest('.os-step-tabs').find('.os-step-tab').removeClass('active');
3279 jQuery(this).addClass('active');
3280 var target = jQuery(this).data('target');
3281 jQuery(this).closest('.os-step-tabs-w').find('.os-step-tab-content').hide();
3282 jQuery(target).show();
3283 });
3284
3285
3286 jQuery('.bf-save-btn').on('click', function(){
3287 jQuery(this).addClass('os-loading');
3288 latepoint_booking_form_save_changes();
3289 return false;
3290 });
3291
3292 jQuery('.bf-cancel-save-btn').on('click', function(){
3293 jQuery(this).addClass('os-loading');
3294 latepoint_booking_form_discard_changes();
3295 return false;
3296 });
3297
3298
3299 jQuery('.booking-form-preview .bf-next-btn').on('click', function(){
3300 jQuery(this).addClass('os-loading');
3301 jQuery("#selected_step_code > option:selected")
3302 .prop("selected", false)
3303 .next()
3304 .prop("selected", true).trigger('change');
3305 });
3306
3307 jQuery('.booking-form-preview .bf-prev-btn').on('click', function(){
3308 jQuery(this).addClass('os-loading');
3309 jQuery("#selected_step_code > option:selected")
3310 .prop("selected", false)
3311 .prev()
3312 .prop("selected", true).trigger('change');
3313 });
3314
3315
3316 jQuery('.booking-form-preview .os-image-selector-trigger').on('click', function(){
3317 jQuery('.booking-form-preview').addClass('has-changes');
3318 });
3319
3320 jQuery('.booking-form-preview .editable-setting').on('focus', function(){
3321 jQuery('.booking-form-preview').addClass('has-changes');
3322 });
3323
3324
3325 let editor = new MediumEditor('.booking-form-preview .os-editable', {toolbar: {
3326 buttons: [
3327 {
3328 name: 'bold',
3329 classList: ['latepoint-icon', 'latepoint-icon-format_bold'],
3330 },
3331 {
3332 name: 'anchor',
3333 classList: ['latepoint-icon', 'latepoint-icon-format_link'],
3334 },
3335 {
3336 name: 'h3',
3337 classList: ['latepoint-icon', 'latepoint-icon-format_h3'],
3338 },
3339 {
3340 name: 'h4',
3341 classList: ['latepoint-icon', 'latepoint-icon-format_h4'],
3342 },
3343 {
3344 name: 'h5',
3345 classList: ['latepoint-icon', 'latepoint-icon-format_h5'],
3346 },
3347
3348 ]
3349 }
3350 });
3351 let editor_basic = new MediumEditor('.booking-form-preview .os-editable-basic', {toolbar: {
3352 buttons: [
3353 {
3354 name: 'bold',
3355 classList: ['latepoint-icon', 'latepoint-icon-format_bold'],
3356 },
3357 {
3358 name: 'italic',
3359 classList: ['latepoint-icon', 'latepoint-icon-format_italic'],
3360 },
3361 {
3362 name: 'underline',
3363 classList: ['latepoint-icon', 'latepoint-icon-format_underlined'],
3364 },
3365 {
3366 name: 'anchor',
3367 classList: ['latepoint-icon', 'latepoint-icon-format_link'],
3368 },
3369
3370 ]
3371 }
3372 });
3373 }
3374
3375 function latepoint_reload_booking_form_preview(){
3376 latepoint_booking_form_save_changes();
3377 }
3378
3379 function latepoint_init_steps_settings(){
3380
3381 jQuery('.booking-form-preview-settings').on('change', ' select, input[type="hidden"]', function(){
3382 jQuery('.booking-form-preview-settings').addClass('os-loading');
3383 latepoint_reload_booking_form_preview();
3384 });
3385
3386 jQuery('.trigger-custom-color-save').on('click', function(){
3387 jQuery('.booking-form-preview-settings').addClass('os-loading');
3388 latepoint_booking_form_save_changes();
3389 return false;
3390 });
3391
3392 jQuery('.bf-color-scheme-color-trigger').on('click', function(){
3393 jQuery('.bf-color-scheme-color-trigger.is-selected').removeClass('is-selected');
3394 jQuery(this).addClass('is-selected');
3395 let color_scheme = jQuery(this).data('color-code');
3396 jQuery('.os-color-scheme-selector-wrapper select').val(color_scheme).trigger('change');
3397 if(color_scheme == 'custom'){
3398 jQuery('.os-custom-color-selector-wrapper').removeClass('is-hidden');
3399 }else{
3400 jQuery('.os-custom-color-selector-wrapper').addClass('is-hidden');
3401 }
3402 return false;
3403 });
3404
3405 jQuery('.os-section-collapsible-trigger').on('click', function(){
3406 jQuery(this).closest('.os-section-collapsible-wrapper').toggleClass('is-open');
3407 return false;
3408 })
3409 }
3410
3411
3412 function latepoint_booking_form_preview_init_timeslots($booking_form_element = false){
3413 if(!$booking_form_element) return;
3414 $booking_form_element.on('click', '.dp-timepicker-trigger', function(){
3415 if(jQuery(this).hasClass('is-booked') || jQuery(this).hasClass('is-off')){
3416 // Show error message that you cant select a booked period
3417 }else{
3418 if(jQuery(this).hasClass('selected')){
3419 jQuery(this).removeClass('selected');
3420 jQuery(this).find('.dp-success-label').remove();
3421 }else{
3422 $booking_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove();
3423 var selected_timeslot_time = jQuery(this).find('.dp-label-time').html();
3424 jQuery(this).addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>');
3425
3426 var minutes = parseInt(jQuery(this).data('minutes'));
3427 var start_date = new Date($booking_form_element.find('.os-day.selected').data('date'));
3428 $booking_form_element.find('.latepoint_start_date').val(start_date.toISOString().split('T')[0])
3429 latepoint_trigger_next_btn($booking_form_element);
3430 }
3431 }
3432 return false;
3433 });
3434 }
3435
3436
3437 function latepoint_booking_form_preview_day_timeslots($day){
3438 let $wrapper_element = jQuery('.booking-form-preview');
3439 $day.addClass('selected');
3440
3441 var service_duration = $day.data('service-duration');
3442 var interval = $day.data('interval');
3443 var work_start_minutes = $day.data('work-start-time');
3444 var work_end_minutes = $day.data('work-end-time');
3445 var total_work_minutes = $day.data('total-work-minutes');
3446 var bookable_minutes = [];
3447 var available_capacities_of_bookable_minute = [];
3448 if($day.attr('data-bookable-minutes')){
3449 if($day.data('bookable-minutes').toString().indexOf(':') > -1){
3450 // has capacity information embedded into bookable minutes string
3451 let bookable_minutes_with_capacity = $day.data('bookable-minutes').toString().split(',');
3452 for(let i = 0; i < bookable_minutes_with_capacity.length; i++){
3453 bookable_minutes.push(parseInt(bookable_minutes_with_capacity[i].split(':')[0]));
3454 available_capacities_of_bookable_minute.push(parseInt(bookable_minutes_with_capacity[i].split(':')[1]));
3455 }
3456 }else{
3457 bookable_minutes = $day.data('bookable-minutes').toString().split(',').map(Number);
3458 }
3459 }
3460 var work_minutes = $day.data('work-minutes').toString().split(',').map(Number);
3461
3462 var $timeslots = $wrapper_element.find('.timeslots');
3463 $timeslots.html('');
3464
3465 if(total_work_minutes > 0 && bookable_minutes.length && work_minutes.length){
3466 var prev_minutes = false;
3467 work_minutes.forEach(function(current_minutes){
3468 var ampm = latepoint_am_or_pm(current_minutes);
3469
3470 var timeslot_class = 'dp-timepicker-trigger';
3471 var timeslot_available_capacity = 0;
3472 if($wrapper_element.find('.os-dates-w').data('time-pick-style') == 'timeline'){
3473 timeslot_class+= ' dp-timeslot';
3474 }else{
3475 timeslot_class+= ' dp-timebox';
3476 }
3477
3478 if(prev_minutes !== false && ((current_minutes - prev_minutes) > service_duration)){
3479 // show interval that is off between two work periods
3480 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);
3481 var off_width = (((current_minutes - prev_minutes - service_duration) / total_work_minutes) * 100);
3482 $timeslots.append('<div class="'+ timeslot_class +' is-off" style="max-width:'+ off_width +'%; width:'+ off_width +'%"><span class="dp-label">' + off_label + '</span></div>');
3483 }
3484
3485 if(!bookable_minutes.includes(current_minutes)){
3486 timeslot_class+= ' is-booked';
3487 }else{
3488 if(available_capacities_of_bookable_minute.length) timeslot_available_capacity = available_capacities_of_bookable_minute[bookable_minutes.indexOf(current_minutes)];
3489 }
3490 var tick_html = '';
3491 var capacity_label = '';
3492 var capacity_label_html = '';
3493 var capacity_internal_label_html = '';
3494
3495 if(((current_minutes % 60) == 0) || (interval >= 60)){
3496 timeslot_class+= ' with-tick';
3497 tick_html = '<span class="dp-tick"><strong>'+latepoint_minutes_to_hours_preferably(current_minutes)+'</strong>'+' '+ampm+'</span>';
3498 }
3499 var timeslot_label = latepoint_minutes_to_hours_and_minutes(current_minutes)+' '+ampm;
3500 if(latepoint_show_booking_end_time()){
3501 var end_minutes = current_minutes + service_duration;
3502 if(end_minutes > 1440) end_minutes = end_minutes - 1440;
3503 var end_minutes_ampm = latepoint_am_or_pm(end_minutes);
3504 timeslot_label+= ' - <span class="dp-label-end-time">' + latepoint_minutes_to_hours_and_minutes(end_minutes)+' '+end_minutes_ampm + '</span>';
3505 }
3506 if(timeslot_available_capacity){
3507 var spaces_message = timeslot_available_capacity > 1 ? latepoint_helper.many_spaces_message : latepoint_helper.single_space_message;
3508 capacity_label = timeslot_available_capacity + ' ' + spaces_message;
3509 capacity_label_html = '<span class="dp-capacity">' + capacity_label + '</span>';
3510 capacity_internal_label_html = '<span class="dp-label-capacity">' + capacity_label + '</span>';
3511 }
3512 timeslot_label = timeslot_label.trim();
3513 $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>');
3514 prev_minutes = current_minutes;
3515 });
3516 }else{
3517 // No working hours this day
3518 $timeslots.addClass('slots-not-available').append('<div class="not-working-message">' + latepoint_helper.msg_not_available + "</div>");
3519 }
3520 jQuery('.times-header-label span').text($day.data('nice-date'));
3521 $wrapper_element.find('.time-selector-w').slideDown(200);
3522 }
3523
3524 function latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element){
3525
3526 if(!$booking_form_element) return;
3527 $booking_form_element.on('click', '.os-month-next-btn', function(){
3528 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
3529 var next_month_route_name = jQuery(this).data('route');
3530 if($booking_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length){
3531 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active');
3532 latepoint_booking_form_preview_calendar_set_month_label($booking_form_element);
3533 }else{
3534 alert('Disabled in preview');
3535 }
3536 latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element);
3537 return false;
3538 });
3539 $booking_form_element.on('click', '.os-month-prev-btn', function(){
3540 var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element');
3541 if($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length){
3542 $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active');
3543 latepoint_booking_form_preview_calendar_set_month_label($booking_form_element);
3544 }
3545 return false;
3546 });
3547 }
3548
3549
3550 function latepoint_booking_form_preview_calendar_set_month_label(){
3551 jQuery('.os-current-month-label .current-month').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-month-label'));
3552 jQuery('.os-current-month-label .current-year').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-year'));
3553 }
3554
3555
3556
3557 function latepoint_booking_form_preview_init_datepicker(){
3558 let $booking_form_element = jQuery('.latepoint-booking-form-element');
3559 latepoint_booking_form_preview_init_timeslots($booking_form_element);
3560 latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element);
3561 $booking_form_element.on('click', '.os-months .os-day', function(){
3562 if(jQuery(this).hasClass('os-day-passed')) return false;
3563 if(jQuery(this).hasClass('os-not-in-allowed-period')) return false;
3564 if(jQuery(this).hasClass('os-month-prev')) return false;
3565 if(jQuery(this).hasClass('os-month-next')) return false;
3566 if(jQuery(this).closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')){
3567
3568 // HIDE TIMESLOT IF ONLY ONE TIMEPOINT
3569 if(jQuery(this).hasClass('os-not-available')){
3570 // clicked on a day that has no available timeslots
3571 // do nothing
3572 }else{
3573 $booking_form_element.find('.os-day.selected').removeClass('selected');
3574 jQuery(this).addClass('selected');
3575 // set date
3576 $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date'));
3577 if(jQuery(this).hasClass('os-one-slot-only')){
3578 // clicked on a day that has only one slot available
3579 var bookable_minutes = jQuery(this).data('bookable-minutes').toString().split(':')[0];
3580 var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number(jQuery(this).data('service-duration')));
3581 $booking_form_element.find('.time-selector-w').slideUp(200);
3582 }else{
3583 // regular day with more than 1 timeslots available
3584 // build timeslots
3585 latepoint_booking_form_preview_day_timeslots(jQuery(this));
3586 // clear time and hide next btn
3587 }
3588 }
3589 }else{
3590 // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT
3591 $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date'));
3592 $booking_form_element.find('.os-day.selected').removeClass('selected');
3593 jQuery(this).addClass('selected');
3594
3595 // build timeslots
3596 latepoint_booking_form_preview_day_timeslots(jQuery(this));
3597 // clear time and hide next btn
3598 }
3599
3600
3601 return false;
3602 });
3603 }
3604
3605
3606
3607 /*
3608 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
3609 */
3610
3611 function latepoint_submit_quick_order_form(){
3612 let $quick_edit_form = jQuery('form.order-quick-edit-form');
3613
3614 let errors = latepoint_validate_form($quick_edit_form);
3615 if(errors.length){
3616 let error_messages = errors.map(error => error.message ).join(', ');
3617 latepoint_add_notification(error_messages, 'error');
3618 return false;
3619 }
3620
3621 $quick_edit_form.find('button[type="submit"]').addClass('os-loading');
3622 jQuery.ajax({
3623 type: "post",
3624 dataType: "json",
3625 processData: false,
3626 contentType: false,
3627 url: latepoint_timestamped_ajaxurl(),
3628 data: latepoint_create_form_data($quick_edit_form),
3629 success: function (response) {
3630 if(response.fields_to_update){
3631 for (const [key, value] of Object.entries(response.fields_to_update)) {
3632 $quick_edit_form.find('input[name="' + key + '"]').val(value)
3633 }
3634 }
3635 $quick_edit_form.find('button[type="submit"]').removeClass('os-loading');
3636 if(response.form_values_to_update){
3637 jQuery.each(response.form_values_to_update, function(name, value){
3638 $quick_edit_form.find('[name="'+ name +'"]').val(value);
3639 });
3640 }
3641 if (response.status === "success") {
3642 latepoint_add_notification(response.message);
3643 latepoint_reload_after_order_save();
3644 }else{
3645 latepoint_add_notification(response.message, 'error');
3646 }
3647 }
3648 });
3649
3650 }
3651
3652 function latepoint_apply_agent_selector_change(){
3653 if(jQuery('.quick-availability-per-day-w').length){
3654
3655 let booking_form_id = jQuery('.quick-availability-per-day-w').data('trigger-form-booking-id');
3656 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
3657
3658 latepoint_load_quick_availability($trigger_btn);
3659 }
3660 }
3661
3662 function latepoint_apply_service_selector_change($form){
3663 let field_base_name = 'order_items[' + $form.data('order-item-id') +'][bookings][' + $form.data('booking-id') +']';
3664
3665 var $selected_service = $form.find('.os-services-select-field-w .service-option-selected');
3666 var service_id = $selected_service.data('id');
3667 var buffer_before = $selected_service.data('buffer-before');
3668 var buffer_after = $selected_service.data('buffer-after');
3669 var default_duration = $selected_service.data('duration');
3670 var default_duration_name = $selected_service.data('duration-name');
3671 var min_capacity = $selected_service.data('capacity-min');
3672 var max_capacity = $selected_service.data('capacity-max');
3673
3674 var extra_durations = $selected_service.data('extra-durations');
3675
3676 $form.find('input[name="'+field_base_name+'[buffer_before]"]').val(buffer_before).trigger('change').closest('.os-form-group').addClass('has-value');
3677 $form.find('input[name="'+field_base_name+'[buffer_after]"]').val(buffer_after).trigger('change').closest('.os-form-group').addClass('has-value');
3678 $form.find('input[name="'+field_base_name+'[service_id]"]').val(service_id).trigger('change').closest('.os-form-group').addClass('has-value');
3679
3680 var duration_name = default_duration_name ? default_duration_name : (default_duration + ' ' + latepoint_helper.string_minutes);
3681 var options = '<option value="'+ default_duration +'">' + duration_name + '</option>';
3682 if(extra_durations.length){
3683 jQuery.each(extra_durations, function(index, value){
3684 var duration_name = value.name ? value.name : value.duration + ' ' + latepoint_helper.string_minutes;
3685 options+= '<option value="'+ value.duration +'">' + duration_name + '</option>';
3686 });
3687 $form.find('.os-service-durations').show();
3688 }else{
3689 $form.find('.os-service-durations').hide();
3690 }
3691
3692 $form.find('.booking-total-attendees-selector-w .capacity-info strong').text(max_capacity);
3693 var attendees_options_html = '';
3694 for(var i=1;i<=max_capacity;i++){
3695 attendees_options_html+= '<option value="' + i + '">' + i + '</option>';
3696 }
3697 var selected_attendees = Math.min(jQuery('.booking-total-attendees-selector-w select').val(), max_capacity);
3698 $form.find('.booking-total-attendees-selector-w select').html(attendees_options_html).val(selected_attendees);
3699 if(max_capacity > 1){
3700 $form.find('.booking-total-attendees-selector-w').show();
3701 }else{
3702 $form.find('.booking-total-attendees-selector-w').hide();
3703 }
3704
3705 $form.find('.os-service-durations select').html(options);
3706
3707 latepoint_set_booking_end_time($form);
3708 if(jQuery('.quick-availability-per-day-w').length){
3709 latepoint_load_quick_availability($form.find('.trigger-quick-availability'));
3710 }
3711
3712 latepoint_init_input_masks($form);
3713 }
3714
3715 function latepoint_reload_balance_and_payments(){
3716 let $wrapper = jQuery('.balance-payment-info');
3717 $wrapper.closest('.balance-payment-wrapper').addClass('os-loading');
3718 let route_name = $wrapper.data('route');
3719 let $quick_edit_form = $wrapper.closest('form.order-quick-edit-form');
3720 let form_data = new FormData($quick_edit_form[0]);
3721
3722 let data = { action: latepoint_helper.route_action, route_name: route_name, params: latepoint_formdata_to_url_encoded_string(form_data), return_format: 'json' }
3723 jQuery.ajax({
3724 type : "post",
3725 dataType : "json",
3726 url : latepoint_timestamped_ajaxurl(),
3727 data : data,
3728 success: function(response){
3729 $wrapper.closest('.balance-payment-wrapper').removeClass('os-loading');
3730 if(response.status === "success"){
3731 jQuery('.balance-payment-wrapper').html(response.message);
3732 latepoint_init_input_masks(jQuery('.balance-payment-wrapper'));
3733 latepoint_init_daterangepicker(jQuery('.balance-payment-wrapper .os-date-range-picker'));
3734 latepoint_init_payment_request_form(jQuery('.quick-order-form-w'));
3735 }else{
3736 alert(response.message);
3737 }
3738 }
3739 });
3740 }
3741
3742
3743
3744 function latepoint_cancel_adding_new_order_item_to_quick_edit_form(){
3745 jQuery('.order-items-list').removeClass('is-blurred');
3746 jQuery('.new-order-item-list-bundles-wrapper').removeClass('is-open');
3747 jQuery('.new-order-item-variant-selector-wrapper').removeClass('is-open');
3748 jQuery('.order-form-add-item-btn').removeClass('is-cancelling').find('span').text(jQuery('.order-form-add-item-btn').data('add-label'));
3749 }
3750
3751 function latepoint_build_new_booking_order_item(){
3752 jQuery('.order-form-add-item-btn').addClass('os-loading');
3753 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3754 let params = {}
3755
3756 var data = {
3757 action: 'latepoint_route_call',
3758 route_name: jQuery('.order-form-add-item-btn').data('booking-form-route-name'),
3759 params: params,
3760 return_format: 'json'
3761 }
3762 jQuery.ajax({
3763 type : "post",
3764 dataType : "json",
3765 url : latepoint_timestamped_ajaxurl(),
3766 data : data,
3767 success: function(response){
3768 if(response.status === "success"){
3769 let $form = jQuery(response.message);
3770 jQuery('.order-items-list').prepend($form);
3771 jQuery('.order-form-add-item-btn').removeClass('os-loading');
3772 latepoint_init_booking_data_form(jQuery('.order-item-booking-data-form-wrapper[data-order-item-id="' + $form.data('order-item-id') + '"]'));
3773 // new item added, trigger change event
3774 latepoint_quick_order_items_changed();
3775 }else{
3776 alert(response.message, 'error');
3777 }
3778 }
3779 });
3780 }
3781
3782 function latepoint_build_booking_data_form_for_bundle($slot_for_booking){
3783 $slot_for_booking.addClass('os-loading');
3784 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3785 let params = {}
3786
3787 let is_booked = $slot_for_booking.hasClass('is-booked');
3788
3789 var data = {
3790 action: 'latepoint_route_call',
3791 route_name: jQuery('.order-form-add-item-btn').data('booking-form-route-name'),
3792 params: {
3793 order_item_id: $slot_for_booking.data('order-item-id'),
3794 order_item_variant: $slot_for_booking.data('order-item-variant'),
3795 booking_id: $slot_for_booking.data('booking-id'),
3796 booking_item_data: is_booked ? $slot_for_booking.find('.booking_item_data').val() : $slot_for_booking.find('.unscheduled_booking_item_data').val()
3797 },
3798 return_format: 'json'
3799 }
3800 jQuery.ajax({
3801 type : "post",
3802 dataType : "json",
3803 url : latepoint_timestamped_ajaxurl(),
3804 data : data,
3805 success: function(response){
3806 if(response.status === "success"){
3807 let $form = jQuery(response.message);
3808 $slot_for_booking.removeClass('os-loading');
3809 if($slot_for_booking){
3810 $slot_for_booking.find('.scheduled-bundle-booking').html($form).closest('.order-item-variant-bundle-booking ').addClass('is-booked');
3811 }else{
3812 jQuery('.order-items-list').prepend($form);
3813 }
3814 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') + '"]'));
3815 // new item added, trigger change event
3816 if(!$slot_for_booking) latepoint_quick_order_items_changed();
3817 }else{
3818 alert(response.message, 'error');
3819 }
3820 }
3821 });
3822 }
3823
3824 function latepoint_bundle_added_to_quick_order(){
3825 latepoint_quick_order_items_changed();
3826 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
3827 }
3828
3829 function latepoint_quick_order_items_changed(){
3830 latepoint_reload_price_breakdown();
3831 }
3832
3833
3834 function latepoint_fold_booking_data_form_in_order_quick_edit($booking_data_form){
3835 if(!$booking_data_form.length) return false;
3836 latepoint_close_quick_availability_form();
3837 latepoint_show_all_order_items();
3838 let order_item_id = $booking_data_form.data('order-item-id');
3839 let booking_id = $booking_data_form.data('booking-id');
3840 let order_item_variant = $booking_data_form.data('order-item-variant');
3841
3842
3843 $booking_data_form.addClass('is-loading');
3844
3845 let form_data = new FormData(jQuery('.order-quick-edit-form')[0]);
3846 form_data.set('order_item_id', order_item_id);
3847 form_data.set('booking_id', booking_id);
3848 var data = {
3849 action: 'latepoint_route_call',
3850 route_name: jQuery('.order-form-add-item-btn').data('fold-booking-data-route-name'),
3851 params: latepoint_formdata_to_url_encoded_string(form_data),
3852 return_format: 'json'
3853 }
3854 jQuery.ajax({
3855 type : "post",
3856 dataType : "json",
3857 url : latepoint_timestamped_ajaxurl(),
3858 data : data,
3859 success: function(response){
3860 if(response.status === "success"){
3861 $booking_data_form.removeClass('is-loading').removeClass('is-unfolded').addClass('is-folded');
3862 if(order_item_variant == latepoint_helper.order_item_variant_bundle){
3863 $booking_data_form.closest('.order-item-variant-bundle-booking').addClass('is-booked');
3864 $booking_data_form.find('.bundle-booking-item-pill').replaceWith(response.message);
3865 }else{
3866 $booking_data_form.find('.order-item-pill').replaceWith(response.message);
3867 }
3868 }else{
3869 alert(response.message, 'error');
3870 }
3871 }
3872 });
3873 }
3874
3875
3876 function latepoint_init_booking_data_form($booking_data_form){
3877 latepoint_init_input_masks($booking_data_form);
3878
3879 $booking_data_form.find('.fold-order-item-booking-data-form-btn').on('click', function(){
3880 latepoint_fold_booking_data_form_in_order_quick_edit($booking_data_form);
3881 return false;
3882 });
3883
3884 $booking_data_form.find('.quick-booking-form-view-log-btn').on('click', function(){
3885 var $trigger_elem = jQuery(this);
3886 $trigger_elem.addClass('os-loading');
3887 var route = $trigger_elem.data('route');
3888 var data = { action: 'latepoint_route_call', route_name: route, params: {booking_id: $trigger_elem.data('booking-id')}, return_format: 'json' }
3889 jQuery.ajax({
3890 type : "post",
3891 dataType : "json",
3892 url : latepoint_timestamped_ajaxurl(),
3893 data : data,
3894 success: function(response){
3895 $trigger_elem.removeClass('os-loading');
3896 if(response.status === "success"){
3897 latepoint_display_in_side_sub_panel(response.message);
3898 jQuery('body').addClass('has-side-sub-panel');
3899 }else{
3900 alert(response.message, 'error');
3901 }
3902 }
3903 });
3904 return false;
3905 });
3906
3907
3908 $booking_data_form.find('.os-late-select').lateSelect();
3909
3910 $booking_data_form.find('.trigger-quick-availability').on('click', function(){
3911 latepoint_load_quick_availability(jQuery(this));
3912 return false;
3913 });
3914
3915 let field_base_name = 'order_items[' + $booking_data_form.data('order-item-id') +'][bookings][' + $booking_data_form.data('booking-id') +']';
3916
3917 $booking_data_form.find('input[name="' + field_base_name +'[start_time][formatted_value]"]').on('change', function(){
3918 latepoint_set_booking_end_time($booking_data_form);
3919 });
3920 $booking_data_form.find('input[name="' + field_base_name +'[end_time][formatted_value]"]').on('change', function(){
3921 latepoint_is_next_day($booking_data_form);
3922 });
3923
3924
3925
3926 $booking_data_form.on('change', '.agent-selector', function(){
3927 latepoint_apply_agent_selector_change($booking_data_form);
3928 });
3929 $booking_data_form.on('change', '.location-selector', function(){
3930 latepoint_apply_agent_selector_change($booking_data_form);
3931 });
3932 $booking_data_form.on('change', 'select[name="booking[location_id]"]', function(){
3933 latepoint_apply_agent_selector_change($booking_data_form);
3934 });
3935 $booking_data_form.on('change', 'select[name="booking[total_attendees]"]', function(){
3936 latepoint_apply_agent_selector_change($booking_data_form);
3937 });
3938
3939 $booking_data_form.on('change', '.os-affects-duration', function(){
3940 latepoint_set_booking_end_time($booking_data_form);
3941 if(jQuery('.quick-availability-per-day-w').length){
3942 latepoint_load_quick_availability($booking_data_form.find('.trigger-quick-availability'));
3943 }
3944 });
3945
3946 $booking_data_form.on('change', '.os-affects-price', function(){
3947 latepoint_reload_price_breakdown();
3948 });
3949
3950 $booking_data_form.on('change', '.os-affects-balance', function(){
3951 latepoint_reload_balance_and_payments();
3952 });
3953 $booking_data_form.on('keyup', '.os-affects-balance', function(event){
3954 if(event.keyCode == 13) {
3955 latepoint_reload_balance_and_payments();
3956 }
3957 });
3958
3959
3960 $booking_data_form.on('click', '.services-options-list .service-option', function(){
3961 var selected_option_html = jQuery(this).html();
3962 var $selected_option = jQuery(this).closest('.os-services-select-field-w').find('.service-option-selected');
3963 $selected_option.html(selected_option_html)
3964 .data('id', jQuery(this).data('id'))
3965 .data('duration', jQuery(this).data('duration'))
3966 .data('duration-name', jQuery(this).data('duration-name'))
3967 .data('buffer-before', jQuery(this).data('buffer-before'))
3968 .data('buffer-after', jQuery(this).data('buffer-after'))
3969 .data('capacity-min', jQuery(this).data('capacity-min'))
3970 .data('capacity-max', jQuery(this).data('capacity-max'))
3971 .data('extra-durations', jQuery(this).data('extra-durations'));
3972 jQuery(this).closest('.os-services-select-field-w').find('.service-option.selected').removeClass('selected');
3973 jQuery(this).addClass('selected').closest('.os-services-select-field-w').removeClass('active');
3974 latepoint_apply_service_selector_change($booking_data_form);
3975 return false;
3976 });
3977
3978 $booking_data_form.trigger('latepoint:initBookingDataForm');
3979
3980 }
3981
3982 function latepoint_init_payment_request_form($quick_order_form){
3983 $quick_order_form.find('select[name="payment_request[portion]"]').on('change', function(){
3984 if(jQuery(this).val() == 'custom'){
3985 $quick_order_form.find('.custom-charge-amount-wrapper').show();
3986 }else{
3987 $quick_order_form.find('.custom-charge-amount-wrapper').hide();
3988 }
3989 })
3990 }
3991
3992 function latepoint_show_all_order_items(){
3993 let $quick_order_form = jQuery('.quick-order-form-w');
3994 $quick_order_form.find('.order-items-info-w').removeClass('show-preselected-only');
3995 $quick_order_form.find('.holds-preselected-booking').removeClass('holds-preselected-booking');
3996 }
3997
3998 function latepoint_init_quick_order_form(){
3999 let $quick_order_form = jQuery('.quick-order-form-w');
4000 $quick_order_form.trigger('latepoint:initOrderEditForm');
4001
4002 $quick_order_form.on('change', '.os-affects-balance', function(){
4003 latepoint_reload_balance_and_payments();
4004 });
4005 $quick_order_form.on('keyup', '.os-affects-balance', function(event){
4006 if(event.keyCode == 13) {
4007 latepoint_reload_balance_and_payments();
4008 }
4009 });
4010
4011 latepoint_init_customer_inline_edit_form($quick_order_form.find('.customer-info-w'));
4012 $quick_order_form.find('.order-item-booking-data-form-wrapper').each(function(){
4013 latepoint_init_booking_data_form(jQuery(this));
4014 });
4015
4016 latepoint_lightbox_close();
4017 latepoint_remove_floating_popup();
4018 latepoint_init_input_masks($quick_order_form);
4019 latepoint_init_daterangepicker($quick_order_form.find('.os-date-range-picker'));
4020 latepoint_init_payment_request_form($quick_order_form);
4021
4022 // Transactions
4023
4024 $quick_order_form.on('click', '.transaction-refund-settings-button', function(){
4025 jQuery(this).closest('.quick-add-transaction-box-w').addClass('show-refund-settings');
4026 });
4027 $quick_order_form.on('click', '.transaction-refund-submit-button', function(){
4028 let $trigger_elem = jQuery(this);
4029 if(confirm(jQuery(this).data('os-prompt'))){
4030 $trigger_elem.addClass('os-loading');
4031 let route = $trigger_elem.data('route');
4032 let data = { action: 'latepoint_route_call', route_name: route, params: $trigger_elem.closest('.refund-settings-fields').find('input, textarea, select').serialize(), return_format: 'json' }
4033 jQuery.ajax({
4034 type : "post",
4035 dataType : "json",
4036 url : latepoint_timestamped_ajaxurl(),
4037 data : data,
4038 success: function(response){
4039 $trigger_elem.removeClass('os-loading');
4040 if(response.status === "success"){
4041 $trigger_elem.closest('.quick-add-transaction-box-w').replaceWith(response.message);
4042 latepoint_reload_balance_and_payments();
4043 }else{
4044 alert(response.message, 'error');
4045 }
4046 }
4047 });
4048 return false;
4049 }
4050 });
4051
4052 $quick_order_form.on('click', '.refund-settings-close', function(){
4053 jQuery(this).closest('.quick-add-transaction-box-w').removeClass('show-refund-settings');
4054 });
4055 $quick_order_form.on('change', '.refund-portion-selector', function(){
4056 if(jQuery(this).val() == 'full'){
4057 jQuery(this).closest('.refund-settings-fields').find('.custom-charge-amount-wrapper').hide();
4058 }else{
4059 jQuery(this).closest('.refund-settings-fields').find('.custom-charge-amount-wrapper').show();
4060 }
4061 });
4062
4063 // Log
4064
4065 $quick_order_form.find('.quick-order-form-view-log-btn').on('click', function(){
4066 var $trigger_elem = jQuery(this);
4067 $trigger_elem.addClass('os-loading');
4068 var route = $trigger_elem.data('route');
4069 var data = { action: 'latepoint_route_call', route_name: route, params: {order_id: $trigger_elem.data('order-id')}, return_format: 'json' }
4070 jQuery.ajax({
4071 type : "post",
4072 dataType : "json",
4073 url : latepoint_timestamped_ajaxurl(),
4074 data : data,
4075 success: function(response){
4076 $trigger_elem.removeClass('os-loading');
4077 if(response.status === "success"){
4078 latepoint_display_in_side_sub_panel(response.message);
4079 jQuery('body').addClass('has-side-sub-panel');
4080 }else{
4081 alert(response.message, 'error');
4082 }
4083 }
4084 });
4085 return false;
4086 });
4087
4088
4089 $quick_order_form.find('.new-order-item-variant-bundle').on('click', function(){
4090 $quick_order_form.find('.new-order-item-list-bundles-wrapper').toggleClass('is-open');
4091 $quick_order_form.find('.new-order-item-variant-selector-wrapper').toggleClass('is-open');
4092 return false;
4093 });
4094
4095
4096
4097
4098 $quick_order_form.find('.hidden-order-items-notice-link, .hidden-bundle-items-notice-link').on('click', function(e){
4099 latepoint_show_all_order_items();
4100 return false;
4101 });
4102
4103 $quick_order_form.find('.order-quick-edit-form').on('submit', function(e){
4104 if(jQuery(this).find('button[type="submit"]').hasClass('os-loading')) return false;
4105 e.preventDefault();
4106 latepoint_submit_quick_order_form();
4107 });
4108
4109 $quick_order_form.on("keydown", ":input:not(textarea):not(:submit)", function(event) {
4110 if (event.key == "Enter") {
4111 event.preventDefault();
4112 }
4113 });
4114
4115 $quick_order_form.find('.order-items-list').on('click', '.remove-order-item-btn', function(){
4116 latepoint_close_quick_availability_form();
4117 if(confirm(jQuery(this).data('os-prompt'))){
4118 if(jQuery(this).closest('.order-item-variant-bundle-booking-wrapper').length){
4119 // it's a bundle booking
4120 // need to figure out how to remove it when bundle
4121 jQuery(this).closest('.order-item-variant-bundle-booking').removeClass('is-booked').find('.scheduled-bundle-booking').html('');
4122 }else{
4123 jQuery(this).closest('.order-item').remove();
4124 jQuery(this).closest('.order-item-booking-data-form-wrapper').remove();
4125
4126 }
4127 latepoint_quick_order_items_changed();
4128 }
4129 return false;
4130 });
4131
4132 $quick_order_form.find('.new-order-item-variant-booking').on('click', function(){
4133 latepoint_fold_all_open_booking_data_forms();
4134 latepoint_build_new_booking_order_item();
4135 });
4136
4137 $quick_order_form.on('click', '.order-item-pill.order-item-pill-variant-booking', function(){
4138 jQuery(this).closest('.order-item-booking-data-form-wrapper').removeClass('is-folded').addClass('is-unfolded');
4139 return false;
4140 });
4141
4142 $quick_order_form.on('click', '.bundle-booking-item-pill', function(){
4143 jQuery(this).closest('.order-item-booking-data-form-wrapper').removeClass('is-folded').addClass('is-unfolded');
4144 return false;
4145 });
4146
4147 $quick_order_form.on('click', '.unscheduled-bundle-booking', function(){
4148 latepoint_build_booking_data_form_for_bundle(jQuery(this).closest('.order-item-variant-bundle-booking'));
4149 });
4150
4151
4152 $quick_order_form.find('.order-form-add-item-btn').on('click', function(){
4153 let $booking_data_forms = jQuery('.order-item-booking-data-form-wrapper');
4154 $booking_data_forms.each(function(){
4155 latepoint_fold_booking_data_form_in_order_quick_edit(jQuery(this));
4156 });
4157 if(jQuery(this).hasClass('is-cancelling')){
4158 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
4159 }else{
4160 if(jQuery('.new-order-item-variant-selector-wrapper').length){
4161 jQuery('.order-items-list').addClass('is-blurred');
4162 jQuery('.new-order-item-variant-selector-wrapper').addClass('is-open');
4163 jQuery(this).addClass('is-cancelling').find('span').text(jQuery(this).data('cancel-label'));
4164 }else{
4165 // no bundles exist, create booking form
4166 latepoint_cancel_adding_new_order_item_to_quick_edit_form();
4167 latepoint_build_new_booking_order_item();
4168 }
4169 }
4170 return false;
4171 });
4172
4173
4174 $quick_order_form.on('click', '.order-item-variant-bundle .bundle-icon', function(){
4175 jQuery(this).closest('.order-item-variant-bundle').toggleClass('is-open');
4176 return false;
4177 });
4178
4179 $quick_order_form.find('.reload-price-breakdown').on('click', function(){
4180 latepoint_reload_price_breakdown();
4181 return false;
4182 });
4183
4184 $quick_order_form.on('click', '.trigger-remove-transaction-btn', function(){
4185 jQuery(this).closest('.quick-add-transaction-box-w').remove();
4186 return false;
4187 });
4188
4189
4190 $quick_order_form.trigger('latepoint:initQuickOrderForm');
4191 }
4192
4193 function latepoint_fold_all_open_booking_data_forms(){
4194 let $booking_data_forms = jQuery('.order-item-booking-data-form-wrapper');
4195 $booking_data_forms.each(function(){
4196 latepoint_fold_booking_data_form_in_order_quick_edit(jQuery(this));
4197 });
4198 }
4199
4200 function latepoint_init_customer_inline_edit_form($customer_form){
4201
4202 latepoint_init_input_masks($customer_form);
4203
4204 $customer_form.find('.customers-selector-search-input').on('keyup',function(){
4205 var $queryInput = jQuery(this);
4206 var query = $queryInput.val().toLowerCase();
4207 if(query == $queryInput.data('current-query')) return;
4208
4209 // Search
4210 $queryInput.closest('.customers-selector-search-w').addClass('os-loading');
4211 $queryInput.data('searching-query', query);
4212 setTimeout(function(){
4213 if(query != jQuery('.customers-selector-search-input').data('searching-query')) return;
4214 var data = { action: latepoint_helper.route_action, route_name: $queryInput.data('route'), params: {query: query}, return_format: 'json' }
4215 jQuery.ajax({
4216 type : "post",
4217 dataType : "json",
4218 url : latepoint_timestamped_ajaxurl(),
4219 data : data,
4220 success: function(response){
4221 if($queryInput.data('searching-query') != query) return;
4222 $queryInput.closest('.customers-selector-search-w').removeClass('os-loading');
4223 if(response.status === "success"){
4224 $queryInput.data('current-query', query);
4225 jQuery('.quick-order-form-w .customers-options-list').html(response.message);
4226 }else{
4227 // console.log(response.message);
4228 }
4229 }
4230 });
4231 }, 300, query, $queryInput);
4232 });
4233
4234 }
4235
4236
4237 function latepoint_load_quick_availability($trigger_elem, custom_agent_id = false, start_date = false, load_more_days = false, load_prev_days = false){
4238 $trigger_elem.addClass('os-loading');
4239
4240 let $booking_form = $trigger_elem.closest('.order-item-booking-data-form-wrapper');
4241 var route = $booking_form.find('.trigger-quick-availability').data('route');
4242 var $quick_order_form = jQuery('.quick-order-form-w');
4243
4244 if(custom_agent_id) $quick_order_form.find('.agent-selector').val(custom_agent_id);
4245 if(!$quick_order_form.find('.service-selector').val() || $quick_order_form.find('.service-selector').val() == '0'){
4246 $quick_order_form.find('.os-services-select-field-w .service-option:first').trigger('click');
4247 }
4248
4249 let form_data = new FormData($quick_order_form.find('form')[0]);
4250
4251
4252 form_data.set('trigger_form_booking_id', $booking_form.data('booking-id'));
4253 form_data.set('trigger_form_order_item_id', $booking_form.data('order-item-id'));
4254
4255 if(start_date) form_data.set('start_date', start_date);
4256 if(load_more_days || load_prev_days) form_data.set('show_days_only', true);
4257 if(load_prev_days) form_data.set('previous_days', true);
4258
4259 var data = {
4260 action: latepoint_helper.route_action,
4261 route_name: route,
4262 params: latepoint_formdata_to_url_encoded_string(form_data),
4263 return_format: 'json'
4264 }
4265
4266 jQuery.ajax({
4267 type : "post",
4268 dataType : "json",
4269 url : latepoint_timestamped_ajaxurl(),
4270 data : data,
4271 success: function(response){
4272 $trigger_elem.removeClass('os-loading');
4273 if(response.status === "success"){
4274 if(load_more_days){
4275 jQuery('.latepoint-side-panel-w .quick-availability-per-day-w').html(response.message);
4276 jQuery('.latepoint-side-panel-w .os-availability-days').scrollTop(52);
4277 }else if(load_prev_days){
4278 jQuery('.latepoint-side-panel-w .quick-availability-per-day-w').html(response.message);
4279 console.log(jQuery('.latepoint-side-panel-w .os-availability-days')[0].scrollHeight);
4280 jQuery('.latepoint-side-panel-w .os-availability-days').scrollTop(jQuery('.latepoint-side-panel-w .os-availability-days')[0].scrollHeight - jQuery('.latepoint-side-panel-w .os-availability-days')[0].clientHeight - 50);
4281 }else{
4282 latepoint_display_in_side_sub_panel(response.message);
4283 jQuery('.latepoint-side-panel-w .os-availability-days').scrollTop(52);
4284 jQuery('body').addClass('has-side-sub-panel');
4285 latepoint_init_quick_availability_form();
4286 }
4287 }else{
4288 alert(response.message, 'error');
4289 }
4290 }
4291 });
4292 }
4293
4294 function latepoint_create_field_base_name(order_item_id, booking_id){
4295 return 'order_items['+order_item_id+'][bookings]['+booking_id+']';
4296 }
4297
4298 function latepoint_close_quick_availability_form(){
4299 jQuery('.quick-availability-per-day-w').remove();
4300 jQuery('body').removeClass('has-side-sub-panel');
4301 }
4302
4303 function latepoint_init_quick_availability_form(){
4304 // TODO set booking ID
4305 let $quick_availability_wrapper = jQuery('.quick-availability-per-day-w');
4306
4307 let trigger_form_order_item_id = $quick_availability_wrapper.data('trigger-form-order-item-id');
4308 let trigger_form_booking_id = $quick_availability_wrapper.data('trigger-form-booking-id');
4309
4310 let field_base_name = latepoint_create_field_base_name(trigger_form_order_item_id, trigger_form_booking_id);
4311
4312 let $booking_data_form = jQuery('.quick-order-form-w .order-item-booking-data-form-wrapper[data-booking-id="'+trigger_form_booking_id+'"]');
4313
4314 var selected_start_date = $booking_data_form.find('input[name="'+field_base_name+'[start_date_formatted]"').val();
4315 var selected_start_time = $booking_data_form.find('input[name="'+field_base_name+'[start_time][formatted_value]"]').val();
4316 var selected_start_time_ampm = $booking_data_form.find('input[name="'+field_base_name+'[start_time][ampm]"]').val();
4317
4318
4319 var selected_start_time_minutes = latepoint_hours_and_minutes_to_minutes(selected_start_time, selected_start_time_ampm);
4320 $quick_availability_wrapper.find('.os-availability-days').find('.agent-timeslot[data-formatted-date="'+ selected_start_date +'"][data-minutes="' + selected_start_time_minutes + '"]').addClass('selected');
4321 $quick_availability_wrapper.on('click', '.load-more-quick-availability', function(){
4322 jQuery(this).addClass('os-loading');
4323 let booking_form_id = jQuery(this).closest('.quick-availability-per-day-w').data('trigger-form-booking-id');
4324 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
4325 latepoint_load_quick_availability($trigger_btn, false, jQuery(this).data('start-date'), true);
4326 return false;
4327 });
4328 $quick_availability_wrapper.on('click', '.load-prev-quick-availability', function(){
4329 jQuery(this).addClass('os-loading');
4330 let booking_form_id = jQuery(this).closest('.quick-availability-per-day-w').data('trigger-form-booking-id');
4331 let $trigger_btn = jQuery('.order-item-booking-data-form-wrapper[data-booking-id="' + booking_form_id + '"]').find('.trigger-quick-availability');
4332 latepoint_load_quick_availability($trigger_btn, false, jQuery(this).data('start-date'), false, true);
4333 return false;
4334 });
4335 $quick_availability_wrapper.find('select[name="booking[agent_id]"]').on('change', function(){
4336 latepoint_load_quick_availability(jQuery('.trigger-quick-availability'), jQuery(this).val());
4337 });
4338 jQuery('.os-time-group label').on('click', function(){
4339 jQuery(this).closest('.os-time-group').find('.os-form-control').trigger('focus');
4340 });
4341 $quick_availability_wrapper.on('click', '.fill-booking-time', function(){
4342 jQuery('.os-availability-days .agent-timeslot.selected').removeClass('selected');
4343 jQuery(this).addClass('selected');
4344 var formatted_date = jQuery(this).data('formatted-date');
4345 var minutes = jQuery(this).data('minutes');
4346 $booking_data_form.find('input[name="'+field_base_name+'[start_date_formatted]"]').val(formatted_date);
4347 var start_minutes = minutes;
4348 var start_hours_and_minutes = latepoint_minutes_to_hours_and_minutes(start_minutes);
4349
4350 if(start_minutes >= 720){
4351 $booking_data_form.find('.quick-start-time-w .time-pm').trigger('click');
4352 }else{
4353 $booking_data_form.find('.quick-start-time-w .time-am').trigger('click');
4354 }
4355
4356 $booking_data_form.find('input[name="'+field_base_name+'[start_time][formatted_value]"]').val(start_hours_and_minutes);
4357 latepoint_set_booking_end_time($booking_data_form);
4358 $booking_data_form.find('.ws-period, .as-period').addClass('animate-filled-in');
4359 setTimeout(function(){
4360 $booking_data_form.find('.ws-period, .as-period').removeClass('animate-filled-in');
4361 }, 500)
4362 });
4363 }
4364
4365
4366 function latepoint_reload_after_order_save(){
4367 latepoint_reload_calendar_view();
4368
4369 jQuery('.os-widget').each(function(){
4370 latepoint_reload_widget(jQuery(this));
4371 });
4372 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'));
4373 latepoint_close_side_panel();
4374 }
4375
4376 /*
4377 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
4378 */
4379
4380 class LatepointStripeConnectAdmin {
4381
4382 // Init
4383 constructor(){
4384 this.ready();
4385 }
4386
4387 ready() {
4388 jQuery(document).ready(() => {
4389 jQuery('.stripe-connect-status-wrapper').on('click', '.payment-start-connecting', function(){
4390 let $link = jQuery(this);
4391 $link.addClass('os-loading');
4392 var data = {
4393 action: 'latepoint_route_call',
4394 route_name: $link.data('route-name'),
4395 params: { env: $link.data('env') },
4396 layout: 'none',
4397 return_format: 'json'
4398 }
4399 jQuery.ajax({
4400 type : "post",
4401 dataType : "json",
4402 url : latepoint_timestamped_ajaxurl(),
4403 data : data,
4404 success: (data) => {
4405 window.location.href = data.url;
4406 }
4407 });
4408 return false;
4409 });
4410
4411 if(jQuery('.stripe-connect-status-wrapper').length){
4412 jQuery('.stripe-connect-status-wrapper').each((index, elem) => {
4413 let $wrapper = jQuery(elem);
4414 var data = {
4415 action: 'latepoint_route_call',
4416 route_name: $wrapper.data('route-name'),
4417 params: { env: $wrapper.data('env') },
4418 layout: 'none',
4419 return_format: 'json'
4420 }
4421 jQuery.ajax({
4422 type : "post",
4423 dataType : "json",
4424 url : latepoint_timestamped_ajaxurl(),
4425 data : data,
4426 success: (data) => {
4427 this.reload_connect_status_wrapper($wrapper, data);
4428 }
4429 });
4430 })
4431 }
4432 });
4433 }
4434
4435
4436 reload_connect_status_wrapper($elem, data){
4437 if(data.status === 'success'){
4438 if($elem.hasClass('.stripe-connect-status-wrapper')){
4439 $elem.html(data.message);
4440 }else{
4441 $elem.closest('.stripe-connect-status-wrapper').html(data.message);
4442 }
4443 }else{
4444 alert(data.message);
4445 }
4446 }
4447
4448
4449 }
4450
4451
4452 window.latepointStripeConnectAdmin = new LatepointStripeConnectAdmin();
4453
4454 /*
4455 * Copyright (c) 2022 LatePoint LLC. All rights reserved.
4456 */
4457
4458 // @codekit-prepend "bin/time.js";
4459 // @codekit-prepend "bin/lateselect.js";
4460 // @codekit-prepend "bin/latecheckbox.js";
4461 // @codekit-prepend "bin/actions.js";
4462 // @codekit-prepend "bin/notifications.js";
4463 // @codekit-prepend "bin/shared.js";
4464 // @codekit-prepend "bin/admin/updates.js";
4465 // @codekit-prepend "bin/admin/main.js";
4466 // @codekit-prepend "bin/admin/_agents.js";
4467 // @codekit-prepend "bin/admin/_customers.js";
4468 // @codekit-prepend "bin/admin/_chart.js";
4469 // @codekit-prepend "bin/admin/_calendar.js";
4470 // @codekit-prepend "bin/admin/_processes.js";
4471 // @codekit-prepend "bin/admin/_steps.js";
4472 // @codekit-prepend "bin/admin/_orders.js";
4473 // @codekit-prepend "bin/admin/_stripe_connect.js";
4474
4475
4476
4477 // DOCUMENT READY
4478 jQuery(document).ready(function( $ ) {
4479
4480
4481 // DASHBOARD
4482 latepoint_init_calendars();
4483 latepoint_init_circles_charts();
4484 latepoint_init_donut_charts();
4485 latepoint_init_daily_bookings_chart();
4486 latepoint_init_element_togglers();
4487 latepoint_init_daterangepicker(jQuery('.os-date-range-picker'));
4488 latepoint_init_monthly_view();
4489 latepoint_init_form_blocks();
4490 latepoint_init_reminders_form();
4491 latepoint_init_coupons_form();
4492 latepoint_init_copy_on_click_elements();
4493 latepoint_init_side_menu();
4494 latepoint_init_color_picker();
4495 latepoint_init_clickable_cells();
4496 latepoint_init_input_masks();
4497 latepoint_init_process_forms();
4498 latepoint_init_sticky_side_menu();
4499 latepoint_init_sortable_columns();
4500 latepoint_init_accordions();
4501 latepoint_init_default_form_fields_settings();
4502 latepoint_init_steps_settings();
4503 latepoint_init_booking_form_preview();
4504
4505 latepoint_init_version5_intro();
4506
4507 jQuery(document).on({
4508 mouseenter: function () {
4509 let $elem = jQuery(this);
4510 let offset = $elem.offset();
4511 jQuery('body > .late-tooltip').remove();
4512 let $popup = jQuery('<div/>').addClass('late-tooltip').text($elem.data('late-tooltip')).appendTo(jQuery('body'));
4513 $popup.css('top', offset.top - 2);
4514 $popup.css('left', offset.left + $elem.outerWidth() / 2);
4515 return false;
4516 },
4517 mouseleave: function () {
4518 jQuery('body > .late-tooltip').remove();
4519 }
4520 }, "[data-late-tooltip]");
4521
4522 jQuery('body').on('click', '.disabled-items-open-trigger', function(){
4523 jQuery('.disabled-items-wrapper').toggleClass('is-open');
4524 return false;
4525 });
4526
4527 jQuery('body').on('click', '.latepoint-side-panel-close', function(){
4528 jQuery('.side-sub-panel-wrapper').remove();
4529 return false;
4530 });
4531
4532 jQuery('#settings_list_of_phone_countries').on('change', function(){
4533 if(jQuery(this).val() == latepoint_helper.value_all){
4534 jQuery('.select-phone-countries-wrapper').hide();
4535 }else{
4536 jQuery('.select-phone-countries-wrapper').show();
4537 }
4538 });
4539
4540 jQuery('.os-select-all-toggler').on('change', function(){
4541 var $connection_wrappers = jQuery(this).closest('.white-box').find('.os-complex-connections-selector .connection');
4542 if(jQuery(this).is(':checked')){
4543 latepoint_complex_selector_select($connection_wrappers);
4544 }else{
4545 latepoint_complex_selector_deselect($connection_wrappers);
4546 }
4547 return false;
4548 });
4549
4550
4551 jQuery('.os-main-location-selector').on('change', function(){
4552 var route = jQuery(this).data('route');
4553 var params = 'id=' + jQuery(this).val();
4554 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4555 jQuery('.latepoint-content-w').addClass('os-loading');
4556 jQuery.ajax({
4557 type : "post",
4558 dataType : "json",
4559 url : latepoint_timestamped_ajaxurl(),
4560 data : data,
4561 success: function(data){
4562 location.reload();
4563 }
4564 });
4565 });
4566
4567 jQuery('.os-service-durations-w').on('click', '.os-remove-duration', function(){
4568 jQuery(this).closest('.duration-box').slideUp(300, function(){
4569 jQuery(this).remove();
4570 });
4571 return false;
4572 });
4573
4574
4575 jQuery('.menu-color-toggler').on('click', function(){
4576 jQuery('.latepoint-side-menu-w').toggleClass('dark');
4577 return false;
4578 });
4579
4580
4581 jQuery('.latepoint-mobile-top-menu-trigger').on('click', function(){
4582 jQuery(this).closest('.latepoint-all-wrapper').toggleClass('os-show-mobile-menu');
4583 if(jQuery(this).closest('.latepoint-all-wrapper').hasClass('os-show-mobile-menu')){
4584 jQuery('.latepoint-side-menu-w ul.side-menu > li.has-children > a').on('click', function(){
4585 jQuery(this).closest('li').toggleClass('menu-item-sub-open-mobile');
4586 return false;
4587 });
4588 }else{
4589 jQuery('.latepoint-side-menu-w ul.side-menu > li.has-children > a').off('click');
4590 }
4591 return false;
4592 });
4593
4594 jQuery('.latepoint-mobile-top-search-trigger-cancel').on('click', function(){
4595 jQuery(this).closest('.latepoint-all-wrapper').removeClass('os-show-mobile-search');
4596 return false;
4597 });
4598
4599 jQuery('.latepoint-mobile-top-search-trigger').on('click', function(){
4600 jQuery(this).closest('.latepoint-all-wrapper').toggleClass('os-show-mobile-search');
4601 if(jQuery(this).closest('.latepoint-all-wrapper').hasClass('os-show-mobile-search')){
4602 jQuery('.latepoint-top-search').trigger('focus');
4603 }
4604 return false;
4605 });
4606
4607
4608 jQuery('.latepoint-side-menu-w').on('click', '.top-user-info-toggler', function(){
4609 jQuery('.latepoint-user-info-dropdown').toggleClass('os-visible');
4610 return false;
4611 });
4612
4613 jQuery('.latepoint-content').on('click', '.mobile-calendar-actions-trigger', function(){
4614 jQuery(this).closest('.calendar-mobile-controls').toggleClass('os-show-actions');
4615 return false;
4616 });
4617
4618 jQuery('.latepoint-content').on('click', '.os-widget-header-actions-trigger', function(){
4619 jQuery(this).closest('.os-widget-header').toggleClass('os-show-actions');
4620 return false;
4621 });
4622
4623 jQuery('.latepoint-content').on('click', '.mobile-table-actions-trigger', function(){
4624 jQuery(this).closest('.os-pagination-w').toggleClass('os-show-actions');
4625 return false;
4626 });
4627
4628
4629
4630
4631
4632
4633 jQuery('.download-csv-with-filters').on('click', function(){
4634 var filter_params = jQuery(this).closest('.table-with-pagination-w').find('.os-table-filter').serialize();
4635 filter_params+= '&download=csv';
4636 jQuery(this).attr('href', this.href + '&' + filter_params);
4637 });
4638
4639 jQuery('select.pagination-page-select').on('change', function(){
4640 latepoint_filter_table(jQuery(this).closest('.table-with-pagination-w').find('table'), jQuery(this).closest('.pagination-page-select-w'), false);
4641 });
4642
4643 jQuery('select.os-table-filter').on('change', function(){
4644 latepoint_filter_table(jQuery(this).closest('table'), jQuery(this).closest('.os-form-group'));
4645 });
4646
4647 jQuery('input.os-table-filter').on('keyup', function(){
4648 latepoint_filter_table(jQuery(this).closest('table'), jQuery(this).closest('.os-form-group'));
4649 });
4650
4651
4652 jQuery('.customize-connection-btn').on('click', function(){
4653 jQuery(this).closest('.connection').toggleClass('show-customize-box');
4654 return false;
4655 });
4656
4657 jQuery('.connection-children-list').on('click', 'li', function(){
4658 if(jQuery(this).hasClass('active')){
4659 jQuery(this).removeClass('active');
4660 jQuery(this).find('input.connection-child-is-connected').val('no');
4661 }else{
4662 jQuery(this).addClass('active');
4663 jQuery(this).find('input.connection-child-is-connected').val('yes');
4664 }
4665 latepoint_count_active_connections(jQuery(this).closest('.connection'));
4666 return false;
4667 });
4668
4669 jQuery('.display-toggler-control').on('change', function(){
4670 let group = jQuery(this).data('toggler-group');
4671 let key = jQuery(this).val();
4672 jQuery('.display-toggler-target[data-toggler-group="' + group + '"]').hide();
4673 jQuery('.display-toggler-target[data-toggler-group="' + group + '"][data-toggler-key="'+ key +'"]').show();
4674 return false;
4675 });
4676
4677 jQuery('.add-item-category-trigger').on('click', function(){
4678 jQuery('.add-item-category-box').toggle();
4679 jQuery('.os-new-item-category-form-w').toggle();
4680 return false;
4681 });
4682
4683 jQuery('.latepoint-top-search').on('keyup', function(event){
4684 var $wrapper = jQuery(this).closest('.latepoint-top-search-w');
4685 $wrapper.addClass('os-loading');
4686 var query = jQuery(this).val();
4687 if(event.keyCode == 27){
4688 $wrapper.removeClass('typing');
4689 jQuery('.latepoint-top-search-results-w').html('');
4690 jQuery(this).val('');
4691 $wrapper.removeClass('os-loading');
4692 return;
4693 }
4694 if(query == ''){
4695 $wrapper.removeClass('typing');
4696 jQuery('.latepoint-top-search-results-w').html('');
4697 $wrapper.removeClass('os-loading');
4698 return;
4699 }
4700 var route = jQuery(this).data('route');
4701 var params = 'query=' + query;
4702 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4703 $wrapper.addClass('typing');
4704 jQuery.ajax({
4705 type : "post",
4706 dataType : "json",
4707 url : latepoint_timestamped_ajaxurl(),
4708 data : data,
4709 success: function(data){
4710 if(!$wrapper.hasClass('typing')) return;
4711 $wrapper.removeClass('os-loading');
4712 if(data.status === "success"){
4713 jQuery('.latepoint-top-search-results-w').html(data.message);
4714 }else{
4715 // console.log(data.message);
4716 }
4717 }
4718 });
4719 });
4720
4721
4722 jQuery('.appointment-status-selector').on('click', function(e){
4723 e.stopPropagation();
4724 });
4725
4726 jQuery('.latepoint-show-license-details').on('click', function(e){
4727 jQuery(this).closest('.active-license-info').find('.license-info-w').slideToggle(200);
4728 return false;
4729 });
4730
4731 jQuery('.aba-button-w').on('click', function(e){
4732 e.stopPropagation();
4733 var confirm_message = (jQuery(this).hasClass('aba-approve')) ? latepoint_helper.approve_confirm : latepoint_helper.reject_confirm;
4734 if(confirm(confirm_message)){
4735 var $box = jQuery(this).closest('.appointment-box-large');
4736 $box.find('.appointment-status-selector select').val(jQuery(this).data('status')).trigger('change');
4737 }
4738 return false;
4739 });
4740
4741
4742
4743 jQuery('.appointment-status-selector select').on('change', function(e){
4744 var $wrapper = jQuery(this).closest('.appointment-status-selector');
4745 var route = $wrapper.data('route');
4746 var nonce = $wrapper.data('wp-nonce');
4747 var booking_id = $wrapper.data('booking-id');
4748 var status = jQuery(this).val();
4749 jQuery(this).closest('.appointment-box-large').attr('class', 'appointment-box-large status-' + status);
4750 var params = 'id=' + booking_id + '&status=' + status + '&_wpnonce=' + nonce;
4751 var data = { action: latepoint_helper.route_action, route_name: route, params: params, layout: 'none', return_format: 'json' };
4752 jQuery.ajax({
4753 type : "post",
4754 dataType : "json",
4755 url : latepoint_timestamped_ajaxurl(),
4756 data : data,
4757 success: function(data){
4758 if(data.status === "success"){
4759 latepoint_add_notification(data.message);
4760 }else{
4761 latepoint_add_notification(data.message, 'error');
4762 // console.log(data.message);
4763 }
4764 }
4765 });
4766 });
4767
4768 jQuery('body').on('click', '.open-template-variables-panel', function(){
4769 jQuery('.latepoint-template-variables').toggleClass('is-visible');
4770 return false;
4771 });
4772
4773 jQuery('body').on('click', '.close-template-variables-panel', function(){
4774 jQuery('.latepoint-template-variables').removeClass('is-visible');
4775 return false;
4776 });
4777
4778 jQuery('body').on('click', '.open-layout-template-variables-panel', function(){
4779 jQuery('.latepoint-layout-template-variables').toggleClass('is-visible');
4780 return false;
4781 });
4782
4783 jQuery('body').on('click', '.close-layout-template-variables-panel', function(){
4784 jQuery('.latepoint-layout-template-variables').removeClass('is-visible');
4785 return false;
4786 });
4787
4788 jQuery('body').on('click', '.os-notifications .os-notification-close', function(){
4789 jQuery(this).closest('.item').remove();
4790 return false;
4791 });
4792
4793
4794 jQuery('body').on('keyup', '.os-form-group .os-form-control', function(){
4795 if(jQuery(this).val()){
4796 jQuery(this).closest('.os-form-group').addClass('has-value');
4797 }else{
4798 jQuery(this).closest('.os-form-group').removeClass('has-value');
4799 }
4800 });
4801
4802
4803
4804 jQuery('.os-wizard-setup-w, .latepoint-settings-w, .custom-schedule-wrapper').on('click', '.ws-head', function(){
4805 var $schedule_wrapper = jQuery(this).closest('.weekday-schedule-w');
4806 $schedule_wrapper.toggleClass('is-editing').removeClass('day-off');
4807 $schedule_wrapper.find('.os-toggler').removeClass('off');
4808 $schedule_wrapper.find('input.is-active').val(1);
4809 });
4810
4811
4812 jQuery('.latepoint').on('click', '.wizard-add-edit-item-trigger', function(e){
4813 jQuery(this).addClass('os-loading');
4814 var add_item_route_name = jQuery(this).data('route');
4815 var item_info = { };
4816 if(jQuery(this).data('id')){
4817 item_info.id = jQuery(this).data('id');
4818 }
4819 var data = { action: latepoint_helper.route_action, route_name: add_item_route_name, params: item_info, layout: 'none', return_format: 'json' };
4820 jQuery.ajax({
4821 type : "post",
4822 dataType : "json",
4823 url : latepoint_timestamped_ajaxurl(),
4824 data : data,
4825 success: function(data){
4826 jQuery('.wizard-add-edit-item-trigger.os-loading').removeClass('os-loading');
4827 if(data.status === "success"){
4828 jQuery('.os-wizard-step-content-i').html(data.message);
4829 jQuery('.os-wizard-setup-w').addClass('is-sub-editing');
4830 jQuery('.os-wizard-footer').hide();
4831 latepoint_init_wizard_content();
4832 }else{
4833 // console.log(data.message);
4834 }
4835 }
4836 });
4837 });
4838
4839
4840
4841
4842 jQuery('.latepoint').on('click', '.os-wizard-trigger-next-btn', function(){
4843 var $next_btn = jQuery(this);
4844 $next_btn.addClass('os-loading');
4845 var current_step_code = jQuery('#wizard_current_step_code').val();
4846 var params = 'current_step_code='+current_step_code;
4847
4848 // work periods step
4849 if(jQuery('.os-wizard-setup-w form.weekday-schedules-w').length){
4850 params+= '&'+ jQuery('.os-wizard-setup-w form.weekday-schedules-w .weekday-schedule-w:not(.day-off) input').serialize();
4851 }
4852 // agent/notifications step
4853 if(jQuery('.os-wizard-default-agent-form').length){
4854 params+= '&'+ jQuery('.os-wizard-default-agent-form input').serialize();
4855
4856 var $form = $('.os-wizard-default-agent-form');
4857 var form_data = new FormData($form[0]);
4858 form_data.set('current_step_code', current_step_code);
4859
4860 if (('lp_intlTelInputGlobals' in window) && ('lp_intlTelInputUtils' in window)) {
4861 // Get e164 formatted number from phone fields when form is submitted
4862 $form.find('input.os-mask-phone').each(function () {
4863 let telInstance = window.lp_intlTelInputGlobals.getInstance(this);
4864 if(telInstance){
4865 const phoneInputName = this.getAttribute('name');
4866 const phoneInputValue = window.lp_intlTelInputGlobals.getInstance(this).getNumber(window.lp_intlTelInputUtils.numberFormat.E164);
4867 form_data.set(phoneInputName, phoneInputValue);
4868 }
4869 });
4870 }
4871 params = latepoint_formdata_to_url_encoded_string(form_data);
4872 }
4873
4874 var data = {
4875 action: latepoint_helper.route_action,
4876 route_name: jQuery(this).data('route-name'),
4877 params: params,
4878 layout: 'none',
4879 return_format: 'json'};
4880 jQuery.ajax({
4881 type : "post",
4882 dataType : "json",
4883 url : latepoint_timestamped_ajaxurl(),
4884 data : data,
4885 success: function(data){
4886 $next_btn.removeClass('os-loading');
4887 if(data.status === "success"){
4888 jQuery('#wizard_current_step_code').val(data.step_code);
4889 jQuery('.os-wizard-setup-w').attr('class', 'os-wizard-setup-w step-' + data.step_code);
4890 jQuery('.os-wizard-step-content').html(data.message);
4891 latepoint_init_wizard_content();
4892 if(data.show_prev_btn){
4893 jQuery('.os-wizard-prev-btn').show();
4894 }else{
4895 jQuery('.os-wizard-prev-btn').hide();
4896 }
4897 if(data.show_next_btn){
4898 jQuery('.os-wizard-next-btn').show();
4899 }else{
4900 jQuery('.os-wizard-next-btn').hide();
4901 }
4902 if(!data.show_next_btn && !data.show_prev_btn){
4903 jQuery('.os-wizard-footer').hide();
4904 }else{
4905 jQuery('.os-wizard-footer').show();
4906 }
4907 }
4908 }
4909 });
4910 return false;
4911 });
4912
4913 // WIZARD PREV BUTTON CLICK LOGIC
4914 jQuery('.latepoint').on('click', '.os-wizard-trigger-prev-btn', function(){
4915 var $prev_btn = jQuery(this);
4916 $prev_btn.addClass('os-loading');
4917 var current_step_code = jQuery('#wizard_current_step_code').val();
4918 var params = 'current_step_code='+current_step_code;
4919 var data = { action: latepoint_helper.route_action, route_name: jQuery(this).data('route-name'), params: params, layout: 'none', return_format: 'json'};
4920 jQuery.ajax({
4921 type : "post",
4922 dataType : "json",
4923 url : latepoint_timestamped_ajaxurl(),
4924 data : data,
4925 success: function(data){
4926 $prev_btn.removeClass('os-loading');
4927 if(data.status === "success"){
4928 jQuery('#wizard_current_step_code').val(data.step_code);
4929 jQuery('.os-wizard-setup-w').attr('class', 'os-wizard-setup-w step-' + data.step_code);
4930 jQuery('.os-wizard-step-content').html(data.message);
4931 latepoint_init_wizard_content();
4932 if(data.show_prev_btn){
4933 jQuery('.os-wizard-prev-btn').show();
4934 }else{
4935 jQuery('.os-wizard-prev-btn').hide();
4936 }
4937 if(data.show_next_btn){
4938 jQuery('.os-wizard-next-btn').show();
4939 }else{
4940 jQuery('.os-wizard-next-btn').hide();
4941 }
4942 if(!data.show_next_btn && !data.show_prev_btn){
4943 jQuery('.os-wizard-footer').hide();
4944 }else{
4945 jQuery('.os-wizard-footer').show();
4946 }
4947 }
4948 }
4949 });
4950 return false;
4951 });
4952
4953 jQuery('.latepoint-content-w').on('change', '.os-widget .os-trigger-reload-widget', function(){
4954 latepoint_reload_widget(jQuery(this).closest('.os-widget'));
4955 });
4956
4957 jQuery('.latepoint-content-w').on('click', '.os-widget .timeline-type-toggle .timeline-type-option', function(){
4958 jQuery(this).closest('.timeline-type-toggle').find('.timeline-type-option.active').removeClass('active');
4959 jQuery(this).addClass('active');
4960 jQuery('.timeline-and-availability-contents').removeClass('shows-appointments shows-availability').addClass('shows-' + jQuery(this).data('value'));
4961 jQuery('#' + jQuery(this).closest('.timeline-type-toggle').data('value-holder-id')).val(jQuery(this).data('value'));
4962 });
4963
4964
4965 dragula([].slice.apply(document.querySelectorAll('.os-categories-ordering-w .os-category-children')), {
4966 moves: function (el, container, handle) {
4967 return (handle.classList.contains('os-category-drag') || handle.classList.contains('os-category-item-drag'));
4968 },
4969 }).on('drop', function(el){
4970 var $categories_wrapper = jQuery('.os-categories-ordering-w');
4971 var category_datas = [];
4972 var item_datas = [];
4973
4974 $categories_wrapper.find('.os-category-parent-w').each(function(index){
4975 var order_number = jQuery(this).index() + 1;
4976 var parent_id = jQuery(this).parent().closest('.os-category-parent-w').data('id') || 0;
4977 category_datas.push({id: jQuery(this).data('id'), order_number: order_number, parent_id: parent_id});
4978 });
4979 $categories_wrapper.find('.item-in-category-w').each(function(index){
4980 var item_order_number = jQuery(this).index() + 1;
4981 var category_id = jQuery(this).closest('.os-category-parent-w').data('id') || 0;
4982 item_datas.push({id: jQuery(this).data('id'), order_number: item_order_number, category_id: category_id});
4983 });
4984 latepoint_recalculate_items_count_in_category();
4985 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' }
4986 $categories_wrapper.addClass('os-loading');
4987 jQuery.ajax({
4988 type : "post",
4989 dataType : "json",
4990 url : latepoint_timestamped_ajaxurl(),
4991 data : data,
4992 success: function(response){
4993 $categories_wrapper.removeClass('os-loading');
4994 if(response.status === "success"){
4995 // latepoint_add_notification(response.message);
4996 }else{
4997 alert(response.message);
4998 }
4999 }
5000 });
5001 });
5002
5003
5004 // Universal re-ordering dragging for form blocks
5005 dragula([jQuery('.os-draggable-form-blocks')[0]], {
5006 moves: function (el, container, handle) {
5007 return handle.classList.contains('os-form-block-drag');
5008 },
5009 }).on('drop', function(el){
5010 var blocks_order_data = {};
5011 var $draggable_form_blocks_wrapper = jQuery('.os-draggable-form-blocks');
5012 $draggable_form_blocks_wrapper.find('.os-form-block').each(function(index){
5013 var new_order_number = jQuery(this).index() + 1;
5014 var $block_model_id = jQuery(this).find('.os-form-block-id');
5015 if($block_model_id.length && $block_model_id.val()) blocks_order_data[$block_model_id.val()] = new_order_number;
5016 });
5017 var data = { action: latepoint_helper.route_action,
5018 route_name: $draggable_form_blocks_wrapper.data('order-update-route'),
5019 params: {ordered_fields: blocks_order_data,
5020 fields_for: $draggable_form_blocks_wrapper.data('fields-for')},
5021 return_format: 'json' }
5022 $draggable_form_blocks_wrapper.addClass('os-loading');
5023 jQuery.ajax({
5024 type : "post",
5025 dataType : "json",
5026 url : latepoint_timestamped_ajaxurl(),
5027 data : data,
5028 success: function(response){
5029 $draggable_form_blocks_wrapper.removeClass('os-loading');
5030 }
5031 });
5032 });
5033
5034
5035 jQuery('body.latepoint-admin').on('click', '.os-category-edit-btn, .os-category-edit-cancel-btn, .os-category-w .os-category-name', function(){
5036 jQuery(this).closest('.os-category-w').toggleClass('editing');
5037 return false;
5038 });
5039
5040 jQuery('body.latepoint-admin').on('click', '.step-edit-btn, .step-edit-cancel-btn, .step-w .step-head', function(){
5041 jQuery(this).closest('.step-w').toggleClass('editing');
5042 return false;
5043 });
5044
5045 jQuery('body.latepoint-admin').on('click', '.agent-info-change-agent-btn', function(){
5046 jQuery(this).closest('.agent-info-w').removeClass('selected').addClass('selecting');
5047 return false;
5048 });
5049
5050 jQuery('body.latepoint-admin').on('click', '.agent-info-change-agent-btn', function(){
5051 jQuery(this).closest('.agent-info-w').removeClass('selected').addClass('selecting');
5052 return false;
5053 });
5054
5055
5056 jQuery('body.latepoint-admin').on('click', '.customer-info-create-btn', function(){
5057 jQuery(this).closest('.customer-info-w').removeClass('selecting').addClass('selected');
5058 return false;
5059 });
5060
5061 jQuery('body.latepoint-admin').on('click', '.customer-info-load-btn', function(){
5062 jQuery(this).closest('.customer-info-w').removeClass('selected').addClass('selecting').find('.customers-selector-search-input').trigger('focus');
5063 return false;
5064 });
5065
5066 jQuery('body.latepoint-admin').on('click', '.customers-selector-cancel', function(){
5067 jQuery(this).closest('.customer-info-w').removeClass('selecting').addClass('selected ');
5068 jQuery('.customers-options-list .customer-option').show();
5069 jQuery('.customers-selector-search-input').val('');
5070 return false;
5071 });
5072
5073 // CUSTOMER SELECTOR
5074
5075 // SERVICES SELECTOR
5076 jQuery('body.latepoint-admin').on('click', '.service-option-selected', function(){
5077 var $select = jQuery(this).closest('.os-services-select-field-w');
5078 if($select.hasClass('active')){
5079 $select.removeClass('active');
5080 }else{
5081 $select.addClass('active').find('input').trigger('focus');
5082 }
5083 return false;
5084 });
5085
5086
5087 jQuery('body.latepoint-admin').on('keyup', '.service-options-filter-input', function(){
5088 var $list = jQuery(this).closest('.services-options-list');
5089 var text = jQuery(this).val().toLowerCase();
5090 $list.find('.service-option').hide();
5091
5092 // Search
5093 $list.find('.service-option').each(function(){
5094
5095 if(jQuery(this).text().toLowerCase().indexOf(""+text+"") != -1 ){
5096 jQuery(this).show();
5097 }
5098 });
5099 return false;
5100 });
5101
5102
5103 jQuery('.calendar-week-agent-w').on('click', '.calendar-load-target-date', function(event){
5104 jQuery(this).addClass('os-loading');
5105 latepoint_reload_week_view_calendar(jQuery(this).data('target-date'));
5106 return false;
5107 });
5108
5109 jQuery('.calendar-week-agent-w').on('change', '.cc-availability-toggler #overlay_service_availability', function(event){
5110 if(jQuery(this).val() == 'on'){
5111 jQuery('.calendar-week-agent-w .cc-service-selector').show();
5112 }else{
5113 jQuery('.calendar-week-agent-w .cc-service-selector').hide();
5114 }
5115 latepoint_reload_week_view_calendar();
5116 });
5117
5118
5119 jQuery('.calendar-week-agent-w').on('change', '.trigger-weekly-calendar-reload', function(event){
5120 latepoint_reload_week_view_calendar();
5121 return false;
5122 });
5123
5124 jQuery('.latepoint-admin').on('click', '.os-complex-connections-selector .selector-trigger', function(e){
5125 var $connection_wrapper = jQuery(this).closest('.connection');
5126 if($connection_wrapper.hasClass('active')){
5127 latepoint_complex_selector_deselect($connection_wrapper);
5128 jQuery(this).closest('.white-box').find('.os-select-all-toggler').prop('checked', false);
5129 }else{
5130 latepoint_complex_selector_select($connection_wrapper);
5131 }
5132 return false;
5133 });
5134
5135 jQuery('.latepoint-admin').on('click', '.os-complex-connections-selector .item-quantity-selector', function(e){
5136 let val = parseInt(jQuery(this).closest('.item-quantity-selector-w').find('.item-quantity-selector-input').val());
5137 if(jQuery(this).data('sign') == 'plus'){
5138 val = val + 1;
5139 }else{
5140 val = val - 1;
5141 }
5142 val = (val > 0) ? val : 0;
5143 jQuery(this).closest('.item-quantity-selector-w').find('.item-quantity-selector-input').val(val).trigger('change');
5144 return false;
5145 });
5146
5147 jQuery('.latepoint-admin').on('change', '.os-complex-connections-selector .item-quantity-selector-input', function(e){
5148 let $this = jQuery(this);
5149 let $connection_wrapper = jQuery(this).closest('.connection');
5150 if($this.val() > 0){
5151 latepoint_complex_selector_select($connection_wrapper, $this.val());
5152 }else{
5153 latepoint_complex_selector_deselect($connection_wrapper);
5154 }
5155 return false;
5156 });
5157
5158 jQuery('.latepoint-admin').on('click', '.os-agents-selector .agent', function(){
5159 if(jQuery(this).hasClass('active')){
5160 jQuery(this).removeClass('active');
5161 jQuery(this).find('.connection-child-is-connected').val('no');
5162 }else{
5163 jQuery(this).addClass('active');
5164 jQuery(this).find('.connection-child-is-connected').val('yes');
5165 }
5166 return false;
5167 });
5168
5169 jQuery('.latepoint-admin').on('click', '.os-services-selector .service', function(){
5170 if(jQuery(this).hasClass('active')){
5171 jQuery(this).removeClass('active');
5172 jQuery(this).find('.connection-child-is-connected').val('no');
5173 }else{
5174 jQuery(this).addClass('active');
5175 jQuery(this).find('.connection-child-is-connected').val('yes');
5176 }
5177 return false;
5178 });
5179
5180 jQuery('.latepoint-admin').on( 'click', '.os-form-toggler-group', function( event ){
5181 jQuery(this).find('.os-toggler').trigger('click');
5182 return false;
5183 });
5184
5185 jQuery('.latepoint-admin').on( 'click', '.os-toggler', function( event ){
5186 let $toggler = jQuery(this);
5187 if($toggler.data('confirm')){
5188 if(!confirm($toggler.data('confirm'))) return false;
5189 }
5190 if($toggler.hasClass('on')){
5191 $toggler.removeClass('on').addClass('off');
5192 }else{
5193 $toggler.removeClass('off').addClass('on');
5194 }
5195 if($toggler.data('for')){
5196 if($toggler.hasClass('os-toggler-radio')){
5197 // radio
5198 // uncheck all radio buttons with the same name
5199 let $radio = jQuery('#' + $toggler.data('for'));
5200 jQuery('input[type="radio"][name="'+ $radio.prop('name') + '"]:checked').each(function(index){
5201 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');
5202 jQuery('#'+ toggle_content_id).hide();
5203 });
5204 $radio.prop('checked', !$toggler.hasClass('off'));
5205 }else{
5206 var $hiddenInput = jQuery('input[type="hidden"]#' + $toggler.data('for'));
5207 if($hiddenInput.length){
5208 // hidden input
5209 if($toggler.data('is-string-value')){
5210 $hiddenInput.val($toggler.hasClass('off') ? 'off' : 'on').trigger('change');
5211 }else{
5212 $hiddenInput.val($toggler.hasClass('off') ? 0 : 1).trigger('change');
5213 }
5214
5215 if($toggler.data('os-instant-update')){
5216 let data = new FormData();
5217
5218 let params = $hiddenInput.serialize();
5219 if($toggler.data('nonce')) params+= '&_wpnonce='+$toggler.data('nonce');
5220 data.append('params', params);
5221 data.append('action', latepoint_helper.route_action);
5222 data.append('route_name', $toggler.data('os-instant-update'));
5223 data.append('return_format', 'json');
5224
5225 jQuery.ajax({
5226 type: "post",
5227 dataType: "json",
5228 processData: false,
5229 contentType: false,
5230 url: latepoint_timestamped_ajaxurl(),
5231 data: data,
5232 success: function (response) {
5233
5234 }
5235 });
5236 }
5237 }else{
5238 // checkbox
5239 jQuery('#' + $toggler.data('for')).prop('checked', !$toggler.hasClass('off'));
5240 }
5241 }
5242 }
5243 if($toggler.data('controlled-toggle-id')){
5244 if($toggler.hasClass('off')){
5245 jQuery('#' + $toggler.data('controlled-toggle-id')).hide();
5246 }else{
5247 jQuery('#' + $toggler.data('controlled-toggle-id')).show();
5248 }
5249 }
5250 $toggler.trigger('ostoggler:toggle');
5251 return false;
5252 });
5253
5254
5255
5256 // UPLOAD/REMOVE IMAGE LINK LOGIC
5257 jQuery('.latepoint-admin').on( 'click', '.os-image-selector-trigger', function( event ){
5258 var frame;
5259
5260 event.preventDefault();
5261
5262 var $image_uploader_trigger = jQuery(this);
5263 var $image_selector_w = jQuery(this).closest('.os-image-selector-w');
5264 var $image_container = $image_selector_w.find('.os-image-container');
5265 var $image_id_holder = $image_selector_w.find('.os-image-id-holder');
5266
5267 let is_avatar = $image_selector_w.hasClass('is-avatar');
5268
5269 var image_exists = is_avatar ? $image_container.find('.image-self').length : $image_container.find('img').length;
5270
5271 if(image_exists){
5272 $image_id_holder.val('');
5273 $image_selector_w.removeClass('has-image');
5274 $image_container.html('');
5275 $image_uploader_trigger.find('.os-text-holder').text($image_uploader_trigger.data('label-set-str'));
5276 }else{
5277 // If the media frame already exists, reopen it.
5278 if ( frame ) {
5279 frame.open();
5280 return false;
5281 }
5282
5283 // Create a new media frame
5284 frame = wp.media({
5285 title: 'Select or Upload Media',
5286 button: { text: 'Use this media' },
5287 multiple: false
5288 });
5289
5290 frame.on( 'select', function() {
5291 var attachment = frame.state().get('selection').first().toJSON();
5292 if(is_avatar){
5293 $image_container.html( '<div class="image-self" style="background-image: url('+attachment.url+')"></div>' );
5294 }else{
5295 $image_container.html( '<img src="'+attachment.url+'" alt=""/>' );
5296 }
5297 $image_id_holder.val( attachment.id );
5298 $image_selector_w.addClass('has-image');
5299 $image_uploader_trigger.find('.os-text-holder').text($image_uploader_trigger.data('label-remove-str'));
5300 });
5301
5302 frame.open();
5303 }
5304
5305 return false;
5306 });
5307
5308
5309
5310 jQuery('body').on('click', '.latepoint-lightbox-close', function(){
5311 latepoint_lightbox_close();
5312 return false;
5313 });
5314
5315
5316 jQuery('body').on('click', '.latepoint-side-panel-close-trigger', function(){
5317 latepoint_close_side_panel();
5318 return false;
5319 });
5320 jQuery('body').on('click', '.latepoint-side-sub-panel-close-trigger', function(){
5321 jQuery(this).closest('.side-sub-panel-wrapper').remove();
5322 return false;
5323 });
5324
5325
5326
5327 jQuery('body.latepoint-admin').on('click', '.time-ampm-select', function(){
5328 let $form = jQuery(this).closest('.order-item-booking-data-form-wrapper');
5329 jQuery(this).closest('.time-ampm-w').find('.active').removeClass('active');
5330 jQuery(this).addClass('active');
5331 var ampm_value = jQuery(this).data('ampm-value');
5332 jQuery(this).closest('.os-time-group').find('.ampm-value-hidden-holder').val(ampm_value);
5333 if(jQuery(this).closest('.quick-start-time-w').length){
5334 // 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
5335 latepoint_set_booking_end_time($form);
5336 latepoint_is_next_day($form);
5337 }
5338 if(jQuery(this).closest('.quick-end-time-w').length){
5339 latepoint_is_next_day($form);
5340 }
5341 return false;
5342 });
5343
5344
5345 jQuery('body.latepoint-admin').on('click', '.latepoint-lightbox-shadow', function(){
5346 latepoint_lightbox_close();
5347 return false;
5348 });
5349
5350 jQuery('body.latepoint-admin').on('click', '.latepoint-side-panel-shadow', function(){
5351 jQuery('.latepoint-side-panel-w').remove();
5352 return false;
5353 });
5354
5355 // SCHEDULE
5356
5357 jQuery('body.latepoint-admin').on('click', '.ws-period-remove', function(e){
5358 jQuery(this).closest('.ws-period').remove();
5359 return false;
5360 });
5361
5362
5363 jQuery('.latepoint-admin').on( 'click', '.weekday-schedule-w .os-toggler', function( event ){
5364 if(jQuery(this).hasClass('off')){
5365 jQuery(this).closest('.weekday-schedule-w').addClass('day-off').removeClass('is-editing').find('input.is-active').val(0);
5366 }else{
5367 jQuery(this).closest('.weekday-schedule-w').removeClass('day-off').addClass('is-editing').find('input.is-active').val(1);
5368 }
5369 return false;
5370 });
5371
5372
5373
5374 });