/** * Single Trip Page JavaScript * * Handles frontend interactions for the single trip page including: * - Group discount calculations * - Traveler count management * - Pricing updates * - Flatpickr initialization * * @package Yatra */ document.addEventListener('DOMContentLoaded', function() { // Initialize date pickers when DOM is ready const bookingDateInput = document.getElementById('travel_date'); if (bookingDateInput) { const form = bookingDateInput.closest('.yatra-booking-form'); const bookingMode = form ? form.getAttribute('data-booking-mode') : 'regular'; if (bookingMode === 'availability') { // Availability-based: Only specific dates const availabilityDates = window.yatraTripData?.availabilityDates || []; if (availabilityDates.length > 0) { flatpickr(bookingDateInput, { dateFormat: 'Y-m-d', minDate: 'today', enable: availabilityDates, disableMobile: false }); } } else { // Flexible booking: Any future date with constraints const minDate = bookingDateInput.getAttribute('data-min-date') || 'today'; const maxDate = bookingDateInput.getAttribute('data-max-date'); const config = { dateFormat: 'Y-m-d', minDate: minDate, disableMobile: false }; if (maxDate) { config.maxDate = maxDate; } flatpickr(bookingDateInput, config); } } // Enquiry modal date picker (always flexible) const enquiryDateInput = document.getElementById('enquiry-travel-date'); if (enquiryDateInput) { flatpickr(enquiryDateInput, { dateFormat: 'Y-m-d', minDate: 'today', disableMobile: false }); } }); // Group Discount Calculation for Booking Widget document.addEventListener('DOMContentLoaded', function () { const bookingForm = document.querySelector('.yatra-booking-form'); const totalAmountElement = document.getElementById('total-amount'); const travelerInputs = document.querySelectorAll('input[name*="travelers["], input[name="num_travelers"]'); const dateInput = document.getElementById('travel_date'); let currentGroupDiscounts = null; let selectedAvailability = null; // Load group discounts for this trip async function loadGroupDiscounts() { try { const response = await fetch(window.yatraTripData?.groupDiscountsUrl || '', { method: 'GET', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ trip_ids: [window.yatraTripData?.tripId] }) }); if (response.ok) { const data = await response.json(); if (data[window.yatraTripData?.tripId] && data[window.yatraTripData?.tripId].has_group_discounts) { currentGroupDiscounts = data[window.yatraTripData?.tripId].discounts; } } } catch (error) { console.warn('Failed to load group discounts:', error); } } // Calculate total travelers function calculateTotalTravelers() { let total = 0; // Handle traveler-based pricing (multiple categories) const travelerCategoryInputs = document.querySelectorAll('input[name*="travelers["]'); travelerCategoryInputs.forEach(input => { total += parseInt(input.value) || 0; }); // Handle simple pricing (single traveler count) const simpleTravelerInput = document.querySelector('input[name="num_travelers"]'); if (simpleTravelerInput) { total = parseInt(simpleTravelerInput.value) || 0; } return total; } // Calculate group discount for current traveler count function calculateGroupDiscount(totalTravelers, basePrice) { if (!currentGroupDiscounts || totalTravelers < 2) { return 0; } // Find applicable discount for this group size let applicableDiscount = null; for (const discount of currentGroupDiscounts) { const minSize = discount.min_group_size; const maxSize = discount.max_group_size; if (totalTravelers >= minSize && (!maxSize || totalTravelers <= maxSize)) { applicableDiscount = discount; break; } } if (!applicableDiscount) { return 0; } let discountAmount = 0; if (applicableDiscount.discount_mode === 'category_based' && applicableDiscount.category_discounts) { // Calculate category-based discount const travelerCounts = getTravelerCountsByCategory(); for (const [category, discountConfig] of Object.entries(applicableDiscount.category_discounts)) { const count = travelerCounts[category] || 0; if (count > 0) { // Calculate category-specific price const categoryMultiplier = getCategoryMultiplier(category); const categoryPrice = basePrice * categoryMultiplier; const categoryTotal = categoryPrice * count; if (discountConfig.type === 'percentage') { discountAmount += categoryTotal * (discountConfig.amount / 100); } else { // Fixed amount per person discountAmount += Math.min(discountConfig.amount * count, categoryTotal); } } } } else { // Total-based discount if (applicableDiscount.discount_type === 'percentage') { discountAmount = basePrice * totalTravelers * (applicableDiscount.discount_amount / 100); } else { discountAmount = Math.min(applicableDiscount.discount_amount, basePrice * totalTravelers); } } return discountAmount; } // Update pricing when date changes if (dateInput) { dateInput.addEventListener('change', function() { const selectedDate = this.value; const bookingCard = document.querySelector('.yatra-booking-card'); if (bookingCard) { const availabilityData = bookingCard.getAttribute('data-availability'); if (availabilityData) { try { const availabilities = JSON.parse(availabilityData); selectedAvailability = availabilities.find(a => a.departure_date === selectedDate); // Update traveler input prices if traveler-based pricing if (selectedAvailability && selectedAvailability.pricing_type === 'traveler_based' && selectedAvailability.price_types) { selectedAvailability.price_types.forEach((pt, index) => { const input = document.querySelector(`input[name="travelers[${pt.category_id}]"]`); if (input) { const price = pt.discounted_price || pt.original_price || 0; input.setAttribute('data-price', price); } }); } // Recalculate total updatePricing(); } catch (e) { console.error('Error parsing availability data:', e); } } } }); // Set today's date by default if available, otherwise use trip fallback pricing const today = new Date().toISOString().split('T')[0]; const bookingCard = document.querySelector('.yatra-booking-card'); if (bookingCard && !dateInput.value) { const availabilityData = bookingCard.getAttribute('data-availability'); if (availabilityData) { try { const availabilities = JSON.parse(availabilityData); const todayAvailability = availabilities.find(a => a.departure_date === today); if (todayAvailability) { dateInput.value = today; dateInput.dispatchEvent(new Event('change')); } else { // No availability for today - use trip's default pricing (already set in HTML) // Just trigger initial calculation with trip prices updatePricing(); } } catch (e) { console.error('Error setting default date:', e); } } } } // Update pricing display function updatePricing() { const totalTravelers = calculateTotalTravelers(); let basePrice = window.yatraTripData?.basePrice || 0; // Calculate subtotal let subtotal = 0; const categoryInputs = document.querySelectorAll('input[name*="travelers["]'); if (categoryInputs.length > 0) { // Traveler-based pricing: read actual prices from data attributes (updated by date change) categoryInputs.forEach(input => { const count = parseInt(input.value) || 0; const price = parseFloat(input.dataset.price) || 0; const pricingMode = input.dataset.pricingMode || 'per_person'; if (pricingMode === 'per_group') { // Per group: charge flat price once if any travelers if (count > 0) { subtotal += price; } } else { // Per person: charge per traveler subtotal += price * count; } }); } else { // Simple pricing - use selected availability price if available if (selectedAvailability && selectedAvailability.price) { basePrice = parseFloat(selectedAvailability.price); } subtotal = basePrice * totalTravelers; } // Calculate group discount const groupDiscount = calculateGroupDiscount(totalTravelers, basePrice); const finalTotal = subtotal - groupDiscount; // Update display (total element has been removed from sidebar) // The total price display is no longer shown in the sidebar // This code is kept for reference but will not execute as totalAmountElement is null if (totalAmountElement) { totalAmountElement.textContent = (window.yatraTripData?.currencySymbol || '$') + finalTotal.toFixed(2); } // Show/hide group discount indicator updateGroupDiscountIndicator(totalTravelers, groupDiscount); } // Update group discount indicator (total element has been removed) function updateGroupDiscountIndicator(totalTravelers, discountAmount) { let indicator = document.querySelector('.yatra-group-discount-indicator'); if (discountAmount > 0) { if (!indicator) { indicator = document.createElement('div'); indicator.className = 'yatra-group-discount-indicator'; // Find a suitable parent to append the indicator const bookingForm = document.querySelector('.yatra-booking-form'); if (bookingForm) { bookingForm.appendChild(indicator); } } indicator.innerHTML = `