1/*start single day and appointment pricing booking*/ 2 3/* Start Calendar Script */ 4let bikecarsd_price_arr = {}; 5let service_price_arr = {}; 6 7 8jQuery(document).on('click','.rbfw_back_step_btn',function (e) { 9 let back_step = jQuery(this).attr('back-step'); 10 let current_step = jQuery(this).attr('data-step'); 11 jQuery('.rbfw-bikecarsd-step[data-step="'+current_step+'"]').hide(); 12 jQuery('.rbfw-bikecarsd-step[data-step="'+back_step+'"]').show(); 13}); 14 15 16jQuery(document).on('click','.rbfw_bikecarsd_time:not(.rbfw_bikecarsd_time.disabled)',function (e) { 17 18 let gTime = jQuery(this).attr('data-time'); 19 20 let selected_date = jQuery('[name="rbfw_bikecarsd_selected_date"]').val(); 21 let post_id = jQuery('#rbfw_post_id').val(); 22 let rent_type = jQuery('#rbfw_rent_type').val(); 23 let is_muffin_template = jQuery('.rbfw_muffin_template').length; 24 25 jQuery('.rbfw_bikecarsd_time').removeClass('selected'); 26 jQuery(this).addClass('selected'); 27 jQuery('#rbfw_start_time').val(gTime); 28 29 if(is_muffin_template > 0){ 30 is_muffin_template = '1'; 31 } else { 32 is_muffin_template = '0'; 33 } 34 35 jQuery.ajax({ 36 type: 'POST', 37 url: rbfw_ajax_front.rbfw_ajaxurl, 38 data: { 39 'action' : 'rbfw_bikecarsd_type_list', 40 'post_id': post_id, 41 'selected_time': gTime, 42 'selected_date': selected_date, 43 'is_muffin_template': is_muffin_template, 44 'nonce' : rbfw_ajax_front.nonce_bikecarsd_type_list 45 }, 46 beforeSend: function() { 47 48 jQuery('.rbfw_bikecarsd_pricing_table_wrap').addClass('rbfw_loader_in'); 49 jQuery('.rbfw_bikecarsd_pricing_table_wrap').append('<i class="fas fa-spinner fa-spin"></i>'); 50 51 if( rent_type == 'appointment' ){ 52 jQuery('.rbfw_bikecarsd_price_summary').addClass('old'); 53 } 54 }, 55 success: function (response) { 56 57 jQuery('.rbfw_bikecarsd_pricing_table_wrap').removeClass('rbfw_loader_in'); 58 jQuery('.rbfw_bikecarsd_pricing_table_wrap i.fa-spinner').remove(); 59 60 if( rent_type == 'bike_car_sd' ){ 61 jQuery('.rbfw-bikecarsd-step[data-step="2"]').hide(); 62 } 63 jQuery('.rbfw_bikecarsd_pricing_table_container').remove(); 64 jQuery('.rbfw-bikecarsd-result').append(response); 65 66 if( rent_type == 'appointment' ){ 67 jQuery('.rbfw-bikecarsd-step[data-step="3"] .rbfw_back_step_btn').hide(); 68 jQuery('.rbfw-bikecarsd-step[data-step="3"] .rbfw_step_selected_date').hide(); 69 jQuery('#rbfw_bikecarsd_selected_time').val(); 70 jQuery('.rbfw-bikecarsd-step[data-step="2"] .rbfw_step_selected_date span.rbfw_selected_time').remove(); 71 } 72 73 jQuery('.rbfw_muff_registration_wrapper .rbfw_regf_wrap').show(); 74 75 76 77 }, 78 complete:function(response) { 79 jQuery('html, body').animate({ 80 scrollTop: jQuery(".rbfw-bikecarsd-calendar-header").offset().top 81 }, 100); 82 } 83 }); 84}); 85 86 87 88function rbfw_off_day_dates(date,type='',today_enable='no',dropoff=null){ 89 90 91 92 var curr_date = ("0" + (date.getDate())).slice(-2); 93 var curr_month = ("0" + (date.getMonth() + 1)).slice(-2); 94 var curr_year = date.getFullYear(); 95 var date_in = curr_date+"-"+curr_month+"-"+curr_year; 96 var date_today = new Date(); 97 var rbfw_buffer_time = parseInt(jQuery("#rbfw_buffer_time").val()); 98 99 100 if(rbfw_buffer_time){ 101 date_today = new Date(date_today); 102 date_today.setHours(date_today.getHours() + rbfw_buffer_time); 103 date_today.setDate(date_today.getDate() - 1); 104 }else{ 105 if(today_enable=='yes'){ 106 date_today.setDate(date_today.getDate() - 1); 107 } 108 } 109 110 //alert(date_today); 111 112 /* if(today_enable=='yes'){ 113 date_today.setDate(date_today.getDate() - 1); 114 }*/ 115 116 var weekday = ["sunday","monday","tuesday","wednesday","thursday","friday","saturday"]; 117 var day_in = weekday[date.getDay()]; 118 var rbfw_off_days = JSON.parse(jQuery("#rbfw_off_days").val()); 119 120 var rbfw_offday_range = JSON.parse(jQuery("#rbfw_offday_range").val()); 121 122 123 124 125 if(jQuery.inArray( day_in, rbfw_off_days )>= 0 || jQuery.inArray( date_in, rbfw_offday_range )>= 0 || (date < date_today) ){ 126 127 if(type=='md'){ 128 if((date < date_today)){ 129 return [false, "notav", '']; 130 }else{ 131 return [false, "notav", rbfw_translation.off_label]; 132 } 133 134 }else{ 135 return true; 136 } 137 }else{ 138 139 if(type=='md'){ 140 141 let rbfw_rent_type = jQuery("#rbfw_rent_type").val(); 142 143 if(rbfw_rent_type == 'bike_car_md'){ 144 if(jQuery('#rbfw_month_wise_inventory').val()){ 145 const day_wise_inventory = JSON.parse(jQuery('#rbfw_month_wise_inventory').val()); 146 147 if(day_wise_inventory[date_in]==0){ 148 return [false, "notav", rbfw_translation.sold_out]; 149 } 150 151 152 if(dropoff){ 153 // Additional check for return date selection 154 // If pickup date is already selected and we're selecting return date 155 let pickup_date = jQuery('input[name="rbfw_pickup_start_date"]').val(); 156 if(pickup_date && pickup_date !== '') { 157 // Check if this is for return date calendar by checking if current date is after pickup date 158 let pickup_date_obj = new Date(pickup_date); 159 if(date > pickup_date_obj) { 160 // Check for first sold-out date in the sequence from pickup to current date 161 let current_check_date = new Date(pickup_date_obj); 162 current_check_date.setDate(current_check_date.getDate() + 1); // Start from day after pickup 163 164 while(current_check_date <= date) { 165 let check_curr_date = ("0" + current_check_date.getDate()).slice(-2); 166 let check_curr_month = ("0" + (current_check_date.getMonth() + 1)).slice(-2); 167 let check_curr_year = current_check_date.getFullYear(); 168 let check_date_in = check_curr_date+"-"+check_curr_month+"-"+check_curr_year; 169 170 // If we find a sold-out date in the sequence, disable all subsequent dates 171 if(day_wise_inventory[check_date_in] == 0) { 172 return [false, "notav", '']; 173 } 174 175 current_check_date.setDate(current_check_date.getDate() + 1); 176 } 177 } 178 } 179 } 180 181 182 183 184 185 } 186 187 } 188 189 190 return [true, "av", ""]; 191 }else{ 192 return false;
193 } 194 } 195} 196 197 198function getAvailableTimes(schedule, givenDate,rdfw_available_time,pickup_time_particular,is_calendar=null) { 199 200 var rbfw_buffer_time = parseInt(jQuery("#rbfw_buffer_time").val()); 201 202 203 var scheduleJson = []; 204 try { 205 var parsedAvailable = (typeof schedule === 'string') ? JSON.parse(schedule) : schedule; 206 if (Array.isArray(parsedAvailable)) { 207 scheduleJson = parsedAvailable; 208 } else if (parsedAvailable && typeof parsedAvailable === 'object') { 209 scheduleJson = Object.values(parsedAvailable); 210 } else { 211 scheduleJson = []; 212 } 213 } catch (e) { 214 scheduleJson = []; 215 } 216 // Safely parse and normalize rdfw_available_time into an array 217 var rdfw_available_timeJson = []; 218 try { 219 var parsedAvailable = (typeof rdfw_available_time === 'string') ? JSON.parse(rdfw_available_time) : rdfw_available_time; 220 if (Array.isArray(parsedAvailable)) { 221 rdfw_available_timeJson = parsedAvailable; 222 } else if (parsedAvailable && typeof parsedAvailable === 'object') { 223 rdfw_available_timeJson = Object.values(parsedAvailable); 224 } else { 225 rdfw_available_timeJson = []; 226 } 227 } catch (e) { 228 rdfw_available_timeJson = []; 229 } 230 let sapecific_date_time = false; 231 let time_enable = false; 232 let past_time = '' 233 234 const selectedDate = new Date(givenDate); 235 236 const timeSelect = document.getElementById(pickup_time_particular); 237 238 239 if(is_calendar=='calendar'){ 240 timeSelect.innerHTML = ''; 241 }else{ 242 timeSelect.innerHTML = '<option value="">'+ rbfw_translation.pickup_time +'</option>'; // reset options 243 } 244 245 246 // loop through data 247 Object.values(scheduleJson).forEach(item => { 248 const start = new Date(item.start_date); 249 const end = new Date(item.end_date); 250 251 // check if selected date is within range 252 if (selectedDate >= start && selectedDate <= end) { 253 254 255 var specific_available_time = []; 256 try { 257 var parsedAvailable = (typeof item.available_time === 'string') ? JSON.parse(item.available_time) : item.available_time; 258 if (Array.isArray(parsedAvailable)) { 259 specific_available_time = parsedAvailable; 260 } else if (parsedAvailable && typeof parsedAvailable === 'object') { 261 specific_available_time = Object.values(parsedAvailable); 262 } else { 263 specific_available_time = []; 264 } 265 } catch (e) { 266 specific_available_time = []; 267 } 268 269 270 specific_available_time.forEach(timeObj => { 271 if (timeObj.status === "enabled") { 272 273 let current_date_time = new Date(rbfw_js_variables.currentDateTime.replace(" ", "T"));// new Date(); 274 let actual_booking_date_time_format = new Date(current_date_time); 275 actual_booking_date_time_format.setHours(current_date_time.getHours() + rbfw_buffer_time); 276 277 let actual_booking_date_time = new Date(actual_booking_date_time_format); 278 let actual_booking_date = actual_booking_date_time.toLocaleDateString('en-CA'); 279 280 let selectedDateStr = selectedDate.toISOString().split("T")[0]; 281 282 if (selectedDateStr === actual_booking_date) { 283 // Parse available_time into a Date object for comparison 284 let [hours, minutes] = timeObj.time.split(":").map(Number); 285 //et timeDate = new Date(rbfw_js_variables.currentDateTime.replace(" ", "T")); 286 actual_booking_date_time_format.setHours(hours, minutes, 0, 0); 287 288 console.log('actual_booking_date_time_format',actual_booking_date_time_format); 289 // console.log('timeDate',timeDate); 290 291 if (actual_booking_date_time >= actual_booking_date_time_format) { 292 time_enable = true; 293 past_time = 'Past time'; 294 }else{ 295 time_enable = false;
296 past_time = ''; 297 } 298 } 299 300 301 let myTime = timeObj.time; 302 303 // Split into hours and minutes 304 let [hours, minutes] = myTime.split(":").map(Number); 305 306 // Create a JS Date object for formatting 307 let date = new Date(); 308 date.setHours(hours); 309 date.setMinutes(minutes); 310 311 sapecific_date_time = true; 312 313 if(is_calendar=='calendar'){ 314 315 const a = document.createElement("a"); 316 if(time_enable){ 317 a.className = "rbfw_bikecarsd_time_disable"; 318 a.title = "Past Time"; 319 }else{ 320 a.className = "rbfw_bikecarsd_time"; 321 } 322 323 a.setAttribute("data-time", timeObj.time); 324 325 const span = document.createElement("span"); 326 span.className = "rbfw_bikecarsd_time_span"; 327 span.textContent = formatTime(date, rbfw_js_variables.timeFormat); timeObj.time;; 328 329 a.appendChild(span); 330 timeSelect.appendChild(a); 331 332 }else{ 333 const option = document.createElement("option"); 334 option.value = timeObj.time; 335 option.textContent = formatTime(date, rbfw_js_variables.timeFormat); timeObj.time; 336 option.disabled = time_enable; 337 option.title = past_time; 338 timeSelect.appendChild(option); 339 } 340 } 341 }); 342 } 343 }); 344 345 if(sapecific_date_time==false && Array.isArray(rdfw_available_timeJson)){ 346 rdfw_available_timeJson.forEach(timeObj => { 347 if (timeObj.status === "enabled") { 348 349 350 let current_date_time = new Date(rbfw_js_variables.currentDateTime.replace(" ", "T"));// new Date(); 351 let actual_booking_date_time_format = new Date(current_date_time); 352 actual_booking_date_time_format.setHours(current_date_time.getHours() + rbfw_buffer_time); 353 354 let actual_booking_date_time = new Date(actual_booking_date_time_format); 355 let actual_booking_date = actual_booking_date_time.toLocaleDateString('en-CA'); 356 357 let selectedDateStr = selectedDate.toISOString().split("T")[0]; 358 359 if (selectedDateStr === actual_booking_date) { 360 // Parse available_time into a Date object for comparison 361 let [hours, minutes] = timeObj.time.split(":").map(Number); 362 //et timeDate = new Date(rbfw_js_variables.currentDateTime.replace(" ", "T")); 363 actual_booking_date_time_format.setHours(hours, minutes, 0, 0); 364 365 console.log('actual_booking_date_time_format',actual_booking_date_time_format); 366 // console.log('timeDate',timeDate); 367 368 if (actual_booking_date_time >= actual_booking_date_time_format) { 369 time_enable = true; 370 past_time = 'Past time'; 371 }else{ 372 time_enable = false; 373 past_time = ''; 374 } 375 } 376 377 378 let myTime = timeObj.time; // 2:30 PM 379 380 let [time, modifier] = myTime.split(" "); // "2:30" and "PM" 381 let [hours, minutes] = time.split(":").map(Number); 382 383 if (modifier === "PM" && hours !== 12) { 384 hours += 12; 385 } 386 if (modifier === "AM" && hours === 12) { 387 hours = 0; 388 } 389 390 391 let date = new Date(); 392 393 const h = parseInt(hours, 10); 394 const m = parseInt(minutes, 10); 395 396 if (!isNaN(h) && !isNaN(m)) { 397 date.setHours(h); 398 date.setMinutes(m); 399 date.setSeconds(0); 400 } else { 401 console.error("Invalid hours or minutes:", hours, minutes); 402 } 403 404 if (isNaN(date.getTime())) { 405 console.error("Invalid Date generated:", date); 406 } else { 407 sapecific_date_time = true; 408 409 if (is_calendar === 'calendar') { 410 const a = document.createElement("a"); 411 if (time_enable) { 412 a.className = "rbfw_bikecarsd_time_disable"; 413 a.title = "Past Time"; 414 } else { 415 a.className = "rbfw_bikecarsd_time"; 416 } 417 a.setAttribute("data-time", timeObj.time); 418 419 const span = document.createElement("span"); 420 span.className = "rbfw_bikecarsd_time_span"; 421
422 console.log('date', formatTime(date, rbfw_js_variables.timeFormat)); 423 424 span.textContent = formatTime(date, rbfw_js_variables.timeFormat); 425 426 a.appendChild(span); 427 timeSelect.appendChild(a); 428 }else{ 429 const option = document.createElement("option"); 430 option.value = timeObj.time; 431 option.textContent = formatTime(date, rbfw_js_variables.timeFormat); timeObj.time; 432 option.disabled = time_enable; 433 option.title = past_time; 434 timeSelect.appendChild(option); 435 } 436 } 437 438 439 440 441 442 443 444 /*let date = new Date(); 445 date.setHours(hours); 446 date.setMinutes(minutes); 447 sapecific_date_time = true; 448 449 if(is_calendar=='calendar'){ 450 451 const a = document.createElement("a"); 452 if(time_enable){ 453 a.className = "rbfw_bikecarsd_time_disable"; 454 a.title = "Past Time"; 455 }else{ 456 a.className = "rbfw_bikecarsd_time"; 457 } 458 a.setAttribute("data-time", timeObj.time); 459 460 const span = document.createElement("span"); 461 span.className = "rbfw_bikecarsd_time_span"; 462 span.textContent = formatTime(date, rbfw_js_variables.timeFormat); timeObj.time;; 463 464 a.appendChild(span); 465 timeSelect.appendChild(a); 466 467 468 }else{ 469 const option = document.createElement("option"); 470 option.value = timeObj.time; 471 option.textContent = formatTime(date, rbfw_js_variables.timeFormat); timeObj.time; 472 option.disabled = time_enable; 473 option.title = past_time; 474 timeSelect.appendChild(option); 475 }*/ 476 477 478 } 479 }) 480 } 481 482 let pickup_date = jQuery('#hidden_pickup_date').val(); 483 let dropoff_date = jQuery('#hidden_dropoff_date').val(); 484 let selected_time = jQuery('.pickup_time').val(); 485 486 487 // Only validate if both dates are selected and they are the same day 488 if (pickup_date && dropoff_date && pickup_date == dropoff_date && selected_time) { 489 // Convert pickup time to comparable format (HH:MM) 490 let pickup_time_parts = selected_time.split(':'); 491 let pickup_hours = parseInt(pickup_time_parts[0]); 492 let pickup_minutes = parseInt(pickup_time_parts[1]); 493 let pickup_time_minutes = pickup_hours * 60 + pickup_minutes; 494 495 // Clear current return time selection 496 jQuery(".dropoff_time").val("").trigger("change"); 497 498 // Update return time options 499 jQuery("#dropoff_time option").each(function() { 500 var thisOptionValue = jQuery(this).val(); 501 if (thisOptionValue && thisOptionValue !== '') { 502 // Convert return time to comparable format (HH:MM) 503 let return_time_parts = thisOptionValue.split(':'); 504 let return_hours = parseInt(return_time_parts[0]); 505 let return_minutes = parseInt(return_time_parts[1]); 506 let return_time_minutes = return_hours * 60 + return_minutes; 507 508 // Disable return times that are earlier than or equal to pickup time 509 if (return_time_minutes <= pickup_time_minutes) { 510 jQuery(this).attr('disabled', true); 511 } else { 512 jQuery(this).attr('disabled', false); 513 } 514 } else { 515 jQuery(this).attr('disabled', true); 516 } 517 }); 518 } 519 520 521} 522 523 524function formatTime(date, format) { 525 // Map WP PHP formats to JS Intl options 526 let options = {}; 527 if (format.includes('a') || format.includes('A')) { 528 options.hour12 = true; 529 } else { 530 options.hour12 = false; 531 } 532 options.hour = 'numeric'; 533 options.minute = '2-digit'; 534 535 return new Intl.DateTimeFormat([], options).format(date); 536} 537 538 539 540jQuery(document).on('click', '#add-date-range-row',function(e){ 541 e.preventDefault(); 542 var off_date_range_content = jQuery('.off_date_range_content').clone(true); 543 544 jQuery('.off_date_range').append(off_date_range_content); 545 546 off_date_range_content.find('.rbfw_off_days_range_start').attr('name','off_days_start[]'); 547 off_date_range_content.find('.rbfw_off_days_range_end').attr('name','off_days_end[]'); 548 off_date_range_content.removeClass('off_date_range_content hidden'); 549 off_date_range_content.addClass('off_date_range_remove'); 550 off_date_range_content.insertBefore(".off_date_range_content"); 551 return false;
552 553}); 554 555 556/*jQuery(document).on('click', '.remove-row',function(e){ 557 if (confirm('Are You Sure , Remove this row ? \n\n 1. Ok : To Remove . \n 2. Cancel : To Cancel .')) { 558 jQuery(this).parents('.off_date_range_child').remove(); 559 } else { 560 return false; 561 } 562});*/ 563 564jQuery(document).on("click", ".rbfw_off_days_range", function (e) { 565 jQuery(this).datepicker({ 566 dateFormat: 'dd-mm-yy', 567 minDate: 0 568 }).datepicker( "show" ); 569}); 570 571 572jQuery(document).on('click', '.groupCheckBox .customCheckboxLabel', function () { 573 let parent = jQuery(this).closest('.groupCheckBox'); 574 let value = ''; 575 let separator = ','; 576 parent.find(' input[type="checkbox"]').each(function () { 577 if (jQuery(this).is(":checked")) { 578 let currentValue = jQuery(this).attr('data-checked'); 579 value = value + (value ? separator : '') + currentValue; 580 } 581 }).promise().done(function () { 582 parent.find('input[type="hidden"]').val(value); 583 }); 584}); 585 586// Real-time validation for pickup time change 587jQuery(document).on('change', '.pickup_time', function() { 588 let pickup_date = jQuery('#hidden_pickup_date').val(); 589 let dropoff_date = jQuery('#hidden_dropoff_date').val(); 590 let selected_time = jQuery('.pickup_time').val(); 591 592 593 // Only validate if both dates are selected and they are the same day 594 if (pickup_date && dropoff_date && pickup_date == dropoff_date && selected_time) { 595 // Convert pickup time to comparable format (HH:MM) 596 let pickup_time_parts = selected_time.split(':'); 597 let pickup_hours = parseInt(pickup_time_parts[0]); 598 let pickup_minutes = parseInt(pickup_time_parts[1]); 599 let pickup_time_minutes = pickup_hours * 60 + pickup_minutes; 600 601 // Clear current return time selection 602 jQuery(".dropoff_time").val("").trigger("change"); 603 604 // Update return time options 605 jQuery("#dropoff_time option").each(function() { 606 var thisOptionValue = jQuery(this).val(); 607 if (thisOptionValue && thisOptionValue !== '') { 608 // Convert return time to comparable format (HH:MM) 609 let return_time_parts = thisOptionValue.split(':'); 610 let return_hours = parseInt(return_time_parts[0]); 611 let return_minutes = parseInt(return_time_parts[1]); 612 let return_time_minutes = return_hours * 60 + return_minutes; 613 614 // Disable return times that are earlier than or equal to pickup time 615 if (return_time_minutes <= pickup_time_minutes) { 616 jQuery(this).attr('disabled', true); 617 } else { 618 jQuery(this).attr('disabled', false); 619 } 620 } else { 621 jQuery(this).attr('disabled', true); 622 } 623 }); 624 } 625}); 626 627function fee_management(sub_total_price,total_days=1,quantity=1){ 628 let rbfw_management_price = 0; 629 jQuery('.rbfw-management-price:checked').each(function() { 630 let price_type = jQuery(this).data('price_type'); 631 let price = parseFloat(jQuery(this).data('price')) || 0; 632 let frequency = jQuery(this).data('frequency'); 633 634 if (price_type === 'percentage') { 635 rbfw_management_price += ((price / 100) * sub_total_price); 636 } else { 637 if (frequency === 'one-time') { 638 rbfw_management_price += price * quantity; 639 } else { 640 rbfw_management_price += price * quantity * total_days; 641 } 642 } 643 }); 644 return rbfw_management_price; 645} 646 647
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.