_agents.js
1 year ago
_calendar.js
1 year ago
_chart.js
1 year ago
_customers.js
1 year ago
_orders.js
1 year ago
_processes.js
1 year ago
_steps.js
1 year ago
_stripe_connect.js
1 year ago
main.js
1 year ago
updates.js
1 year ago
_steps.js
439 lines
| 1 | /* |
| 2 | * Copyright (c) 2024 LatePoint LLC. All rights reserved. |
| 3 | */ |
| 4 | |
| 5 | |
| 6 | function latepoint_preview_init_step_category_items(step_code){ |
| 7 | jQuery('.booking-form-preview .os-item-category-info').on('click', function(){ |
| 8 | var $booking_form_element = jQuery(this).closest('.booking-form-preview'); |
| 9 | jQuery(this).closest('.latepoint-step-content').addClass('selecting-item-category'); |
| 10 | var $category_wrapper = jQuery(this).closest('.os-item-category-w'); |
| 11 | var $main_parent = jQuery(this).closest('.os-item-categories-main-parent'); |
| 12 | if($category_wrapper.hasClass('selected')){ |
| 13 | $category_wrapper.removeClass('selected'); |
| 14 | if($category_wrapper.parent().closest('.os-item-category-w').length){ |
| 15 | $category_wrapper.parent().closest('.os-item-category-w').addClass('selected'); |
| 16 | }else{ |
| 17 | $main_parent.removeClass('show-selected-only'); |
| 18 | } |
| 19 | }else{ |
| 20 | $main_parent.find('.os-item-category-w.selected').removeClass('selected'); |
| 21 | $main_parent.addClass('show-selected-only'); |
| 22 | $category_wrapper.addClass('selected'); |
| 23 | } |
| 24 | return false; |
| 25 | }); |
| 26 | } |
| 27 | |
| 28 | function latepoint_booking_form_discard_changes(){ |
| 29 | |
| 30 | let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]); |
| 31 | |
| 32 | var data = { |
| 33 | action: latepoint_helper.route_action, |
| 34 | route_name: jQuery('.booking-form-preview-settings').data('route-name'), |
| 35 | params: latepoint_formdata_to_url_encoded_string(form_data), |
| 36 | layout: 'none', |
| 37 | return_format: 'json' |
| 38 | } |
| 39 | |
| 40 | jQuery.ajax({ |
| 41 | type : "post", |
| 42 | dataType : "json", |
| 43 | url : latepoint_timestamped_ajaxurl(), |
| 44 | data : data, |
| 45 | success: function(data){ |
| 46 | if(data.status === "success"){ |
| 47 | jQuery('.booking-form-preview-inner').html(data.booking_form_html); |
| 48 | latepoint_init_booking_form_preview(); |
| 49 | }else{ |
| 50 | latepoint_add_notification(data.message, 'error'); |
| 51 | } |
| 52 | } |
| 53 | }); |
| 54 | } |
| 55 | |
| 56 | function latepoint_booking_form_save_changes(){ |
| 57 | |
| 58 | let form_data = new FormData(jQuery('.booking-form-preview-settings')[0]); |
| 59 | |
| 60 | jQuery('.editable-setting').each(function(){ |
| 61 | form_data.set('steps_settings' + jQuery(this).data('setting-key'), jQuery(this).html()); |
| 62 | }); |
| 63 | |
| 64 | |
| 65 | 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()); |
| 66 | |
| 67 | |
| 68 | var data = { |
| 69 | action: latepoint_helper.route_action, |
| 70 | route_name: jQuery('.booking-form-preview-settings').data('route-name'), |
| 71 | params: latepoint_formdata_to_url_encoded_string(form_data), |
| 72 | layout: 'none', |
| 73 | return_format: 'json' |
| 74 | } |
| 75 | |
| 76 | jQuery.ajax({ |
| 77 | type : "post", |
| 78 | dataType : "json", |
| 79 | url : latepoint_timestamped_ajaxurl(), |
| 80 | data : data, |
| 81 | success: function(data){ |
| 82 | jQuery('.booking-form-preview-settings').removeClass('os-loading'); |
| 83 | if(data.status === "success"){ |
| 84 | jQuery('.bf-preview-step-settings').html(data.step_settings_html); |
| 85 | jQuery('.booking-form-preview-inner').html(data.booking_form_html); |
| 86 | jQuery('#latepoint-main-admin-inline-css').html(data.css_variables); |
| 87 | latepoint_init_booking_form_preview(); |
| 88 | }else{ |
| 89 | latepoint_add_notification(data.message, 'error'); |
| 90 | } |
| 91 | } |
| 92 | }); |
| 93 | } |
| 94 | |
| 95 | function latepoint_init_booking_form_preview(){ |
| 96 | |
| 97 | latepoint_preview_init_step_category_items(); |
| 98 | latepoint_booking_form_preview_init_datepicker(); |
| 99 | |
| 100 | |
| 101 | jQuery('.booking-form-preview-wrapper').on('click', '.os-step-tab', function(){ |
| 102 | jQuery(this).closest('.os-step-tabs').find('.os-step-tab').removeClass('active'); |
| 103 | jQuery(this).addClass('active'); |
| 104 | var target = jQuery(this).data('target'); |
| 105 | jQuery(this).closest('.os-step-tabs-w').find('.os-step-tab-content').hide(); |
| 106 | jQuery(target).show(); |
| 107 | }); |
| 108 | |
| 109 | |
| 110 | jQuery('.bf-save-btn').on('click', function(){ |
| 111 | jQuery(this).addClass('os-loading'); |
| 112 | latepoint_booking_form_save_changes(); |
| 113 | return false; |
| 114 | }); |
| 115 | |
| 116 | jQuery('.bf-cancel-save-btn').on('click', function(){ |
| 117 | jQuery(this).addClass('os-loading'); |
| 118 | latepoint_booking_form_discard_changes(); |
| 119 | return false; |
| 120 | }); |
| 121 | |
| 122 | |
| 123 | jQuery('.booking-form-preview .bf-next-btn').on('click', function(){ |
| 124 | jQuery(this).addClass('os-loading'); |
| 125 | jQuery("#selected_step_code > option:selected") |
| 126 | .prop("selected", false) |
| 127 | .next() |
| 128 | .prop("selected", true).trigger('change'); |
| 129 | }); |
| 130 | |
| 131 | jQuery('.booking-form-preview .bf-prev-btn').on('click', function(){ |
| 132 | jQuery(this).addClass('os-loading'); |
| 133 | jQuery("#selected_step_code > option:selected") |
| 134 | .prop("selected", false) |
| 135 | .prev() |
| 136 | .prop("selected", true).trigger('change'); |
| 137 | }); |
| 138 | |
| 139 | |
| 140 | jQuery('.booking-form-preview .os-image-selector-trigger').on('click', function(){ |
| 141 | jQuery('.booking-form-preview').addClass('has-changes'); |
| 142 | }); |
| 143 | |
| 144 | jQuery('.booking-form-preview .editable-setting').on('focus', function(){ |
| 145 | jQuery('.booking-form-preview').addClass('has-changes'); |
| 146 | }); |
| 147 | |
| 148 | |
| 149 | let editor = new MediumEditor('.booking-form-preview .os-editable', {toolbar: { |
| 150 | buttons: [ |
| 151 | { |
| 152 | name: 'bold', |
| 153 | classList: ['latepoint-icon', 'latepoint-icon-format_bold'], |
| 154 | }, |
| 155 | { |
| 156 | name: 'anchor', |
| 157 | classList: ['latepoint-icon', 'latepoint-icon-format_link'], |
| 158 | }, |
| 159 | { |
| 160 | name: 'h3', |
| 161 | classList: ['latepoint-icon', 'latepoint-icon-format_h3'], |
| 162 | }, |
| 163 | { |
| 164 | name: 'h4', |
| 165 | classList: ['latepoint-icon', 'latepoint-icon-format_h4'], |
| 166 | }, |
| 167 | { |
| 168 | name: 'h5', |
| 169 | classList: ['latepoint-icon', 'latepoint-icon-format_h5'], |
| 170 | }, |
| 171 | |
| 172 | ] |
| 173 | } |
| 174 | }); |
| 175 | let editor_basic = new MediumEditor('.booking-form-preview .os-editable-basic', {toolbar: { |
| 176 | buttons: [ |
| 177 | { |
| 178 | name: 'bold', |
| 179 | classList: ['latepoint-icon', 'latepoint-icon-format_bold'], |
| 180 | }, |
| 181 | { |
| 182 | name: 'italic', |
| 183 | classList: ['latepoint-icon', 'latepoint-icon-format_italic'], |
| 184 | }, |
| 185 | { |
| 186 | name: 'underline', |
| 187 | classList: ['latepoint-icon', 'latepoint-icon-format_underlined'], |
| 188 | }, |
| 189 | { |
| 190 | name: 'anchor', |
| 191 | classList: ['latepoint-icon', 'latepoint-icon-format_link'], |
| 192 | }, |
| 193 | |
| 194 | ] |
| 195 | } |
| 196 | }); |
| 197 | } |
| 198 | |
| 199 | function latepoint_reload_booking_form_preview(){ |
| 200 | latepoint_booking_form_save_changes(); |
| 201 | } |
| 202 | |
| 203 | function latepoint_init_steps_settings(){ |
| 204 | |
| 205 | jQuery('.booking-form-preview-settings').on('change', ' select, input[type="hidden"]', function(){ |
| 206 | jQuery('.booking-form-preview-settings').addClass('os-loading'); |
| 207 | latepoint_reload_booking_form_preview(); |
| 208 | }); |
| 209 | |
| 210 | jQuery('.trigger-custom-color-save').on('click', function(){ |
| 211 | jQuery('.booking-form-preview-settings').addClass('os-loading'); |
| 212 | latepoint_booking_form_save_changes(); |
| 213 | return false; |
| 214 | }); |
| 215 | |
| 216 | jQuery('.bf-color-scheme-color-trigger').on('click', function(){ |
| 217 | jQuery('.bf-color-scheme-color-trigger.is-selected').removeClass('is-selected'); |
| 218 | jQuery(this).addClass('is-selected'); |
| 219 | let color_scheme = jQuery(this).data('color-code'); |
| 220 | jQuery('.os-color-scheme-selector-wrapper select').val(color_scheme).trigger('change'); |
| 221 | if(color_scheme == 'custom'){ |
| 222 | jQuery('.os-custom-color-selector-wrapper').removeClass('is-hidden'); |
| 223 | }else{ |
| 224 | jQuery('.os-custom-color-selector-wrapper').addClass('is-hidden'); |
| 225 | } |
| 226 | return false; |
| 227 | }); |
| 228 | |
| 229 | jQuery('.os-section-collapsible-trigger').on('click', function(){ |
| 230 | jQuery(this).closest('.os-section-collapsible-wrapper').toggleClass('is-open'); |
| 231 | return false; |
| 232 | }) |
| 233 | } |
| 234 | |
| 235 | |
| 236 | function latepoint_booking_form_preview_init_timeslots($booking_form_element = false){ |
| 237 | if(!$booking_form_element) return; |
| 238 | $booking_form_element.on('click', '.dp-timepicker-trigger', function(){ |
| 239 | if(jQuery(this).hasClass('is-booked') || jQuery(this).hasClass('is-off')){ |
| 240 | // Show error message that you cant select a booked period |
| 241 | }else{ |
| 242 | if(jQuery(this).hasClass('selected')){ |
| 243 | jQuery(this).removeClass('selected'); |
| 244 | jQuery(this).find('.dp-success-label').remove(); |
| 245 | }else{ |
| 246 | $booking_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove(); |
| 247 | var selected_timeslot_time = jQuery(this).find('.dp-label-time').html(); |
| 248 | jQuery(this).addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>'); |
| 249 | |
| 250 | var minutes = parseInt(jQuery(this).data('minutes')); |
| 251 | var timeshift_minutes = parseInt($booking_form_element.find('.latepoint_timeshift_minutes').val()); |
| 252 | // we substract timeshift minutes because its timeshift minutes that the business is running in, in opposite of what we do when we generate a calendar for a client |
| 253 | if(timeshift_minutes) minutes = minutes - timeshift_minutes; |
| 254 | var start_date = new Date($booking_form_element.find('.os-day.selected').data('date')); |
| 255 | if(minutes < 0){ |
| 256 | // business minutes are in previous day |
| 257 | minutes = 24*60 + minutes; |
| 258 | // move start date back 1 day |
| 259 | start_date.setDate(start_date.getDate() - 1); |
| 260 | }else if(minutes >= 24*60){ |
| 261 | // business minutes are in next day |
| 262 | minutes = minutes - 24*60; |
| 263 | start_date.setDate(start_date.getDate() + 1); |
| 264 | } |
| 265 | $booking_form_element.find('.latepoint_start_date').val(start_date.toISOString().split('T')[0]) |
| 266 | latepoint_trigger_next_btn($booking_form_element); |
| 267 | } |
| 268 | } |
| 269 | return false; |
| 270 | }); |
| 271 | } |
| 272 | |
| 273 | |
| 274 | function latepoint_booking_form_preview_day_timeslots($day){ |
| 275 | let $wrapper_element = jQuery('.booking-form-preview'); |
| 276 | $day.addClass('selected'); |
| 277 | |
| 278 | var service_duration = $day.data('service-duration'); |
| 279 | var interval = $day.data('interval'); |
| 280 | var work_start_minutes = $day.data('work-start-time'); |
| 281 | var work_end_minutes = $day.data('work-end-time'); |
| 282 | var total_work_minutes = $day.data('total-work-minutes'); |
| 283 | var bookable_minutes = []; |
| 284 | var available_capacities_of_bookable_minute = []; |
| 285 | if($day.attr('data-bookable-minutes')){ |
| 286 | if($day.data('bookable-minutes').toString().indexOf(':') > -1){ |
| 287 | // has capacity information embedded into bookable minutes string |
| 288 | let bookable_minutes_with_capacity = $day.data('bookable-minutes').toString().split(','); |
| 289 | for(let i = 0; i < bookable_minutes_with_capacity.length; i++){ |
| 290 | bookable_minutes.push(parseInt(bookable_minutes_with_capacity[i].split(':')[0])); |
| 291 | available_capacities_of_bookable_minute.push(parseInt(bookable_minutes_with_capacity[i].split(':')[1])); |
| 292 | } |
| 293 | }else{ |
| 294 | bookable_minutes = $day.data('bookable-minutes').toString().split(',').map(Number); |
| 295 | } |
| 296 | } |
| 297 | var work_minutes = $day.data('work-minutes').toString().split(',').map(Number); |
| 298 | |
| 299 | var $timeslots = $wrapper_element.find('.timeslots'); |
| 300 | $timeslots.html(''); |
| 301 | |
| 302 | if(total_work_minutes > 0 && bookable_minutes.length && work_minutes.length){ |
| 303 | var prev_minutes = false; |
| 304 | work_minutes.forEach(function(current_minutes){ |
| 305 | var ampm = latepoint_am_or_pm(current_minutes); |
| 306 | |
| 307 | var timeslot_class = 'dp-timepicker-trigger'; |
| 308 | var timeslot_available_capacity = 0; |
| 309 | if($wrapper_element.find('.os-dates-w').data('time-pick-style') == 'timeline'){ |
| 310 | timeslot_class+= ' dp-timeslot'; |
| 311 | }else{ |
| 312 | timeslot_class+= ' dp-timebox'; |
| 313 | } |
| 314 | |
| 315 | if(prev_minutes !== false && ((current_minutes - prev_minutes) > service_duration)){ |
| 316 | // show interval that is off between two work periods |
| 317 | 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); |
| 318 | var off_width = (((current_minutes - prev_minutes - service_duration) / total_work_minutes) * 100); |
| 319 | $timeslots.append('<div class="'+ timeslot_class +' is-off" style="max-width:'+ off_width +'%; width:'+ off_width +'%"><span class="dp-label">' + off_label + '</span></div>'); |
| 320 | } |
| 321 | |
| 322 | if(!bookable_minutes.includes(current_minutes)){ |
| 323 | timeslot_class+= ' is-booked'; |
| 324 | }else{ |
| 325 | if(available_capacities_of_bookable_minute.length) timeslot_available_capacity = available_capacities_of_bookable_minute[bookable_minutes.indexOf(current_minutes)]; |
| 326 | } |
| 327 | var tick_html = ''; |
| 328 | var capacity_label = ''; |
| 329 | var capacity_label_html = ''; |
| 330 | var capacity_internal_label_html = ''; |
| 331 | |
| 332 | if(((current_minutes % 60) == 0) || (interval >= 60)){ |
| 333 | timeslot_class+= ' with-tick'; |
| 334 | tick_html = '<span class="dp-tick"><strong>'+latepoint_minutes_to_hours_preferably(current_minutes)+'</strong>'+' '+ampm+'</span>'; |
| 335 | } |
| 336 | var timeslot_label = latepoint_minutes_to_hours_and_minutes(current_minutes)+' '+ampm; |
| 337 | if(latepoint_show_booking_end_time()){ |
| 338 | var end_minutes = current_minutes + service_duration; |
| 339 | if(end_minutes > 1440) end_minutes = end_minutes - 1440; |
| 340 | var end_minutes_ampm = latepoint_am_or_pm(end_minutes); |
| 341 | timeslot_label+= ' - <span class="dp-label-end-time">' + latepoint_minutes_to_hours_and_minutes(end_minutes)+' '+end_minutes_ampm + '</span>'; |
| 342 | } |
| 343 | if(timeslot_available_capacity){ |
| 344 | var spaces_message = timeslot_available_capacity > 1 ? latepoint_helper.many_spaces_message : latepoint_helper.single_space_message; |
| 345 | capacity_label = timeslot_available_capacity + ' ' + spaces_message; |
| 346 | capacity_label_html = '<span class="dp-capacity">' + capacity_label + '</span>'; |
| 347 | capacity_internal_label_html = '<span class="dp-label-capacity">' + capacity_label + '</span>'; |
| 348 | } |
| 349 | timeslot_label = timeslot_label.trim(); |
| 350 | $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>'); |
| 351 | prev_minutes = current_minutes; |
| 352 | }); |
| 353 | }else{ |
| 354 | // No working hours this day |
| 355 | $timeslots.addClass('slots-not-available').append('<div class="not-working-message">' + latepoint_helper.msg_not_available + "</div>"); |
| 356 | } |
| 357 | jQuery('.times-header-label span').text($day.data('nice-date')); |
| 358 | $wrapper_element.find('.time-selector-w').slideDown(200); |
| 359 | } |
| 360 | |
| 361 | function latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element){ |
| 362 | |
| 363 | if(!$booking_form_element) return; |
| 364 | $booking_form_element.on('click', '.os-month-next-btn', function(){ |
| 365 | var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 366 | var next_month_route_name = jQuery(this).data('route'); |
| 367 | if($booking_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length){ |
| 368 | $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active'); |
| 369 | latepoint_booking_form_preview_calendar_set_month_label($booking_form_element); |
| 370 | }else{ |
| 371 | alert('Disabled in preview'); |
| 372 | } |
| 373 | latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element); |
| 374 | return false; |
| 375 | }); |
| 376 | $booking_form_element.on('click', '.os-month-prev-btn', function(){ |
| 377 | var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 378 | if($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length){ |
| 379 | $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active'); |
| 380 | latepoint_booking_form_preview_calendar_set_month_label($booking_form_element); |
| 381 | } |
| 382 | return false; |
| 383 | }); |
| 384 | } |
| 385 | |
| 386 | |
| 387 | function latepoint_booking_form_preview_calendar_set_month_label(){ |
| 388 | jQuery('.os-current-month-label .current-month').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-month-label')); |
| 389 | jQuery('.os-current-month-label .current-year').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-year')); |
| 390 | } |
| 391 | |
| 392 | |
| 393 | |
| 394 | function latepoint_booking_form_preview_init_datepicker(){ |
| 395 | let $booking_form_element = jQuery('.latepoint-booking-form-element'); |
| 396 | latepoint_booking_form_preview_init_timeslots($booking_form_element); |
| 397 | latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element); |
| 398 | $booking_form_element.on('click', '.os-months .os-day', function(){ |
| 399 | if(jQuery(this).hasClass('os-day-passed')) return false; |
| 400 | if(jQuery(this).hasClass('os-not-in-allowed-period')) return false; |
| 401 | if(jQuery(this).closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')){ |
| 402 | |
| 403 | // HIDE TIMESLOT IF ONLY ONE TIMEPOINT |
| 404 | if(jQuery(this).hasClass('os-not-available')){ |
| 405 | // clicked on a day that has no available timeslots |
| 406 | // do nothing |
| 407 | }else{ |
| 408 | $booking_form_element.find('.os-day.selected').removeClass('selected'); |
| 409 | jQuery(this).addClass('selected'); |
| 410 | // set date |
| 411 | $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 412 | if(jQuery(this).hasClass('os-one-slot-only')){ |
| 413 | // clicked on a day that has only one slot available |
| 414 | var bookable_minutes = jQuery(this).data('bookable-minutes').toString().split(':')[0]; |
| 415 | var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number(jQuery(this).data('service-duration'))); |
| 416 | $booking_form_element.find('.time-selector-w').slideUp(200); |
| 417 | }else{ |
| 418 | // regular day with more than 1 timeslots available |
| 419 | // build timeslots |
| 420 | latepoint_booking_form_preview_day_timeslots(jQuery(this)); |
| 421 | // clear time and hide next btn |
| 422 | } |
| 423 | } |
| 424 | }else{ |
| 425 | // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT |
| 426 | $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 427 | $booking_form_element.find('.os-day.selected').removeClass('selected'); |
| 428 | jQuery(this).addClass('selected'); |
| 429 | |
| 430 | // build timeslots |
| 431 | latepoint_booking_form_preview_day_timeslots(jQuery(this)); |
| 432 | // clear time and hide next btn |
| 433 | } |
| 434 | |
| 435 | |
| 436 | return false; |
| 437 | }); |
| 438 | } |
| 439 |