PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.11
Yatra – Travel Booking & Tour Operator Software v3.0.11
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 / booking-confirmation.php

booking-confirmation.php in Yatra – Travel Booking & Tour Operator Software 3.0.11, at templates/booking-confirmation.php

1,778 lines 74.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Booking Confirmation Template
4 *
5 * Displays booking confirmation after successful booking
6 *
7 * @package Yatra
8 *
9 * Global variables available:
10 * - $booking_data or $GLOBALS['yatra_booking']
11 */
12
13 if (!defined('ABSPATH')) {
14 exit;
15 }
16
17 // Get booking data
18 $booking = $GLOBALS['yatra_booking'] ?? null;
19
20 if (!$booking) {
21 wp_safe_redirect(home_url('/'));
22 exit;
23 }
24
25 // Completed booking: ensure checkout session and its transient cannot repopulate the booking form.
26 if (function_exists('yatra_clear_booking_session')) {
27 yatra_clear_booking_session();
28 }
29
30 // Format dates
31 $travel_date_formatted = \Yatra\Helpers\FormatHelper::formatDate((string) ($booking->travel_date ?? ''));
32 $booking_date_formatted = \Yatra\Helpers\FormatHelper::formatDateTime((string) ($booking->created_at ?? ''));
33
34 // "Balance just paid" context detection.
35 // A `?balance=paid` query arg is appended by the remaining-payment flows
36 // (see PaymentGatewayController::create_remaining_balance_intent and
37 // BookingSessionController::process_remaining_payment). We only render the
38 // "balance paid" copy when BOTH the flag is present AND the booking actually
39 // reports a paid status — that way a stale bookmarked URL or a tampered
40 // query string can't show misleading content if a balance is still due.
41 $is_balance_paid_request = isset($_GET['balance']) && sanitize_key((string) $_GET['balance']) === 'paid';
42 $booking_payment_status = (string) ($booking->payment_status ?? '');
43 $booking_amount_due = (float) ($booking->amount_due ?? 0);
44 $booking_is_fully_paid = $booking_payment_status === 'paid' || $booking_amount_due <= 0.01;
45 $show_balance_paid_banner = $is_balance_paid_request && $booking_is_fully_paid;
46
47 // Resolve the most recent gateway used on this booking.
48 // `$booking->payment_gateway` is the *initial* method chosen at booking time
49 // (e.g. Pay Later), which is misleading when the customer later settled the
50 // balance via a different gateway (e.g. Stripe). Show the latest payment's
51 // gateway in the Payment Method line; fall back to the booking's stored
52 // gateway when no payment row exists yet.
53 $display_payment_gateway = (string) ($booking->payment_gateway ?? '');
54 if (!empty($booking->id)) {
55 try {
56 $latest_payment = (new \Yatra\Repositories\PaymentRepository())->findLatestByBookingId((int) $booking->id);
57 if ($latest_payment) {
58 $latest_gateway = (string) ($latest_payment->payment_gateway ?? $latest_payment->gateway ?? '');
59 if ($latest_gateway !== '') {
60 $display_payment_gateway = $latest_gateway;
61 }
62 }
63 } catch (\Throwable $e) {
64 // Repository unavailable for some reason — keep the booking's stored gateway.
65 }
66 }
67
68 // Resolved customer account URL (configurable via Settings → Permalink → Account base).
69 $yatra_account_url = home_url('/' . \Yatra\Services\SettingsService::getAccountBase());
70
71 // Get status color
72 $status_colors = [
73 'pending' => ['bg' => '#fef3c7', 'text' => '#d97706', 'label' => 'Pending'],
74 'confirmed' => ['bg' => '#d1fae5', 'text' => '#059669', 'label' => 'Confirmed'],
75 'processing' => ['bg' => '#dbeafe', 'text' => '#2563eb', 'label' => 'Processing'],
76 'completed' => ['bg' => '#d1fae5', 'text' => '#059669', 'label' => 'Completed'],
77 'cancelled' => ['bg' => '#fee2e2', 'text' => '#dc2626', 'label' => 'Cancelled'],
78 'refunded' => ['bg' => '#fce7f3', 'text' => '#db2777', 'label' => 'Refunded'],
79 'on_hold' => ['bg' => '#e5e7eb', 'text' => '#6b7280', 'label' => 'On Hold'],
80 ];
81
82 $status_style = $status_colors[$booking->status] ?? $status_colors['pending'];
83
84 // Ensure Font Awesome CSS is available for icon-picker rendered icons (fa-solid/fa-regular).
85 // This template can be displayed outside normal "trip page" contexts, so we explicitly
86 // register/enqueue the shared stylesheet dependencies before printing the header.
87 if (class_exists(\Yatra\Providers\FrontendAssetsProvider::class)) {
88 \Yatra\Providers\FrontendAssetsProvider::registerCoreFrontendStylesheets();
89 if (wp_style_is('yatra-fontawesome-6', 'registered')) {
90 wp_enqueue_style('yatra-fontawesome-6');
91 }
92 if (wp_style_is('yatra-common', 'registered')) {
93 wp_enqueue_style('yatra-common');
94 }
95 }
96
97 yatra_get_header();
98
99 // Hook for Pro modules to add custom scripts (Facebook Pixel, etc.)
100 do_action('yatra_booking_confirmation_header', $booking);
101 ?>
102
103 <div class="yatra-wrapper yatra-confirmation-wrapper">
104 <div class="yatra-confirmation-container">
105
106 <!-- Success Header -->
107 <div class="yatra-confirmation-header">
108 <div class="yatra-confirmation-icon">
109 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
110 <circle cx="12" cy="12" r="10"></circle>
111 <polyline points="9,12 12,15 16,10"></polyline>
112 </svg>
113 </div>
114 <h1 class="yatra-confirmation-title">
115 <?php
116 if ($show_balance_paid_banner) {
117 esc_html_e('Balance Paid!', 'yatra');
118 } elseif ($booking->status === 'confirmed') {
119 esc_html_e('Booking Confirmed!', 'yatra');
120 } elseif ($booking->status === 'pending') {
121 esc_html_e('Booking Received!', 'yatra');
122 } elseif ($booking->status === 'cancelled') {
123 esc_html_e('Booking Cancelled', 'yatra');
124 } else {
125 esc_html_e('Booking Submitted!', 'yatra');
126 }
127 ?>
128 </h1>
129 <p class="yatra-confirmation-subtitle">
130 <?php
131 if ($show_balance_paid_banner) {
132 esc_html_e('Your remaining balance has been received. This booking is now fully paid.', 'yatra');
133 } elseif ($booking->status === 'confirmed') {
134 esc_html_e('Thank you for your booking. We look forward to hosting you!', 'yatra');
135 } elseif ($booking->status === 'pending') {
136 esc_html_e('Thank you for your booking. Your booking is pending confirmation.', 'yatra');
137 } elseif ($booking->status === 'cancelled') {
138 esc_html_e('This booking has been cancelled.', 'yatra');
139 } else {
140 esc_html_e('Thank you for your booking submission.', 'yatra');
141 }
142 ?>
143 </p>
144 <div class="yatra-confirmation-reference">
145 <span class="yatra-ref-label"><?php esc_html_e('Booking Reference:', 'yatra'); ?></span>
146 <span class="yatra-ref-code"><?php echo esc_html($booking->reference); ?></span>
147 </div>
148 </div>
149
150 <?php if ($show_balance_paid_banner) : ?>
151 <div class="yatra-balance-paid-banner" role="status" aria-live="polite" style="margin: 16px 0; padding: 14px 18px; background: #d1fae5; border: 1px solid #6ee7b7; border-left: 4px solid #059669; border-radius: 8px; color: #065f46; display: flex; gap: 12px; align-items: flex-start;">
152 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex: 0 0 22px; width: 22px; height: 22px; margin-top: 1px;">
153 <path stroke-linecap="round" stroke-linejoin="round" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"/>
154 </svg>
155 <div style="flex: 1; line-height: 1.45;">
156 <strong style="display: block; margin-bottom: 2px;">
157 <?php esc_html_e('Balance payment received.', 'yatra'); ?>
158 </strong>
159 <span>
160 <?php
161 printf(
162 wp_kses(
163 /* translators: 1: booking reference number (HTML <strong> wrapped), 2: link labelled "payment history" pointing to the customer account page (HTML <a> wrapped). */
164 __('You\'ve completed payment for booking %1$s. A receipt has been emailed to you. View or download your %2$s anytime from your account.', 'yatra'),
165 ['a' => ['href' => true], 'strong' => []]
166 ),
167 '<strong>' . esc_html((string) ($booking->reference ?? '')) . '</strong>',
168 '<a href="' . esc_url(add_query_arg('tab', 'payments', $yatra_account_url)) . '">' . esc_html__('payment history', 'yatra') . '</a>'
169 );
170 ?>
171 </span>
172 </div>
173 </div>
174 <?php endif; ?>
175
176 <?php
177 // Resolve featured image URL (handle attachment ID or direct URL).
178 // Falls back to the bundled trip-placeholder.svg so the confirmation
179 // card always renders with a visual on the left — never an empty
180 // text-only block, regardless of whether the operator set a featured
181 // image for the trip.
182 $featured_image_url = '';
183 if (!empty($booking->featured_image)) {
184 if (is_numeric($booking->featured_image)) {
185 $featured_image_url = wp_get_attachment_url((int) $booking->featured_image) ?: '';
186 } else {
187 $featured_image_url = $booking->featured_image;
188 }
189 }
190 if ($featured_image_url === '') {
191 $featured_image_url = YATRA_PLUGIN_URL . 'assets/images/trip-placeholder.svg';
192 $featured_image_is_placeholder = true;
193 } else {
194 $featured_image_is_placeholder = false;
195 }
196 ?>
197
198 <div class="yatra-confirmation-content">
199 <!-- Trip Summary Card -->
200 <div class="yatra-confirmation-card yatra-trip-summary-card">
201 <div class="yatra-trip-summary">
202 <div class="yatra-trip-image<?php echo $featured_image_is_placeholder ? ' yatra-trip-image--placeholder' : ''; ?>">
203 <img src="<?php echo esc_url($featured_image_url); ?>"
204 alt="<?php echo esc_attr($booking->trip_title); ?>"
205 loading="lazy"
206 onerror="this.onerror=null;this.src='<?php echo esc_url(YATRA_PLUGIN_URL . 'assets/images/trip-placeholder.svg'); ?>';this.parentNode.classList.add('yatra-trip-image--placeholder');">
207 </div>
208
209 <div class="yatra-trip-info">
210 <h2 class="yatra-trip-name"><?php echo esc_html($booking->trip_title); ?></h2>
211
212 <?php if (!empty($booking->trip_average_rating) && $booking->trip_review_count >= 0) : ?>
213 <div class="yatra-trip-rating">
214 <div class="yatra-rating-stars">
215 <?php
216 // floor() returns a float, so the strict `$i === $filled_stars + 1`
217 // below compared int against float and never matched — the half
218 // star was silently dropped and a 4.5 rating rendered as 4 solid
219 // stars beside the text "4.5". Cast so the comparison holds.
220 $average_rating = (float) $booking->trip_average_rating;
221 $filled_stars = (int) floor($average_rating);
222 $has_half = ($average_rating - $filled_stars) >= 0.5;
223 for ($i = 1; $i <= 5; $i++) :
224 $class = $i <= $filled_stars ? 'yatra-star-filled' : ($has_half && $i === $filled_stars + 1 ? 'yatra-star-half' : '');
225 ?>
226 <span class="yatra-star <?php echo esc_attr($class); ?>">
227 <svg viewBox="0 0 24 24" fill="currentColor"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26"></polygon></svg>
228 </span>
229 <?php endfor; ?>
230 </div>
231 <div class="yatra-rating-meta">
232 <strong><?php echo esc_html(number_format($booking->trip_average_rating, 1)); ?></strong>
233 <span>
234 <?php
235 printf(
236 esc_html(
237 /* translators: %d: number of reviews. */
238 _n('%d Review', '%d Reviews', (int) $booking->trip_review_count, 'yatra')
239 ),
240 (int) $booking->trip_review_count
241 );
242 ?>
243 </span>
244 </div>
245 </div>
246 <?php endif; ?>
247
248 <div class="yatra-trip-meta">
249 <?php if (!empty($booking->duration_days)) : ?>
250 <span class="yatra-meta-item">
251 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
252 <circle cx="12" cy="12" r="10"></circle>
253 <polyline points="12 6 12 12 16 14"></polyline>
254 </svg>
255 <?php
256 $days = (int) ($booking->duration_days ?? 0);
257 $nights = (int) ($booking->duration_nights ?? 0);
258
259 if ($days > 0 && $nights > 0) {
260 printf(
261 /* translators: 1: number of days, 2: number of nights. */
262 esc_html__('%1$d Days / %2$d Nights', 'yatra'),
263 $days,
264 $nights
265 );
266 } elseif ($days > 0) {
267 printf(
268 esc_html(
269 /* translators: %d: number of days. */
270 _n('%d Day', '%d Days', $days, 'yatra')
271 ),
272 $days
273 );
274 } elseif ($nights > 0) {
275 printf(
276 esc_html(
277 /* translators: %d: number of nights. */
278 _n('%d Night', '%d Nights', $nights, 'yatra')
279 ),
280 $nights
281 );
282 }
283 ?>
284 </span>
285 <?php endif; ?>
286
287 <?php if (!empty($booking->difficulty_level)) : ?>
288 <span class="yatra-meta-item">
289 <?php
290 $difficulty = \Yatra\Models\Trip::resolveDifficultyDisplay(
291 (string) $booking->difficulty_level
292 );
293
294 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
295 echo yatra_stored_picker_icon_markup(
296 $difficulty['icon_picker'] ?? null,
297 '',
298 'yatra-icon-sm'
299 );
300
301 echo esc_html($difficulty['level'] ?? (string) $booking->difficulty_level);
302 ?>
303 </span>
304 <?php endif; ?>
305 </div>
306
307 <?php if (!empty($booking->starting_location)) : ?>
308 <p class="yatra-trip-location">
309 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
310 <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
311 <circle cx="12" cy="10" r="3"></circle>
312 </svg>
313 <?php echo esc_html($booking->starting_location); ?>
314 <?php if (!empty($booking->ending_location) && $booking->ending_location !== $booking->starting_location) : ?>
315 → <?php echo esc_html($booking->ending_location); ?>
316 <?php endif; ?>
317 </p>
318 <?php endif; ?>
319
320 <?php if (!empty($booking->trip_destinations_list)) : ?>
321 <div class="yatra-trip-tags">
322 <span class="yatra-tag-label"><?php esc_html_e('Destinations:', 'yatra'); ?></span>
323 <div class="yatra-tag-group">
324 <?php foreach ($booking->trip_destinations_list as $destination) : ?>
325 <span class="yatra-tag-item"><?php echo esc_html($destination); ?></span>
326 <?php endforeach; ?>
327 </div>
328 </div>
329 <?php endif; ?>
330
331 <?php if (!empty($booking->trip_activities_list)) : ?>
332 <div class="yatra-trip-tags">
333 <span class="yatra-tag-label"><?php esc_html_e('Activities:', 'yatra'); ?></span>
334 <div class="yatra-tag-group">
335 <?php foreach ($booking->trip_activities_list as $activity) : ?>
336 <span class="yatra-tag-item"><?php echo esc_html($activity); ?></span>
337 <?php endforeach; ?>
338 </div>
339 </div>
340 <?php endif; ?>
341
342 <?php if (!empty($booking->trip_categories_list)) : ?>
343 <div class="yatra-trip-tags">
344 <span class="yatra-tag-label"><?php esc_html_e('Trip Type:', 'yatra'); ?></span>
345 <div class="yatra-tag-group">
346 <?php foreach ($booking->trip_categories_list as $category) : ?>
347 <span class="yatra-tag-item"><?php echo esc_html($category); ?></span>
348 <?php endforeach; ?>
349 </div>
350 </div>
351 <?php endif; ?>
352
353 </div>
354 </div>
355 </div>
356
357 <!-- Booking Details -->
358 <div class="yatra-confirmation-grid">
359 <!-- Left Column -->
360 <div class="yatra-confirmation-column">
361 <!-- Booking Info Card -->
362 <div class="yatra-confirmation-card">
363 <h3 class="yatra-card-title">
364 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
365 <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
366 <line x1="16" y1="2" x2="16" y2="6"></line>
367 <line x1="8" y1="2" x2="8" y2="6"></line>
368 <line x1="3" y1="10" x2="21" y2="10"></line>
369 </svg>
370 <?php esc_html_e('Booking Information', 'yatra'); ?>
371 </h3>
372
373 <div class="yatra-info-grid">
374 <div class="yatra-info-item">
375 <span class="yatra-info-label"><?php esc_html_e('Status', 'yatra'); ?></span>
376 <span class="yatra-info-value">
377 <span class="yatra-status-badge" style="background: <?php echo esc_attr($status_style['bg']); ?>; color: <?php echo esc_attr($status_style['text']); ?>;">
378 <?php echo esc_html($status_style['label']); ?>
379 </span>
380 </span>
381 </div>
382 <div class="yatra-info-item">
383 <span class="yatra-info-label"><?php esc_html_e('Travel Date', 'yatra'); ?></span>
384 <span class="yatra-info-value"><?php echo esc_html($travel_date_formatted); ?></span>
385 </div>
386 <div class="yatra-info-item">
387 <span class="yatra-info-label"><?php esc_html_e('Number of Travelers', 'yatra'); ?></span>
388 <span class="yatra-info-value"><?php echo esc_html($booking->travelers_count); ?></span>
389 </div>
390 <div class="yatra-info-item">
391 <span class="yatra-info-label"><?php esc_html_e('Booked On', 'yatra'); ?></span>
392 <span class="yatra-info-value"><?php echo esc_html($booking_date_formatted); ?></span>
393 </div>
394 </div>
395 </div>
396
397 <!-- Travelers Card -->
398 <?php if (!empty($booking->travelers)) : ?>
399 <div class="yatra-confirmation-card">
400 <h3 class="yatra-card-title">
401 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
402 <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
403 <circle cx="9" cy="7" r="4"></circle>
404 <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
405 <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
406 </svg>
407 <?php esc_html_e('Travelers', 'yatra'); ?>
408 </h3>
409
410 <div class="yatra-travelers-list">
411 <?php foreach ($booking->travelers as $index => $traveler) :
412 $traveler_name = trim(($traveler['first_name'] ?? '') . ' ' . ($traveler['last_name'] ?? ''));
413 ?>
414 <div class="yatra-traveler-item">
415 <span class="yatra-traveler-number"><?php echo esc_html($index + 1); ?></span>
416 <div class="yatra-traveler-details">
417 <span class="yatra-traveler-name">
418 <?php echo esc_html($traveler_name ?: __('Traveler', 'yatra') . ' ' . ($index + 1)); ?>
419 </span>
420 <?php if (!empty($traveler['date_of_birth'])) : ?>
421 <span class="yatra-traveler-dob">
422 <?php echo esc_html(\Yatra\Helpers\FormatHelper::formatDate((string) $traveler['date_of_birth'])); ?>
423 </span>
424 <?php endif; ?>
425 </div>
426 </div>
427 <?php endforeach; ?>
428 </div>
429 </div>
430 <?php endif; ?>
431
432 <?php
433 // Allow gateways to inject cards (e.g., Bank Transfer instructions)
434 do_action('yatra_booking_confirmation_after_details', $booking);
435 ?>
436 </div>
437
438 <!-- Right Column -->
439 <div class="yatra-confirmation-column">
440 <!-- Payment Summary Card -->
441 <div class="yatra-confirmation-card yatra-payment-card">
442 <h3 class="yatra-card-title">
443 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
444 <rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect>
445 <line x1="1" y1="10" x2="23" y2="10"></line>
446 </svg>
447 <?php esc_html_e('Payment Summary', 'yatra'); ?>
448 </h3>
449
450 <div class="yatra-payment-rows">
451 <?php
452 // ── Raw figures from DB ───────────────────────────────────
453 $db_subtotal = (float) ($booking->subtotal ?? $booking->total_amount);
454 $discount_amount = (float) ($booking->discount_amount ?? 0);
455 $itinerary_costs_total = (float) ($booking->itinerary_costs_total ?? 0);
456 $tax_amount = (float) ($booking->tax_amount ?? 0);
457 $tax_inclusive = !empty($booking->tax_inclusive);
458 $total_amount = (float) $booking->total_amount;
459 $amount_paid = (float) ($booking->amount_paid ?? 0);
460 $amount_due = (float) ($booking->amount_due ?? 0);
461
462 // ── Tax breakdown (built first so it can gate later rows) ─
463 $tax_breakdown = [];
464 if (!empty($booking->tax_details)) {
465 $taxes = json_decode($booking->tax_details, true) ?: [];
466 foreach ($taxes as $tax) {
467 $tax_breakdown[] = [
468 'name' => $tax['name'] ?? __('Tax', 'yatra'),
469 'rate' => (float) ($tax['rate'] ?? 0),
470 'amount' => (float) ($tax['amount'] ?? 0),
471 ];
472 }
473 } elseif ($tax_amount > 0) {
474 $tax_breakdown[] = [
475 'name' => __('Tax', 'yatra'),
476 'rate' => (float) ($booking->tax_rate ?? 0),
477 'amount' => $tax_amount,
478 ];
479 }
480
481 // ── Itinerary costs ───────────────────────────────────────
482 $itinerary_costs = [];
483 if (!empty($booking->itinerary_costs)) {
484 $itinerary_costs = json_decode($booking->itinerary_costs, true) ?: [];
485 }
486
487 // ── Additional services ───────────────────────────────────
488 $raw_services = apply_filters('yatra_booking_get_services', [], (int) ($booking->id ?? 0));
489 $selected_services = [];
490 if (!empty($raw_services) && is_array($raw_services)) {
491 foreach ($raw_services as $s) {
492 $arr = is_array($s) ? $s : (array) $s;
493 if (!isset($arr['selected']) || !empty($arr['selected'])) {
494 $selected_services[] = $arr;
495 }
496 }
497 }
498 $services_total = 0.0;
499 foreach ($selected_services as $s) {
500 $services_total += (float) ($s['total_price'] ?? $s['calculated_price'] ?? $s['total_cost'] ?? $s['amount'] ?? $s['unit_price'] ?? $s['price'] ?? 0);
501 }
502
503 // ── Derived amounts ───────────────────────────────────────
504 // base_trip_cost: the trip price without services (services are embedded in db_subtotal by Pro)
505 $base_trip_cost = $db_subtotal - $services_total;
506 // taxable_amount: what tax is calculated on
507 $taxable_amount = max(0.0, $db_subtotal - $discount_amount) + $itinerary_costs_total;
508
509 $has_services = !empty($selected_services);
510 $has_discount = $discount_amount > 0;
511 $has_itinerary = !empty($itinerary_costs) && $itinerary_costs_total > 0;
512 $has_tax = !empty($tax_breakdown);
513 $show_taxable_row = $has_tax && ($has_discount || $has_itinerary);
514 ?>
515
516 <!-- Trip Base Price (always the first line) -->
517 <div class="yatra-payment-row">
518 <span>
519 <?php esc_html_e('Trip Base Price', 'yatra'); ?>
520 <?php if ($tax_inclusive): ?>
521 <span style="display:inline-flex;align-items:center;padding:1px 6px;border-radius:4px;font-size:0.72em;font-weight:600;background:#eff6ff;color:#1d4ed8;margin-left:5px;letter-spacing:0;">
522 <?php esc_html_e('Tax Incl.', 'yatra'); ?>
523 </span>
524 <?php endif; ?>
525 </span>
526 <span><?php echo esc_html(yatra_format_price($base_trip_cost, $booking->currency)); ?></span>
527 </div>
528
529 <?php if ($has_services): ?>
530 <!-- Additional Services section header -->
531 <div class="yatra-payment-row" style="margin-top: 4px;">
532 <span style="font-size: 0.75em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280;">
533 + <?php esc_html_e('Additional Services', 'yatra'); ?>
534 </span>
535 <span></span>
536 </div>
537 <!-- Service line items -->
538 <?php foreach ($selected_services as $svc): ?>
539 <?php
540 $svc_name = $svc['service_name'] ?? $svc['name'] ?? $svc['title'] ?? $svc['label'] ?? __('Service', 'yatra');
541 $svc_amount = (float) ($svc['total_price'] ?? $svc['calculated_price'] ?? $svc['total_cost'] ?? $svc['amount'] ?? $svc['unit_price'] ?? $svc['price'] ?? 0);
542 ?>
543 <div class="yatra-payment-row" style="margin-left: 16px;">
544 <span><?php echo esc_html($svc_name); ?></span>
545 <span><?php echo esc_html(yatra_format_price($svc_amount, $booking->currency, false)); ?></span>
546 </div>
547 <?php endforeach; ?>
548 <!-- Gross Total = Trip Base Price + Services -->
549 <div class="yatra-payment-row" style="border-top: 1px solid #e5e7eb; margin-top: 6px; padding-top: 6px;">
550 <span><strong><?php esc_html_e('Gross Total', 'yatra'); ?></strong></span>
551 <span><strong><?php echo esc_html(yatra_format_price($db_subtotal, $booking->currency)); ?></strong></span>
552 </div>
553 <?php endif; ?>
554
555 <?php if ($has_discount): ?>
556 <!-- Discount -->
557 <div class="yatra-payment-row">
558 <span><?php esc_html_e('Discount', 'yatra'); ?></span>
559 <span style="color: #059669; font-weight: 500;">-<?php echo esc_html(yatra_format_price($discount_amount, $booking->currency)); ?></span>
560 </div>
561 <?php endif; ?>
562
563 <?php if ($has_itinerary): ?>
564 <!-- Itinerary costs header -->
565 <div class="yatra-payment-row" style="margin-top: 4px;">
566 <span><strong><?php esc_html_e('Itinerary Costs', 'yatra'); ?></strong></span>
567 <span></span>
568 </div>
569 <?php foreach ($itinerary_costs as $cost): ?>
570 <div class="yatra-payment-row" style="margin-left: 20px;">
571 <span>
572 <?php echo esc_html($cost['name']); ?>
573 <?php if (!empty($cost['price_per'])): ?>
574 <small style="opacity: 0.65;">
575 <?php
576 if ($cost['price_per'] === 'person') {
577 esc_html_e('(per person)', 'yatra');
578 } elseif ($cost['price_per'] === 'group') {
579 esc_html_e('(per booking)', 'yatra');
580 } else {
581 esc_html_e('(flat rate)', 'yatra');
582 }
583 ?>
584 </small>
585 <?php endif; ?>
586 </span>
587 <span><?php echo esc_html(yatra_format_price($cost['total_cost'] ?? $cost['price'], $booking->currency)); ?></span>
588 </div>
589 <?php endforeach; ?>
590 <?php endif; ?>
591
592 <?php if (!$tax_inclusive && $show_taxable_row): ?>
593 <!-- Taxable Amount (only for exclusive tax when there are deductions above it) -->
594 <div class="yatra-payment-row" style="border-top: 1px dashed #e5e7eb; margin-top: 8px; padding-top: 8px;">
595 <span><strong><?php esc_html_e('Taxable Amount', 'yatra'); ?></strong></span>
596 <span><strong><?php echo esc_html(yatra_format_price($taxable_amount, $booking->currency)); ?></strong></span>
597 </div>
598 <?php endif; ?>
599
600 <?php if ($has_tax && !$tax_inclusive): ?>
601 <!-- Exclusive tax: shown as an addition before Net Amount -->
602 <div class="yatra-payment-row" style="margin-top: 4px;">
603 <span style="font-size: 0.75em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280;">
604 + <?php esc_html_e('Tax', 'yatra'); ?>
605 </span>
606 <span></span>
607 </div>
608 <?php foreach ($tax_breakdown as $tax): ?>
609 <div class="yatra-payment-row" style="margin-left: 16px;">
610 <span>
611 <?php echo esc_html($tax['name']); ?>
612 <?php if ($tax['rate'] > 0): ?>
613 (<?php echo esc_html($tax['rate']); ?>%)
614 <?php endif; ?>
615 </span>
616 <span>+<?php echo esc_html(yatra_format_price($tax['amount'], $booking->currency)); ?></span>
617 </div>
618 <?php endforeach; ?>
619 <?php endif; ?>
620
621 <!-- Net Amount -->
622 <div class="yatra-payment-row" style="border-top: 2px solid #111827; margin-top: 10px; padding-top: 10px;">
623 <span style="font-size: 1.05em;"><strong><?php esc_html_e('Net Amount', 'yatra'); ?></strong></span>
624 <span style="font-size: 1.05em;"><strong><?php echo esc_html(yatra_format_price($total_amount, $booking->currency)); ?></strong></span>
625 </div>
626
627 <?php if ($has_tax && $tax_inclusive): ?>
628 <!-- Inclusive tax: shown as an informational footnote after Net Amount -->
629 <?php foreach ($tax_breakdown as $tax): ?>
630 <div class="yatra-payment-row" style="margin-top: 4px; opacity: 0.7;">
631 <span style="font-size: 0.85em; font-style: italic;">
632 <?php
633 printf(
634 /* translators: %1$s = tax name, %2$s = rate, %3$s = amount */
635 esc_html__('Incl. %1$s%2$s: %3$s', 'yatra'),
636 esc_html($tax['name']),
637 $tax['rate'] > 0 ? ' (' . esc_html($tax['rate']) . '%)' : '',
638 esc_html(yatra_format_price($tax['amount'], $booking->currency))
639 );
640 ?>
641 </span>
642 <span></span>
643 </div>
644 <?php endforeach; ?>
645 <?php endif; ?>
646
647 <?php if ($amount_paid > 0): ?>
648 <div class="yatra-payment-row" style="margin-top: 6px;">
649 <span><?php esc_html_e('Amount Paid', 'yatra'); ?></span>
650 <span style="color: #059669;"><?php echo esc_html(yatra_format_price($amount_paid, $booking->currency)); ?></span>
651 </div>
652 <?php endif; ?>
653
654 <?php if ($amount_due > 0): ?>
655 <?php
656 // Label the "due now" amount by payment type so a
657 // deposit/partial reads clearly instead of just "Due Now".
658 $payment_method_type = (string) ($booking->payment_method ?? 'full');
659 $remaining_balance = max(0.0, $total_amount - $amount_paid - $amount_due);
660 if ($payment_method_type === 'deposit') {
661 $due_now_label = __('Deposit Due Now', 'yatra');
662 } elseif ($payment_method_type === 'partial') {
663 $due_now_label = __('Partial Payment Due Now', 'yatra');
664 } else {
665 $due_now_label = __('Due Now', 'yatra');
666 }
667 ?>
668 <div class="yatra-payment-row yatra-due-row">
669 <span><strong><?php echo esc_html($due_now_label); ?></strong></span>
670 <span><strong><?php echo esc_html(yatra_format_price($amount_due, $booking->currency)); ?></strong></span>
671 </div>
672 <?php if ($payment_method_type !== 'full' && $remaining_balance > 0.01): ?>
673 <div class="yatra-payment-row" style="margin-top: 6px;">
674 <span><?php esc_html_e('Remaining Balance', 'yatra'); ?></span>
675 <span><?php echo esc_html(yatra_format_price($remaining_balance, $booking->currency)); ?></span>
676 </div>
677 <?php endif; ?>
678 <?php endif; ?>
679 </div>
680
681 <div class="yatra-payment-method">
682 <span class="yatra-pm-label"><?php esc_html_e('Payment Method:', 'yatra'); ?></span>
683 <span class="yatra-pm-value"><?php echo esc_html(ucwords(str_replace('_', ' ', (string) $display_payment_gateway))); ?></span>
684 </div>
685 </div>
686
687 <!-- Contact Info Card -->
688 <div class="yatra-confirmation-card">
689 <h3 class="yatra-card-title">
690 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
691 <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
692 <polyline points="22,6 12,13 2,6"></polyline>
693 </svg>
694 <?php esc_html_e('Contact Information', 'yatra'); ?>
695 </h3>
696
697 <div class="yatra-contact-info">
698 <?php
699 // Try to get contact data from multiple sources
700 $contact_data = [];
701 if (!empty($booking->contact_data)) {
702 $contact_data = json_decode($booking->contact_data, true) ?: [];
703 }
704
705 $contact_name = trim((
706 $contact_data['first_name'] ??
707 $booking->contact_first_name ??
708 ($booking->contact['first_name'] ?? '')
709 ) . ' ' . (
710 $contact_data['last_name'] ??
711 $booking->contact_last_name ??
712 ($booking->contact['last_name'] ?? '')
713 ));
714
715 $contact_email = $contact_data['email'] ?? $booking->contact_email ?? ($booking->contact['email'] ?? '');
716 $contact_phone = $contact_data['phone'] ?? $booking->contact_phone ?? ($booking->contact['phone'] ?? '');
717 ?>
718
719 <?php if ($contact_name) : ?>
720 <p class="yatra-contact-item">
721 <strong><?php esc_html_e('Name:', 'yatra'); ?></strong>
722 <?php echo esc_html($contact_name); ?>
723 </p>
724 <?php endif; ?>
725
726 <?php if ($contact_email) : ?>
727 <p class="yatra-contact-item">
728 <strong><?php esc_html_e('Email:', 'yatra'); ?></strong>
729 <?php echo esc_html($contact_email); ?>
730 </p>
731 <?php endif; ?>
732
733 <?php if ($contact_phone) : ?>
734 <p class="yatra-contact-item">
735 <strong><?php esc_html_e('Phone:', 'yatra'); ?></strong>
736 <?php echo esc_html($contact_phone); ?>
737 </p>
738 <?php endif; ?>
739
740 <?php if (!$contact_name && !$contact_email && !$contact_phone) : ?>
741 <p class="yatra-contact-item">
742 <em><?php esc_html_e('Contact information not available', 'yatra'); ?></em>
743 </p>
744 <?php endif; ?>
745 </div>
746 </div>
747 </div>
748 </div>
749
750 <!-- What's Next Section -->
751 <div class="yatra-confirmation-card yatra-whats-next">
752 <h3 class="yatra-card-title">
753 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
754 <circle cx="12" cy="12" r="10"></circle>
755 <polyline points="12 16 16 12 12 8"></polyline>
756 <line x1="8" y1="12" x2="16" y2="12"></line>
757 </svg>
758 <?php esc_html_e("What's Next?", 'yatra'); ?>
759 </h3>
760
761 <div class="yatra-next-steps">
762 <div class="yatra-step">
763 <span class="yatra-step-number">1</span>
764 <div class="yatra-step-content">
765 <h4><?php esc_html_e('Check Your Email', 'yatra'); ?></h4>
766 <p><?php esc_html_e('We\'ve sent a confirmation email with all the details to your registered email address.', 'yatra'); ?></p>
767 </div>
768 </div>
769
770 <div class="yatra-step">
771 <span class="yatra-step-number">2</span>
772 <div class="yatra-step-content">
773 <h4><?php esc_html_e('Detailed Itinerary', 'yatra'); ?></h4>
774 <p><?php esc_html_e('You\'ll receive a detailed itinerary and preparation guide within 24-48 hours.', 'yatra'); ?></p>
775 </div>
776 </div>
777
778 <div class="yatra-step">
779 <span class="yatra-step-number">3</span>
780 <div class="yatra-step-content">
781 <h4><?php esc_html_e('Prepare for Adventure', 'yatra'); ?></h4>
782 <p><?php esc_html_e('Ensure all travelers have valid ID or travel documents and any required visas for your destination.', 'yatra'); ?></p>
783 </div>
784 </div>
785 </div>
786 </div>
787
788 <!-- Action Buttons -->
789 <div class="yatra-confirmation-actions">
790 <a href="<?php echo esc_url(home_url('/')); ?>" class="yatra-btn yatra-btn-secondary">
791 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
792 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
793 <polyline points="9 22 9 12 15 12 15 22"></polyline>
794 </svg>
795 <?php esc_html_e('Return to Home', 'yatra'); ?>
796 </a>
797
798 <?php
799 // Get latest payment for this booking to enable invoice download.
800 // The invoice endpoint authorises via: admin → owner → signed invoice_token → guest booking_token.
801 // We always issue a signed invoice_token here so the link works for guests
802 // (no session required) AND for logged-in users who don't own the booking
803 // (e.g. site admins viewing the page) — without re-checking login on the client.
804 $paymentRepository = new \Yatra\Repositories\PaymentRepository();
805 $latestPayment = $paymentRepository->findLatestByBookingId((int) $booking->id);
806 if ($latestPayment && in_array($latestPayment->status, ['completed', 'paid'], true)) :
807 $invoiceToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken(
808 (int) $latestPayment->id,
809 (int) ($latestPayment->booking_id ?? $booking->id)
810 );
811 $invoiceUrl = add_query_arg(
812 [
813 'download' => '1',
814 'invoice_token' => $invoiceToken,
815 ],
816 rest_url('yatra/v1/payment/' . (int) $latestPayment->id . '/invoice')
817 );
818 ?>
819 <a href="<?php echo esc_url($invoiceUrl); ?>"
820 target="_blank"
821 rel="noopener"
822 class="yatra-btn yatra-btn-primary">
823 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
824 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
825 <polyline points="7 10 12 15 17 10"></polyline>
826 <line x1="12" y1="15" x2="12" y2="3"></line>
827 </svg>
828 <?php esc_html_e('Download Invoice', 'yatra'); ?>
829 </a>
830 <?php
831 // No completed payment yet (e.g. Bank Transfer / offline): offer a
832 // pro-forma invoice that carries the payment instructions so the
833 // customer knows how to pay. Uses a booking-scoped invoice token.
834 elseif ((float) ($booking->amount_due ?? $booking->total_amount ?? 0) > 0) :
835 $proformaToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken(0, (int) $booking->id);
836 $proformaUrl = add_query_arg(
837 [
838 'download' => '1',
839 'invoice_token' => $proformaToken,
840 ],
841 rest_url('yatra/v1/booking/' . (int) $booking->id . '/invoice')
842 );
843 ?>
844 <a href="<?php echo esc_url($proformaUrl); ?>"
845 target="_blank"
846 rel="noopener"
847 class="yatra-btn yatra-btn-primary">
848 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
849 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
850 <polyline points="7 10 12 15 17 10"></polyline>
851 <line x1="12" y1="15" x2="12" y2="3"></line>
852 </svg>
853 <?php esc_html_e('Download Invoice', 'yatra'); ?>
854 </a>
855 <?php endif; ?>
856
857 <button type="button" data-yatra-print="confirmation" class="yatra-btn yatra-btn-outline">
858 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
859 <polyline points="6 9 6 2 18 2 18 9"></polyline>
860 <path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
861 <rect x="6" y="14" width="12" height="8"></rect>
862 </svg>
863 <?php esc_html_e('Print Confirmation', 'yatra'); ?>
864 </button>
865 </div>
866
867 </div>
868 </div>
869 </div>
870
871 <style>
872 /* Confirmation Page Styles */
873 .yatra-confirmation-wrapper {
874 max-width: 1300px;
875 margin: 0 auto;
876 padding: 40px 20px;
877 }
878
879 .yatra-confirmation-container {
880 max-width: 900px;
881 margin: 0 auto;
882 }
883
884 .yatra-confirmation-header {
885 text-align: center;
886 margin-bottom: 40px;
887 }
888
889 .yatra-confirmation-icon {
890 width: 100px;
891 height: 100px;
892 margin: 0 auto 24px;
893 background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
894 border-radius: 50%;
895 display: flex;
896 align-items: center;
897 justify-content: center;
898 animation: scaleIn 0.5s ease-out;
899 }
900
901 .yatra-confirmation-icon svg {
902 width: 50px;
903 height: 50px;
904 color: white;
905 }
906
907 @keyframes scaleIn {
908 0% { transform: scale(0); opacity: 0; }
909 50% { transform: scale(1.1); }
910 100% { transform: scale(1); opacity: 1; }
911 }
912
913 .yatra-confirmation-title {
914 font-size: 36px;
915 font-weight: 700;
916 color: #111827;
917 margin: 0 0 12px;
918 }
919
920 .yatra-confirmation-subtitle {
921 font-size: 18px;
922 color: #6b7280;
923 margin: 0 0 24px;
924 }
925
926 .yatra-confirmation-reference {
927 display: inline-flex;
928 align-items: center;
929 gap: 12px;
930 background: #f3f4f6;
931 padding: 12px 24px;
932 border-radius: 100px;
933 }
934
935 .yatra-ref-label {
936 color: #6b7280;
937 font-size: 14px;
938 }
939
940 .yatra-ref-code {
941 font-size: 18px;
942 font-weight: 700;
943 color: #111827;
944 font-family: monospace;
945 letter-spacing: 1px;
946 }
947
948 .yatra-confirmation-card {
949 background: #fff;
950 border: 1px solid #e5e7eb;
951 border-radius: 16px;
952 padding: 24px;
953 margin-bottom: 24px;
954 }
955
956 .yatra-card-title {
957 display: flex;
958 align-items: center;
959 gap: 12px;
960 font-size: 18px;
961 font-weight: 600;
962 color: #111827;
963 margin: 0 0 20px;
964 padding-bottom: 16px;
965 border-bottom: 1px solid #e5e7eb;
966 }
967
968 .yatra-card-title svg {
969 width: 22px;
970 height: 22px;
971 color: #3b82f6;
972 }
973
974 .yatra-trip-summary-card {
975 background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
976 border-color: #bfdbfe;
977 }
978
979 .yatra-trip-summary {
980 display: flex;
981 gap: 24px;
982 align-items: center;
983 }
984
985 .yatra-trip-image {
986 width: 120px;
987 height: 120px;
988 border-radius: 12px;
989 overflow: hidden;
990 flex-shrink: 0;
991 }
992
993 .yatra-trip-image img {
994 width: 100%;
995 height: 100%;
996 object-fit: cover;
997 }
998
999 .yatra-trip-name {
1000 font-size: 22px;
1001 font-weight: 700;
1002 color: #111827;
1003 margin: 0 0 12px;
1004 }
1005
1006 /* Star rating. This confirmation page only enqueues yatra-common + fontawesome,
1007 not booking.css/trip.css where these live, so without them the inline SVG
1008 stars render with no size or colour (invisible). Mirrors booking.css. */
1009 .yatra-trip-rating {
1010 display: flex;
1011 align-items: center;
1012 gap: 12px;
1013 margin-bottom: 12px;
1014 }
1015
1016 .yatra-rating-stars {
1017 display: inline-flex;
1018 gap: 4px;
1019 }
1020
1021 .yatra-star {
1022 width: 20px;
1023 height: 20px;
1024 color: #e2e8f0;
1025 }
1026
1027 .yatra-star svg {
1028 width: 100%;
1029 height: 100%;
1030 }
1031
1032 .yatra-star-filled {
1033 color: #f59e0b;
1034 }
1035
1036 /* Half star: base star stays grey; overlay the left half in amber via an
1037 SVG mask (size-independent, so it tracks the star's dimensions). */
1038 .yatra-star-half {
1039 position: relative;
1040 color: #e2e8f0;
1041 }
1042
1043 .yatra-star-half::after {
1044 content: "";
1045 position: absolute;
1046 top: 0;
1047 left: 0;
1048 bottom: 0;
1049 width: 50%;
1050 overflow: hidden;
1051 background: #f59e0b;
1052 -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%;
1053 mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%;
1054 }
1055
1056 .yatra-rating-meta strong {
1057 color: #0f172a;
1058 margin-right: 6px;
1059 }
1060
1061 .yatra-rating-meta span {
1062 color: #64748b;
1063 font-size: 14px;
1064 }
1065
1066 .yatra-trip-meta {
1067 display: flex;
1068 gap: 20px;
1069 flex-wrap: wrap;
1070 margin-bottom: 8px;
1071 }
1072
1073 .yatra-meta-item {
1074 display: flex;
1075 align-items: center;
1076 gap: 6px;
1077 font-size: 14px;
1078 color: #4b5563;
1079 }
1080
1081 .yatra-meta-item svg {
1082 width: 16px;
1083 height: 16px;
1084 }
1085
1086 .yatra-trip-location {
1087 display: flex;
1088 align-items: center;
1089 gap: 6px;
1090 font-size: 14px;
1091 color: #6b7280;
1092 margin: 0;
1093 }
1094
1095 .yatra-trip-location svg {
1096 width: 16px;
1097 height: 16px;
1098 }
1099
1100 .yatra-confirmation-grid {
1101 display: grid;
1102 grid-template-columns: 1fr 1fr;
1103 gap: 24px;
1104 }
1105
1106 @media (max-width: 768px) {
1107 .yatra-confirmation-grid {
1108 grid-template-columns: 1fr;
1109 }
1110
1111 .yatra-trip-summary {
1112 flex-direction: column;
1113 text-align: center;
1114 }
1115
1116 .yatra-info-grid {
1117 grid-template-columns: 1fr;
1118 gap: 12px;
1119 }
1120 }
1121
1122 .yatra-info-grid {
1123 display: grid;
1124 grid-template-columns: 1fr 1fr;
1125 gap: 16px;
1126 }
1127
1128 .yatra-info-item {
1129 display: flex;
1130 flex-direction: column;
1131 gap: 4px;
1132 padding: 12px 14px;
1133 background: #f9fafb;
1134 border: 1px solid #eef2f7;
1135 border-radius: 12px;
1136 }
1137
1138 .yatra-info-label {
1139 font-size: 13px;
1140 color: #6b7280;
1141 line-height: 1.2;
1142 }
1143
1144 .yatra-info-value {
1145 font-size: 15px;
1146 font-weight: 600;
1147 color: #111827;
1148 line-height: 1.25;
1149 text-align: left;
1150 }
1151
1152 .yatra-status-badge {
1153 display: inline-block;
1154 padding: 4px 12px;
1155 border-radius: 100px;
1156 font-size: 13px;
1157 font-weight: 600;
1158 }
1159
1160 .yatra-travelers-list {
1161 display: flex;
1162 flex-direction: column;
1163 gap: 12px;
1164 }
1165
1166 .yatra-traveler-item {
1167 display: flex;
1168 align-items: center;
1169 gap: 12px;
1170 padding: 12px;
1171 background: #f9fafb;
1172 border-radius: 8px;
1173 }
1174
1175 .yatra-traveler-number {
1176 width: 28px;
1177 height: 28px;
1178 display: flex;
1179 align-items: center;
1180 justify-content: center;
1181 background: #3b82f6;
1182 color: white;
1183 border-radius: 50%;
1184 font-size: 13px;
1185 font-weight: 600;
1186 }
1187
1188 .yatra-traveler-name {
1189 font-weight: 600;
1190 color: #111827;
1191 }
1192
1193 .yatra-traveler-dob {
1194 font-size: 13px;
1195 color: #6b7280;
1196 }
1197
1198 .yatra-payment-card {
1199 background: #fafafa;
1200 }
1201
1202 .yatra-payment-rows {
1203 border: 1px solid #e5e7eb;
1204 border-radius: 8px;
1205 overflow: hidden;
1206 }
1207
1208 .yatra-payment-row {
1209 display: flex;
1210 justify-content: space-between;
1211 padding: 12px 16px;
1212 border-bottom: 1px solid #e5e7eb;
1213 }
1214
1215 .yatra-payment-row:last-child {
1216 border-bottom: none;
1217 background: #111827;
1218 color: white;
1219 font-weight: 600;
1220 }
1221
1222 .yatra-discount-row span:last-child {
1223 color: #22c55e;
1224 }
1225
1226 /* Bank-transfer details (markup injected by Yatra Pro's Bank Transfer gateway
1227 into this page). The card reuses this page's .yatra-confirmation-card /
1228 .yatra-card-title classes, but its rows had no styling at all, so the values
1229 sat immediately after their label while every other row on the page is
1230 flex/space-between — the bank values were the only ones not flush right.
1231 Styling lives here because this template owns the confirmation page's CSS
1232 and Pro enqueues no stylesheet on this page. */
1233 .yatra-bank-info-grid {
1234 border: 1px solid #e5e7eb;
1235 border-radius: 8px;
1236 overflow: hidden;
1237 }
1238
1239 .yatra-bank-info-item {
1240 display: flex;
1241 justify-content: space-between;
1242 align-items: baseline;
1243 gap: 12px;
1244 padding: 12px 16px;
1245 border-bottom: 1px solid #e5e7eb;
1246 }
1247
1248 .yatra-bank-info-item:last-child {
1249 border-bottom: none;
1250 }
1251
1252 .yatra-bank-label {
1253 color: #6b7280;
1254 flex-shrink: 0;
1255 }
1256
1257 .yatra-bank-value {
1258 text-align: right;
1259 word-break: break-word;
1260 }
1261
1262 .yatra-payment-method {
1263 margin-top: 16px;
1264 padding: 12px;
1265 background: white;
1266 border-radius: 8px;
1267 display: flex;
1268 justify-content: space-between;
1269 }
1270
1271 .yatra-pm-label {
1272 color: #6b7280;
1273 }
1274
1275 .yatra-pm-value {
1276 font-weight: 600;
1277 color: #111827;
1278 }
1279
1280 .yatra-contact-info p {
1281 margin: 0 0 8px;
1282 }
1283
1284 .yatra-whats-next {
1285 background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
1286 border-color: #bbf7d0;
1287 }
1288
1289 .yatra-next-steps {
1290 display: flex;
1291 flex-direction: column;
1292 gap: 20px;
1293 }
1294
1295 .yatra-step {
1296 display: flex;
1297 gap: 16px;
1298 }
1299
1300 .yatra-step-number {
1301 width: 32px;
1302 height: 32px;
1303 display: flex;
1304 align-items: center;
1305 justify-content: center;
1306 background: #22c55e;
1307 color: white;
1308 border-radius: 50%;
1309 font-weight: 600;
1310 flex-shrink: 0;
1311 }
1312
1313 .yatra-step-content h4 {
1314 margin: 0 0 4px;
1315 font-size: 16px;
1316 color: #111827;
1317 }
1318
1319 .yatra-step-content p {
1320 margin: 0;
1321 font-size: 14px;
1322 color: #6b7280;
1323 }
1324
1325 .yatra-confirmation-actions {
1326 display: flex;
1327 gap: 16px;
1328 justify-content: center;
1329 margin-top: 32px;
1330 }
1331
1332 .yatra-btn {
1333 display: inline-flex;
1334 align-items: center;
1335 gap: 8px;
1336 padding: 14px 28px;
1337 border-radius: 8px;
1338 font-size: 15px;
1339 font-weight: 600;
1340 text-decoration: none;
1341 cursor: pointer;
1342 transition: all 0.2s;
1343 border: none;
1344 }
1345
1346 .yatra-btn svg {
1347 width: 18px;
1348 height: 18px;
1349 }
1350
1351 .yatra-btn-secondary {
1352 background: #3b82f6;
1353 color: white;
1354 }
1355
1356 .yatra-btn-secondary:hover {
1357 background: #2563eb;
1358 }
1359
1360 .yatra-btn-outline {
1361 background: white;
1362 color: #374151;
1363 border: 2px solid #e5e7eb;
1364 }
1365
1366 .yatra-btn-outline:hover {
1367 border-color: #3b82f6;
1368 color: #3b82f6;
1369 }
1370
1371 /* =====================================================================
1372 Print Styles — produce a clean, single-page-friendly receipt.
1373 Triggered by the print button (adds .yatra-printing-confirmation
1374 to <body> + clones the confirmation card into .yatra-print-root).
1375 ===================================================================== */
1376 @media print {
1377 @page {
1378 size: A4;
1379 margin: 9mm 10mm;
1380 }
1381
1382 /* Force browsers to print our colors / borders */
1383 body.yatra-printing-confirmation,
1384 body.yatra-printing-confirmation * {
1385 -webkit-print-color-adjust: exact !important;
1386 print-color-adjust: exact !important;
1387 color-adjust: exact !important;
1388 }
1389
1390 /* Reset body, kill animations & transitions */
1391 body.yatra-printing-confirmation {
1392 background: #fff !important;
1393 color: #111827 !important;
1394 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
1395 Helvetica, Arial, sans-serif !important;
1396 font-size: 10pt !important;
1397 line-height: 1.45 !important;
1398 }
1399 body.yatra-printing-confirmation *,
1400 body.yatra-printing-confirmation *::before,
1401 body.yatra-printing-confirmation *::after {
1402 animation: none !important;
1403 transition: none !important;
1404 box-shadow: none !important;
1405 text-shadow: none !important;
1406 }
1407
1408 /* Hide everything except our cloned print root */
1409 body.yatra-printing-confirmation > *:not(.yatra-print-root) {
1410 display: none !important;
1411 }
1412 body.yatra-printing-confirmation .yatra-print-root,
1413 body.yatra-printing-confirmation .yatra-print-root * {
1414 visibility: visible;
1415 }
1416 body.yatra-printing-confirmation .yatra-print-root {
1417 position: static !important;
1418 left: auto;
1419 top: auto;
1420 width: 100%;
1421 margin: 0;
1422 padding: 0;
1423 }
1424
1425 /* Wrappers — remove screen padding/widths */
1426 body.yatra-printing-confirmation .yatra-confirmation-wrapper,
1427 body.yatra-printing-confirmation .yatra-confirmation-container {
1428 max-width: none !important;
1429 margin: 0 !important;
1430 padding: 0 !important;
1431 }
1432
1433 /* Hide things that don't belong on paper */
1434 body.yatra-printing-confirmation .yatra-confirmation-actions,
1435 body.yatra-printing-confirmation .yatra-no-print,
1436 body.yatra-printing-confirmation .yatra-whats-next,
1437 body.yatra-printing-confirmation .yatra-trip-rating {
1438 display: none !important;
1439 }
1440
1441 /* Confirmation header — compact, two-column with status icon left & ref right */
1442 body.yatra-printing-confirmation .yatra-confirmation-header {
1443 display: flex !important;
1444 align-items: center !important;
1445 justify-content: space-between !important;
1446 gap: 16pt !important;
1447 text-align: left !important;
1448 margin: 0 0 8pt !important;
1449 padding: 0 0 6pt !important;
1450 border-bottom: 1pt solid #111827 !important;
1451 }
1452 body.yatra-printing-confirmation .yatra-confirmation-icon {
1453 width: 28pt !important;
1454 height: 28pt !important;
1455 margin: 0 !important;
1456 background: #16a34a !important;
1457 flex-shrink: 0 !important;
1458 }
1459 body.yatra-printing-confirmation .yatra-confirmation-icon svg {
1460 width: 16pt !important;
1461 height: 16pt !important;
1462 }
1463 body.yatra-printing-confirmation .yatra-confirmation-title {
1464 font-size: 14pt !important;
1465 font-weight: 700 !important;
1466 margin: 0 !important;
1467 flex: 1 !important;
1468 color: #111827 !important;
1469 }
1470 body.yatra-printing-confirmation .yatra-confirmation-subtitle {
1471 display: none !important;
1472 }
1473 body.yatra-printing-confirmation .yatra-confirmation-reference {
1474 display: inline-flex !important;
1475 flex-direction: column !important;
1476 align-items: flex-end !important;
1477 gap: 2pt !important;
1478 background: transparent !important;
1479 padding: 0 !important;
1480 border: none !important;
1481 border-radius: 0 !important;
1482 }
1483 body.yatra-printing-confirmation .yatra-ref-label {
1484 font-size: 8pt !important;
1485 text-transform: uppercase !important;
1486 letter-spacing: 0.4pt !important;
1487 color: #6b7280 !important;
1488 }
1489 body.yatra-printing-confirmation .yatra-ref-code {
1490 font-size: 11pt !important;
1491 font-weight: 700 !important;
1492 color: #111827 !important;
1493 letter-spacing: 0.6pt !important;
1494 }
1495
1496 /* Cards — flat, thin border, never split across pages */
1497 body.yatra-printing-confirmation .yatra-confirmation-card {
1498 background: #fff !important;
1499 border: 0.75pt solid #d1d5db !important;
1500 border-radius: 3pt !important;
1501 padding: 8pt 10pt !important;
1502 margin: 0 0 6pt !important;
1503 page-break-inside: avoid !important;
1504 break-inside: avoid !important;
1505 }
1506 body.yatra-printing-confirmation .yatra-trip-summary-card {
1507 background: #f9fafb !important;
1508 border-color: #d1d5db !important;
1509 }
1510 body.yatra-printing-confirmation .yatra-card-title {
1511 font-size: 10.5pt !important;
1512 font-weight: 700 !important;
1513 gap: 6pt !important;
1514 margin: 0 0 8pt !important;
1515 padding: 0 0 5pt !important;
1516 border-bottom: 0.5pt solid #e5e7eb !important;
1517 color: #111827 !important;
1518 }
1519 body.yatra-printing-confirmation .yatra-card-title svg {
1520 width: 12pt !important;
1521 height: 12pt !important;
1522 color: #111827 !important;
1523 }
1524
1525 /* Trip summary — small image, tight spacing */
1526 body.yatra-printing-confirmation .yatra-trip-summary {
1527 gap: 10pt !important;
1528 align-items: flex-start !important;
1529 }
1530 /* Images often render as empty placeholders in print preview; hide for a cleaner receipt. */
1531 body.yatra-printing-confirmation .yatra-trip-image {
1532 display: none !important;
1533 }
1534 body.yatra-printing-confirmation .yatra-trip-name {
1535 font-size: 12pt !important;
1536 font-weight: 700 !important;
1537 margin: 0 0 4pt !important;
1538 color: #111827 !important;
1539 }
1540 body.yatra-printing-confirmation .yatra-trip-meta {
1541 font-size: 9pt !important;
1542 gap: 10pt !important;
1543 margin-bottom: 4pt !important;
1544 color: #374151 !important;
1545 }
1546 body.yatra-printing-confirmation .yatra-trip-meta svg,
1547 body.yatra-printing-confirmation .yatra-trip-location svg {
1548 width: 9pt !important;
1549 height: 9pt !important;
1550 }
1551 body.yatra-printing-confirmation .yatra-trip-location {
1552 font-size: 9pt !important;
1553 margin: 0 0 4pt !important;
1554 color: #374151 !important;
1555 }
1556
1557 /* Tags — outline pills, no fills */
1558 body.yatra-printing-confirmation .yatra-trip-tags {
1559 font-size: 9pt !important;
1560 margin-top: 4pt !important;
1561 }
1562 body.yatra-printing-confirmation .yatra-tag-label {
1563 font-weight: 700 !important;
1564 color: #374151 !important;
1565 margin-right: 4pt !important;
1566 }
1567 body.yatra-printing-confirmation .yatra-tag-item {
1568 display: inline-block !important;
1569 background: #fff !important;
1570 border: 0.5pt solid #d1d5db !important;
1571 padding: 1pt 5pt !important;
1572 border-radius: 2pt !important;
1573 font-size: 8.5pt !important;
1574 color: #374151 !important;
1575 margin: 1pt 2pt 1pt 0 !important;
1576 }
1577
1578 /* Two-column grid stays two columns on paper */
1579 body.yatra-printing-confirmation .yatra-confirmation-grid {
1580 display: grid !important;
1581 grid-template-columns: 1.15fr 0.85fr !important;
1582 gap: 6pt !important;
1583 align-items: start !important;
1584 }
1585 body.yatra-printing-confirmation .yatra-confirmation-column {
1586 min-width: 0 !important;
1587 }
1588
1589 /* Booking info grid */
1590 body.yatra-printing-confirmation .yatra-info-grid {
1591 display: grid !important;
1592 grid-template-columns: 1fr 1fr !important;
1593 gap: 5pt 9pt !important;
1594 }
1595 body.yatra-printing-confirmation .yatra-info-item {
1596 display: flex !important;
1597 flex-direction: column !important;
1598 gap: 1pt !important;
1599 }
1600 body.yatra-printing-confirmation .yatra-info-label {
1601 font-size: 7.5pt !important;
1602 text-transform: uppercase !important;
1603 letter-spacing: 0.3pt !important;
1604 color: #6b7280 !important;
1605 }
1606 body.yatra-printing-confirmation .yatra-info-value {
1607 font-size: 10pt !important;
1608 font-weight: 600 !important;
1609 color: #111827 !important;
1610 }
1611 body.yatra-printing-confirmation .yatra-status-badge {
1612 display: inline-block !important;
1613 padding: 1pt 6pt !important;
1614 border: 0.75pt solid currentColor !important;
1615 border-radius: 2pt !important;
1616 font-size: 8.5pt !important;
1617 font-weight: 700 !important;
1618 }
1619
1620 /* Travelers */
1621 body.yatra-printing-confirmation .yatra-travelers-list {
1622 margin: 0 !important;
1623 }
1624 body.yatra-printing-confirmation .yatra-traveler-item {
1625 display: flex !important;
1626 align-items: center !important;
1627 gap: 8pt !important;
1628 padding: 4pt 0 !important;
1629 border-bottom: 0.5pt solid #e5e7eb !important;
1630 }
1631 body.yatra-printing-confirmation .yatra-traveler-item:last-child {
1632 border-bottom: none !important;
1633 }
1634 body.yatra-printing-confirmation .yatra-traveler-number {
1635 display: inline-flex !important;
1636 align-items: center !important;
1637 justify-content: center !important;
1638 width: 16pt !important;
1639 height: 16pt !important;
1640 background: #111827 !important;
1641 color: #fff !important;
1642 border-radius: 50% !important;
1643 font-size: 8.5pt !important;
1644 font-weight: 700 !important;
1645 flex-shrink: 0 !important;
1646 }
1647 body.yatra-printing-confirmation .yatra-traveler-name {
1648 font-size: 10pt !important;
1649 font-weight: 600 !important;
1650 color: #111827 !important;
1651 }
1652 body.yatra-printing-confirmation .yatra-traveler-dob {
1653 font-size: 8.5pt !important;
1654 color: #6b7280 !important;
1655 }
1656
1657 /* Payment summary rows */
1658 body.yatra-printing-confirmation .yatra-payment-rows {
1659 margin: 0 !important;
1660 }
1661 body.yatra-printing-confirmation .yatra-payment-row,
1662 body.yatra-printing-confirmation .yatra-bank-info-item {
1663 display: flex !important;
1664 justify-content: space-between !important;
1665 align-items: baseline !important;
1666 gap: 12pt !important;
1667 font-size: 9.25pt !important;
1668 padding: 1.5pt 0 !important;
1669 color: #111827 !important;
1670 }
1671 body.yatra-printing-confirmation .yatra-due-row {
1672 background: #fef3c7 !important;
1673 padding: 4pt 6pt !important;
1674 margin-top: 5pt !important;
1675 border-radius: 2pt !important;
1676 border: 0.5pt solid #fbbf24 !important;
1677 }
1678 body.yatra-printing-confirmation .yatra-payment-method {
1679 margin-top: 6pt !important;
1680 padding-top: 5pt !important;
1681 font-size: 9pt !important;
1682 border-top: 0.5pt solid #e5e7eb !important;
1683 color: #374151 !important;
1684 }
1685
1686 /* Contact info */
1687 body.yatra-printing-confirmation .yatra-contact-info {
1688 margin: 0 !important;
1689 }
1690 body.yatra-printing-confirmation .yatra-contact-item {
1691 font-size: 9.5pt !important;
1692 margin: 0 0 3pt !important;
1693 color: #111827 !important;
1694 }
1695 body.yatra-printing-confirmation .yatra-contact-item strong {
1696 color: #6b7280 !important;
1697 font-weight: 600 !important;
1698 margin-right: 4pt !important;
1699 }
1700
1701 /* Links — print as plain text, no underline (URL is still in browser footer) */
1702 body.yatra-printing-confirmation a,
1703 body.yatra-printing-confirmation a:visited {
1704 color: inherit !important;
1705 text-decoration: none !important;
1706 }
1707
1708 /* Avoid orphan headings */
1709 body.yatra-printing-confirmation h1,
1710 body.yatra-printing-confirmation h2,
1711 body.yatra-printing-confirmation h3,
1712 body.yatra-printing-confirmation h4 {
1713 page-break-after: avoid !important;
1714 break-after: avoid !important;
1715 }
1716 }
1717 </style>
1718
1719 <script>
1720 (function () {
1721 document.addEventListener('click', function (e) {
1722 var btn = e.target.closest('[data-yatra-print="confirmation"]');
1723 if (!btn) {
1724 return;
1725 }
1726 e.preventDefault();
1727
1728 var card = document.querySelector('.yatra-confirmation-container');
1729 if (!card) {
1730 window.print();
1731 return;
1732 }
1733
1734 // Wrap (or reuse) a print-only root so the @media print rules can target a single
1735 // direct child of <body>. Reused on the account page if the same data attribute
1736 // and CSS rules are added there.
1737 var root = document.querySelector('.yatra-print-root');
1738 var addedWrapper = false;
1739 if (!root) {
1740 root = document.createElement('div');
1741 root.className = 'yatra-print-root';
1742 document.body.appendChild(root);
1743 addedWrapper = true;
1744 }
1745 var clone = card.cloneNode(true);
1746 // Drop the action buttons from the clone so they don't appear on paper.
1747 clone.querySelectorAll('.yatra-confirmation-actions').forEach(function (n) { n.remove(); });
1748 root.innerHTML = '';
1749 root.appendChild(clone);
1750
1751 document.body.classList.add('yatra-printing-confirmation');
1752
1753 var cleanup = function () {
1754 document.body.classList.remove('yatra-printing-confirmation');
1755 if (addedWrapper && root && root.parentNode) {
1756 root.parentNode.removeChild(root);
1757 } else if (root) {
1758 root.innerHTML = '';
1759 }
1760 window.removeEventListener('afterprint', cleanup);
1761 };
1762
1763 window.addEventListener('afterprint', cleanup);
1764 // Safety net for browsers that don't fire afterprint reliably.
1765 window.setTimeout(function () {
1766 if (document.body.classList.contains('yatra-printing-confirmation')) {
1767 cleanup();
1768 }
1769 }, 5000);
1770
1771 window.print();
1772 });
1773 })();
1774 </script>
1775
1776 <?php yatra_get_footer(); ?>
1777
1778