PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.3
Yatra – Travel Booking & Tour Operator Software v3.0.3
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
yatra / templates / partials / single-trip / content-sidebar.php

content-sidebar.php in Yatra – Travel Booking & Tour Operator Software 3.0.3, at templates/partials/single-trip/content-sidebar.php

381 lines 21.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) {
3 exit;
4 }
5 ?>
6 <aside class="yatra-trip-sidebar" id="booking">
7 <?php
8 // Group discounts (Advanced Discount / Pro): same payload as the public REST discoverability endpoint
9 $sidebar_has_group_discounts = false;
10 $sidebar_group_discount_cards = [];
11 if (function_exists('yatra_single_trip_get_group_discounts')) {
12 $gd = yatra_single_trip_get_group_discounts((int) $trip->getId());
13 $sidebar_has_group_discounts = !empty($gd['has_group_discounts']);
14 $sidebar_group_discount_cards = isset($gd['group_discounts_data']) && is_array($gd['group_discounts_data'])
15 ? $gd['group_discounts_data']
16 : [];
17 }
18
19 // Pro: check whether this trip has booking disabled (enquiry-only mode)
20 $booking_disabled = method_exists($trip, 'isBookingDisabled') && $trip->isBookingDisabled();
21
22 // Pricing — resolved via centralized TripPricingService (single source of truth)
23 // SingleTripController pre-computes effective_price_min, min_category_original_price, max_discount_percentage
24 $displayPricing = \Yatra\Services\TripPricingService::resolveDisplayPricing($trip);
25
26 $pricing = [
27 'has_price' => $displayPricing['effective_price_min'] > 0,
28 'current_price' => $displayPricing['effective_price_min'] > 0 ? yatra_format_price($displayPricing['effective_price_min']) : '',
29 'original_price' => $displayPricing['has_discount'] ? yatra_format_price($displayPricing['min_category_original_price']) : '',
30 'price_prefix' => $displayPricing['price_prefix'],
31 'has_discount' => $displayPricing['has_discount'],
32 'raw_current_price' => $displayPricing['effective_price_min'],
33 'raw_original_price' => $displayPricing['min_category_original_price'],
34 'is_traveler_based' => $displayPricing['has_traveler_pricing'],
35 ];
36
37 $discount = [
38 'has_discount' => $displayPricing['has_discount'] && $displayPricing['max_discount_percentage'] > 0,
39 'discount_text' => $displayPricing['max_discount_percentage'] > 0
40 ? sprintf(__('Save up to %d%%', 'yatra'), $displayPricing['max_discount_percentage']) : '',
41 'discount_percentage' => $displayPricing['max_discount_percentage'],
42 ];
43
44 $dp_display_sidebar = apply_filters('yatra_get_dynamic_pricing_display_settings', [
45 'show_original_price' => true,
46 'show_savings_badge' => true,
47 'show_urgency_messages' => false,
48 ]);
49 $dp_show_savings_sidebar = filter_var($dp_display_sidebar['show_savings_badge'] ?? true, FILTER_VALIDATE_BOOLEAN);
50 $show_strike_original_sidebar = filter_var($dp_display_sidebar['show_original_price'] ?? true, FILTER_VALIDATE_BOOLEAN);
51 $yatra_sidebar_urgency = function_exists('yatra_trip_card_dynamic_pricing_urgency_lines')
52 ? yatra_trip_card_dynamic_pricing_urgency_lines((int) $trip->getId(), [
53 'base_sale_price' => (float) ($displayPricing['effective_price_min'] ?? 0),
54 'base_original_price' => (float) ($displayPricing['min_category_original_price'] ?? 0),
55 'sale_price' => (float) ($displayPricing['effective_price_min'] ?? 0),
56 'original_price' => (float) ($displayPricing['min_category_original_price'] ?? 0),
57 'departure_date' => null,
58 'spots_remaining' => null,
59 'availability_id' => null,
60 'surface' => 'single_sidebar',
61 ])
62 : [];
63 ?>
64 <?php if ($booking_disabled): ?>
65 <div class="yatra-booking-card yatra-enquiry-only-card">
66 <!-- Price Display -->
67 <div class="yatra-booking-price">
68 <?php if ($discount['has_discount'] && $dp_show_savings_sidebar): ?>
69 <div class="yatra-booking-discount-badge">
70 <?php echo esc_html($discount['discount_text']); ?>
71 </div>
72 <?php endif; ?>
73 <div class="yatra-booking-price-main">
74 <?php if ($pricing['has_price']): ?>
75 <span class="yatra-booking-price-label-top"><?php echo esc_html__('From', 'yatra'); ?></span>
76 <?php if ($pricing['has_discount'] && !empty($pricing['original_price']) && $show_strike_original_sidebar): ?>
77 <span class="yatra-booking-price-original"><?php echo esc_html($pricing['original_price']); ?></span>
78 <?php endif; ?>
79 <span class="yatra-booking-price-amount" id="display-price"><?php echo esc_html($pricing['current_price']); ?></span>
80 <span class="yatra-booking-price-label"><?php echo esc_html__('per person', 'yatra'); ?></span>
81 <?php if (!empty($yatra_sidebar_urgency)) : ?>
82 <?php foreach ($yatra_sidebar_urgency as $yatra_sb_urg) : ?>
83 <div class="yatra-booking-dp-urgency" style="background-color:#fef3c7;color:#92400e;padding:6px 8px;border-radius:6px;margin-top:8px;font-size:12px;line-height:1.35;">
84 <?php echo esc_html((string) $yatra_sb_urg); ?>
85 </div>
86 <?php endforeach; ?>
87 <?php endif; ?>
88 <?php else: ?>
89 <span class="yatra-booking-price-amount yatra-contact-pricing" id="display-price"><?php echo esc_html__('Contact for pricing', 'yatra'); ?></span>
90 <?php endif; ?>
91 </div>
92 </div>
93
94 <!-- Enquiry-only notice -->
95 <div class="yatra-enquiry-notice" style="margin:12px 0 4px;padding:10px 12px;background:#f0f7ff;border:1px solid #cce0ff;border-radius:6px;font-size:0.85rem;color:#1a5fa8;display:flex;align-items:flex-start;gap:8px;">
96 <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="flex-shrink:0;margin-top:1px">
97 <circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>
98 </svg>
99 <span><?php esc_html_e('This trip is available for enquiry only. Please contact us to discuss dates and availability.', 'yatra'); ?></span>
100 </div>
101
102 <!-- Enquiry button -->
103 <button type="button" class="yatra-booking-button" style="margin-top:12px;" id="open-enquiry-modal" onclick="window.YatraEnquiry?.open?.(); return false;">
104 <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
105 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/>
106 </svg>
107 <?php echo esc_html__('Send Enquiry', 'yatra'); ?>
108 </button>
109 </div>
110 <?php else: ?>
111 <div class="yatra-booking-card">
112
113 <?php if ($sidebar_has_group_discounts && !empty($sidebar_group_discount_cards)): ?>
114 <?php
115 $group_discount_cards = $sidebar_group_discount_cards;
116 $popover_context = 'booking';
117 $popover_uid = 'sb-' . (int) $trip->getId();
118 yatra_get_template('partials/single-trip/group-discount-booking-popover', compact('group_discount_cards', 'popover_context', 'popover_uid'));
119 ?>
120 <?php endif; ?>
121
122 <!-- Price Display -->
123 <div class="yatra-booking-price">
124 <?php if ($discount['has_discount'] && $dp_show_savings_sidebar): ?>
125 <div class="yatra-booking-discount-badge">
126 <?php echo esc_html($discount['discount_text']); ?>
127 </div>
128 <?php endif; ?>
129 <div class="yatra-booking-price-main">
130 <?php if ($pricing['has_price']): ?>
131 <?php if ($has_availability || $has_traveler_pricing): ?>
132 <span class="yatra-booking-price-label-top"><?php echo esc_html__('From', 'yatra'); ?></span>
133 <?php endif; ?>
134 <?php if ($pricing['has_discount'] && !empty($pricing['original_price']) && $show_strike_original_sidebar): ?>
135 <span class="yatra-booking-price-original"><?php echo esc_html($pricing['original_price']); ?></span>
136 <?php endif; ?>
137 <span class="yatra-booking-price-amount" id="display-price"><?php echo esc_html($pricing['current_price']); ?></span>
138 <span class="yatra-booking-price-label"><?php echo esc_html__('per person', 'yatra'); ?></span>
139 <?php if (!empty($yatra_sidebar_urgency)) : ?>
140 <?php foreach ($yatra_sidebar_urgency as $yatra_sb_urg) : ?>
141 <div class="yatra-booking-dp-urgency" style="background-color:#fef3c7;color:#92400e;padding:6px 8px;border-radius:6px;margin-top:8px;font-size:12px;line-height:1.35;">
142 <?php echo esc_html((string) $yatra_sb_urg); ?>
143 </div>
144 <?php endforeach; ?>
145 <?php endif; ?>
146 <?php else: ?>
147 <span class="yatra-booking-price-amount yatra-contact-pricing" id="display-price"><?php echo esc_html__('Contact for pricing', 'yatra'); ?></span>
148 <span class="yatra-booking-price-label"><?php echo esc_html__('per person', 'yatra'); ?></span>
149 <?php endif; ?>
150 </div>
151 </div>
152
153 <?php if ($trip->getBookingMode() === 'date_specific' && $has_availability): ?>
154 <!-- ========================================== -->
155 <!-- DATE-SPECIFIC BOOKING (Has Availability Dates/Rules) -->
156 <!-- ========================================== -->
157 <div class="yatra-availability-info">
158 <span class="yatra-availability-count">
159 <?php echo esc_html(sprintf(_n('%d departure available', '%d departures available', count($trip->getAvailabilityDates()), 'yatra'), count($trip->getAvailabilityDates()))); ?>
160 </span>
161 </div>
162
163 <form class="yatra-booking-form" data-booking-mode="date_specific">
164 <!-- Date Selection -->
165 <div class="yatra-booking-field-select">
166 <div class="yatra-booking-field-icon">
167 <?php echo yatra_svg_icon('calendar', 'yatra-icon-sm'); ?>
168 </div>
169 <input type="text"
170 id="travel_date"
171 name="travel_date"
172 class="yatra-booking-select yatra-datepicker"
173 placeholder="<?php esc_attr_e('Select date', 'yatra'); ?>"
174 readonly
175 required>
176 <svg class="yatra-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
177 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
178 </svg>
179 </div>
180
181 <!-- Travelers Selection - Respects Trip's Pricing Type -->
182 <?php
183 // Use helper function to prepare traveler data
184 $traveler_data = \Yatra\Controllers\SingleTripController::prepareTravelerSelectorData($trip, 'availability');
185
186 if ($traveler_data['has_traveler_pricing']):
187 // Setup variables for traveler-selector.php
188 $root_id = '';
189 $root_class = 'yatra-booking-field-select yatra-participants-select yatra-availability-participants';
190 $container_attrs = [];
191
192 $display_id = 'participants-display';
193 $display_class = 'yatra-participants-display yatra-availability-participants-display';
194 $display_attrs = [];
195
196 $dropdown_id = 'quantity-selector';
197 $dropdown_class = 'yatra-booking-quantity-selector yatra-availability-quantity-selector';
198 $dropdown_attrs = [];
199
200 $display_text = $traveler_data['traveler_display_text'];
201 $icon_html = yatra_svg_icon('users', 'yatra-icon-sm');
202 $rows = $traveler_data['traveler_rows'];
203
204 include YATRA_PLUGIN_PATH . 'templates/partials/traveler-selector.php';
205 else:
206 // Regular Pricing: Simple number of travelers input
207 ?>
208 <div class="yatra-booking-field-group">
209 <label for="num_travelers" class="yatra-booking-field-label"><?php echo esc_html__('Number of Travelers', 'yatra'); ?></label>
210 <?php
211 // Setup variables for traveler-input-simple.php
212 $input_id = 'num_travelers';
213 $input_name = 'num_travelers';
214 $value = 1;
215 $min = $trip->getMinTravelers() ?: 1;
216 $max = $trip->getMaxTravelers() ?: 20;
217 $data_price = $base_price;
218 $range_text = sprintf(__('Min: %d, Max: %d', 'yatra'), $min, $max);
219
220 include YATRA_PLUGIN_PATH . 'templates/partials/traveler-input-simple.php';
221 ?>
222 </div>
223 <?php endif; ?>
224 <?php else: ?>
225 <!-- ========================================== -->
226 <!-- FLEXIBLE BOOKING MODE (No Specific Availability Configured) -->
227 <!-- ========================================== -->
228 <div class="yatra-availability-info yatra-flexible-booking-info">
229 <span class="yatra-availability-count">
230 <?php echo esc_html__('Flexible booking available', 'yatra'); ?>
231 </span>
232 <?php if (!empty($trip->getAvailableFrom()) || !empty($trip->getAvailableTo())): ?>
233 <span class="yatra-availability-note">
234 <?php
235 if (!empty($trip->getAvailableFrom()) && !empty($trip->getAvailableTo())) {
236 echo esc_html(sprintf(__('Available: %s - %s', 'yatra'),
237 date_i18n(get_option('date_format'), strtotime($trip->getAvailableFrom())),
238 date_i18n(get_option('date_format'), strtotime($trip->getAvailableTo()))
239 ));
240 } elseif (!empty($trip->getAvailableFrom())) {
241 echo esc_html(sprintf(__('Available from: %s', 'yatra'),
242 date_i18n(get_option('date_format'), strtotime($trip->getAvailableFrom()))
243 ));
244 } else {
245 echo esc_html(sprintf(__('Available until: %s', 'yatra'),
246 date_i18n(get_option('date_format'), strtotime($trip->getAvailableTo()))
247 ));
248 }
249 ?>
250 </span>
251 <?php endif; ?>
252 </div>
253
254 <form class="yatra-booking-form" data-booking-mode="flexible">
255 <!-- Date Selection (Flexible) -->
256 <div class="yatra-booking-field-select">
257 <div class="yatra-booking-field-icon">
258 <?php echo yatra_svg_icon('calendar', 'yatra-icon-sm'); ?>
259 </div>
260 <input type="text"
261 id="travel_date"
262 name="travel_date"
263 class="yatra-booking-select yatra-datepicker"
264 placeholder="<?php esc_attr_e('Select date', 'yatra'); ?>"
265 data-min-date="<?php echo esc_attr($trip->getAvailableFrom() ?: date('Y-m-d')); ?>"
266 data-max-date="<?php echo esc_attr($trip->getAvailableTo() ?: ''); ?>"
267 readonly
268 required>
269 <svg class="yatra-select-arrow" fill="none" stroke="currentColor" viewBox="0 0 24 24">
270 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
271 </svg>
272 </div>
273
274 <!-- Travelers Selection -->
275 <?php
276 // Use helper function to prepare traveler data
277 $traveler_data = \Yatra\Controllers\SingleTripController::prepareTravelerSelectorData($trip, 'sidebar');
278
279 if ($traveler_data['has_traveler_pricing']):
280 // Setup variables for traveler-selector.php
281 $root_id = '';
282 $root_class = 'yatra-booking-field-select yatra-participants-select';
283 $container_attrs = [];
284
285 $display_id = 'participants-display';
286 $display_class = 'yatra-participants-display';
287 $display_attrs = [];
288
289 $dropdown_id = 'quantity-selector';
290 $dropdown_class = 'yatra-booking-quantity-selector';
291 $dropdown_attrs = [];
292
293 $display_text = $traveler_data['traveler_display_text'];
294 $icon_html = yatra_svg_icon('users', 'yatra-icon-sm');
295 $rows = $traveler_data['traveler_rows'];
296
297 include YATRA_PLUGIN_PATH . 'templates/partials/traveler-selector.php';
298 else:
299 // Regular Pricing: Simple number of travelers input
300 ?>
301 <div class="yatra-booking-field-group">
302 <label for="num_travelers" class="yatra-booking-field-label"><?php echo esc_html__('Number of Travelers', 'yatra'); ?></label>
303 <?php
304 // Setup variables for traveler-input-simple.php
305 $input_id = 'num_travelers';
306 $input_name = 'num_travelers';
307 $value = 1;
308 $min = $trip->getMinTravelers() ?: 1;
309 $max = $trip->getMaxTravelers() ?: 20;
310 $data_price = $base_price;
311 $range_text = sprintf(__('Min: %d, Max: %d', 'yatra'), $min, $max);
312
313 include YATRA_PLUGIN_PATH . 'templates/partials/traveler-input-simple.php';
314 ?>
315 </div>
316 <?php endif; ?>
317 <?php endif; ?>
318
319
320 <!-- Action Buttons -->
321 <button type="button" class="yatra-booking-button" id="check-availability-btn" data-trip-id="<?php echo esc_attr($trip->getId()); ?>">
322 <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
323 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
324 </svg>
325 <?php echo esc_html__('Check Availability', 'yatra'); ?>
326 </button>
327
328 <button type="button" class="yatra-booking-enquiry-button" id="open-enquiry-modal" onclick="window.YatraEnquiry?.open?.(); return false;">
329 <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
330 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/>
331 </svg>
332 <?php echo esc_html__('Make Enquiry', 'yatra'); ?>
333 </button>
334
335 <!-- Cancellation Policy Trust Signal -->
336 <?php
337 $cancellation_policy = '';
338 if (method_exists($trip, 'getCancellationPolicy')) {
339 $cancellation_policy = $trip->getCancellationPolicy();
340 } elseif (isset($trip->cancellation_policy)) {
341 $cancellation_policy = $trip->cancellation_policy;
342 }
343
344 $cancellation_text = '';
345 if (!empty($cancellation_policy)) {
346 // Extract cancellation info from policy
347 $policy_lower = strtolower($cancellation_policy);
348 if (strpos($policy_lower, 'free') !== false || strpos($policy_lower, 'no charge') !== false) {
349 if (preg_match('/(\d+)\s*(hour|day|week)s?\s*before/i', $cancellation_policy, $matches)) {
350 $time_value = $matches[1];
351 $time_unit = $matches[2];
352 $cancellation_text = sprintf(
353 __('Free cancellation up to %d %s%s before', 'yatra'),
354 $time_value,
355 $time_unit,
356 $time_value > 1 ? 's' : ''
357 );
358 } else {
359 $cancellation_text = __('Free cancellation', 'yatra');
360 }
361 } else {
362 // Non-free cancellation, show brief info
363 $cancellation_text = __('Cancellation policy applies', 'yatra');
364 }
365 } else {
366 // Default fallback when no policy is set
367 $cancellation_text = __('Cancellation policy may apply', 'yatra');
368 }
369 ?>
370 <div class="yatra-booking-trust">
371 <div class="yatra-booking-trust-icon">
372 <?php echo yatra_svg_icon('check', 'yatra-icon-xs'); ?>
373 </div>
374 <div class="yatra-booking-trust-text">
375 <strong><?php echo esc_html($cancellation_text); ?></strong>
376 </div>
377 </div>
378 </form>
379 </div>
380 <?php endif; // end else (booking not disabled) ?>
381 </aside>