| 1 |
<?php |
| 2 |
/** |
| 3 |
* Single Activity Template |
| 4 |
* |
| 5 |
* Displays individual activity page with associated trips |
| 6 |
* Uses global $activity object (similar to WordPress $post) |
| 7 |
* |
| 8 |
* @package Yatra |
| 9 |
* @global object $activity Activity data object |
| 10 |
*/ |
| 11 |
|
| 12 |
// Prevent direct access |
| 13 |
if (!defined('ABSPATH')) { |
| 14 |
exit; |
| 15 |
} |
| 16 |
|
| 17 |
// Access global $activity object |
| 18 |
global $activity; |
| 19 |
|
| 20 |
// Debug: Check what data we have |
| 21 |
if (defined('WP_DEBUG') && WP_DEBUG) { |
| 22 |
} |
| 23 |
|
| 24 |
// Bail if no activity data - return proper 404 |
| 25 |
if (!$activity) { |
| 26 |
global $wp_query; |
| 27 |
$wp_query->set_404(); |
| 28 |
status_header(404); |
| 29 |
get_template_part(404); |
| 30 |
exit; |
| 31 |
} |
| 32 |
|
| 33 |
// Set up page title |
| 34 |
add_filter('wp_title', function($title) { |
| 35 |
global $activity; |
| 36 |
return esc_html($activity->name) . ' - ' . get_bloginfo('name'); |
| 37 |
}, 10, 1); |
| 38 |
|
| 39 |
yatra_get_header(); |
| 40 |
?> |
| 41 |
|
| 42 |
<div class="yatra-single-activity" style="max-width: 1200px; margin: 0 auto; padding: 40px 20px;"> |
| 43 |
<!-- Activity Header --> |
| 44 |
<div class="activity-header" style="margin-bottom: 40px;"> |
| 45 |
<h1 style="font-size: 2.5rem; margin-bottom: 16px; color: #1f2937;"> |
| 46 |
<?php echo esc_html($activity->name); ?> |
| 47 |
</h1> |
| 48 |
|
| 49 |
<?php if (!empty($activity->description)): ?> |
| 50 |
<div class="activity-description" style="font-size: 1.125rem; color: #6b7280; line-height: 1.6;"> |
| 51 |
<?php echo wp_kses_post($activity->description); ?> |
| 52 |
</div> |
| 53 |
<?php endif; ?> |
| 54 |
</div> |
| 55 |
|
| 56 |
<!-- Activity Icon/Image --> |
| 57 |
<?php if (!empty($activity->icon)): ?> |
| 58 |
<div class="activity-media" style="margin-bottom: 40px;"> |
| 59 |
<?php |
| 60 |
$icon = maybe_unserialize($activity->icon); |
| 61 |
$image_url = ''; |
| 62 |
$icon_class = ''; |
| 63 |
|
| 64 |
if (is_array($icon)) { |
| 65 |
$type = $icon['type'] ?? $icon[0] ?? ''; |
| 66 |
$value = $icon['value'] ?? $icon[1] ?? ''; |
| 67 |
|
| 68 |
if ($type === 'image' && !empty($value)) { |
| 69 |
if (is_numeric($value)) { |
| 70 |
$maybe_url = wp_get_attachment_image_url((int) $value, 'large'); |
| 71 |
if (!empty($maybe_url)) { |
| 72 |
$image_url = $maybe_url; |
| 73 |
} |
| 74 |
} elseif (is_string($value) && filter_var($value, FILTER_VALIDATE_URL)) { |
| 75 |
$image_url = $value; |
| 76 |
} |
| 77 |
} elseif ($type === 'icon' && !empty($value) && is_string($value)) { |
| 78 |
$icon_class = $value; |
| 79 |
} |
| 80 |
} |
| 81 |
?> |
| 82 |
|
| 83 |
<?php if (!empty($image_url)): ?> |
| 84 |
<div class="activity-image" style="width: 100%; max-width: 600px; margin: 0 auto;"> |
| 85 |
<img src="<?php echo esc_url($image_url); ?>" |
| 86 |
alt="<?php echo esc_attr($activity->name); ?>" |
| 87 |
style="width: 100%; height: auto; border-radius: 12px; box-shadow: 0 10px 25px rgba(0,0,0,0.1);"> |
| 88 |
</div> |
| 89 |
<?php elseif (!empty($icon_class)): ?> |
| 90 |
<div class="activity-icon" style="text-align: center; padding: 60px; background: linear-gradient(135deg, #f3f4f6 0%, #e5e7eb 100%); border-radius: 12px; margin: 0 auto; max-width: 400px;"> |
| 91 |
<div style="font-size: 4rem; color: #4b5563;"> |
| 92 |
<?php echo yatra_svg_icon($icon_class, 'activity-large-icon'); ?> |
| 93 |
</div> |
| 94 |
</div> |
| 95 |
<?php endif; ?> |
| 96 |
</div> |
| 97 |
<?php endif; ?> |
| 98 |
|
| 99 |
<!-- Activity Stats --> |
| 100 |
<?php if (!empty($activity->trips_count) || !empty($activity->avg_rating)): ?> |
| 101 |
<div class="activity-stats" style="display: flex; gap: 24px; margin-bottom: 40px; justify-content: center; flex-wrap: wrap;"> |
| 102 |
<?php if (!empty($activity->trips_count)): ?> |
| 103 |
<div class="stat-item" style="text-align: center; padding: 20px; background: #f8fafc; border-radius: 8px; min-width: 120px;"> |
| 104 |
<div style="font-size: 2rem; font-weight: bold; color: #059669; margin-bottom: 4px;"> |
| 105 |
<?php echo esc_html($activity->trips_count); ?> |
| 106 |
</div> |
| 107 |
<div style="color: #6b7280; font-size: 0.875rem;"> |
| 108 |
<?php echo esc_html(_n('Trip', 'Trips', (int)$activity->trips_count, 'yatra')); ?> |
| 109 |
</div> |
| 110 |
</div> |
| 111 |
<?php endif; ?> |
| 112 |
|
| 113 |
<?php if (!empty($activity->avg_rating)): ?> |
| 114 |
<div class="stat-item" style="text-align: center; padding: 20px; background: #f8fafc; border-radius: 8px; min-width: 120px;"> |
| 115 |
<div style="font-size: 2rem; font-weight: bold; color: #f59e0b; margin-bottom: 4px;"> |
| 116 |
<?php echo esc_html(number_format($activity->avg_rating, 1)); ?> |
| 117 |
</div> |
| 118 |
<div style="color: #6b7280; font-size: 0.875rem;"> |
| 119 |
<?php esc_html_e('Rating', 'yatra'); ?> |
| 120 |
</div> |
| 121 |
</div> |
| 122 |
<?php endif; ?> |
| 123 |
|
| 124 |
<?php if (!empty($activity->starting_price)): ?> |
| 125 |
<div class="stat-item" style="text-align: center; padding: 20px; background: #f8fafc; border-radius: 8px; min-width: 120px;"> |
| 126 |
<div style="font-size: 1.5rem; font-weight: bold; color: #2563eb; margin-bottom: 4px;"> |
| 127 |
<?php echo esc_html($activity->starting_price); ?> |
| 128 |
</div> |
| 129 |
<div style="color: #6b7280; font-size: 0.875rem;"> |
| 130 |
<?php esc_html_e('From', 'yatra'); ?> |
| 131 |
</div> |
| 132 |
</div> |
| 133 |
<?php endif; ?> |
| 134 |
</div> |
| 135 |
<?php endif; ?> |
| 136 |
|
| 137 |
<!-- Available Trips --> |
| 138 |
<div class="activity-trips" style="margin-top: 60px;"> |
| 139 |
<h2 style="font-size: 2rem; margin-bottom: 24px; color: #1f2937; text-align: center;"> |
| 140 |
<?php esc_html_e('Available Trips', 'yatra'); ?> |
| 141 |
</h2> |
| 142 |
|
| 143 |
<?php if (!empty($activity->trips) && is_array($activity->trips)): ?> |
| 144 |
<?php |
| 145 |
$yatra_dp_flags_activity = function_exists('yatra_get_dynamic_pricing_display_flags') ? yatra_get_dynamic_pricing_display_flags() : [ |
| 146 |
'show_original_price' => true, |
| 147 |
'show_savings_badge' => true, |
| 148 |
'show_urgency_messages' => false, |
| 149 |
]; |
| 150 |
?> |
| 151 |
<div class="yatra-trip-grid"> |
| 152 |
<?php foreach ($activity->trips as $trip): ?> |
| 153 |
<div class="yatra-trip-card"> |
| 154 |
<div class="yatra-trip-image"> |
| 155 |
<?php if (!empty($trip->featured_image_url)): ?> |
| 156 |
<img src="<?php echo esc_url($trip->featured_image_url); ?>" alt="<?php echo esc_attr($trip->title ?? $trip->name ?? __('Trip', 'yatra')); ?>"> |
| 157 |
<?php else: ?> |
| 158 |
<img src="<?php echo esc_url(plugins_url('assets/images/trip-placeholder.svg', YATRA_PLUGIN_FILE)); ?>" alt="<?php echo esc_attr($trip->title ?? $trip->name ?? __('Trip', 'yatra')); ?>"> |
| 159 |
<?php endif; ?> |
| 160 |
|
| 161 |
<?php if (!empty($trip->discount_percentage) && $trip->discount_percentage > 0 && !empty($yatra_dp_flags_activity['show_savings_badge'])): ?> |
| 162 |
<div class="yatra-discount-badge"> |
| 163 |
<?php |
| 164 |
printf( |
| 165 |
/* translators: %s: discount percentage */ |
| 166 |
esc_html__('%s%% OFF', 'yatra'), |
| 167 |
esc_html($trip->discount_percentage) |
| 168 |
); |
| 169 |
?> |
| 170 |
</div> |
| 171 |
<?php endif; ?> |
| 172 |
|
| 173 |
<?php if (function_exists('yatra_wishlist_enabled') && yatra_wishlist_enabled() && !empty($trip->id)) : ?> |
| 174 |
<button type="button" class="yatra-favorite-btn yatra-similar-favorite-btn" data-trip-id="<?php echo esc_attr((string) $trip->id); ?>" title="<?php esc_attr_e('Save to wishlist', 'yatra'); ?>"> |
| 175 |
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 176 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"/> |
| 177 |
</svg> |
| 178 |
</button> |
| 179 |
<?php endif; ?> |
| 180 |
</div> |
| 181 |
|
| 182 |
<div class="yatra-trip-content"> |
| 183 |
<div class="yatra-trip-meta"> |
| 184 |
<span class="yatra-trip-location"><?php echo esc_html($trip->location ?? $activity->name); ?></span> |
| 185 |
<?php if (!empty($trip->duration)): ?> |
| 186 |
<span class="yatra-trip-separator">•</span> |
| 187 |
<span class="yatra-trip-duration"><?php echo esc_html($trip->duration); ?> <?php esc_html_e('Days', 'yatra'); ?></span> |
| 188 |
<?php endif; ?> |
| 189 |
<?php if (!empty($trip->difficulty)): ?> |
| 190 |
<span class="yatra-trip-separator">•</span> |
| 191 |
<span class="yatra-trip-difficulty"><?php echo esc_html($trip->difficulty); ?></span> |
| 192 |
<?php endif; ?> |
| 193 |
</div> |
| 194 |
|
| 195 |
<h3 class="yatra-trip-title"> |
| 196 |
<a href="<?php echo esc_url($trip->permalink ?? ''); ?>"> |
| 197 |
<?php echo esc_html($trip->title ?? $trip->name ?? __('Untitled Trip', 'yatra')); ?> |
| 198 |
</a> |
| 199 |
</h3> |
| 200 |
|
| 201 |
<?php if (!empty($trip->destinations) && is_array($trip->destinations)): ?> |
| 202 |
<div class="yatra-trip-highlights"> |
| 203 |
<?php foreach (array_slice($trip->destinations, 0, 3) as $destination): ?> |
| 204 |
<span class="yatra-highlight-badge"><?php echo esc_html($destination->name ?? ''); ?></span> |
| 205 |
<?php endforeach; ?> |
| 206 |
</div> |
| 207 |
<?php endif; ?> |
| 208 |
|
| 209 |
<div class="yatra-trip-rating"> |
| 210 |
<div class="yatra-rating-stars"> |
| 211 |
<svg width="16" height="16" fill="#fbbf24" viewBox="0 0 24 24"> |
| 212 |
<path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/> |
| 213 |
</svg> |
| 214 |
<span class="yatra-rating-value"><?php echo esc_html(number_format($trip->average_rating ?? 0, 1)); ?></span> |
| 215 |
</div> |
| 216 |
<span class="yatra-reviews-count">(<?php echo esc_html($trip->review_count ?? 0); ?> <?php esc_html_e('reviews', 'yatra'); ?>)</span> |
| 217 |
</div> |
| 218 |
|
| 219 |
<div class="yatra-trip-footer"> |
| 220 |
<div class="yatra-trip-price"> |
| 221 |
<?php |
| 222 |
$raw_orig_act = (float) ($trip->original_price ?? 0); |
| 223 |
$raw_eff_act = (float) ($trip->effective_price_min ?? $trip->original_price ?? 0); |
| 224 |
$disp_orig_act = $raw_orig_act; |
| 225 |
$disp_eff_act = $raw_eff_act; |
| 226 |
if (apply_filters('yatra_dynamic_pricing_enabled', false)) { |
| 227 |
if ($disp_eff_act > 0) { |
| 228 |
$disp_eff_act = apply_filters('yatra_trip_display_price', $disp_eff_act, (int) ($trip->id ?? 0), [ |
| 229 |
'departure_date' => null, |
| 230 |
'spots_remaining' => null, |
| 231 |
'original_price' => $raw_orig_act > 0 ? $raw_orig_act : (float) $disp_eff_act, |
| 232 |
'discounted_price' => $raw_eff_act > 0 ? $raw_eff_act : (float) $disp_eff_act, |
| 233 |
]); |
| 234 |
} |
| 235 |
} |
| 236 |
$yatra_act_urgency = function_exists('yatra_trip_card_dynamic_pricing_urgency_lines') |
| 237 |
? yatra_trip_card_dynamic_pricing_urgency_lines((int) ($trip->id ?? 0), [ |
| 238 |
'base_sale_price' => $raw_eff_act, |
| 239 |
'base_original_price' => $raw_orig_act, |
| 240 |
'sale_price' => (float) $disp_eff_act, |
| 241 |
'original_price' => (float) $disp_orig_act, |
| 242 |
'departure_date' => null, |
| 243 |
'spots_remaining' => null, |
| 244 |
'availability_id' => null, |
| 245 |
'surface' => 'activity_card', |
| 246 |
]) |
| 247 |
: []; |
| 248 |
?> |
| 249 |
<?php if (!empty($yatra_dp_flags_activity['show_original_price']) && $disp_orig_act > 0 && $disp_eff_act > 0 && $disp_orig_act > $disp_eff_act): ?> |
| 250 |
<div class="yatra-original-price"><?php echo esc_html(yatra_format_price($disp_orig_act)); ?></div> |
| 251 |
<?php endif; ?> |
| 252 |
<div class="yatra-current-price"> |
| 253 |
<?php |
| 254 |
if ($disp_eff_act > 0) { |
| 255 |
echo esc_html(yatra_format_price($disp_eff_act)); |
| 256 |
} elseif ($disp_orig_act > 0) { |
| 257 |
echo esc_html(yatra_format_price($disp_orig_act)); |
| 258 |
} else { |
| 259 |
echo esc_html__('Price on request', 'yatra'); |
| 260 |
} |
| 261 |
?> |
| 262 |
</div> |
| 263 |
<div class="yatra-price-note"><?php esc_html_e('per person', 'yatra'); ?></div> |
| 264 |
<?php if (!empty($yatra_act_urgency)) : ?> |
| 265 |
<?php foreach ($yatra_act_urgency as $yatra_a_urg) : ?> |
| 266 |
<div style="margin-top:6px;font-size:11px;line-height:1.35;color:#92400e;background:#fef3c7;padding:4px 6px;border-radius:4px;"> |
| 267 |
<?php echo esc_html((string) $yatra_a_urg); ?> |
| 268 |
</div> |
| 269 |
<?php endforeach; ?> |
| 270 |
<?php endif; ?> |
| 271 |
</div> |
| 272 |
<a href="<?php echo esc_url($trip->permalink ?? ''); ?>" class="yatra-btn yatra-btn-primary yatra-archive-card-cta yatra-card-view-btn"> |
| 273 |
<?php echo yatra_svg_icon('file-text', 'yatra-btn-icon'); ?> |
| 274 |
<span><?php esc_html_e('View Details', 'yatra'); ?></span> |
| 275 |
</a> |
| 276 |
</div> |
| 277 |
</div> |
| 278 |
</div> |
| 279 |
<?php endforeach; ?> |
| 280 |
</div> |
| 281 |
<?php else: ?> |
| 282 |
<div style="text-align: center; padding: 40px; background: #f9fafb; border-radius: 12px; margin-bottom: 40px;"> |
| 283 |
<p style="color: #6b7280; margin: 0 0 16px 0;"> |
| 284 |
<?php esc_html_e('No trips are currently available with this activity.', 'yatra'); ?> |
| 285 |
</p> |
| 286 |
<a href="<?php echo esc_url(function_exists('yatra_get_trip_listing_url') ? yatra_get_trip_listing_url() : home_url('/' . \Yatra\Services\SettingsService::getTripBase() . '/')); ?>" |
| 287 |
style="color: #2563eb; text-decoration: none; font-weight: 500;"> |
| 288 |
<?php esc_html_e('Browse all trips', 'yatra'); ?> |
| 289 |
</a> |
| 290 |
</div> |
| 291 |
<?php endif; ?> |
| 292 |
|
| 293 |
<div style="text-align: center;"> |
| 294 |
<a href="<?php echo esc_url(add_query_arg(['activity' => urlencode($activity->slug)], function_exists('yatra_get_trip_listing_url') ? yatra_get_trip_listing_url() : home_url('/' . \Yatra\Services\SettingsService::getTripBase() . '/'))); ?>" |
| 295 |
class="yatra-btn" |
| 296 |
style="display: inline-flex; align-items: center; gap: 8px; padding: 12px 24px; background: #059669; color: white; text-decoration: none; border-radius: 6px; font-weight: 600; transition: background-color 0.2s;"> |
| 297 |
<svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 298 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/> |
| 299 |
</svg> |
| 300 |
<?php esc_html_e('View All Trips with', 'yatra'); ?> <?php echo esc_html($activity->name); ?> |
| 301 |
</a> |
| 302 |
</div> |
| 303 |
</div> |
| 304 |
|
| 305 |
<!-- Back to Activities --> |
| 306 |
<div style="text-align: center; margin-top: 60px; padding-top: 40px; border-top: 1px solid #e5e7eb;"> |
| 307 |
<a href="<?php echo esc_url(function_exists('yatra_get_taxonomy_listing_url') ? yatra_get_taxonomy_listing_url('activity') : home_url('/' . \Yatra\Services\SettingsService::getActivityBase() . '/')); ?>" |
| 308 |
style="color: #6b7280; text-decoration: none; display: inline-flex; align-items: center; gap: 8px;"> |
| 309 |
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 310 |
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"/> |
| 311 |
</svg> |
| 312 |
<?php esc_html_e('Back to All Activities', 'yatra'); ?> |
| 313 |
</a> |
| 314 |
</div> |
| 315 |
</div> |
| 316 |
|
| 317 |
<?php |
| 318 |
yatra_get_footer(); |
| 319 |
?> |
| 320 |
|