Add additional services system (v0.5.0)
All checks were successful
Create Release Package / build-release (push) Successful in 1m0s
All checks were successful
Create Release Package / build-release (push) Successful in 1m0s
- Service CPT with pricing types: Included, Per Booking, Per Night - ServiceCategory taxonomy with default categories - Booking-services integration with service selector - Real-time price calculation based on nights and quantity - Services total and grand total display in booking admin Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -755,6 +755,185 @@
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize service pricing type toggle.
|
||||
*/
|
||||
function initServicePricing() {
|
||||
var $pricingTypeInputs = $('input[name="bnb_service_pricing_type"]');
|
||||
var $priceRow = $('#bnb-service-price-row');
|
||||
var $priceSuffix = $('#bnb-service-price-suffix');
|
||||
var $priceDescription = $('#bnb-service-price-description');
|
||||
|
||||
if (!$pricingTypeInputs.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pricingTypeInputs.on('change', function() {
|
||||
var pricingType = $('input[name="bnb_service_pricing_type"]:checked').val();
|
||||
|
||||
if (pricingType === 'included') {
|
||||
$priceRow.hide();
|
||||
} else {
|
||||
$priceRow.show();
|
||||
|
||||
if (pricingType === 'per_night') {
|
||||
$priceSuffix.text(' / ' + (wpBnbAdmin.i18n.night || 'night'));
|
||||
$priceDescription.text(wpBnbAdmin.i18n.perNightDescription || 'This price will be charged per night of the stay.');
|
||||
} else {
|
||||
$priceSuffix.text('');
|
||||
$priceDescription.text(wpBnbAdmin.i18n.perBookingDescription || 'This price will be charged once for the booking.');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize booking services selector.
|
||||
*/
|
||||
function initBookingServices() {
|
||||
var $servicesSelector = $('.bnb-services-selector');
|
||||
var $servicesList = $servicesSelector.find('.bnb-services-list');
|
||||
var $totalDisplay = $('#bnb-services-total-amount');
|
||||
|
||||
if (!$servicesSelector.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current number of nights from booking form.
|
||||
*
|
||||
* @return {number} Number of nights.
|
||||
*/
|
||||
function getNights() {
|
||||
var checkIn = $('#bnb_booking_check_in').val();
|
||||
var checkOut = $('#bnb_booking_check_out').val();
|
||||
|
||||
if (checkIn && checkOut) {
|
||||
var startDate = new Date(checkIn);
|
||||
var endDate = new Date(checkOut);
|
||||
var nights = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));
|
||||
return Math.max(1, nights);
|
||||
}
|
||||
|
||||
return parseInt($servicesSelector.data('nights'), 10) || 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate service line total.
|
||||
*
|
||||
* @param {jQuery} $item Service item element.
|
||||
* @param {number} nights Number of nights.
|
||||
* @return {number} Calculated price.
|
||||
*/
|
||||
function calculateServiceTotal($item, nights) {
|
||||
var price = parseFloat($item.data('price')) || 0;
|
||||
var pricingType = $item.data('pricing-type');
|
||||
var quantity = parseInt($item.find('.bnb-service-qty-input').val(), 10) || 1;
|
||||
|
||||
if (pricingType === 'included') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pricingType === 'per_night') {
|
||||
return price * quantity * nights;
|
||||
}
|
||||
|
||||
return price * quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update service line total display.
|
||||
*
|
||||
* @param {jQuery} $item Service item element.
|
||||
*/
|
||||
function updateServiceLineTotal($item) {
|
||||
var nights = getNights();
|
||||
var total = calculateServiceTotal($item, nights);
|
||||
var $lineTotal = $item.find('.bnb-service-line-total');
|
||||
var $totalValue = $item.find('.bnb-service-total-value');
|
||||
var isSelected = $item.find('input[type="checkbox"]').is(':checked');
|
||||
var pricingType = $item.data('pricing-type');
|
||||
|
||||
if (isSelected && pricingType !== 'included' && total > 0) {
|
||||
$totalValue.text(formatPrice(total));
|
||||
$lineTotal.show();
|
||||
} else {
|
||||
$lineTotal.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update total services amount.
|
||||
*/
|
||||
function updateServicesTotal() {
|
||||
var nights = getNights();
|
||||
var total = 0;
|
||||
|
||||
$servicesList.find('.bnb-service-item').each(function() {
|
||||
var $item = $(this);
|
||||
var isSelected = $item.find('input[type="checkbox"]').is(':checked');
|
||||
|
||||
if (isSelected) {
|
||||
total += calculateServiceTotal($item, nights);
|
||||
}
|
||||
});
|
||||
|
||||
$totalDisplay.text(formatPrice(total));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format price for display (simple formatting).
|
||||
*
|
||||
* @param {number} price Price value.
|
||||
* @return {string} Formatted price.
|
||||
*/
|
||||
function formatPrice(price) {
|
||||
return parseFloat(price).toFixed(2);
|
||||
}
|
||||
|
||||
// Handle service checkbox change.
|
||||
$servicesList.on('change', 'input[type="checkbox"]', function() {
|
||||
var $item = $(this).closest('.bnb-service-item');
|
||||
var isSelected = $(this).is(':checked');
|
||||
|
||||
$item.toggleClass('selected', isSelected);
|
||||
|
||||
// Show/hide quantity input.
|
||||
var $quantity = $item.find('.bnb-service-quantity');
|
||||
if ($quantity.length) {
|
||||
$quantity.toggle(isSelected);
|
||||
}
|
||||
|
||||
updateServiceLineTotal($item);
|
||||
updateServicesTotal();
|
||||
});
|
||||
|
||||
// Handle quantity change.
|
||||
$servicesList.on('change input', '.bnb-service-qty-input', function() {
|
||||
var $item = $(this).closest('.bnb-service-item');
|
||||
var maxQty = parseInt($item.data('max-quantity'), 10) || 1;
|
||||
var value = parseInt($(this).val(), 10) || 1;
|
||||
|
||||
// Enforce min/max.
|
||||
value = Math.max(1, Math.min(value, maxQty));
|
||||
$(this).val(value);
|
||||
|
||||
updateServiceLineTotal($item);
|
||||
updateServicesTotal();
|
||||
});
|
||||
|
||||
// Update when booking dates change.
|
||||
$('#bnb_booking_check_in, #bnb_booking_check_out').on('change', function() {
|
||||
$servicesList.find('.bnb-service-item.selected').each(function() {
|
||||
updateServiceLineTotal($(this));
|
||||
});
|
||||
updateServicesTotal();
|
||||
});
|
||||
|
||||
// Initial calculation.
|
||||
updateServicesTotal();
|
||||
}
|
||||
|
||||
// Initialize on document ready.
|
||||
$(document).ready(function() {
|
||||
initLicenseManagement();
|
||||
@@ -765,6 +944,8 @@
|
||||
initBookingForm();
|
||||
initCalendarPage();
|
||||
initGuestSearch();
|
||||
initServicePricing();
|
||||
initBookingServices();
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
Reference in New Issue
Block a user