PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.5
Yatra – Travel Booking & Tour Operator Software v3.0.5
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.5, at templates/booking-confirmation.php

1,632 lines 68.3 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 $filled_stars = floor($booking->trip_average_rating);
217 $has_half = ($booking->trip_average_rating - $filled_stars) >= 0.5;
218 for ($i = 1; $i <= 5; $i++) :
219 $class = $i <= $filled_stars ? 'yatra-star-filled' : ($has_half && $i === $filled_stars + 1 ? 'yatra-star-half' : '');
220 ?>
221 <span class="yatra-star <?php echo esc_attr($class); ?>">
222 <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>
223 </span>
224 <?php endfor; ?>
225 </div>
226 <div class="yatra-rating-meta">
227 <strong><?php echo esc_html(number_format($booking->trip_average_rating, 1)); ?></strong>
228 <span>
229 <?php
230 printf(
231 esc_html(
232 /* translators: %d: number of reviews. */
233 _n('%d Review', '%d Reviews', (int) $booking->trip_review_count, 'yatra')
234 ),
235 (int) $booking->trip_review_count
236 );
237 ?>
238 </span>
239 </div>
240 </div>
241 <?php endif; ?>
242
243 <div class="yatra-trip-meta">
244 <?php if (!empty($booking->duration_days)) : ?>
245 <span class="yatra-meta-item">
246 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
247 <circle cx="12" cy="12" r="10"></circle>
248 <polyline points="12 6 12 12 16 14"></polyline>
249 </svg>
250 <?php
251 $days = (int) ($booking->duration_days ?? 0);
252 $nights = (int) ($booking->duration_nights ?? 0);
253
254 if ($days > 0 && $nights > 0) {
255 printf(
256 /* translators: 1: number of days, 2: number of nights. */
257 esc_html__('%1$d Days / %2$d Nights', 'yatra'),
258 $days,
259 $nights
260 );
261 } elseif ($days > 0) {
262 printf(
263 esc_html(
264 /* translators: %d: number of days. */
265 _n('%d Day', '%d Days', $days, 'yatra')
266 ),
267 $days
268 );
269 } elseif ($nights > 0) {
270 printf(
271 esc_html(
272 /* translators: %d: number of nights. */
273 _n('%d Night', '%d Nights', $nights, 'yatra')
274 ),
275 $nights
276 );
277 }
278 ?>
279 </span>
280 <?php endif; ?>
281
282 <?php if (!empty($booking->difficulty_level)) : ?>
283 <span class="yatra-meta-item">
284 <?php
285 $difficulty = \Yatra\Models\Trip::resolveDifficultyDisplay(
286 (string) $booking->difficulty_level
287 );
288
289 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
290 echo yatra_stored_picker_icon_markup(
291 $difficulty['icon_picker'] ?? null,
292 '',
293 'yatra-icon-sm'
294 );
295
296 echo esc_html($difficulty['level'] ?? (string) $booking->difficulty_level);
297 ?>
298 </span>
299 <?php endif; ?>
300 </div>
301
302 <?php if (!empty($booking->starting_location)) : ?>
303 <p class="yatra-trip-location">
304 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
305 <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
306 <circle cx="12" cy="10" r="3"></circle>
307 </svg>
308 <?php echo esc_html($booking->starting_location); ?>
309 <?php if (!empty($booking->ending_location) && $booking->ending_location !== $booking->starting_location) : ?>
310 → <?php echo esc_html($booking->ending_location); ?>
311 <?php endif; ?>
312 </p>
313 <?php endif; ?>
314
315 <?php if (!empty($booking->trip_destinations_list)) : ?>
316 <div class="yatra-trip-tags">
317 <span class="yatra-tag-label"><?php esc_html_e('Destinations:', 'yatra'); ?></span>
318 <div class="yatra-tag-group">
319 <?php foreach ($booking->trip_destinations_list as $destination) : ?>
320 <span class="yatra-tag-item"><?php echo esc_html($destination); ?></span>
321 <?php endforeach; ?>
322 </div>
323 </div>
324 <?php endif; ?>
325
326 <?php if (!empty($booking->trip_activities_list)) : ?>
327 <div class="yatra-trip-tags">
328 <span class="yatra-tag-label"><?php esc_html_e('Activities:', 'yatra'); ?></span>
329 <div class="yatra-tag-group">
330 <?php foreach ($booking->trip_activities_list as $activity) : ?>
331 <span class="yatra-tag-item"><?php echo esc_html($activity); ?></span>
332 <?php endforeach; ?>
333 </div>
334 </div>
335 <?php endif; ?>
336
337 <?php if (!empty($booking->trip_categories_list)) : ?>
338 <div class="yatra-trip-tags">
339 <span class="yatra-tag-label"><?php esc_html_e('Trip Type:', 'yatra'); ?></span>
340 <div class="yatra-tag-group">
341 <?php foreach ($booking->trip_categories_list as $category) : ?>
342 <span class="yatra-tag-item"><?php echo esc_html($category); ?></span>
343 <?php endforeach; ?>
344 </div>
345 </div>
346 <?php endif; ?>
347
348 </div>
349 </div>
350 </div>
351
352 <!-- Booking Details -->
353 <div class="yatra-confirmation-grid">
354 <!-- Left Column -->
355 <div class="yatra-confirmation-column">
356 <!-- Booking Info Card -->
357 <div class="yatra-confirmation-card">
358 <h3 class="yatra-card-title">
359 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
360 <rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect>
361 <line x1="16" y1="2" x2="16" y2="6"></line>
362 <line x1="8" y1="2" x2="8" y2="6"></line>
363 <line x1="3" y1="10" x2="21" y2="10"></line>
364 </svg>
365 <?php esc_html_e('Booking Information', 'yatra'); ?>
366 </h3>
367
368 <div class="yatra-info-grid">
369 <div class="yatra-info-item">
370 <span class="yatra-info-label"><?php esc_html_e('Status', 'yatra'); ?></span>
371 <span class="yatra-info-value">
372 <span class="yatra-status-badge" style="background: <?php echo esc_attr($status_style['bg']); ?>; color: <?php echo esc_attr($status_style['text']); ?>;">
373 <?php echo esc_html($status_style['label']); ?>
374 </span>
375 </span>
376 </div>
377 <div class="yatra-info-item">
378 <span class="yatra-info-label"><?php esc_html_e('Travel Date', 'yatra'); ?></span>
379 <span class="yatra-info-value"><?php echo esc_html($travel_date_formatted); ?></span>
380 </div>
381 <div class="yatra-info-item">
382 <span class="yatra-info-label"><?php esc_html_e('Number of Travelers', 'yatra'); ?></span>
383 <span class="yatra-info-value"><?php echo esc_html($booking->travelers_count); ?></span>
384 </div>
385 <div class="yatra-info-item">
386 <span class="yatra-info-label"><?php esc_html_e('Booked On', 'yatra'); ?></span>
387 <span class="yatra-info-value"><?php echo esc_html($booking_date_formatted); ?></span>
388 </div>
389 </div>
390 </div>
391
392 <!-- Travelers Card -->
393 <?php if (!empty($booking->travelers)) : ?>
394 <div class="yatra-confirmation-card">
395 <h3 class="yatra-card-title">
396 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
397 <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
398 <circle cx="9" cy="7" r="4"></circle>
399 <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
400 <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
401 </svg>
402 <?php esc_html_e('Travelers', 'yatra'); ?>
403 </h3>
404
405 <div class="yatra-travelers-list">
406 <?php foreach ($booking->travelers as $index => $traveler) :
407 $traveler_name = trim(($traveler['first_name'] ?? '') . ' ' . ($traveler['last_name'] ?? ''));
408 ?>
409 <div class="yatra-traveler-item">
410 <span class="yatra-traveler-number"><?php echo esc_html($index + 1); ?></span>
411 <div class="yatra-traveler-details">
412 <span class="yatra-traveler-name">
413 <?php echo esc_html($traveler_name ?: __('Traveler', 'yatra') . ' ' . ($index + 1)); ?>
414 </span>
415 <?php if (!empty($traveler['date_of_birth'])) : ?>
416 <span class="yatra-traveler-dob">
417 <?php echo esc_html(\Yatra\Helpers\FormatHelper::formatDate((string) $traveler['date_of_birth'])); ?>
418 </span>
419 <?php endif; ?>
420 </div>
421 </div>
422 <?php endforeach; ?>
423 </div>
424 </div>
425 <?php endif; ?>
426
427 <?php
428 // Allow gateways to inject cards (e.g., Bank Transfer instructions)
429 do_action('yatra_booking_confirmation_after_details', $booking);
430 ?>
431 </div>
432
433 <!-- Right Column -->
434 <div class="yatra-confirmation-column">
435 <!-- Payment Summary Card -->
436 <div class="yatra-confirmation-card yatra-payment-card">
437 <h3 class="yatra-card-title">
438 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
439 <rect x="1" y="4" width="22" height="16" rx="2" ry="2"></rect>
440 <line x1="1" y1="10" x2="23" y2="10"></line>
441 </svg>
442 <?php esc_html_e('Payment Summary', 'yatra'); ?>
443 </h3>
444
445 <div class="yatra-payment-rows">
446 <?php
447 // ── Raw figures from DB ───────────────────────────────────
448 $db_subtotal = (float) ($booking->subtotal ?? $booking->total_amount);
449 $discount_amount = (float) ($booking->discount_amount ?? 0);
450 $itinerary_costs_total = (float) ($booking->itinerary_costs_total ?? 0);
451 $tax_amount = (float) ($booking->tax_amount ?? 0);
452 $tax_inclusive = !empty($booking->tax_inclusive);
453 $total_amount = (float) $booking->total_amount;
454 $amount_paid = (float) ($booking->amount_paid ?? 0);
455 $amount_due = (float) ($booking->amount_due ?? 0);
456
457 // ── Tax breakdown (built first so it can gate later rows) ─
458 $tax_breakdown = [];
459 if (!empty($booking->tax_details)) {
460 $taxes = json_decode($booking->tax_details, true) ?: [];
461 foreach ($taxes as $tax) {
462 $tax_breakdown[] = [
463 'name' => $tax['name'] ?? __('Tax', 'yatra'),
464 'rate' => (float) ($tax['rate'] ?? 0),
465 'amount' => (float) ($tax['amount'] ?? 0),
466 ];
467 }
468 } elseif ($tax_amount > 0) {
469 $tax_breakdown[] = [
470 'name' => __('Tax', 'yatra'),
471 'rate' => (float) ($booking->tax_rate ?? 0),
472 'amount' => $tax_amount,
473 ];
474 }
475
476 // ── Itinerary costs ───────────────────────────────────────
477 $itinerary_costs = [];
478 if (!empty($booking->itinerary_costs)) {
479 $itinerary_costs = json_decode($booking->itinerary_costs, true) ?: [];
480 }
481
482 // ── Additional services ───────────────────────────────────
483 $raw_services = apply_filters('yatra_booking_get_services', [], (int) ($booking->id ?? 0));
484 $selected_services = [];
485 if (!empty($raw_services) && is_array($raw_services)) {
486 foreach ($raw_services as $s) {
487 $arr = is_array($s) ? $s : (array) $s;
488 if (!isset($arr['selected']) || !empty($arr['selected'])) {
489 $selected_services[] = $arr;
490 }
491 }
492 }
493 $services_total = 0.0;
494 foreach ($selected_services as $s) {
495 $services_total += (float) ($s['total_price'] ?? $s['calculated_price'] ?? $s['total_cost'] ?? $s['amount'] ?? $s['unit_price'] ?? $s['price'] ?? 0);
496 }
497
498 // ── Derived amounts ───────────────────────────────────────
499 // base_trip_cost: the trip price without services (services are embedded in db_subtotal by Pro)
500 $base_trip_cost = $db_subtotal - $services_total;
501 // taxable_amount: what tax is calculated on
502 $taxable_amount = max(0.0, $db_subtotal - $discount_amount) + $itinerary_costs_total;
503
504 $has_services = !empty($selected_services);
505 $has_discount = $discount_amount > 0;
506 $has_itinerary = !empty($itinerary_costs) && $itinerary_costs_total > 0;
507 $has_tax = !empty($tax_breakdown);
508 $show_taxable_row = $has_tax && ($has_discount || $has_itinerary);
509 ?>
510
511 <!-- Trip Base Price (always the first line) -->
512 <div class="yatra-payment-row">
513 <span>
514 <?php esc_html_e('Trip Base Price', 'yatra'); ?>
515 <?php if ($tax_inclusive): ?>
516 <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;">
517 <?php esc_html_e('Tax Incl.', 'yatra'); ?>
518 </span>
519 <?php endif; ?>
520 </span>
521 <span><?php echo esc_html(yatra_format_price($base_trip_cost, $booking->currency)); ?></span>
522 </div>
523
524 <?php if ($has_services): ?>
525 <!-- Additional Services section header -->
526 <div class="yatra-payment-row" style="margin-top: 4px;">
527 <span style="font-size: 0.75em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280;">
528 + <?php esc_html_e('Additional Services', 'yatra'); ?>
529 </span>
530 <span></span>
531 </div>
532 <!-- Service line items -->
533 <?php foreach ($selected_services as $svc): ?>
534 <?php
535 $svc_name = $svc['service_name'] ?? $svc['name'] ?? $svc['title'] ?? $svc['label'] ?? __('Service', 'yatra');
536 $svc_amount = (float) ($svc['total_price'] ?? $svc['calculated_price'] ?? $svc['total_cost'] ?? $svc['amount'] ?? $svc['unit_price'] ?? $svc['price'] ?? 0);
537 ?>
538 <div class="yatra-payment-row" style="margin-left: 16px;">
539 <span><?php echo esc_html($svc_name); ?></span>
540 <span><?php echo esc_html(yatra_format_price($svc_amount, $booking->currency, false)); ?></span>
541 </div>
542 <?php endforeach; ?>
543 <!-- Gross Total = Trip Base Price + Services -->
544 <div class="yatra-payment-row" style="border-top: 1px solid #e5e7eb; margin-top: 6px; padding-top: 6px;">
545 <span><strong><?php esc_html_e('Gross Total', 'yatra'); ?></strong></span>
546 <span><strong><?php echo esc_html(yatra_format_price($db_subtotal, $booking->currency)); ?></strong></span>
547 </div>
548 <?php endif; ?>
549
550 <?php if ($has_discount): ?>
551 <!-- Discount -->
552 <div class="yatra-payment-row">
553 <span><?php esc_html_e('Discount', 'yatra'); ?></span>
554 <span style="color: #059669; font-weight: 500;">-<?php echo esc_html(yatra_format_price($discount_amount, $booking->currency)); ?></span>
555 </div>
556 <?php endif; ?>
557
558 <?php if ($has_itinerary): ?>
559 <!-- Itinerary costs header -->
560 <div class="yatra-payment-row" style="margin-top: 4px;">
561 <span><strong><?php esc_html_e('Itinerary Costs', 'yatra'); ?></strong></span>
562 <span></span>
563 </div>
564 <?php foreach ($itinerary_costs as $cost): ?>
565 <div class="yatra-payment-row" style="margin-left: 20px;">
566 <span>
567 <?php echo esc_html($cost['name']); ?>
568 <?php if (!empty($cost['price_per'])): ?>
569 <small style="opacity: 0.65;">
570 <?php
571 if ($cost['price_per'] === 'person') {
572 esc_html_e('(per person)', 'yatra');
573 } elseif ($cost['price_per'] === 'group') {
574 esc_html_e('(per booking)', 'yatra');
575 } else {
576 esc_html_e('(flat rate)', 'yatra');
577 }
578 ?>
579 </small>
580 <?php endif; ?>
581 </span>
582 <span><?php echo esc_html(yatra_format_price($cost['total_cost'] ?? $cost['price'], $booking->currency)); ?></span>
583 </div>
584 <?php endforeach; ?>
585 <?php endif; ?>
586
587 <?php if (!$tax_inclusive && $show_taxable_row): ?>
588 <!-- Taxable Amount (only for exclusive tax when there are deductions above it) -->
589 <div class="yatra-payment-row" style="border-top: 1px dashed #e5e7eb; margin-top: 8px; padding-top: 8px;">
590 <span><strong><?php esc_html_e('Taxable Amount', 'yatra'); ?></strong></span>
591 <span><strong><?php echo esc_html(yatra_format_price($taxable_amount, $booking->currency)); ?></strong></span>
592 </div>
593 <?php endif; ?>
594
595 <?php if ($has_tax && !$tax_inclusive): ?>
596 <!-- Exclusive tax: shown as an addition before Net Amount -->
597 <div class="yatra-payment-row" style="margin-top: 4px;">
598 <span style="font-size: 0.75em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: #6b7280;">
599 + <?php esc_html_e('Tax', 'yatra'); ?>
600 </span>
601 <span></span>
602 </div>
603 <?php foreach ($tax_breakdown as $tax): ?>
604 <div class="yatra-payment-row" style="margin-left: 16px;">
605 <span>
606 <?php echo esc_html($tax['name']); ?>
607 <?php if ($tax['rate'] > 0): ?>
608 (<?php echo esc_html($tax['rate']); ?>%)
609 <?php endif; ?>
610 </span>
611 <span>+<?php echo esc_html(yatra_format_price($tax['amount'], $booking->currency)); ?></span>
612 </div>
613 <?php endforeach; ?>
614 <?php endif; ?>
615
616 <!-- Net Amount -->
617 <div class="yatra-payment-row" style="border-top: 2px solid #111827; margin-top: 10px; padding-top: 10px;">
618 <span style="font-size: 1.05em;"><strong><?php esc_html_e('Net Amount', 'yatra'); ?></strong></span>
619 <span style="font-size: 1.05em;"><strong><?php echo esc_html(yatra_format_price($total_amount, $booking->currency)); ?></strong></span>
620 </div>
621
622 <?php if ($has_tax && $tax_inclusive): ?>
623 <!-- Inclusive tax: shown as an informational footnote after Net Amount -->
624 <?php foreach ($tax_breakdown as $tax): ?>
625 <div class="yatra-payment-row" style="margin-top: 4px; opacity: 0.7;">
626 <span style="font-size: 0.85em; font-style: italic;">
627 <?php
628 printf(
629 /* translators: %1$s = tax name, %2$s = rate, %3$s = amount */
630 esc_html__('Incl. %1$s%2$s: %3$s', 'yatra'),
631 esc_html($tax['name']),
632 $tax['rate'] > 0 ? ' (' . esc_html($tax['rate']) . '%)' : '',
633 esc_html(yatra_format_price($tax['amount'], $booking->currency))
634 );
635 ?>
636 </span>
637 <span></span>
638 </div>
639 <?php endforeach; ?>
640 <?php endif; ?>
641
642 <?php if ($amount_paid > 0): ?>
643 <div class="yatra-payment-row" style="margin-top: 6px;">
644 <span><?php esc_html_e('Amount Paid', 'yatra'); ?></span>
645 <span style="color: #059669;"><?php echo esc_html(yatra_format_price($amount_paid, $booking->currency)); ?></span>
646 </div>
647 <?php endif; ?>
648
649 <?php if ($amount_due > 0): ?>
650 <div class="yatra-payment-row yatra-due-row">
651 <span><strong><?php esc_html_e('Due Now', 'yatra'); ?></strong></span>
652 <span><strong><?php echo esc_html(yatra_format_price($amount_due, $booking->currency)); ?></strong></span>
653 </div>
654 <?php endif; ?>
655 </div>
656
657 <div class="yatra-payment-method">
658 <span class="yatra-pm-label"><?php esc_html_e('Payment Method:', 'yatra'); ?></span>
659 <span class="yatra-pm-value"><?php echo esc_html(ucwords(str_replace('_', ' ', (string) $display_payment_gateway))); ?></span>
660 </div>
661 </div>
662
663 <!-- Contact Info Card -->
664 <div class="yatra-confirmation-card">
665 <h3 class="yatra-card-title">
666 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
667 <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>
668 <polyline points="22,6 12,13 2,6"></polyline>
669 </svg>
670 <?php esc_html_e('Contact Information', 'yatra'); ?>
671 </h3>
672
673 <div class="yatra-contact-info">
674 <?php
675 // Try to get contact data from multiple sources
676 $contact_data = [];
677 if (!empty($booking->contact_data)) {
678 $contact_data = json_decode($booking->contact_data, true) ?: [];
679 }
680
681 $contact_name = trim((
682 $contact_data['first_name'] ??
683 $booking->contact_first_name ??
684 ($booking->contact['first_name'] ?? '')
685 ) . ' ' . (
686 $contact_data['last_name'] ??
687 $booking->contact_last_name ??
688 ($booking->contact['last_name'] ?? '')
689 ));
690
691 $contact_email = $contact_data['email'] ?? $booking->contact_email ?? ($booking->contact['email'] ?? '');
692 $contact_phone = $contact_data['phone'] ?? $booking->contact_phone ?? ($booking->contact['phone'] ?? '');
693 ?>
694
695 <?php if ($contact_name) : ?>
696 <p class="yatra-contact-item">
697 <strong><?php esc_html_e('Name:', 'yatra'); ?></strong>
698 <?php echo esc_html($contact_name); ?>
699 </p>
700 <?php endif; ?>
701
702 <?php if ($contact_email) : ?>
703 <p class="yatra-contact-item">
704 <strong><?php esc_html_e('Email:', 'yatra'); ?></strong>
705 <?php echo esc_html($contact_email); ?>
706 </p>
707 <?php endif; ?>
708
709 <?php if ($contact_phone) : ?>
710 <p class="yatra-contact-item">
711 <strong><?php esc_html_e('Phone:', 'yatra'); ?></strong>
712 <?php echo esc_html($contact_phone); ?>
713 </p>
714 <?php endif; ?>
715
716 <?php if (!$contact_name && !$contact_email && !$contact_phone) : ?>
717 <p class="yatra-contact-item">
718 <em><?php esc_html_e('Contact information not available', 'yatra'); ?></em>
719 </p>
720 <?php endif; ?>
721 </div>
722 </div>
723 </div>
724 </div>
725
726 <!-- What's Next Section -->
727 <div class="yatra-confirmation-card yatra-whats-next">
728 <h3 class="yatra-card-title">
729 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
730 <circle cx="12" cy="12" r="10"></circle>
731 <polyline points="12 16 16 12 12 8"></polyline>
732 <line x1="8" y1="12" x2="16" y2="12"></line>
733 </svg>
734 <?php esc_html_e("What's Next?", 'yatra'); ?>
735 </h3>
736
737 <div class="yatra-next-steps">
738 <div class="yatra-step">
739 <span class="yatra-step-number">1</span>
740 <div class="yatra-step-content">
741 <h4><?php esc_html_e('Check Your Email', 'yatra'); ?></h4>
742 <p><?php esc_html_e('We\'ve sent a confirmation email with all the details to your registered email address.', 'yatra'); ?></p>
743 </div>
744 </div>
745
746 <div class="yatra-step">
747 <span class="yatra-step-number">2</span>
748 <div class="yatra-step-content">
749 <h4><?php esc_html_e('Detailed Itinerary', 'yatra'); ?></h4>
750 <p><?php esc_html_e('You\'ll receive a detailed itinerary and preparation guide within 24-48 hours.', 'yatra'); ?></p>
751 </div>
752 </div>
753
754 <div class="yatra-step">
755 <span class="yatra-step-number">3</span>
756 <div class="yatra-step-content">
757 <h4><?php esc_html_e('Prepare for Adventure', 'yatra'); ?></h4>
758 <p><?php esc_html_e('Ensure all travelers have valid ID or travel documents and any required visas for your destination.', 'yatra'); ?></p>
759 </div>
760 </div>
761 </div>
762 </div>
763
764 <!-- Action Buttons -->
765 <div class="yatra-confirmation-actions">
766 <a href="<?php echo esc_url(home_url('/')); ?>" class="yatra-btn yatra-btn-secondary">
767 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
768 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
769 <polyline points="9 22 9 12 15 12 15 22"></polyline>
770 </svg>
771 <?php esc_html_e('Return to Home', 'yatra'); ?>
772 </a>
773
774 <?php
775 // Get latest payment for this booking to enable invoice download.
776 // The invoice endpoint authorises via: admin → owner → signed invoice_token → guest booking_token.
777 // We always issue a signed invoice_token here so the link works for guests
778 // (no session required) AND for logged-in users who don't own the booking
779 // (e.g. site admins viewing the page) — without re-checking login on the client.
780 $paymentRepository = new \Yatra\Repositories\PaymentRepository();
781 $latestPayment = $paymentRepository->findLatestByBookingId((int) $booking->id);
782 if ($latestPayment && in_array($latestPayment->status, ['completed', 'paid'], true)) :
783 $invoiceToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken(
784 (int) $latestPayment->id,
785 (int) ($latestPayment->booking_id ?? $booking->id)
786 );
787 $invoiceUrl = add_query_arg(
788 [
789 'download' => '1',
790 'invoice_token' => $invoiceToken,
791 ],
792 rest_url('yatra/v1/payment/' . (int) $latestPayment->id . '/invoice')
793 );
794 ?>
795 <a href="<?php echo esc_url($invoiceUrl); ?>"
796 target="_blank"
797 rel="noopener"
798 class="yatra-btn yatra-btn-primary">
799 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
800 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
801 <polyline points="7 10 12 15 17 10"></polyline>
802 <line x1="12" y1="15" x2="12" y2="3"></line>
803 </svg>
804 <?php esc_html_e('Download Invoice', 'yatra'); ?>
805 </a>
806 <?php endif; ?>
807
808 <button type="button" data-yatra-print="confirmation" class="yatra-btn yatra-btn-outline">
809 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
810 <polyline points="6 9 6 2 18 2 18 9"></polyline>
811 <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>
812 <rect x="6" y="14" width="12" height="8"></rect>
813 </svg>
814 <?php esc_html_e('Print Confirmation', 'yatra'); ?>
815 </button>
816 </div>
817
818 </div>
819 </div>
820 </div>
821
822 <style>
823 /* Confirmation Page Styles */
824 .yatra-confirmation-wrapper {
825 max-width: 1300px;
826 margin: 0 auto;
827 padding: 40px 20px;
828 }
829
830 .yatra-confirmation-container {
831 max-width: 900px;
832 margin: 0 auto;
833 }
834
835 .yatra-confirmation-header {
836 text-align: center;
837 margin-bottom: 40px;
838 }
839
840 .yatra-confirmation-icon {
841 width: 100px;
842 height: 100px;
843 margin: 0 auto 24px;
844 background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
845 border-radius: 50%;
846 display: flex;
847 align-items: center;
848 justify-content: center;
849 animation: scaleIn 0.5s ease-out;
850 }
851
852 .yatra-confirmation-icon svg {
853 width: 50px;
854 height: 50px;
855 color: white;
856 }
857
858 @keyframes scaleIn {
859 0% { transform: scale(0); opacity: 0; }
860 50% { transform: scale(1.1); }
861 100% { transform: scale(1); opacity: 1; }
862 }
863
864 .yatra-confirmation-title {
865 font-size: 36px;
866 font-weight: 700;
867 color: #111827;
868 margin: 0 0 12px;
869 }
870
871 .yatra-confirmation-subtitle {
872 font-size: 18px;
873 color: #6b7280;
874 margin: 0 0 24px;
875 }
876
877 .yatra-confirmation-reference {
878 display: inline-flex;
879 align-items: center;
880 gap: 12px;
881 background: #f3f4f6;
882 padding: 12px 24px;
883 border-radius: 100px;
884 }
885
886 .yatra-ref-label {
887 color: #6b7280;
888 font-size: 14px;
889 }
890
891 .yatra-ref-code {
892 font-size: 18px;
893 font-weight: 700;
894 color: #111827;
895 font-family: monospace;
896 letter-spacing: 1px;
897 }
898
899 .yatra-confirmation-card {
900 background: #fff;
901 border: 1px solid #e5e7eb;
902 border-radius: 16px;
903 padding: 24px;
904 margin-bottom: 24px;
905 }
906
907 .yatra-card-title {
908 display: flex;
909 align-items: center;
910 gap: 12px;
911 font-size: 18px;
912 font-weight: 600;
913 color: #111827;
914 margin: 0 0 20px;
915 padding-bottom: 16px;
916 border-bottom: 1px solid #e5e7eb;
917 }
918
919 .yatra-card-title svg {
920 width: 22px;
921 height: 22px;
922 color: #3b82f6;
923 }
924
925 .yatra-trip-summary-card {
926 background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
927 border-color: #bfdbfe;
928 }
929
930 .yatra-trip-summary {
931 display: flex;
932 gap: 24px;
933 align-items: center;
934 }
935
936 .yatra-trip-image {
937 width: 120px;
938 height: 120px;
939 border-radius: 12px;
940 overflow: hidden;
941 flex-shrink: 0;
942 }
943
944 .yatra-trip-image img {
945 width: 100%;
946 height: 100%;
947 object-fit: cover;
948 }
949
950 .yatra-trip-name {
951 font-size: 22px;
952 font-weight: 700;
953 color: #111827;
954 margin: 0 0 12px;
955 }
956
957 .yatra-trip-meta {
958 display: flex;
959 gap: 20px;
960 flex-wrap: wrap;
961 margin-bottom: 8px;
962 }
963
964 .yatra-meta-item {
965 display: flex;
966 align-items: center;
967 gap: 6px;
968 font-size: 14px;
969 color: #4b5563;
970 }
971
972 .yatra-meta-item svg {
973 width: 16px;
974 height: 16px;
975 }
976
977 .yatra-trip-location {
978 display: flex;
979 align-items: center;
980 gap: 6px;
981 font-size: 14px;
982 color: #6b7280;
983 margin: 0;
984 }
985
986 .yatra-trip-location svg {
987 width: 16px;
988 height: 16px;
989 }
990
991 .yatra-confirmation-grid {
992 display: grid;
993 grid-template-columns: 1fr 1fr;
994 gap: 24px;
995 }
996
997 @media (max-width: 768px) {
998 .yatra-confirmation-grid {
999 grid-template-columns: 1fr;
1000 }
1001
1002 .yatra-trip-summary {
1003 flex-direction: column;
1004 text-align: center;
1005 }
1006
1007 .yatra-info-grid {
1008 grid-template-columns: 1fr;
1009 gap: 12px;
1010 }
1011 }
1012
1013 .yatra-info-grid {
1014 display: grid;
1015 grid-template-columns: 1fr 1fr;
1016 gap: 16px;
1017 }
1018
1019 .yatra-info-item {
1020 display: flex;
1021 flex-direction: column;
1022 gap: 4px;
1023 padding: 12px 14px;
1024 background: #f9fafb;
1025 border: 1px solid #eef2f7;
1026 border-radius: 12px;
1027 }
1028
1029 .yatra-info-label {
1030 font-size: 13px;
1031 color: #6b7280;
1032 line-height: 1.2;
1033 }
1034
1035 .yatra-info-value {
1036 font-size: 15px;
1037 font-weight: 600;
1038 color: #111827;
1039 line-height: 1.25;
1040 text-align: left;
1041 }
1042
1043 .yatra-status-badge {
1044 display: inline-block;
1045 padding: 4px 12px;
1046 border-radius: 100px;
1047 font-size: 13px;
1048 font-weight: 600;
1049 }
1050
1051 .yatra-travelers-list {
1052 display: flex;
1053 flex-direction: column;
1054 gap: 12px;
1055 }
1056
1057 .yatra-traveler-item {
1058 display: flex;
1059 align-items: center;
1060 gap: 12px;
1061 padding: 12px;
1062 background: #f9fafb;
1063 border-radius: 8px;
1064 }
1065
1066 .yatra-traveler-number {
1067 width: 28px;
1068 height: 28px;
1069 display: flex;
1070 align-items: center;
1071 justify-content: center;
1072 background: #3b82f6;
1073 color: white;
1074 border-radius: 50%;
1075 font-size: 13px;
1076 font-weight: 600;
1077 }
1078
1079 .yatra-traveler-name {
1080 font-weight: 600;
1081 color: #111827;
1082 }
1083
1084 .yatra-traveler-dob {
1085 font-size: 13px;
1086 color: #6b7280;
1087 }
1088
1089 .yatra-payment-card {
1090 background: #fafafa;
1091 }
1092
1093 .yatra-payment-rows {
1094 border: 1px solid #e5e7eb;
1095 border-radius: 8px;
1096 overflow: hidden;
1097 }
1098
1099 .yatra-payment-row {
1100 display: flex;
1101 justify-content: space-between;
1102 padding: 12px 16px;
1103 border-bottom: 1px solid #e5e7eb;
1104 }
1105
1106 .yatra-payment-row:last-child {
1107 border-bottom: none;
1108 background: #111827;
1109 color: white;
1110 font-weight: 600;
1111 }
1112
1113 .yatra-discount-row span:last-child {
1114 color: #22c55e;
1115 }
1116
1117 .yatra-payment-method {
1118 margin-top: 16px;
1119 padding: 12px;
1120 background: white;
1121 border-radius: 8px;
1122 display: flex;
1123 justify-content: space-between;
1124 }
1125
1126 .yatra-pm-label {
1127 color: #6b7280;
1128 }
1129
1130 .yatra-pm-value {
1131 font-weight: 600;
1132 color: #111827;
1133 }
1134
1135 .yatra-contact-info p {
1136 margin: 0 0 8px;
1137 }
1138
1139 .yatra-whats-next {
1140 background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
1141 border-color: #bbf7d0;
1142 }
1143
1144 .yatra-next-steps {
1145 display: flex;
1146 flex-direction: column;
1147 gap: 20px;
1148 }
1149
1150 .yatra-step {
1151 display: flex;
1152 gap: 16px;
1153 }
1154
1155 .yatra-step-number {
1156 width: 32px;
1157 height: 32px;
1158 display: flex;
1159 align-items: center;
1160 justify-content: center;
1161 background: #22c55e;
1162 color: white;
1163 border-radius: 50%;
1164 font-weight: 600;
1165 flex-shrink: 0;
1166 }
1167
1168 .yatra-step-content h4 {
1169 margin: 0 0 4px;
1170 font-size: 16px;
1171 color: #111827;
1172 }
1173
1174 .yatra-step-content p {
1175 margin: 0;
1176 font-size: 14px;
1177 color: #6b7280;
1178 }
1179
1180 .yatra-confirmation-actions {
1181 display: flex;
1182 gap: 16px;
1183 justify-content: center;
1184 margin-top: 32px;
1185 }
1186
1187 .yatra-btn {
1188 display: inline-flex;
1189 align-items: center;
1190 gap: 8px;
1191 padding: 14px 28px;
1192 border-radius: 8px;
1193 font-size: 15px;
1194 font-weight: 600;
1195 text-decoration: none;
1196 cursor: pointer;
1197 transition: all 0.2s;
1198 border: none;
1199 }
1200
1201 .yatra-btn svg {
1202 width: 18px;
1203 height: 18px;
1204 }
1205
1206 .yatra-btn-secondary {
1207 background: #3b82f6;
1208 color: white;
1209 }
1210
1211 .yatra-btn-secondary:hover {
1212 background: #2563eb;
1213 }
1214
1215 .yatra-btn-outline {
1216 background: white;
1217 color: #374151;
1218 border: 2px solid #e5e7eb;
1219 }
1220
1221 .yatra-btn-outline:hover {
1222 border-color: #3b82f6;
1223 color: #3b82f6;
1224 }
1225
1226 /* =====================================================================
1227 Print Styles — produce a clean, single-page-friendly receipt.
1228 Triggered by the print button (adds .yatra-printing-confirmation
1229 to <body> + clones the confirmation card into .yatra-print-root).
1230 ===================================================================== */
1231 @media print {
1232 @page {
1233 size: A4;
1234 margin: 9mm 10mm;
1235 }
1236
1237 /* Force browsers to print our colors / borders */
1238 body.yatra-printing-confirmation,
1239 body.yatra-printing-confirmation * {
1240 -webkit-print-color-adjust: exact !important;
1241 print-color-adjust: exact !important;
1242 color-adjust: exact !important;
1243 }
1244
1245 /* Reset body, kill animations & transitions */
1246 body.yatra-printing-confirmation {
1247 background: #fff !important;
1248 color: #111827 !important;
1249 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
1250 Helvetica, Arial, sans-serif !important;
1251 font-size: 10pt !important;
1252 line-height: 1.45 !important;
1253 }
1254 body.yatra-printing-confirmation *,
1255 body.yatra-printing-confirmation *::before,
1256 body.yatra-printing-confirmation *::after {
1257 animation: none !important;
1258 transition: none !important;
1259 box-shadow: none !important;
1260 text-shadow: none !important;
1261 }
1262
1263 /* Hide everything except our cloned print root */
1264 body.yatra-printing-confirmation > *:not(.yatra-print-root) {
1265 display: none !important;
1266 }
1267 body.yatra-printing-confirmation .yatra-print-root,
1268 body.yatra-printing-confirmation .yatra-print-root * {
1269 visibility: visible;
1270 }
1271 body.yatra-printing-confirmation .yatra-print-root {
1272 position: static !important;
1273 left: auto;
1274 top: auto;
1275 width: 100%;
1276 margin: 0;
1277 padding: 0;
1278 }
1279
1280 /* Wrappers — remove screen padding/widths */
1281 body.yatra-printing-confirmation .yatra-confirmation-wrapper,
1282 body.yatra-printing-confirmation .yatra-confirmation-container {
1283 max-width: none !important;
1284 margin: 0 !important;
1285 padding: 0 !important;
1286 }
1287
1288 /* Hide things that don't belong on paper */
1289 body.yatra-printing-confirmation .yatra-confirmation-actions,
1290 body.yatra-printing-confirmation .yatra-no-print,
1291 body.yatra-printing-confirmation .yatra-whats-next,
1292 body.yatra-printing-confirmation .yatra-trip-rating {
1293 display: none !important;
1294 }
1295
1296 /* Confirmation header — compact, two-column with status icon left & ref right */
1297 body.yatra-printing-confirmation .yatra-confirmation-header {
1298 display: flex !important;
1299 align-items: center !important;
1300 justify-content: space-between !important;
1301 gap: 16pt !important;
1302 text-align: left !important;
1303 margin: 0 0 8pt !important;
1304 padding: 0 0 6pt !important;
1305 border-bottom: 1pt solid #111827 !important;
1306 }
1307 body.yatra-printing-confirmation .yatra-confirmation-icon {
1308 width: 28pt !important;
1309 height: 28pt !important;
1310 margin: 0 !important;
1311 background: #16a34a !important;
1312 flex-shrink: 0 !important;
1313 }
1314 body.yatra-printing-confirmation .yatra-confirmation-icon svg {
1315 width: 16pt !important;
1316 height: 16pt !important;
1317 }
1318 body.yatra-printing-confirmation .yatra-confirmation-title {
1319 font-size: 14pt !important;
1320 font-weight: 700 !important;
1321 margin: 0 !important;
1322 flex: 1 !important;
1323 color: #111827 !important;
1324 }
1325 body.yatra-printing-confirmation .yatra-confirmation-subtitle {
1326 display: none !important;
1327 }
1328 body.yatra-printing-confirmation .yatra-confirmation-reference {
1329 display: inline-flex !important;
1330 flex-direction: column !important;
1331 align-items: flex-end !important;
1332 gap: 2pt !important;
1333 background: transparent !important;
1334 padding: 0 !important;
1335 border: none !important;
1336 border-radius: 0 !important;
1337 }
1338 body.yatra-printing-confirmation .yatra-ref-label {
1339 font-size: 8pt !important;
1340 text-transform: uppercase !important;
1341 letter-spacing: 0.4pt !important;
1342 color: #6b7280 !important;
1343 }
1344 body.yatra-printing-confirmation .yatra-ref-code {
1345 font-size: 11pt !important;
1346 font-weight: 700 !important;
1347 color: #111827 !important;
1348 letter-spacing: 0.6pt !important;
1349 }
1350
1351 /* Cards — flat, thin border, never split across pages */
1352 body.yatra-printing-confirmation .yatra-confirmation-card {
1353 background: #fff !important;
1354 border: 0.75pt solid #d1d5db !important;
1355 border-radius: 3pt !important;
1356 padding: 8pt 10pt !important;
1357 margin: 0 0 6pt !important;
1358 page-break-inside: avoid !important;
1359 break-inside: avoid !important;
1360 }
1361 body.yatra-printing-confirmation .yatra-trip-summary-card {
1362 background: #f9fafb !important;
1363 border-color: #d1d5db !important;
1364 }
1365 body.yatra-printing-confirmation .yatra-card-title {
1366 font-size: 10.5pt !important;
1367 font-weight: 700 !important;
1368 gap: 6pt !important;
1369 margin: 0 0 8pt !important;
1370 padding: 0 0 5pt !important;
1371 border-bottom: 0.5pt solid #e5e7eb !important;
1372 color: #111827 !important;
1373 }
1374 body.yatra-printing-confirmation .yatra-card-title svg {
1375 width: 12pt !important;
1376 height: 12pt !important;
1377 color: #111827 !important;
1378 }
1379
1380 /* Trip summary — small image, tight spacing */
1381 body.yatra-printing-confirmation .yatra-trip-summary {
1382 gap: 10pt !important;
1383 align-items: flex-start !important;
1384 }
1385 /* Images often render as empty placeholders in print preview; hide for a cleaner receipt. */
1386 body.yatra-printing-confirmation .yatra-trip-image {
1387 display: none !important;
1388 }
1389 body.yatra-printing-confirmation .yatra-trip-name {
1390 font-size: 12pt !important;
1391 font-weight: 700 !important;
1392 margin: 0 0 4pt !important;
1393 color: #111827 !important;
1394 }
1395 body.yatra-printing-confirmation .yatra-trip-meta {
1396 font-size: 9pt !important;
1397 gap: 10pt !important;
1398 margin-bottom: 4pt !important;
1399 color: #374151 !important;
1400 }
1401 body.yatra-printing-confirmation .yatra-trip-meta svg,
1402 body.yatra-printing-confirmation .yatra-trip-location svg {
1403 width: 9pt !important;
1404 height: 9pt !important;
1405 }
1406 body.yatra-printing-confirmation .yatra-trip-location {
1407 font-size: 9pt !important;
1408 margin: 0 0 4pt !important;
1409 color: #374151 !important;
1410 }
1411
1412 /* Tags — outline pills, no fills */
1413 body.yatra-printing-confirmation .yatra-trip-tags {
1414 font-size: 9pt !important;
1415 margin-top: 4pt !important;
1416 }
1417 body.yatra-printing-confirmation .yatra-tag-label {
1418 font-weight: 700 !important;
1419 color: #374151 !important;
1420 margin-right: 4pt !important;
1421 }
1422 body.yatra-printing-confirmation .yatra-tag-item {
1423 display: inline-block !important;
1424 background: #fff !important;
1425 border: 0.5pt solid #d1d5db !important;
1426 padding: 1pt 5pt !important;
1427 border-radius: 2pt !important;
1428 font-size: 8.5pt !important;
1429 color: #374151 !important;
1430 margin: 1pt 2pt 1pt 0 !important;
1431 }
1432
1433 /* Two-column grid stays two columns on paper */
1434 body.yatra-printing-confirmation .yatra-confirmation-grid {
1435 display: grid !important;
1436 grid-template-columns: 1.15fr 0.85fr !important;
1437 gap: 6pt !important;
1438 align-items: start !important;
1439 }
1440 body.yatra-printing-confirmation .yatra-confirmation-column {
1441 min-width: 0 !important;
1442 }
1443
1444 /* Booking info grid */
1445 body.yatra-printing-confirmation .yatra-info-grid {
1446 display: grid !important;
1447 grid-template-columns: 1fr 1fr !important;
1448 gap: 5pt 9pt !important;
1449 }
1450 body.yatra-printing-confirmation .yatra-info-item {
1451 display: flex !important;
1452 flex-direction: column !important;
1453 gap: 1pt !important;
1454 }
1455 body.yatra-printing-confirmation .yatra-info-label {
1456 font-size: 7.5pt !important;
1457 text-transform: uppercase !important;
1458 letter-spacing: 0.3pt !important;
1459 color: #6b7280 !important;
1460 }
1461 body.yatra-printing-confirmation .yatra-info-value {
1462 font-size: 10pt !important;
1463 font-weight: 600 !important;
1464 color: #111827 !important;
1465 }
1466 body.yatra-printing-confirmation .yatra-status-badge {
1467 display: inline-block !important;
1468 padding: 1pt 6pt !important;
1469 border: 0.75pt solid currentColor !important;
1470 border-radius: 2pt !important;
1471 font-size: 8.5pt !important;
1472 font-weight: 700 !important;
1473 }
1474
1475 /* Travelers */
1476 body.yatra-printing-confirmation .yatra-travelers-list {
1477 margin: 0 !important;
1478 }
1479 body.yatra-printing-confirmation .yatra-traveler-item {
1480 display: flex !important;
1481 align-items: center !important;
1482 gap: 8pt !important;
1483 padding: 4pt 0 !important;
1484 border-bottom: 0.5pt solid #e5e7eb !important;
1485 }
1486 body.yatra-printing-confirmation .yatra-traveler-item:last-child {
1487 border-bottom: none !important;
1488 }
1489 body.yatra-printing-confirmation .yatra-traveler-number {
1490 display: inline-flex !important;
1491 align-items: center !important;
1492 justify-content: center !important;
1493 width: 16pt !important;
1494 height: 16pt !important;
1495 background: #111827 !important;
1496 color: #fff !important;
1497 border-radius: 50% !important;
1498 font-size: 8.5pt !important;
1499 font-weight: 700 !important;
1500 flex-shrink: 0 !important;
1501 }
1502 body.yatra-printing-confirmation .yatra-traveler-name {
1503 font-size: 10pt !important;
1504 font-weight: 600 !important;
1505 color: #111827 !important;
1506 }
1507 body.yatra-printing-confirmation .yatra-traveler-dob {
1508 font-size: 8.5pt !important;
1509 color: #6b7280 !important;
1510 }
1511
1512 /* Payment summary rows */
1513 body.yatra-printing-confirmation .yatra-payment-rows {
1514 margin: 0 !important;
1515 }
1516 body.yatra-printing-confirmation .yatra-payment-row {
1517 display: flex !important;
1518 justify-content: space-between !important;
1519 align-items: baseline !important;
1520 gap: 12pt !important;
1521 font-size: 9.25pt !important;
1522 padding: 1.5pt 0 !important;
1523 color: #111827 !important;
1524 }
1525 body.yatra-printing-confirmation .yatra-due-row {
1526 background: #fef3c7 !important;
1527 padding: 4pt 6pt !important;
1528 margin-top: 5pt !important;
1529 border-radius: 2pt !important;
1530 border: 0.5pt solid #fbbf24 !important;
1531 }
1532 body.yatra-printing-confirmation .yatra-payment-method {
1533 margin-top: 6pt !important;
1534 padding-top: 5pt !important;
1535 font-size: 9pt !important;
1536 border-top: 0.5pt solid #e5e7eb !important;
1537 color: #374151 !important;
1538 }
1539
1540 /* Contact info */
1541 body.yatra-printing-confirmation .yatra-contact-info {
1542 margin: 0 !important;
1543 }
1544 body.yatra-printing-confirmation .yatra-contact-item {
1545 font-size: 9.5pt !important;
1546 margin: 0 0 3pt !important;
1547 color: #111827 !important;
1548 }
1549 body.yatra-printing-confirmation .yatra-contact-item strong {
1550 color: #6b7280 !important;
1551 font-weight: 600 !important;
1552 margin-right: 4pt !important;
1553 }
1554
1555 /* Links — print as plain text, no underline (URL is still in browser footer) */
1556 body.yatra-printing-confirmation a,
1557 body.yatra-printing-confirmation a:visited {
1558 color: inherit !important;
1559 text-decoration: none !important;
1560 }
1561
1562 /* Avoid orphan headings */
1563 body.yatra-printing-confirmation h1,
1564 body.yatra-printing-confirmation h2,
1565 body.yatra-printing-confirmation h3,
1566 body.yatra-printing-confirmation h4 {
1567 page-break-after: avoid !important;
1568 break-after: avoid !important;
1569 }
1570 }
1571 </style>
1572
1573 <script>
1574 (function () {
1575 document.addEventListener('click', function (e) {
1576 var btn = e.target.closest('[data-yatra-print="confirmation"]');
1577 if (!btn) {
1578 return;
1579 }
1580 e.preventDefault();
1581
1582 var card = document.querySelector('.yatra-confirmation-container');
1583 if (!card) {
1584 window.print();
1585 return;
1586 }
1587
1588 // Wrap (or reuse) a print-only root so the @media print rules can target a single
1589 // direct child of <body>. Reused on the account page if the same data attribute
1590 // and CSS rules are added there.
1591 var root = document.querySelector('.yatra-print-root');
1592 var addedWrapper = false;
1593 if (!root) {
1594 root = document.createElement('div');
1595 root.className = 'yatra-print-root';
1596 document.body.appendChild(root);
1597 addedWrapper = true;
1598 }
1599 var clone = card.cloneNode(true);
1600 // Drop the action buttons from the clone so they don't appear on paper.
1601 clone.querySelectorAll('.yatra-confirmation-actions').forEach(function (n) { n.remove(); });
1602 root.innerHTML = '';
1603 root.appendChild(clone);
1604
1605 document.body.classList.add('yatra-printing-confirmation');
1606
1607 var cleanup = function () {
1608 document.body.classList.remove('yatra-printing-confirmation');
1609 if (addedWrapper && root && root.parentNode) {
1610 root.parentNode.removeChild(root);
1611 } else if (root) {
1612 root.innerHTML = '';
1613 }
1614 window.removeEventListener('afterprint', cleanup);
1615 };
1616
1617 window.addEventListener('afterprint', cleanup);
1618 // Safety net for browsers that don't fire afterprint reliably.
1619 window.setTimeout(function () {
1620 if (document.body.classList.contains('yatra-printing-confirmation')) {
1621 cleanup();
1622 }
1623 }, 5000);
1624
1625 window.print();
1626 });
1627 })();
1628 </script>
1629
1630 <?php yatra_get_footer(); ?>
1631
1632