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

1,651 lines 69.6 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 <?php
651 // Label the "due now" amount by payment type so a
652 // deposit/partial reads clearly instead of just "Due Now".
653 $payment_method_type = (string) ($booking->payment_method ?? 'full');
654 $remaining_balance = max(0.0, $total_amount - $amount_paid - $amount_due);
655 if ($payment_method_type === 'deposit') {
656 $due_now_label = __('Deposit Due Now', 'yatra');
657 } elseif ($payment_method_type === 'partial') {
658 $due_now_label = __('Partial Payment Due Now', 'yatra');
659 } else {
660 $due_now_label = __('Due Now', 'yatra');
661 }
662 ?>
663 <div class="yatra-payment-row yatra-due-row">
664 <span><strong><?php echo esc_html($due_now_label); ?></strong></span>
665 <span><strong><?php echo esc_html(yatra_format_price($amount_due, $booking->currency)); ?></strong></span>
666 </div>
667 <?php if ($payment_method_type !== 'full' && $remaining_balance > 0.01): ?>
668 <div class="yatra-payment-row" style="margin-top: 6px;">
669 <span><?php esc_html_e('Remaining Balance', 'yatra'); ?></span>
670 <span><?php echo esc_html(yatra_format_price($remaining_balance, $booking->currency)); ?></span>
671 </div>
672 <?php endif; ?>
673 <?php endif; ?>
674 </div>
675
676 <div class="yatra-payment-method">
677 <span class="yatra-pm-label"><?php esc_html_e('Payment Method:', 'yatra'); ?></span>
678 <span class="yatra-pm-value"><?php echo esc_html(ucwords(str_replace('_', ' ', (string) $display_payment_gateway))); ?></span>
679 </div>
680 </div>
681
682 <!-- Contact Info Card -->
683 <div class="yatra-confirmation-card">
684 <h3 class="yatra-card-title">
685 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
686 <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>
687 <polyline points="22,6 12,13 2,6"></polyline>
688 </svg>
689 <?php esc_html_e('Contact Information', 'yatra'); ?>
690 </h3>
691
692 <div class="yatra-contact-info">
693 <?php
694 // Try to get contact data from multiple sources
695 $contact_data = [];
696 if (!empty($booking->contact_data)) {
697 $contact_data = json_decode($booking->contact_data, true) ?: [];
698 }
699
700 $contact_name = trim((
701 $contact_data['first_name'] ??
702 $booking->contact_first_name ??
703 ($booking->contact['first_name'] ?? '')
704 ) . ' ' . (
705 $contact_data['last_name'] ??
706 $booking->contact_last_name ??
707 ($booking->contact['last_name'] ?? '')
708 ));
709
710 $contact_email = $contact_data['email'] ?? $booking->contact_email ?? ($booking->contact['email'] ?? '');
711 $contact_phone = $contact_data['phone'] ?? $booking->contact_phone ?? ($booking->contact['phone'] ?? '');
712 ?>
713
714 <?php if ($contact_name) : ?>
715 <p class="yatra-contact-item">
716 <strong><?php esc_html_e('Name:', 'yatra'); ?></strong>
717 <?php echo esc_html($contact_name); ?>
718 </p>
719 <?php endif; ?>
720
721 <?php if ($contact_email) : ?>
722 <p class="yatra-contact-item">
723 <strong><?php esc_html_e('Email:', 'yatra'); ?></strong>
724 <?php echo esc_html($contact_email); ?>
725 </p>
726 <?php endif; ?>
727
728 <?php if ($contact_phone) : ?>
729 <p class="yatra-contact-item">
730 <strong><?php esc_html_e('Phone:', 'yatra'); ?></strong>
731 <?php echo esc_html($contact_phone); ?>
732 </p>
733 <?php endif; ?>
734
735 <?php if (!$contact_name && !$contact_email && !$contact_phone) : ?>
736 <p class="yatra-contact-item">
737 <em><?php esc_html_e('Contact information not available', 'yatra'); ?></em>
738 </p>
739 <?php endif; ?>
740 </div>
741 </div>
742 </div>
743 </div>
744
745 <!-- What's Next Section -->
746 <div class="yatra-confirmation-card yatra-whats-next">
747 <h3 class="yatra-card-title">
748 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
749 <circle cx="12" cy="12" r="10"></circle>
750 <polyline points="12 16 16 12 12 8"></polyline>
751 <line x1="8" y1="12" x2="16" y2="12"></line>
752 </svg>
753 <?php esc_html_e("What's Next?", 'yatra'); ?>
754 </h3>
755
756 <div class="yatra-next-steps">
757 <div class="yatra-step">
758 <span class="yatra-step-number">1</span>
759 <div class="yatra-step-content">
760 <h4><?php esc_html_e('Check Your Email', 'yatra'); ?></h4>
761 <p><?php esc_html_e('We\'ve sent a confirmation email with all the details to your registered email address.', 'yatra'); ?></p>
762 </div>
763 </div>
764
765 <div class="yatra-step">
766 <span class="yatra-step-number">2</span>
767 <div class="yatra-step-content">
768 <h4><?php esc_html_e('Detailed Itinerary', 'yatra'); ?></h4>
769 <p><?php esc_html_e('You\'ll receive a detailed itinerary and preparation guide within 24-48 hours.', 'yatra'); ?></p>
770 </div>
771 </div>
772
773 <div class="yatra-step">
774 <span class="yatra-step-number">3</span>
775 <div class="yatra-step-content">
776 <h4><?php esc_html_e('Prepare for Adventure', 'yatra'); ?></h4>
777 <p><?php esc_html_e('Ensure all travelers have valid ID or travel documents and any required visas for your destination.', 'yatra'); ?></p>
778 </div>
779 </div>
780 </div>
781 </div>
782
783 <!-- Action Buttons -->
784 <div class="yatra-confirmation-actions">
785 <a href="<?php echo esc_url(home_url('/')); ?>" class="yatra-btn yatra-btn-secondary">
786 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
787 <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
788 <polyline points="9 22 9 12 15 12 15 22"></polyline>
789 </svg>
790 <?php esc_html_e('Return to Home', 'yatra'); ?>
791 </a>
792
793 <?php
794 // Get latest payment for this booking to enable invoice download.
795 // The invoice endpoint authorises via: admin → owner → signed invoice_token → guest booking_token.
796 // We always issue a signed invoice_token here so the link works for guests
797 // (no session required) AND for logged-in users who don't own the booking
798 // (e.g. site admins viewing the page) — without re-checking login on the client.
799 $paymentRepository = new \Yatra\Repositories\PaymentRepository();
800 $latestPayment = $paymentRepository->findLatestByBookingId((int) $booking->id);
801 if ($latestPayment && in_array($latestPayment->status, ['completed', 'paid'], true)) :
802 $invoiceToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken(
803 (int) $latestPayment->id,
804 (int) ($latestPayment->booking_id ?? $booking->id)
805 );
806 $invoiceUrl = add_query_arg(
807 [
808 'download' => '1',
809 'invoice_token' => $invoiceToken,
810 ],
811 rest_url('yatra/v1/payment/' . (int) $latestPayment->id . '/invoice')
812 );
813 ?>
814 <a href="<?php echo esc_url($invoiceUrl); ?>"
815 target="_blank"
816 rel="noopener"
817 class="yatra-btn yatra-btn-primary">
818 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
819 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
820 <polyline points="7 10 12 15 17 10"></polyline>
821 <line x1="12" y1="15" x2="12" y2="3"></line>
822 </svg>
823 <?php esc_html_e('Download Invoice', 'yatra'); ?>
824 </a>
825 <?php endif; ?>
826
827 <button type="button" data-yatra-print="confirmation" class="yatra-btn yatra-btn-outline">
828 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
829 <polyline points="6 9 6 2 18 2 18 9"></polyline>
830 <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>
831 <rect x="6" y="14" width="12" height="8"></rect>
832 </svg>
833 <?php esc_html_e('Print Confirmation', 'yatra'); ?>
834 </button>
835 </div>
836
837 </div>
838 </div>
839 </div>
840
841 <style>
842 /* Confirmation Page Styles */
843 .yatra-confirmation-wrapper {
844 max-width: 1300px;
845 margin: 0 auto;
846 padding: 40px 20px;
847 }
848
849 .yatra-confirmation-container {
850 max-width: 900px;
851 margin: 0 auto;
852 }
853
854 .yatra-confirmation-header {
855 text-align: center;
856 margin-bottom: 40px;
857 }
858
859 .yatra-confirmation-icon {
860 width: 100px;
861 height: 100px;
862 margin: 0 auto 24px;
863 background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
864 border-radius: 50%;
865 display: flex;
866 align-items: center;
867 justify-content: center;
868 animation: scaleIn 0.5s ease-out;
869 }
870
871 .yatra-confirmation-icon svg {
872 width: 50px;
873 height: 50px;
874 color: white;
875 }
876
877 @keyframes scaleIn {
878 0% { transform: scale(0); opacity: 0; }
879 50% { transform: scale(1.1); }
880 100% { transform: scale(1); opacity: 1; }
881 }
882
883 .yatra-confirmation-title {
884 font-size: 36px;
885 font-weight: 700;
886 color: #111827;
887 margin: 0 0 12px;
888 }
889
890 .yatra-confirmation-subtitle {
891 font-size: 18px;
892 color: #6b7280;
893 margin: 0 0 24px;
894 }
895
896 .yatra-confirmation-reference {
897 display: inline-flex;
898 align-items: center;
899 gap: 12px;
900 background: #f3f4f6;
901 padding: 12px 24px;
902 border-radius: 100px;
903 }
904
905 .yatra-ref-label {
906 color: #6b7280;
907 font-size: 14px;
908 }
909
910 .yatra-ref-code {
911 font-size: 18px;
912 font-weight: 700;
913 color: #111827;
914 font-family: monospace;
915 letter-spacing: 1px;
916 }
917
918 .yatra-confirmation-card {
919 background: #fff;
920 border: 1px solid #e5e7eb;
921 border-radius: 16px;
922 padding: 24px;
923 margin-bottom: 24px;
924 }
925
926 .yatra-card-title {
927 display: flex;
928 align-items: center;
929 gap: 12px;
930 font-size: 18px;
931 font-weight: 600;
932 color: #111827;
933 margin: 0 0 20px;
934 padding-bottom: 16px;
935 border-bottom: 1px solid #e5e7eb;
936 }
937
938 .yatra-card-title svg {
939 width: 22px;
940 height: 22px;
941 color: #3b82f6;
942 }
943
944 .yatra-trip-summary-card {
945 background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%);
946 border-color: #bfdbfe;
947 }
948
949 .yatra-trip-summary {
950 display: flex;
951 gap: 24px;
952 align-items: center;
953 }
954
955 .yatra-trip-image {
956 width: 120px;
957 height: 120px;
958 border-radius: 12px;
959 overflow: hidden;
960 flex-shrink: 0;
961 }
962
963 .yatra-trip-image img {
964 width: 100%;
965 height: 100%;
966 object-fit: cover;
967 }
968
969 .yatra-trip-name {
970 font-size: 22px;
971 font-weight: 700;
972 color: #111827;
973 margin: 0 0 12px;
974 }
975
976 .yatra-trip-meta {
977 display: flex;
978 gap: 20px;
979 flex-wrap: wrap;
980 margin-bottom: 8px;
981 }
982
983 .yatra-meta-item {
984 display: flex;
985 align-items: center;
986 gap: 6px;
987 font-size: 14px;
988 color: #4b5563;
989 }
990
991 .yatra-meta-item svg {
992 width: 16px;
993 height: 16px;
994 }
995
996 .yatra-trip-location {
997 display: flex;
998 align-items: center;
999 gap: 6px;
1000 font-size: 14px;
1001 color: #6b7280;
1002 margin: 0;
1003 }
1004
1005 .yatra-trip-location svg {
1006 width: 16px;
1007 height: 16px;
1008 }
1009
1010 .yatra-confirmation-grid {
1011 display: grid;
1012 grid-template-columns: 1fr 1fr;
1013 gap: 24px;
1014 }
1015
1016 @media (max-width: 768px) {
1017 .yatra-confirmation-grid {
1018 grid-template-columns: 1fr;
1019 }
1020
1021 .yatra-trip-summary {
1022 flex-direction: column;
1023 text-align: center;
1024 }
1025
1026 .yatra-info-grid {
1027 grid-template-columns: 1fr;
1028 gap: 12px;
1029 }
1030 }
1031
1032 .yatra-info-grid {
1033 display: grid;
1034 grid-template-columns: 1fr 1fr;
1035 gap: 16px;
1036 }
1037
1038 .yatra-info-item {
1039 display: flex;
1040 flex-direction: column;
1041 gap: 4px;
1042 padding: 12px 14px;
1043 background: #f9fafb;
1044 border: 1px solid #eef2f7;
1045 border-radius: 12px;
1046 }
1047
1048 .yatra-info-label {
1049 font-size: 13px;
1050 color: #6b7280;
1051 line-height: 1.2;
1052 }
1053
1054 .yatra-info-value {
1055 font-size: 15px;
1056 font-weight: 600;
1057 color: #111827;
1058 line-height: 1.25;
1059 text-align: left;
1060 }
1061
1062 .yatra-status-badge {
1063 display: inline-block;
1064 padding: 4px 12px;
1065 border-radius: 100px;
1066 font-size: 13px;
1067 font-weight: 600;
1068 }
1069
1070 .yatra-travelers-list {
1071 display: flex;
1072 flex-direction: column;
1073 gap: 12px;
1074 }
1075
1076 .yatra-traveler-item {
1077 display: flex;
1078 align-items: center;
1079 gap: 12px;
1080 padding: 12px;
1081 background: #f9fafb;
1082 border-radius: 8px;
1083 }
1084
1085 .yatra-traveler-number {
1086 width: 28px;
1087 height: 28px;
1088 display: flex;
1089 align-items: center;
1090 justify-content: center;
1091 background: #3b82f6;
1092 color: white;
1093 border-radius: 50%;
1094 font-size: 13px;
1095 font-weight: 600;
1096 }
1097
1098 .yatra-traveler-name {
1099 font-weight: 600;
1100 color: #111827;
1101 }
1102
1103 .yatra-traveler-dob {
1104 font-size: 13px;
1105 color: #6b7280;
1106 }
1107
1108 .yatra-payment-card {
1109 background: #fafafa;
1110 }
1111
1112 .yatra-payment-rows {
1113 border: 1px solid #e5e7eb;
1114 border-radius: 8px;
1115 overflow: hidden;
1116 }
1117
1118 .yatra-payment-row {
1119 display: flex;
1120 justify-content: space-between;
1121 padding: 12px 16px;
1122 border-bottom: 1px solid #e5e7eb;
1123 }
1124
1125 .yatra-payment-row:last-child {
1126 border-bottom: none;
1127 background: #111827;
1128 color: white;
1129 font-weight: 600;
1130 }
1131
1132 .yatra-discount-row span:last-child {
1133 color: #22c55e;
1134 }
1135
1136 .yatra-payment-method {
1137 margin-top: 16px;
1138 padding: 12px;
1139 background: white;
1140 border-radius: 8px;
1141 display: flex;
1142 justify-content: space-between;
1143 }
1144
1145 .yatra-pm-label {
1146 color: #6b7280;
1147 }
1148
1149 .yatra-pm-value {
1150 font-weight: 600;
1151 color: #111827;
1152 }
1153
1154 .yatra-contact-info p {
1155 margin: 0 0 8px;
1156 }
1157
1158 .yatra-whats-next {
1159 background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
1160 border-color: #bbf7d0;
1161 }
1162
1163 .yatra-next-steps {
1164 display: flex;
1165 flex-direction: column;
1166 gap: 20px;
1167 }
1168
1169 .yatra-step {
1170 display: flex;
1171 gap: 16px;
1172 }
1173
1174 .yatra-step-number {
1175 width: 32px;
1176 height: 32px;
1177 display: flex;
1178 align-items: center;
1179 justify-content: center;
1180 background: #22c55e;
1181 color: white;
1182 border-radius: 50%;
1183 font-weight: 600;
1184 flex-shrink: 0;
1185 }
1186
1187 .yatra-step-content h4 {
1188 margin: 0 0 4px;
1189 font-size: 16px;
1190 color: #111827;
1191 }
1192
1193 .yatra-step-content p {
1194 margin: 0;
1195 font-size: 14px;
1196 color: #6b7280;
1197 }
1198
1199 .yatra-confirmation-actions {
1200 display: flex;
1201 gap: 16px;
1202 justify-content: center;
1203 margin-top: 32px;
1204 }
1205
1206 .yatra-btn {
1207 display: inline-flex;
1208 align-items: center;
1209 gap: 8px;
1210 padding: 14px 28px;
1211 border-radius: 8px;
1212 font-size: 15px;
1213 font-weight: 600;
1214 text-decoration: none;
1215 cursor: pointer;
1216 transition: all 0.2s;
1217 border: none;
1218 }
1219
1220 .yatra-btn svg {
1221 width: 18px;
1222 height: 18px;
1223 }
1224
1225 .yatra-btn-secondary {
1226 background: #3b82f6;
1227 color: white;
1228 }
1229
1230 .yatra-btn-secondary:hover {
1231 background: #2563eb;
1232 }
1233
1234 .yatra-btn-outline {
1235 background: white;
1236 color: #374151;
1237 border: 2px solid #e5e7eb;
1238 }
1239
1240 .yatra-btn-outline:hover {
1241 border-color: #3b82f6;
1242 color: #3b82f6;
1243 }
1244
1245 /* =====================================================================
1246 Print Styles — produce a clean, single-page-friendly receipt.
1247 Triggered by the print button (adds .yatra-printing-confirmation
1248 to <body> + clones the confirmation card into .yatra-print-root).
1249 ===================================================================== */
1250 @media print {
1251 @page {
1252 size: A4;
1253 margin: 9mm 10mm;
1254 }
1255
1256 /* Force browsers to print our colors / borders */
1257 body.yatra-printing-confirmation,
1258 body.yatra-printing-confirmation * {
1259 -webkit-print-color-adjust: exact !important;
1260 print-color-adjust: exact !important;
1261 color-adjust: exact !important;
1262 }
1263
1264 /* Reset body, kill animations & transitions */
1265 body.yatra-printing-confirmation {
1266 background: #fff !important;
1267 color: #111827 !important;
1268 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
1269 Helvetica, Arial, sans-serif !important;
1270 font-size: 10pt !important;
1271 line-height: 1.45 !important;
1272 }
1273 body.yatra-printing-confirmation *,
1274 body.yatra-printing-confirmation *::before,
1275 body.yatra-printing-confirmation *::after {
1276 animation: none !important;
1277 transition: none !important;
1278 box-shadow: none !important;
1279 text-shadow: none !important;
1280 }
1281
1282 /* Hide everything except our cloned print root */
1283 body.yatra-printing-confirmation > *:not(.yatra-print-root) {
1284 display: none !important;
1285 }
1286 body.yatra-printing-confirmation .yatra-print-root,
1287 body.yatra-printing-confirmation .yatra-print-root * {
1288 visibility: visible;
1289 }
1290 body.yatra-printing-confirmation .yatra-print-root {
1291 position: static !important;
1292 left: auto;
1293 top: auto;
1294 width: 100%;
1295 margin: 0;
1296 padding: 0;
1297 }
1298
1299 /* Wrappers — remove screen padding/widths */
1300 body.yatra-printing-confirmation .yatra-confirmation-wrapper,
1301 body.yatra-printing-confirmation .yatra-confirmation-container {
1302 max-width: none !important;
1303 margin: 0 !important;
1304 padding: 0 !important;
1305 }
1306
1307 /* Hide things that don't belong on paper */
1308 body.yatra-printing-confirmation .yatra-confirmation-actions,
1309 body.yatra-printing-confirmation .yatra-no-print,
1310 body.yatra-printing-confirmation .yatra-whats-next,
1311 body.yatra-printing-confirmation .yatra-trip-rating {
1312 display: none !important;
1313 }
1314
1315 /* Confirmation header — compact, two-column with status icon left & ref right */
1316 body.yatra-printing-confirmation .yatra-confirmation-header {
1317 display: flex !important;
1318 align-items: center !important;
1319 justify-content: space-between !important;
1320 gap: 16pt !important;
1321 text-align: left !important;
1322 margin: 0 0 8pt !important;
1323 padding: 0 0 6pt !important;
1324 border-bottom: 1pt solid #111827 !important;
1325 }
1326 body.yatra-printing-confirmation .yatra-confirmation-icon {
1327 width: 28pt !important;
1328 height: 28pt !important;
1329 margin: 0 !important;
1330 background: #16a34a !important;
1331 flex-shrink: 0 !important;
1332 }
1333 body.yatra-printing-confirmation .yatra-confirmation-icon svg {
1334 width: 16pt !important;
1335 height: 16pt !important;
1336 }
1337 body.yatra-printing-confirmation .yatra-confirmation-title {
1338 font-size: 14pt !important;
1339 font-weight: 700 !important;
1340 margin: 0 !important;
1341 flex: 1 !important;
1342 color: #111827 !important;
1343 }
1344 body.yatra-printing-confirmation .yatra-confirmation-subtitle {
1345 display: none !important;
1346 }
1347 body.yatra-printing-confirmation .yatra-confirmation-reference {
1348 display: inline-flex !important;
1349 flex-direction: column !important;
1350 align-items: flex-end !important;
1351 gap: 2pt !important;
1352 background: transparent !important;
1353 padding: 0 !important;
1354 border: none !important;
1355 border-radius: 0 !important;
1356 }
1357 body.yatra-printing-confirmation .yatra-ref-label {
1358 font-size: 8pt !important;
1359 text-transform: uppercase !important;
1360 letter-spacing: 0.4pt !important;
1361 color: #6b7280 !important;
1362 }
1363 body.yatra-printing-confirmation .yatra-ref-code {
1364 font-size: 11pt !important;
1365 font-weight: 700 !important;
1366 color: #111827 !important;
1367 letter-spacing: 0.6pt !important;
1368 }
1369
1370 /* Cards — flat, thin border, never split across pages */
1371 body.yatra-printing-confirmation .yatra-confirmation-card {
1372 background: #fff !important;
1373 border: 0.75pt solid #d1d5db !important;
1374 border-radius: 3pt !important;
1375 padding: 8pt 10pt !important;
1376 margin: 0 0 6pt !important;
1377 page-break-inside: avoid !important;
1378 break-inside: avoid !important;
1379 }
1380 body.yatra-printing-confirmation .yatra-trip-summary-card {
1381 background: #f9fafb !important;
1382 border-color: #d1d5db !important;
1383 }
1384 body.yatra-printing-confirmation .yatra-card-title {
1385 font-size: 10.5pt !important;
1386 font-weight: 700 !important;
1387 gap: 6pt !important;
1388 margin: 0 0 8pt !important;
1389 padding: 0 0 5pt !important;
1390 border-bottom: 0.5pt solid #e5e7eb !important;
1391 color: #111827 !important;
1392 }
1393 body.yatra-printing-confirmation .yatra-card-title svg {
1394 width: 12pt !important;
1395 height: 12pt !important;
1396 color: #111827 !important;
1397 }
1398
1399 /* Trip summary — small image, tight spacing */
1400 body.yatra-printing-confirmation .yatra-trip-summary {
1401 gap: 10pt !important;
1402 align-items: flex-start !important;
1403 }
1404 /* Images often render as empty placeholders in print preview; hide for a cleaner receipt. */
1405 body.yatra-printing-confirmation .yatra-trip-image {
1406 display: none !important;
1407 }
1408 body.yatra-printing-confirmation .yatra-trip-name {
1409 font-size: 12pt !important;
1410 font-weight: 700 !important;
1411 margin: 0 0 4pt !important;
1412 color: #111827 !important;
1413 }
1414 body.yatra-printing-confirmation .yatra-trip-meta {
1415 font-size: 9pt !important;
1416 gap: 10pt !important;
1417 margin-bottom: 4pt !important;
1418 color: #374151 !important;
1419 }
1420 body.yatra-printing-confirmation .yatra-trip-meta svg,
1421 body.yatra-printing-confirmation .yatra-trip-location svg {
1422 width: 9pt !important;
1423 height: 9pt !important;
1424 }
1425 body.yatra-printing-confirmation .yatra-trip-location {
1426 font-size: 9pt !important;
1427 margin: 0 0 4pt !important;
1428 color: #374151 !important;
1429 }
1430
1431 /* Tags — outline pills, no fills */
1432 body.yatra-printing-confirmation .yatra-trip-tags {
1433 font-size: 9pt !important;
1434 margin-top: 4pt !important;
1435 }
1436 body.yatra-printing-confirmation .yatra-tag-label {
1437 font-weight: 700 !important;
1438 color: #374151 !important;
1439 margin-right: 4pt !important;
1440 }
1441 body.yatra-printing-confirmation .yatra-tag-item {
1442 display: inline-block !important;
1443 background: #fff !important;
1444 border: 0.5pt solid #d1d5db !important;
1445 padding: 1pt 5pt !important;
1446 border-radius: 2pt !important;
1447 font-size: 8.5pt !important;
1448 color: #374151 !important;
1449 margin: 1pt 2pt 1pt 0 !important;
1450 }
1451
1452 /* Two-column grid stays two columns on paper */
1453 body.yatra-printing-confirmation .yatra-confirmation-grid {
1454 display: grid !important;
1455 grid-template-columns: 1.15fr 0.85fr !important;
1456 gap: 6pt !important;
1457 align-items: start !important;
1458 }
1459 body.yatra-printing-confirmation .yatra-confirmation-column {
1460 min-width: 0 !important;
1461 }
1462
1463 /* Booking info grid */
1464 body.yatra-printing-confirmation .yatra-info-grid {
1465 display: grid !important;
1466 grid-template-columns: 1fr 1fr !important;
1467 gap: 5pt 9pt !important;
1468 }
1469 body.yatra-printing-confirmation .yatra-info-item {
1470 display: flex !important;
1471 flex-direction: column !important;
1472 gap: 1pt !important;
1473 }
1474 body.yatra-printing-confirmation .yatra-info-label {
1475 font-size: 7.5pt !important;
1476 text-transform: uppercase !important;
1477 letter-spacing: 0.3pt !important;
1478 color: #6b7280 !important;
1479 }
1480 body.yatra-printing-confirmation .yatra-info-value {
1481 font-size: 10pt !important;
1482 font-weight: 600 !important;
1483 color: #111827 !important;
1484 }
1485 body.yatra-printing-confirmation .yatra-status-badge {
1486 display: inline-block !important;
1487 padding: 1pt 6pt !important;
1488 border: 0.75pt solid currentColor !important;
1489 border-radius: 2pt !important;
1490 font-size: 8.5pt !important;
1491 font-weight: 700 !important;
1492 }
1493
1494 /* Travelers */
1495 body.yatra-printing-confirmation .yatra-travelers-list {
1496 margin: 0 !important;
1497 }
1498 body.yatra-printing-confirmation .yatra-traveler-item {
1499 display: flex !important;
1500 align-items: center !important;
1501 gap: 8pt !important;
1502 padding: 4pt 0 !important;
1503 border-bottom: 0.5pt solid #e5e7eb !important;
1504 }
1505 body.yatra-printing-confirmation .yatra-traveler-item:last-child {
1506 border-bottom: none !important;
1507 }
1508 body.yatra-printing-confirmation .yatra-traveler-number {
1509 display: inline-flex !important;
1510 align-items: center !important;
1511 justify-content: center !important;
1512 width: 16pt !important;
1513 height: 16pt !important;
1514 background: #111827 !important;
1515 color: #fff !important;
1516 border-radius: 50% !important;
1517 font-size: 8.5pt !important;
1518 font-weight: 700 !important;
1519 flex-shrink: 0 !important;
1520 }
1521 body.yatra-printing-confirmation .yatra-traveler-name {
1522 font-size: 10pt !important;
1523 font-weight: 600 !important;
1524 color: #111827 !important;
1525 }
1526 body.yatra-printing-confirmation .yatra-traveler-dob {
1527 font-size: 8.5pt !important;
1528 color: #6b7280 !important;
1529 }
1530
1531 /* Payment summary rows */
1532 body.yatra-printing-confirmation .yatra-payment-rows {
1533 margin: 0 !important;
1534 }
1535 body.yatra-printing-confirmation .yatra-payment-row {
1536 display: flex !important;
1537 justify-content: space-between !important;
1538 align-items: baseline !important;
1539 gap: 12pt !important;
1540 font-size: 9.25pt !important;
1541 padding: 1.5pt 0 !important;
1542 color: #111827 !important;
1543 }
1544 body.yatra-printing-confirmation .yatra-due-row {
1545 background: #fef3c7 !important;
1546 padding: 4pt 6pt !important;
1547 margin-top: 5pt !important;
1548 border-radius: 2pt !important;
1549 border: 0.5pt solid #fbbf24 !important;
1550 }
1551 body.yatra-printing-confirmation .yatra-payment-method {
1552 margin-top: 6pt !important;
1553 padding-top: 5pt !important;
1554 font-size: 9pt !important;
1555 border-top: 0.5pt solid #e5e7eb !important;
1556 color: #374151 !important;
1557 }
1558
1559 /* Contact info */
1560 body.yatra-printing-confirmation .yatra-contact-info {
1561 margin: 0 !important;
1562 }
1563 body.yatra-printing-confirmation .yatra-contact-item {
1564 font-size: 9.5pt !important;
1565 margin: 0 0 3pt !important;
1566 color: #111827 !important;
1567 }
1568 body.yatra-printing-confirmation .yatra-contact-item strong {
1569 color: #6b7280 !important;
1570 font-weight: 600 !important;
1571 margin-right: 4pt !important;
1572 }
1573
1574 /* Links — print as plain text, no underline (URL is still in browser footer) */
1575 body.yatra-printing-confirmation a,
1576 body.yatra-printing-confirmation a:visited {
1577 color: inherit !important;
1578 text-decoration: none !important;
1579 }
1580
1581 /* Avoid orphan headings */
1582 body.yatra-printing-confirmation h1,
1583 body.yatra-printing-confirmation h2,
1584 body.yatra-printing-confirmation h3,
1585 body.yatra-printing-confirmation h4 {
1586 page-break-after: avoid !important;
1587 break-after: avoid !important;
1588 }
1589 }
1590 </style>
1591
1592 <script>
1593 (function () {
1594 document.addEventListener('click', function (e) {
1595 var btn = e.target.closest('[data-yatra-print="confirmation"]');
1596 if (!btn) {
1597 return;
1598 }
1599 e.preventDefault();
1600
1601 var card = document.querySelector('.yatra-confirmation-container');
1602 if (!card) {
1603 window.print();
1604 return;
1605 }
1606
1607 // Wrap (or reuse) a print-only root so the @media print rules can target a single
1608 // direct child of <body>. Reused on the account page if the same data attribute
1609 // and CSS rules are added there.
1610 var root = document.querySelector('.yatra-print-root');
1611 var addedWrapper = false;
1612 if (!root) {
1613 root = document.createElement('div');
1614 root.className = 'yatra-print-root';
1615 document.body.appendChild(root);
1616 addedWrapper = true;
1617 }
1618 var clone = card.cloneNode(true);
1619 // Drop the action buttons from the clone so they don't appear on paper.
1620 clone.querySelectorAll('.yatra-confirmation-actions').forEach(function (n) { n.remove(); });
1621 root.innerHTML = '';
1622 root.appendChild(clone);
1623
1624 document.body.classList.add('yatra-printing-confirmation');
1625
1626 var cleanup = function () {
1627 document.body.classList.remove('yatra-printing-confirmation');
1628 if (addedWrapper && root && root.parentNode) {
1629 root.parentNode.removeChild(root);
1630 } else if (root) {
1631 root.innerHTML = '';
1632 }
1633 window.removeEventListener('afterprint', cleanup);
1634 };
1635
1636 window.addEventListener('afterprint', cleanup);
1637 // Safety net for browsers that don't fire afterprint reliably.
1638 window.setTimeout(function () {
1639 if (document.body.classList.contains('yatra-printing-confirmation')) {
1640 cleanup();
1641 }
1642 }, 5000);
1643
1644 window.print();
1645 });
1646 })();
1647 </script>
1648
1649 <?php yatra_get_footer(); ?>
1650
1651