| @@ -142,21 +142,24 @@ | ||
| 142 | 142 | > |
| 143 | 143 | <?php |
| 144 | 144 | // Pass pricing type info to form fields partial |
| 145 | 145 | // Prefer booking pricing data, fallback to trip definition |
| 146 | + $trip_pricing_mode = \Yatra\Services\TripPricingService::resolvePricingType($trip); | |
| 146 | 147 | $pricing_type = !empty($booking->pricing_type) ? $booking->pricing_type : ($trip->pricing_type ?? 'regular'); |
| 147 | 148 | $price_types = !empty($booking->price_types) ? $booking->price_types : ($trip->price_types ?? []); |
| 149 | + if ($trip_pricing_mode === 'regular' && empty($booking->price_types)) { | |
| 150 | + $pricing_type = 'regular'; | |
| 151 | + $price_types = []; | |
| 152 | + } | |
| 148 | 153 | if (empty($pricing_type) && !empty($price_types)) { |
| 149 | 154 | $pricing_type = 'traveler_based'; |
| 150 | 155 | } |
| 151 | - if ($pricing_type === 'regular' && !empty($price_types)) { | |
| 152 | - // Infer traveler-based if price types are present but flag not set | |
| 153 | - $pricing_type = 'traveler_based'; | |
| 154 | - } | |
| 155 | - // Ensure price_types is always the trip's price_types if booking lacks it | |
| 156 | - if (empty($price_types) && !empty($trip->price_types)) { | |
| 156 | + // Do not override explicit regular trip pricing with orphan trip_price_types rows | |
| 157 | + if (empty($price_types) && !empty($trip->price_types) && $trip_pricing_mode === 'traveler_based') { | |
| 157 | 158 | $price_types = $trip->price_types; |
| 158 | - $pricing_type = 'traveler_based'; | |
| 159 | + if (empty($pricing_type) || $pricing_type === 'regular') { | |
| 160 | + $pricing_type = 'traveler_based'; | |
| 161 | + } | |
| 159 | 162 | } |
| 160 | 163 | $traveler_counts = $booking->traveler_counts ?? []; |
| 161 | 164 | |
| 162 | 165 | // Include shared booking form fields |
| @@ -172,9 +175,9 @@ | ||
| 172 | 175 | </svg> |
| 173 | 176 | <span id="pay-button-text"><?php esc_html_e('Complete Booking', 'yatra'); ?></span> |
| 174 | 177 | <span id="pay-amount"><?php echo esc_html(yatra_format_price((float) ($summary_due_amount ?? 0), null, false)); ?></span> |
| 175 | 178 | </button> |
| 176 | - <a href="<?php echo esc_url(home_url('/trip/' . $trip->slug)); ?>" class="yatra-booking-cancel-btn"> | |
| 179 | + <a href="<?php echo esc_url(yatra_get_trip_permalink($trip)); ?>" class="yatra-booking-cancel-btn"> | |
| 177 | 180 | <?php esc_html_e('Cancel', 'yatra'); ?> |
| 178 | 181 | </a> |
| 179 | 182 | </div> |
| 180 | 183 | <div class="yatra-booking-form-errors" id="yatra-booking-form-errors" aria-live="polite"></div> |
| @@ -311,9 +314,9 @@ | ||
| 311 | 314 | <input type="hidden" name="departure_time" form="yatra-booking-form" value="<?php echo esc_attr($departure_time); ?>"> |
| 312 | 315 | <?php endif; ?> |
| 313 | 316 | </div> |
| 314 | 317 | |
| 315 | - <?php if (!empty($trip->price_types) || (!empty($price_types) && $pricing_type === 'traveler_based')): ?> | |
| 318 | + <?php if ($pricing_type === 'traveler_based' && !empty($price_types)): ?> | |
| 316 | 319 | <!-- Traveler-based pricing: use shared traveler selector partial --> |
| 317 | 320 | <div class="yatra-summary-form-group yatra-traveler-categories"> |
| 318 | 321 | <label><?php esc_html_e('Travelers', 'yatra'); ?></label> |
| 319 | 322 | <?php |
| @@ -327,12 +330,15 @@ | ||
| 327 | 330 | $pricing_mode = (!empty($pt->pricing_mode) && $pt->pricing_mode === 'per_group') ? 'per_group' : 'per_person'; |
| 328 | 331 | $age_info = ''; |
| 329 | 332 | if (isset($pt->age_min) || isset($pt->age_max)) { |
| 330 | 333 | if (isset($pt->age_min) && isset($pt->age_max)) { |
| 331 | - $age_info = sprintf(__('(Age %d-%d)', 'yatra'), $pt->age_min, $pt->age_max); | |
| 334 | + /* translators: 1: minimum age, 2: maximum age. */ | |
| 335 | + $age_info = sprintf(__('(Age %1$d-%2$d)', 'yatra'), $pt->age_min, $pt->age_max); | |
| 332 | 336 | } elseif (isset($pt->age_min)) { |
| 337 | + /* translators: %d: minimum age. */ | |
| 333 | 338 | $age_info = sprintf(__('(Age %d+)', 'yatra'), $pt->age_min); |
| 334 | 339 | } else { |
| 340 | + /* translators: %d: maximum age. */ | |
| 335 | 341 | $age_info = sprintf(__('(Up to age %d)', 'yatra'), $pt->age_max); |
| 336 | 342 | } |
| 337 | 343 | } |
| 338 | 344 | $input_id = 'traveler_' . $category_id; |
| @@ -343,17 +349,21 @@ | ||
| 343 | 349 | 'row_attrs' => [ |
| 344 | 350 | 'data-category-id' => $category_id, |
| 345 | 351 | 'data-price' => $category_price, |
| 346 | 352 | 'data-pricing-mode' => $pricing_mode, |
| 353 | + 'data-group-overflow' => $pt->group_overflow ?? 'block', | |
| 354 | + 'data-max-pax' => $pt->max_pax ?? '', | |
| 347 | 355 | ], |
| 348 | 356 | 'minus_disabled' => ($index !== 0 && $count <= 0), |
| 349 | 357 | 'plus_disabled' => false, |
| 350 | 358 | 'minus_attrs' => [ |
| 351 | 359 | 'data-target' => $input_id, |
| 360 | + /* translators: %s: traveler category label (e.g. "Adult", "Child"). */ | |
| 352 | 361 | 'aria-label' => sprintf(__('Decrease %s', 'yatra'), $category_label), |
| 353 | 362 | ], |
| 354 | 363 | 'plus_attrs' => [ |
| 355 | 364 | 'data-target' => $input_id, |
| 365 | + /* translators: %s: traveler category label (e.g. "Adult", "Child"). */ | |
| 356 | 366 | 'aria-label' => sprintf(__('Increase %s', 'yatra'), $category_label), |
| 357 | 367 | ], |
| 358 | 368 | 'input_attrs' => [ |
| 359 | 369 | 'id' => $input_id, |
| @@ -363,8 +373,10 @@ | ||
| 363 | 373 | 'max' => $trip->max_travelers ?: 20, |
| 364 | 374 | 'data-category-label' => $category_label, |
| 365 | 375 | 'data-price' => $category_price, |
| 366 | 376 | 'data-pricing-mode' => $pricing_mode, |
| 377 | + 'data-group-overflow' => $pt->group_overflow ?? 'block', | |
| 378 | + 'data-max-pax' => $pt->max_pax ?? '', | |
| 367 | 379 | ], |
| 368 | 380 | ]; |
| 369 | 381 | } |
| 370 | 382 | $traveler_display_text = !empty($traveler_rows) ? ($traveler_rows[0]['label'] . ' x ' . max(1, (int) $traveler_rows[0]['input_attrs']['value'])) : __('Traveler x 1', 'yatra'); |
| @@ -415,10 +427,13 @@ | ||
| 415 | 427 | <div class="yatra-summary-meta"> |
| 416 | 428 | <?php |
| 417 | 429 | $duration_days = (int) ($trip->duration_days ?? 0); |
| 418 | 430 | $duration_nights = isset($trip->duration_nights) ? (int) $trip->duration_nights : null; |
| 431 | + $duration_hours = (int) ($trip->duration_hours ?? 0); | |
| 419 | 432 | ?> |
| 420 | - <?php if ($duration_days > 0) : ?> | |
| 433 | + <?php if ($duration_hours > 0) : ?> | |
| 434 | + <span><?php echo esc_html(yatra_format_duration(0, null, $duration_hours)); ?></span> | |
| 435 | + <?php elseif ($duration_days > 0) : ?> | |
| 421 | 436 | <?php if ($duration_days <= 1) : ?> |
| 422 | 437 | <span><?php esc_html_e('Day Trip', 'yatra'); ?></span> |
| 423 | 438 | <?php else : ?> |
| 424 | 439 | <span><?php echo esc_html(yatra_format_duration($duration_days, $duration_nights)); ?></span> |
| @@ -423,11 +438,37 @@ | ||
| 423 | 438 | <?php else : ?> |
| 424 | 439 | <span><?php echo esc_html(yatra_format_duration($duration_days, $duration_nights)); ?></span> |
| 425 | 440 | <?php endif; ?> |
| 426 | 441 | <?php endif; ?> |
| 427 | - <?php if (!empty($trip->difficulty_level)) : ?> | |
| 442 | + <?php | |
| 443 | + // Resolve difficulty_level to a human label. | |
| 444 | + // The trip row stores difficulty_level as the | |
| 445 | + // classification FK id (e.g. 32), and that's | |
| 446 | + // what we'd otherwise render — "32" on the | |
| 447 | + // sidebar. Prefer the joined `difficulty_name` | |
| 448 | + // when present; fall back to a one-row lookup | |
| 449 | + // in wp_yatra_classifications when only the | |
| 450 | + // id arrived; finally fall back to the raw | |
| 451 | + // string (legacy trips that stored | |
| 452 | + // 'easy'/'moderate' before the FK migration). | |
| 453 | + $difficulty_label = ''; | |
| 454 | + $difficulty_raw = $trip->difficulty_level ?? null; | |
| 455 | + if (!empty($trip->difficulty_name)) { | |
| 456 | + $difficulty_label = (string) $trip->difficulty_name; | |
| 457 | + } elseif (is_numeric($difficulty_raw) && (int) $difficulty_raw > 0) { | |
| 458 | + global $wpdb; | |
| 459 | + $classifications_table = \Yatra\Database\Tables\ClassificationsTable::getTableName(); | |
| 460 | + $difficulty_label = (string) $wpdb->get_var($wpdb->prepare( | |
| 461 | + "SELECT name FROM {$classifications_table} WHERE id = %d LIMIT 1", | |
| 462 | + (int) $difficulty_raw | |
| 463 | + )); | |
| 464 | + } elseif (is_string($difficulty_raw) && $difficulty_raw !== '') { | |
| 465 | + $difficulty_label = ucfirst($difficulty_raw); | |
| 466 | + } | |
| 467 | + ?> | |
| 468 | + <?php if ($difficulty_label !== '') : ?> | |
| 428 | 469 | <span>•</span> |
| 429 | - <span><?php echo esc_html(ucfirst($trip->difficulty_level)); ?></span> | |
| 470 | + <span><?php echo esc_html($difficulty_label); ?></span> | |
| 430 | 471 | <?php endif; ?> |
| 431 | 472 | </div> |
| 432 | 473 | </div> |
| 433 | 474 | </div> |
| @@ -522,11 +563,33 @@ | ||
| 522 | 563 | </div> |
| 523 | 564 | </div> |
| 524 | 565 | <?php endif; ?> |
| 525 | 566 | |
| 526 | - <!-- Coupon Code Section --> | |
| 567 | + <!-- Coupon Code Section | |
| 568 | + Server-side checks whether a coupon is already | |
| 569 | + applied to this booking session so the correct UI | |
| 570 | + (toggle-to-enter vs applied-with-remove) is rendered | |
| 571 | + on the FIRST byte. Without this, the page always | |
| 572 | + shipped with the applied-coupon block `display:none` | |
| 573 | + and relied on the JS `loadCouponFromSession()` GET | |
| 574 | + to flip the visibility — which fails on page refresh | |
| 575 | + in REST contexts where PHPSESSID doesn't propagate, | |
| 576 | + leaving the user without a remove button. --> | |
| 577 | + <?php | |
| 578 | + $applied_coupon = null; | |
| 579 | + if (!empty($booking) && is_object($booking)) { | |
| 580 | + $session_for_coupon = yatra_get_booking_session(); | |
| 581 | + if (is_array($session_for_coupon) && !empty($session_for_coupon['coupon']['code'])) { | |
| 582 | + $applied_coupon = $session_for_coupon['coupon']; | |
| 583 | + } | |
| 584 | + } | |
| 585 | + $coupon_is_applied = !empty($applied_coupon); | |
| 586 | + $coupon_discount_amount_for_display = $coupon_is_applied | |
| 587 | + ? (float) ($applied_coupon['discount_amount'] ?? $applied_coupon['calculated_amount'] ?? 0) | |
| 588 | + : 0.0; | |
| 589 | + ?> | |
| 527 | 590 | <div class="yatra-coupon-section"> |
| 528 | - <div class="yatra-coupon-toggle"> | |
| 591 | + <div class="yatra-coupon-toggle" <?php echo $coupon_is_applied ? 'style="display: none;"' : ''; ?>> | |
| 529 | 592 | <button type="button" id="yatra-coupon-toggle-btn" class="yatra-coupon-toggle-btn"> |
| 530 | 593 | <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 531 | 594 | <path d="M20 12v6a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-6"></path> |
| 532 | 595 | <path d="M12 2v10"></path> |
| @@ -548,17 +611,19 @@ | ||
| 548 | 611 | </button> |
| 549 | 612 | </div> |
| 550 | 613 | <div id="yatra-coupon-message" class="yatra-coupon-message" style="display: none;"></div> |
| 551 | 614 | </div> |
| 552 | - <!-- Applied Coupon Display --> | |
| 553 | - <div class="yatra-applied-coupon" id="yatra-applied-coupon" style="display: none;"> | |
| 615 | + <!-- Applied Coupon Display — rendered visible on first paint when the | |
| 616 | + session already has a coupon, so the remove button is reachable | |
| 617 | + even before any JS runs. --> | |
| 618 | + <div class="yatra-applied-coupon" id="yatra-applied-coupon" <?php echo $coupon_is_applied ? '' : 'style="display: none;"'; ?>> | |
| 554 | 619 | <div class="yatra-applied-coupon-info"> |
| 555 | 620 | <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 556 | 621 | <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path> |
| 557 | 622 | <polyline points="22 4 12 14.01 9 11.01"></polyline> |
| 558 | 623 | </svg> |
| 559 | - <span class="yatra-coupon-code-display"></span> | |
| 560 | - <span class="yatra-coupon-discount"></span> | |
| 624 | + <span class="yatra-coupon-code-display"><?php echo $coupon_is_applied ? esc_html($applied_coupon['code']) : ''; ?></span> | |
| 625 | + <span class="yatra-coupon-discount"><?php echo $coupon_is_applied && $coupon_discount_amount_for_display > 0 ? '-' . esc_html(yatra_format_price($coupon_discount_amount_for_display)) : ''; ?></span> | |
| 561 | 626 | </div> |
| 562 | 627 | <button type="button" id="yatra-remove-coupon" class="yatra-remove-coupon-btn" title="<?php esc_attr_e('Remove coupon', 'yatra'); ?>"> |
| 563 | 628 | <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 564 | 629 | <line x1="18" y1="6" x2="6" y2="18"></line> |
| @@ -567,9 +632,16 @@ | ||
| 567 | 632 | </button> |
| 568 | 633 | </div> |
| 569 | 634 | </div> |
| 570 | 635 | |
| 571 | - <!-- Additional Services Section (Premium Feature) --> | |
| 636 | + <!-- Additional Services Section (Premium Feature) | |
| 637 | + Renders as its own card BEFORE the Pricing Summary | |
| 638 | + (after the coupon code section). Checkbox toggles fire | |
| 639 | + the change handler in booking.js → updateServicesInSession() | |
| 640 | + → /booking/session POST → schedulePricingSummaryRefresh() | |
| 641 | + → /booking/summary GET → re-render the pricing-summary | |
| 642 | + partial below, which then shows the selected services | |
| 643 | + as compact line items in the price breakdown. --> | |
| 572 | 644 | <?php |
| 573 | 645 | /** |
| 574 | 646 | * Filter: Get additional services for this trip |
| 575 | 647 | * Allows premium modules to add extra services to the booking |
| @@ -574,15 +646,15 @@ | ||
| 574 | 646 | * Filter: Get additional services for this trip |
| 575 | 647 | * Allows premium modules to add extra services to the booking |
| 576 | 648 | */ |
| 577 | 649 | $additional_services = apply_filters('yatra_booking_additional_services', [], $trip_id, $total_travelers, $traveler_counts ?? [], $travel_date); |
| 578 | - | |
| 650 | + | |
| 579 | 651 | // Get selected services from session (set from popup) |
| 580 | 652 | $session = yatra_get_booking_session(); |
| 581 | - $selected_service_ids = isset($session['additional_services']) && is_array($session['additional_services']) | |
| 582 | - ? array_map('intval', $session['additional_services']) | |
| 653 | + $selected_service_ids = isset($session['additional_services']) && is_array($session['additional_services']) | |
| 654 | + ? array_map('intval', $session['additional_services']) | |
| 583 | 655 | : []; |
| 584 | - | |
| 656 | + | |
| 585 | 657 | if (!empty($additional_services)) : |
| 586 | 658 | ?> |
| 587 | 659 | <div class="yatra-additional-services-section"> |
| 588 | 660 | <div class="yatra-services-header"> |
| @@ -589,53 +661,71 @@ | ||
| 589 | 661 | <h4><?php esc_html_e('Additional Services', 'yatra'); ?></h4> |
| 590 | 662 | <p class="yatra-services-subtitle"><?php esc_html_e('Enhance your trip with these optional add-ons', 'yatra'); ?></p> |
| 591 | 663 | </div> |
| 592 | 664 | <div class="yatra-services-list" id="yatra-additional-services"> |
| 593 | - <?php foreach ($additional_services as $service) : | |
| 665 | + <?php foreach ($additional_services as $service) : | |
| 594 | 666 | $service_id = (int) $service['id']; |
| 595 | 667 | $service_name = $service['name']; |
| 596 | - $service_description = $service['description'] ?? ''; | |
| 668 | + $service_description = (string) ($service['description'] ?? ''); | |
| 597 | 669 | $service_price = (float) $service['price']; |
| 598 | 670 | $service_price_per = $service['price_per'] ?? 'person'; |
| 599 | - $service_image = $service['image_url'] ?? ''; | |
| 600 | - // Check is_required - handle various formats (bool, string "1", int 1) | |
| 671 | + $service_price_type = $service['price_type'] ?? 'fixed'; | |
| 601 | 672 | $is_required = isset($service['is_required']) && ($service['is_required'] === true || $service['is_required'] === 1 || $service['is_required'] === '1'); |
| 602 | 673 | $is_included = isset($service['is_included']) && ($service['is_included'] === true || $service['is_included'] === 1 || $service['is_included'] === '1'); |
| 603 | 674 | $is_selected = in_array($service_id, $selected_service_ids, false); |
| 604 | - | |
| 605 | - $price_label = yatra_format_price($service_price); | |
| 606 | - if ($service_price_per === 'person') { | |
| 607 | - $price_label .= ' ' . __('per person', 'yatra'); | |
| 608 | - } elseif ($service_price_per === 'day') { | |
| 609 | - $price_label .= ' ' . __('per day', 'yatra'); | |
| 675 | + | |
| 676 | + // Percentage services show "X% of trip price" (the actual | |
| 677 | + // dollar amount is rendered in the price-breakdown summary). | |
| 678 | + // Price Per does NOT apply to percentage (it's a % of the | |
| 679 | + // whole trip), so no per-person/day/booking suffix is added. | |
| 680 | + // Fixed services show the formatted amount plus the suffix. | |
| 681 | + if ($service_price_type === 'percentage') { | |
| 682 | + $pct_display = rtrim(rtrim(number_format($service_price, 2), '0'), '.'); | |
| 683 | + /* translators: %s: percentage value, e.g. "17" */ | |
| 684 | + $price_label = sprintf(__('%s%% of trip price', 'yatra'), $pct_display); | |
| 610 | 685 | } else { |
| 611 | - $price_label .= ' ' . __('per booking', 'yatra'); | |
| 686 | + $price_label = yatra_format_price($service_price); | |
| 687 | + if ($service_price_per === 'person') { | |
| 688 | + $price_label .= ' ' . __('per person', 'yatra'); | |
| 689 | + } elseif ($service_price_per === 'day') { | |
| 690 | + $price_label .= ' ' . __('per day', 'yatra'); | |
| 691 | + } else { | |
| 692 | + $price_label .= ' ' . __('per booking', 'yatra'); | |
| 693 | + } | |
| 612 | 694 | } |
| 613 | 695 | if ($is_included) { |
| 614 | 696 | $price_label = __('Included', 'yatra'); |
| 615 | 697 | } |
| 616 | - | |
| 617 | - // Determine checked and disabled states | |
| 698 | + | |
| 618 | 699 | $is_checked = $is_required || $is_included || $is_selected; |
| 619 | 700 | $is_disabled = $is_required || $is_included; |
| 620 | 701 | ?> |
| 702 | + <?php | |
| 703 | + // Description shown as a hover tooltip on the | |
| 704 | + // whole row (no separate ⓘ icon). `title` lives | |
| 705 | + // on the outer .yatra-service-item so hovering | |
| 706 | + // anywhere in the block reveals the tooltip — | |
| 707 | + // the small icon variant was easy to miss. | |
| 708 | + $plain_description = $service_description !== '' ? wp_strip_all_tags($service_description) : ''; | |
| 709 | + ?> | |
| 621 | 710 | <div class="yatra-service-item <?php echo $is_required ? 'yatra-service-required' : ''; ?> <?php echo $is_checked ? 'yatra-service-selected' : ''; ?>" |
| 622 | - data-service-id="<?php echo esc_attr($service_id); ?>" | |
| 623 | - data-service-price="<?php echo esc_attr($service_price); ?>" | |
| 711 | + data-service-id="<?php echo esc_attr((string) $service_id); ?>" | |
| 712 | + data-service-price="<?php echo esc_attr((string) $service_price); ?>" | |
| 624 | 713 | data-service-price-per="<?php echo esc_attr($service_price_per); ?>" |
| 625 | - data-is-required="<?php echo $is_required ? '1' : '0'; ?>"> | |
| 714 | + data-is-required="<?php echo $is_required ? '1' : '0'; ?>" | |
| 715 | + <?php if ($plain_description !== '') : ?> | |
| 716 | + data-tooltip="<?php echo esc_attr($plain_description); ?>" | |
| 717 | + aria-label="<?php echo esc_attr($plain_description); ?>" | |
| 718 | + <?php endif; ?>> | |
| 626 | 719 | <label class="yatra-service-label"> |
| 627 | - <input type="checkbox" | |
| 628 | - name="additional_services[]" | |
| 629 | - value="<?php echo esc_attr($service_id); ?>" | |
| 720 | + <input type="checkbox" | |
| 721 | + name="additional_services[]" | |
| 722 | + value="<?php echo esc_attr((string) $service_id); ?>" | |
| 630 | 723 | <?php echo $is_checked ? 'checked' : ''; ?> |
| 631 | 724 | <?php echo $is_disabled ? 'disabled' : ''; ?> |
| 632 | 725 | form="yatra-booking-form"> |
| 633 | 726 | <div class="yatra-service-info"> |
| 634 | 727 | <span class="yatra-service-name"><?php echo esc_html($service_name); ?></span> |
| 635 | - <?php if ($service_description) : ?> | |
| 636 | - <span class="yatra-service-description"><?php echo esc_html($service_description); ?></span> | |
| 637 | - <?php endif; ?> | |
| 638 | 728 | </div> |
| 639 | 729 | <span class="yatra-service-price"><?php echo esc_html($price_label); ?></span> |
| 640 | 730 | </label> |
| 641 | 731 | </div> |
| @@ -643,20 +733,31 @@ | ||
| 643 | 733 | </div> |
| 644 | 734 | </div> |
| 645 | 735 | <?php endif; ?> |
| 646 | 736 | |
| 647 | - | |
| 648 | - <!-- Price Breakdown --> | |
| 737 | + <!-- Price Breakdown — services + dynamic-pricing summary + totals all live | |
| 738 | + in one card so the sidebar reads as a single "Pricing Summary" panel. --> | |
| 649 | 739 | <div class="yatra-summary-pricing" id="yatra-summary-pricing" data-pricing-type="<?php echo esc_attr($pricing_type); ?>" data-is-remaining="<?php echo esc_attr($is_remaining_payment ? 'yes' : 'no'); ?>"> |
| 650 | - <!-- This section is loaded/updated via AJAX --> | |
| 651 | 740 | <?php |
| 652 | 741 | // Get checkout model from booking object |
| 653 | 742 | $checkout = $booking->checkout ?? null; |
| 654 | - | |
| 743 | + | |
| 744 | + // Surface the dynamic-pricing breakdown as a template | |
| 745 | + // variable so the partial can render the DP line items. | |
| 746 | + // CalculationService stuffs the breakdown into | |
| 747 | + // `pricing_calculation.dynamic_pricing` via the | |
| 748 | + // `yatra_price_breakdown` filter; without exposing it | |
| 749 | + // here the partial's DP block stays dark on first load. | |
| 750 | + $dynamic_pricing = $pricing_calculation['dynamic_pricing'] ?? null; | |
| 751 | + $currency = $pricing_calculation['currency'] ?? null; | |
| 752 | + | |
| 753 | + // The pricing-summary partial calls $render_additional_services() | |
| 754 | + // at the right spot — right after the traveler/per-person rows | |
| 755 | + // and before the Trip Subtotal — so the services row shares the | |
| 756 | + // same compact "label … price" layout as the traveler row. | |
| 757 | + | |
| 655 | 758 | // Include pricing summary template (uses $checkout model) |
| 656 | 759 | include YATRA_PLUGIN_PATH . 'templates/partials/pricing-summary.php'; |
| 657 | - | |
| 658 | - | |
| 659 | 760 | ?> |
| 660 | 761 | </div> |
| 661 | 762 | |
| 662 | 763 | <!-- Cancellation Policy --> |