PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / trunk
LatePoint – Calendar Booking Plugin for Appointments and Events vtrunk
5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / assets / javascripts / bin / admin / _steps.js
latepoint / lib / assets / javascripts / bin / admin Last commit date
_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