_agents.js
1 year ago
_calendar.js
3 months ago
_chart.js
9 months ago
_customers.js
1 year ago
_customers_import.js
9 months ago
_delete-confirm.js
1 week ago
_orders.js
9 months ago
_processes.js
1 year ago
_razorpay_connect.js
1 month ago
_steps.js
9 months ago
_stripe_connect.js
1 year ago
main.js
2 weeks ago
updates.js
3 months ago
_steps.js
432 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 | let $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 103 | jQuery(this).closest('.os-step-tabs').find('.os-step-tab').removeClass('active'); |
| 104 | jQuery(this).addClass('active'); |
| 105 | var target = jQuery(this).data('target'); |
| 106 | jQuery(this).closest('.os-step-tabs-w').find('.os-step-tab-content').hide(); |
| 107 | jQuery(target).show(); |
| 108 | if(jQuery(this).data('auth-action')){ |
| 109 | $booking_form_element.find('input[name="auth[action]"]').val(jQuery(this).data('auth-action')); |
| 110 | } |
| 111 | }); |
| 112 | |
| 113 | |
| 114 | jQuery('.bf-save-btn').on('click', function(){ |
| 115 | jQuery(this).addClass('os-loading'); |
| 116 | latepoint_booking_form_save_changes(); |
| 117 | return false; |
| 118 | }); |
| 119 | |
| 120 | jQuery('.bf-cancel-save-btn').on('click', function(){ |
| 121 | jQuery(this).addClass('os-loading'); |
| 122 | latepoint_booking_form_discard_changes(); |
| 123 | return false; |
| 124 | }); |
| 125 | |
| 126 | |
| 127 | jQuery('.booking-form-preview .bf-next-btn').on('click', function(){ |
| 128 | jQuery(this).addClass('os-loading'); |
| 129 | jQuery("#selected_step_code > option:selected") |
| 130 | .prop("selected", false) |
| 131 | .next() |
| 132 | .prop("selected", true).trigger('change'); |
| 133 | }); |
| 134 | |
| 135 | jQuery('.booking-form-preview .bf-prev-btn').on('click', function(){ |
| 136 | jQuery(this).addClass('os-loading'); |
| 137 | jQuery("#selected_step_code > option:selected") |
| 138 | .prop("selected", false) |
| 139 | .prev() |
| 140 | .prop("selected", true).trigger('change'); |
| 141 | }); |
| 142 | |
| 143 | |
| 144 | jQuery('.booking-form-preview .os-image-selector-trigger').on('click', function(){ |
| 145 | jQuery('.booking-form-preview').addClass('has-changes'); |
| 146 | }); |
| 147 | |
| 148 | jQuery('.booking-form-preview .editable-setting').on('focus', function(){ |
| 149 | jQuery('.booking-form-preview').addClass('has-changes'); |
| 150 | }); |
| 151 | |
| 152 | |
| 153 | let editor = new MediumEditor('.booking-form-preview .os-editable', {toolbar: { |
| 154 | buttons: [ |
| 155 | { |
| 156 | name: 'bold', |
| 157 | classList: ['latepoint-icon', 'latepoint-icon-format_bold'], |
| 158 | }, |
| 159 | { |
| 160 | name: 'anchor', |
| 161 | classList: ['latepoint-icon', 'latepoint-icon-format_link'], |
| 162 | }, |
| 163 | { |
| 164 | name: 'h3', |
| 165 | classList: ['latepoint-icon', 'latepoint-icon-format_h3'], |
| 166 | }, |
| 167 | { |
| 168 | name: 'h4', |
| 169 | classList: ['latepoint-icon', 'latepoint-icon-format_h4'], |
| 170 | }, |
| 171 | { |
| 172 | name: 'h5', |
| 173 | classList: ['latepoint-icon', 'latepoint-icon-format_h5'], |
| 174 | }, |
| 175 | |
| 176 | ] |
| 177 | } |
| 178 | }); |
| 179 | let editor_basic = new MediumEditor('.booking-form-preview .os-editable-basic', {toolbar: { |
| 180 | buttons: [ |
| 181 | { |
| 182 | name: 'bold', |
| 183 | classList: ['latepoint-icon', 'latepoint-icon-format_bold'], |
| 184 | }, |
| 185 | { |
| 186 | name: 'italic', |
| 187 | classList: ['latepoint-icon', 'latepoint-icon-format_italic'], |
| 188 | }, |
| 189 | { |
| 190 | name: 'underline', |
| 191 | classList: ['latepoint-icon', 'latepoint-icon-format_underlined'], |
| 192 | }, |
| 193 | { |
| 194 | name: 'anchor', |
| 195 | classList: ['latepoint-icon', 'latepoint-icon-format_link'], |
| 196 | }, |
| 197 | |
| 198 | ] |
| 199 | } |
| 200 | }); |
| 201 | } |
| 202 | |
| 203 | function latepoint_reload_booking_form_preview(){ |
| 204 | latepoint_booking_form_save_changes(); |
| 205 | } |
| 206 | |
| 207 | function latepoint_init_steps_settings(){ |
| 208 | |
| 209 | jQuery('.booking-form-preview-settings').on('change', ' select, input[type="hidden"]', function(){ |
| 210 | jQuery('.booking-form-preview-settings').addClass('os-loading'); |
| 211 | latepoint_reload_booking_form_preview(); |
| 212 | }); |
| 213 | |
| 214 | jQuery('.trigger-custom-color-save').on('click', function(){ |
| 215 | jQuery('.booking-form-preview-settings').addClass('os-loading'); |
| 216 | latepoint_booking_form_save_changes(); |
| 217 | return false; |
| 218 | }); |
| 219 | |
| 220 | jQuery('.bf-color-scheme-color-trigger').on('click', function(){ |
| 221 | jQuery('.bf-color-scheme-color-trigger.is-selected').removeClass('is-selected'); |
| 222 | jQuery(this).addClass('is-selected'); |
| 223 | let color_scheme = jQuery(this).data('color-code'); |
| 224 | jQuery('.os-color-scheme-selector-wrapper select').val(color_scheme).trigger('change'); |
| 225 | if(color_scheme == 'custom'){ |
| 226 | jQuery('.os-custom-color-selector-wrapper').removeClass('is-hidden'); |
| 227 | }else{ |
| 228 | jQuery('.os-custom-color-selector-wrapper').addClass('is-hidden'); |
| 229 | } |
| 230 | return false; |
| 231 | }); |
| 232 | |
| 233 | jQuery('.os-section-collapsible-trigger').on('click', function(){ |
| 234 | jQuery(this).closest('.os-section-collapsible-wrapper').toggleClass('is-open'); |
| 235 | return false; |
| 236 | }) |
| 237 | } |
| 238 | |
| 239 | |
| 240 | function latepoint_booking_form_preview_init_timeslots($booking_form_element = false){ |
| 241 | if(!$booking_form_element) return; |
| 242 | $booking_form_element.on('click', '.dp-timepicker-trigger', function(){ |
| 243 | if(jQuery(this).hasClass('is-booked') || jQuery(this).hasClass('is-off')){ |
| 244 | // Show error message that you cant select a booked period |
| 245 | }else{ |
| 246 | if(jQuery(this).hasClass('selected')){ |
| 247 | jQuery(this).removeClass('selected'); |
| 248 | jQuery(this).find('.dp-success-label').remove(); |
| 249 | }else{ |
| 250 | $booking_form_element.find('.dp-timepicker-trigger.selected').removeClass('selected').find('.dp-success-label').remove(); |
| 251 | var selected_timeslot_time = jQuery(this).find('.dp-label-time').html(); |
| 252 | jQuery(this).addClass('selected').find('.dp-label').prepend('<span class="dp-success-label">' + latepoint_helper.datepicker_timeslot_selected_label + '</span>'); |
| 253 | |
| 254 | var minutes = parseInt(jQuery(this).data('minutes')); |
| 255 | var start_date = new Date($booking_form_element.find('.os-day.selected').data('date')); |
| 256 | $booking_form_element.find('.latepoint_start_date').val(start_date.toISOString().split('T')[0]) |
| 257 | latepoint_trigger_next_btn($booking_form_element); |
| 258 | } |
| 259 | } |
| 260 | return false; |
| 261 | }); |
| 262 | } |
| 263 | |
| 264 | |
| 265 | function latepoint_booking_form_preview_day_timeslots($day){ |
| 266 | let $wrapper_element = jQuery('.booking-form-preview'); |
| 267 | $day.addClass('selected'); |
| 268 | |
| 269 | var service_duration = $day.data('service-duration'); |
| 270 | var interval = $day.data('interval'); |
| 271 | var work_start_minutes = $day.data('work-start-time'); |
| 272 | var work_end_minutes = $day.data('work-end-time'); |
| 273 | var total_work_minutes = $day.data('total-work-minutes'); |
| 274 | var bookable_minutes = []; |
| 275 | var available_capacities_of_bookable_minute = []; |
| 276 | if($day.attr('data-bookable-minutes')){ |
| 277 | if($day.data('bookable-minutes').toString().indexOf(':') > -1){ |
| 278 | // has capacity information embedded into bookable minutes string |
| 279 | let bookable_minutes_with_capacity = $day.data('bookable-minutes').toString().split(','); |
| 280 | for(let i = 0; i < bookable_minutes_with_capacity.length; i++){ |
| 281 | bookable_minutes.push(parseInt(bookable_minutes_with_capacity[i].split(':')[0])); |
| 282 | available_capacities_of_bookable_minute.push(parseInt(bookable_minutes_with_capacity[i].split(':')[1])); |
| 283 | } |
| 284 | }else{ |
| 285 | bookable_minutes = $day.data('bookable-minutes').toString().split(',').map(Number); |
| 286 | } |
| 287 | } |
| 288 | var work_minutes = $day.data('work-minutes').toString().split(',').map(Number); |
| 289 | |
| 290 | var $timeslots = $wrapper_element.find('.timeslots'); |
| 291 | $timeslots.html(''); |
| 292 | |
| 293 | if(total_work_minutes > 0 && bookable_minutes.length && work_minutes.length){ |
| 294 | var prev_minutes = false; |
| 295 | work_minutes.forEach(function(current_minutes){ |
| 296 | var ampm = latepoint_am_or_pm(current_minutes); |
| 297 | |
| 298 | var timeslot_class = 'dp-timepicker-trigger'; |
| 299 | var timeslot_available_capacity = 0; |
| 300 | if($wrapper_element.find('.os-dates-w').data('time-pick-style') == 'timeline'){ |
| 301 | timeslot_class+= ' dp-timeslot'; |
| 302 | }else{ |
| 303 | timeslot_class+= ' dp-timebox'; |
| 304 | } |
| 305 | |
| 306 | if(prev_minutes !== false && ((current_minutes - prev_minutes) > service_duration)){ |
| 307 | // show interval that is off between two work periods |
| 308 | 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); |
| 309 | var off_width = (((current_minutes - prev_minutes - service_duration) / total_work_minutes) * 100); |
| 310 | $timeslots.append('<div class="'+ timeslot_class +' is-off" style="max-width:'+ off_width +'%; width:'+ off_width +'%"><span class="dp-label">' + off_label + '</span></div>'); |
| 311 | } |
| 312 | |
| 313 | if(!bookable_minutes.includes(current_minutes)){ |
| 314 | timeslot_class+= ' is-booked'; |
| 315 | }else{ |
| 316 | if(available_capacities_of_bookable_minute.length) timeslot_available_capacity = available_capacities_of_bookable_minute[bookable_minutes.indexOf(current_minutes)]; |
| 317 | } |
| 318 | var tick_html = ''; |
| 319 | var capacity_label = ''; |
| 320 | var capacity_label_html = ''; |
| 321 | var capacity_internal_label_html = ''; |
| 322 | |
| 323 | if(((current_minutes % 60) == 0) || (interval >= 60)){ |
| 324 | timeslot_class+= ' with-tick'; |
| 325 | tick_html = '<span class="dp-tick"><strong>'+latepoint_minutes_to_hours_preferably(current_minutes)+'</strong>'+' '+ampm+'</span>'; |
| 326 | } |
| 327 | var timeslot_label = latepoint_minutes_to_hours_and_minutes(current_minutes)+' '+ampm; |
| 328 | if(latepoint_show_booking_end_time()){ |
| 329 | var end_minutes = current_minutes + service_duration; |
| 330 | if(end_minutes > 1440) end_minutes = end_minutes - 1440; |
| 331 | var end_minutes_ampm = latepoint_am_or_pm(end_minutes); |
| 332 | timeslot_label+= ' - <span class="dp-label-end-time">' + latepoint_minutes_to_hours_and_minutes(end_minutes)+' '+end_minutes_ampm + '</span>'; |
| 333 | } |
| 334 | if(timeslot_available_capacity){ |
| 335 | var spaces_message = timeslot_available_capacity > 1 ? latepoint_helper.many_spaces_message : latepoint_helper.single_space_message; |
| 336 | capacity_label = timeslot_available_capacity + ' ' + spaces_message; |
| 337 | capacity_label_html = '<span class="dp-capacity">' + capacity_label + '</span>'; |
| 338 | capacity_internal_label_html = '<span class="dp-label-capacity">' + capacity_label + '</span>'; |
| 339 | } |
| 340 | timeslot_label = timeslot_label.trim(); |
| 341 | $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>'); |
| 342 | prev_minutes = current_minutes; |
| 343 | }); |
| 344 | }else{ |
| 345 | // No working hours this day |
| 346 | $timeslots.addClass('slots-not-available').append('<div class="not-working-message">' + latepoint_helper.msg_not_available + "</div>"); |
| 347 | } |
| 348 | jQuery('.times-header-label span').text($day.data('nice-date')); |
| 349 | $wrapper_element.find('.time-selector-w').slideDown(200); |
| 350 | } |
| 351 | |
| 352 | function latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element){ |
| 353 | |
| 354 | if(!$booking_form_element) return; |
| 355 | $booking_form_element.on('click', '.os-month-next-btn', function(){ |
| 356 | var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 357 | var next_month_route_name = jQuery(this).data('route'); |
| 358 | if($booking_form_element.find('.os-monthly-calendar-days-w.active + .os-monthly-calendar-days-w').length){ |
| 359 | $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').next('.os-monthly-calendar-days-w').addClass('active'); |
| 360 | latepoint_booking_form_preview_calendar_set_month_label($booking_form_element); |
| 361 | }else{ |
| 362 | alert('Disabled in preview'); |
| 363 | } |
| 364 | latepoint_calendar_show_or_hide_prev_next_buttons($booking_form_element); |
| 365 | return false; |
| 366 | }); |
| 367 | $booking_form_element.on('click', '.os-month-prev-btn', function(){ |
| 368 | var $booking_form_element = jQuery(this).closest('.latepoint-booking-form-element'); |
| 369 | if($booking_form_element.find('.os-monthly-calendar-days-w.active').prev('.os-monthly-calendar-days-w').length){ |
| 370 | $booking_form_element.find('.os-monthly-calendar-days-w.active').removeClass('active').prev('.os-monthly-calendar-days-w').addClass('active'); |
| 371 | latepoint_booking_form_preview_calendar_set_month_label($booking_form_element); |
| 372 | } |
| 373 | return false; |
| 374 | }); |
| 375 | } |
| 376 | |
| 377 | |
| 378 | function latepoint_booking_form_preview_calendar_set_month_label(){ |
| 379 | jQuery('.os-current-month-label .current-month').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-month-label')); |
| 380 | jQuery('.os-current-month-label .current-year').text(jQuery('.os-monthly-calendar-days-w.active').data('calendar-year')); |
| 381 | } |
| 382 | |
| 383 | |
| 384 | |
| 385 | function latepoint_booking_form_preview_init_datepicker(){ |
| 386 | let $booking_form_element = jQuery('.latepoint-booking-form-element'); |
| 387 | latepoint_booking_form_preview_init_timeslots($booking_form_element); |
| 388 | latepoint_booking_form_preview_init_monthly_calendar_navigation($booking_form_element); |
| 389 | $booking_form_element.on('click', '.os-months .os-day', function(){ |
| 390 | if(jQuery(this).hasClass('os-day-passed')) return false; |
| 391 | if(jQuery(this).hasClass('os-not-in-allowed-period')) return false; |
| 392 | if(jQuery(this).hasClass('os-month-prev')) return false; |
| 393 | if(jQuery(this).hasClass('os-month-next')) return false; |
| 394 | if(jQuery(this).closest('.os-monthly-calendar-days-w').hasClass('hide-if-single-slot')){ |
| 395 | |
| 396 | // HIDE TIMESLOT IF ONLY ONE TIMEPOINT |
| 397 | if(jQuery(this).hasClass('os-not-available')){ |
| 398 | // clicked on a day that has no available timeslots |
| 399 | // do nothing |
| 400 | }else{ |
| 401 | $booking_form_element.find('.os-day.selected').removeClass('selected'); |
| 402 | jQuery(this).addClass('selected'); |
| 403 | // set date |
| 404 | $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 405 | if(jQuery(this).hasClass('os-one-slot-only')){ |
| 406 | // clicked on a day that has only one slot available |
| 407 | var bookable_minutes = jQuery(this).data('bookable-minutes').toString().split(':')[0]; |
| 408 | var selected_timeslot_time = latepoint_format_minutes_to_time(Number(bookable_minutes), Number(jQuery(this).data('service-duration'))); |
| 409 | $booking_form_element.find('.time-selector-w').slideUp(200); |
| 410 | }else{ |
| 411 | // regular day with more than 1 timeslots available |
| 412 | // build timeslots |
| 413 | latepoint_booking_form_preview_day_timeslots(jQuery(this)); |
| 414 | // clear time and hide next btn |
| 415 | } |
| 416 | } |
| 417 | }else{ |
| 418 | // SHOW TIMESLOTS EVEN IF ONLY ONE TIMEPOINT |
| 419 | $booking_form_element.find('.latepoint_start_date').val(jQuery(this).data('date')); |
| 420 | $booking_form_element.find('.os-day.selected').removeClass('selected'); |
| 421 | jQuery(this).addClass('selected'); |
| 422 | |
| 423 | // build timeslots |
| 424 | latepoint_booking_form_preview_day_timeslots(jQuery(this)); |
| 425 | // clear time and hide next btn |
| 426 | } |
| 427 | |
| 428 | |
| 429 | return false; |
| 430 | }); |
| 431 | } |
| 432 |