PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
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
← All changes | templates/booking-confirmation.php +207 -8 3.0.8 → 3.0.16 View file →
@@ -43,8 +43,15 @@
43 43 $booking_amount_due = (float) ($booking->amount_due ?? 0);
44 44 $booking_is_fully_paid = $booking_payment_status === 'paid' || $booking_amount_due <= 0.01;
45 45 $show_balance_paid_banner = $is_balance_paid_request && $booking_is_fully_paid;
46 46
47 +// A gateway may redirect back here with `?payment=cancelled` (user aborted the
48 +// payment at the provider) or `?payment=failed`. Show an informative notice only
49 +// when the booking is not already fully paid, so a genuinely-paid booking that
50 +// happens to carry a stale query arg never shows a misleading "cancelled" message.
51 +$payment_result_flag = isset($_GET['payment']) ? sanitize_key((string) $_GET['payment']) : '';
52 +$show_payment_cancelled_notice = in_array($payment_result_flag, ['cancelled', 'failed'], true) && !$booking_is_fully_paid;
53 +
47 54 // Resolve the most recent gateway used on this booking.
48 55 // `$booking->payment_gateway` is the *initial* method chosen at booking time
49 56 // (e.g. Pay Later), which is misleading when the customer later settled the
50 57 // balance via a different gateway (e.g. Stripe). Show the latest payment's
@@ -172,8 +179,26 @@
172 179 </div>
173 180 </div>
174 181 <?php endif; ?>
175 182
183 + <?php if ($show_payment_cancelled_notice) : ?>
184 + <div class="yatra-payment-cancelled-banner" role="status" aria-live="polite" style="margin: 16px 0; padding: 14px 18px; background: #fef3c7; border: 1px solid #fcd34d; border-left: 4px solid #d97706; border-radius: 8px; color: #92400e; display: flex; gap: 12px; align-items: flex-start;">
185 + <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;">
186 + <circle cx="12" cy="12" r="10"></circle>
187 + <line x1="12" y1="8" x2="12" y2="12"></line>
188 + <line x1="12" y1="16" x2="12.01" y2="16"></line>
189 + </svg>
190 + <div style="flex: 1; line-height: 1.45;">
191 + <strong style="display: block; margin-bottom: 2px;">
192 + <?php esc_html_e('Payment not completed.', 'yatra'); ?>
193 + </strong>
194 + <span>
195 + <?php esc_html_e('Your payment was cancelled and no charge was made. Your booking has been saved — you can complete payment anytime from your account.', 'yatra'); ?>
196 + </span>
197 + </div>
198 + </div>
199 + <?php endif; ?>
200 +
176 201 <?php
177 202 // Resolve featured image URL (handle attachment ID or direct URL).
178 203 // Falls back to the bundled trip-placeholder.svg so the confirmation
179 204 // card always renders with a visual on the left — never an empty
@@ -209,13 +234,55 @@
209 234 <div class="yatra-trip-info">
210 235 <h2 class="yatra-trip-name"><?php echo esc_html($booking->trip_title); ?></h2>
211 236
212 237 <?php if (!empty($booking->trip_average_rating) && $booking->trip_review_count >= 0) : ?>
238 + <?php
239 + // The confirmation page isn't a "booking page" (it has its
240 + // own route), so booking.css — which colours the rating
241 + // stars amber — is never enqueued here and the filled stars
242 + // fell back to the grey base colour. The rest of this page
243 + // is inline-styled, so rather than loading the whole
244 + // stylesheet (and risk restyling it) the rating rules are
245 + // scoped inline here, mirroring assets/css/booking.css.
246 + ?>
247 + <?php
248 + // IMPORTANT: these rules are deliberately scoped to
249 + // `.yatra-trip-rating .yatra-rating-stars .yatra-star*`
250 + // (specificity 0,3,0 / 0,4,1) and set `fill` directly on
251 + // the SVG — NOT just `color` + `fill="currentColor"`.
252 + // trip.css / booking.css define `.yatra-rating-stars
253 + // .yatra-star { color:#d1d5db }` (0,2,0) and colour the
254 + // "filled" state with a `.filled` (dot) class, not the
255 + // `-filled` (hyphen) class this markup uses. If either
256 + // stylesheet is present on the confirmation page, its
257 + // grey base out-specifies a plain `.yatra-star-filled`
258 + // and its amber rule never matches — so every star showed
259 + // grey even at 4.8. Winning on specificity + an explicit
260 + // fill makes the amber stick regardless of what's loaded.
261 + ?>
262 + <style>
263 + .yatra-trip-rating{display:flex;align-items:center;gap:12px;margin-bottom:12px}
264 + .yatra-trip-rating .yatra-rating-stars{display:inline-flex;gap:4px}
265 + .yatra-trip-rating .yatra-rating-stars .yatra-star{width:20px;height:20px;color:#e2e8f0;font-size:0;line-height:0}
266 + .yatra-trip-rating .yatra-rating-stars .yatra-star svg{width:100%;height:100%;display:block;fill:currentColor}
267 + .yatra-trip-rating .yatra-rating-stars .yatra-star-filled{color:#f59e0b}
268 + .yatra-trip-rating .yatra-rating-stars .yatra-star-filled svg{fill:#f59e0b}
269 + .yatra-trip-rating .yatra-rating-stars .yatra-star-half{position:relative;color:#e2e8f0}
270 + .yatra-trip-rating .yatra-rating-stars .yatra-star-half svg{fill:#e2e8f0}
271 + .yatra-trip-rating .yatra-rating-stars .yatra-star-half::after{content:"";position:absolute;top:0;left:0;bottom:0;width:50%;overflow:hidden;background:#f59e0b;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%}
272 + .yatra-trip-rating .yatra-rating-meta strong{color:#0f172a;margin-right:6px}
273 + .yatra-trip-rating .yatra-rating-meta span{color:#64748b;font-size:14px}
274 + </style>
213 275 <div class="yatra-trip-rating">
214 276 <div class="yatra-rating-stars">
215 277 <?php
216 - $filled_stars = floor($booking->trip_average_rating);
217 - $has_half = ($booking->trip_average_rating - $filled_stars) >= 0.5;
278 + // Shared with the reviews block and listing cards so every
279 + // surface draws the same rating. Rounds to the nearest half:
280 + // flooring drew 4.9 as four-and-a-half stars, which looked
281 + // wrong beside the printed "4.9".
282 + $star_parts = yatra_rating_star_parts($booking->trip_average_rating);
283 + $filled_stars = $star_parts['full'];
284 + $has_half = $star_parts['half'];
218 285 for ($i = 1; $i <= 5; $i++) :
219 286 $class = $i <= $filled_stars ? 'yatra-star-filled' : ($has_half && $i === $filled_stars + 1 ? 'yatra-star-half' : '');
220 287 ?>
221 288 <span class="yatra-star <?php echo esc_attr($class); ?>">
@@ -240,9 +307,9 @@
240 307 </div>
241 308 <?php endif; ?>
242 309
243 310 <div class="yatra-trip-meta">
244 - <?php if (!empty($booking->duration_days)) : ?>
311 + <?php if (!empty($booking->duration_days) || !empty($booking->duration_hours)) : ?>
245 312 <span class="yatra-meta-item">
246 313 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
247 314 <circle cx="12" cy="12" r="10"></circle>
248 315 <polyline points="12 6 12 12 16 14"></polyline>
@@ -249,11 +316,21 @@
249 316 </svg>
250 317 <?php
251 318 $days = (int) ($booking->duration_days ?? 0);
252 319 $nights = (int) ($booking->duration_nights ?? 0);
320 + $hours = (int) ($booking->duration_hours ?? 0);
253 321
254 - if ($days > 0 && $nights > 0) {
322 + if ($hours > 0) {
323 + // Hour-based day tour: "8 Hours", not "1 Day".
255 324 printf(
325 + esc_html(
326 + /* translators: %d: number of hours. */
327 + _n('%d Hour', '%d Hours', $hours, 'yatra')
328 + ),
329 + $hours
330 + );
331 + } elseif ($days > 0 && $nights > 0) {
332 + printf(
256 333 /* translators: 1: number of days, 2: number of nights. */
257 334 esc_html__('%1$d Days / %2$d Nights', 'yatra'),
258 335 $days,
259 336 $nights
@@ -674,9 +751,9 @@
674 751 </div>
675 752
676 753 <div class="yatra-payment-method">
677 754 <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>
755 + <span class="yatra-pm-value"><?php echo esc_html(yatra_payment_gateway_label((string) $display_payment_gateway)); ?></span>
679 756 </div>
680 757 </div>
681 758
682 759 <!-- Contact Info Card -->
@@ -810,10 +887,10 @@
810 887 ],
811 888 rest_url('yatra/v1/payment/' . (int) $latestPayment->id . '/invoice')
812 889 );
813 890 ?>
814 - <a href="<?php echo esc_url($invoiceUrl); ?>"
815 - target="_blank"
891 + <a href="<?php echo esc_url($invoiceUrl); ?>"
892 + target="_blank"
816 893 rel="noopener"
817 894 class="yatra-btn yatra-btn-primary">
818 895 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
819 896 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
@@ -821,8 +898,33 @@
821 898 <line x1="12" y1="15" x2="12" y2="3"></line>
822 899 </svg>
823 900 <?php esc_html_e('Download Invoice', 'yatra'); ?>
824 901 </a>
902 + <?php
903 + // No completed payment yet (e.g. Bank Transfer / offline): offer a
904 + // pro-forma invoice that carries the payment instructions so the
905 + // customer knows how to pay. Uses a booking-scoped invoice token.
906 + elseif ((float) ($booking->amount_due ?? $booking->total_amount ?? 0) > 0) :
907 + $proformaToken = \Yatra\Controllers\PaymentGatewayController::issueInvoiceToken(0, (int) $booking->id);
908 + $proformaUrl = add_query_arg(
909 + [
910 + 'download' => '1',
911 + 'invoice_token' => $proformaToken,
912 + ],
913 + rest_url('yatra/v1/booking/' . (int) $booking->id . '/invoice')
914 + );
915 + ?>
916 + <a href="<?php echo esc_url($proformaUrl); ?>"
917 + target="_blank"
918 + rel="noopener"
919 + class="yatra-btn yatra-btn-primary">
920 + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
921 + <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
922 + <polyline points="7 10 12 15 17 10"></polyline>
923 + <line x1="12" y1="15" x2="12" y2="3"></line>
924 + </svg>
925 + <?php esc_html_e('Download Invoice', 'yatra'); ?>
926 + </a>
825 927 <?php endif; ?>
826 928
827 929 <button type="button" data-yatra-print="confirmation" class="yatra-btn yatra-btn-outline">
828 930 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -972,8 +1074,68 @@
972 1074 color: #111827;
973 1075 margin: 0 0 12px;
974 1076 }
975 1077
1078 +/* Star rating. This confirmation page only enqueues yatra-common + fontawesome,
1079 + not booking.css/trip.css where these live, so without them the inline SVG
1080 + stars render with no size or colour (invisible). Mirrors booking.css. */
1081 +.yatra-trip-rating {
1082 + display: flex;
1083 + align-items: center;
1084 + gap: 12px;
1085 + margin-bottom: 12px;
1086 +}
1087 +
1088 +.yatra-rating-stars {
1089 + display: inline-flex;
1090 + gap: 4px;
1091 +}
1092 +
1093 +.yatra-star {
1094 + width: 20px;
1095 + height: 20px;
1096 + color: #e2e8f0;
1097 +}
1098 +
1099 +.yatra-star svg {
1100 + width: 100%;
1101 + height: 100%;
1102 +}
1103 +
1104 +.yatra-star-filled {
1105 + color: #f59e0b;
1106 +}
1107 +
1108 +/* Half star: base star stays grey; overlay the left half in amber via an
1109 + SVG mask (size-independent, so it tracks the star's dimensions). */
1110 +.yatra-star-half {
1111 + position: relative;
1112 + color: #e2e8f0;
1113 +}
1114 +
1115 +.yatra-star-half::after {
1116 + content: "";
1117 + position: absolute;
1118 + top: 0;
1119 + left: 0;
1120 + bottom: 0;
1121 + width: 50%;
1122 + overflow: hidden;
1123 + background: #f59e0b;
1124 + -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%;
1125 + mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26'/%3E%3C/svg%3E") no-repeat left center / 200% 100%;
1126 +}
1127 +
1128 +.yatra-rating-meta strong {
1129 + color: #0f172a;
1130 + margin-right: 6px;
1131 +}
1132 +
1133 +.yatra-rating-meta span {
1134 + color: #64748b;
1135 + font-size: 14px;
1136 +}
1137 +
976 1138 .yatra-trip-meta {
977 1139 display: flex;
978 1140 gap: 20px;
979 1141 flex-wrap: wrap;
@@ -1132,8 +1294,44 @@
1132 1294 .yatra-discount-row span:last-child {
1133 1295 color: #22c55e;
1134 1296 }
1135 1297
1298 +/* Bank-transfer details (markup injected by Yatra Pro's Bank Transfer gateway
1299 + into this page). The card reuses this page's .yatra-confirmation-card /
1300 + .yatra-card-title classes, but its rows had no styling at all, so the values
1301 + sat immediately after their label while every other row on the page is
1302 + flex/space-between — the bank values were the only ones not flush right.
1303 + Styling lives here because this template owns the confirmation page's CSS
1304 + and Pro enqueues no stylesheet on this page. */
1305 +.yatra-bank-info-grid {
1306 + border: 1px solid #e5e7eb;
1307 + border-radius: 8px;
1308 + overflow: hidden;
1309 +}
1310 +
1311 +.yatra-bank-info-item {
1312 + display: flex;
1313 + justify-content: space-between;
1314 + align-items: baseline;
1315 + gap: 12px;
1316 + padding: 12px 16px;
1317 + border-bottom: 1px solid #e5e7eb;
1318 +}
1319 +
1320 +.yatra-bank-info-item:last-child {
1321 + border-bottom: none;
1322 +}
1323 +
1324 +.yatra-bank-label {
1325 + color: #6b7280;
1326 + flex-shrink: 0;
1327 +}
1328 +
1329 +.yatra-bank-value {
1330 + text-align: right;
1331 + word-break: break-word;
1332 +}
1333 +
1136 1334 .yatra-payment-method {
1137 1335 margin-top: 16px;
1138 1336 padding: 12px;
1139 1337 background: white;
@@ -1531,9 +1729,10 @@
1531 1729 /* Payment summary rows */
1532 1730 body.yatra-printing-confirmation .yatra-payment-rows {
1533 1731 margin: 0 !important;
1534 1732 }
1535 - body.yatra-printing-confirmation .yatra-payment-row {
1733 + body.yatra-printing-confirmation .yatra-payment-row,
1734 + body.yatra-printing-confirmation .yatra-bank-info-item {
1536 1735 display: flex !important;
1537 1736 justify-content: space-between !important;
1538 1737 align-items: baseline !important;
1539 1738 gap: 12pt !important;