PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.2.7
Yatra – Travel Booking & Tour Operator Software v3.0.2.7
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 / listing-trip.php

listing-trip.php in Yatra – Travel Booking & Tour Operator Software 3.0.2.7, at templates/listing-trip.php

850 lines 56.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Trip listing template (presentation). Data is prepared in {@see TripListingPageContextFactory} and set by {@see ListingPageHandler}.
4 *
5 * @package Yatra
6 */
7
8 use Yatra\Services\TripListingService;
9
10 if (!defined('ABSPATH')) {
11 exit;
12 }
13
14 $tripListingService = new TripListingService();
15
16 $ctx = $GLOBALS['yatra_trip_listing_context'] ?? [];
17 $filter_data = $ctx['filter_data'] ?? [];
18 if ($filter_data === []) {
19 $filter_data = $tripListingService->getFilterData();
20 }
21 $yatra_trip_list = $ctx['trip_list'] ?? ($GLOBALS['yatra_trip_list'] ?? null);
22 $trips_source = $ctx['trips'] ?? [];
23 $trip_total = (int) ($ctx['total'] ?? 0);
24 $trip_total_pages = (int) ($ctx['pages'] ?? 1);
25 $trip_current_page = (int) ($ctx['current_page'] ?? 1);
26 $trip_dest_options = $ctx['destinations'] ?? [];
27 $trip_act_options = $ctx['activities'] ?? [];
28 $active_filters = $ctx['active_filters'] ?? [];
29 $yatra_listing_title = $ctx['listing_title'] ?? __('All Trips', 'yatra');
30 $current_filter_type = $ctx['taxonomy_type'] ?? '';
31 $current_filter_slug = $ctx['taxonomy_slug'] ?? '';
32 $current_filter_name = $ctx['taxonomy_name'] ?? '';
33 $yatra_results = $ctx['results'] ?? [
34 'display_total' => 0,
35 'start_item' => 0,
36 'end_item' => 0,
37 'per_page' => yatra_get_posts_per_page(),
38 ];
39 $yatra_pagination = $ctx['pagination'] ?? [
40 'total_pages' => 1,
41 'current_page' => 1,
42 'prev_url' => null,
43 'next_url' => null,
44 'items' => [],
45 ];
46 $yatra_sort_options = $ctx['sort_options'] ?? [];
47 $show_taxonomy_context = !empty($ctx['show_taxonomy_context']);
48
49 yatra_get_header();
50 ?>
51
52 <?php if ($show_taxonomy_context) : ?>
53 <div id="yatra-trip-context"
54 data-type="<?php echo esc_attr($current_filter_type); ?>"
55 data-slug="<?php echo esc_attr($current_filter_slug); ?>"
56 data-name="<?php echo esc_attr($current_filter_name); ?>"
57 style="display:none;"></div>
58 <?php endif; ?>
59
60 <div class="yatra-listing-page yatra-trip-listing" id="yatra-trip-listing-root">
61 <!-- Trip Search Shortcode - replaces hardcoded search UI -->
62 <div class="yatra-trip-listing-search-wrap">
63 <?php echo do_shortcode('[yatra_search]'); ?>
64 </div>
65
66 <div class="yatra-listing-wrapper yatra-listing-wrapper--overlay-host">
67 <div id="yatra-listing-loading-overlay" class="yatra-listing-loading-overlay" aria-hidden="true" role="status">
68 <div class="yatra-listing-loading-card">
69 <span class="yatra-listing-loading-spinner" aria-hidden="true"></span>
70 <p class="yatra-listing-loading-text"><?php esc_html_e('Updating trips…', 'yatra'); ?></p>
71 </div>
72 </div>
73 <div class="yatra-listing-container">
74
75 <!-- Results Header -->
76 <div class="yatra-results-header">
77 <div class="yatra-results-info">
78 <h1><?php echo esc_html($yatra_listing_title); ?></h1>
79 <?php if (empty($show_taxonomy_context)) : ?>
80 <p class="yatra-listing-archive-lede"><?php esc_html_e('Compare trips, filter by budget and trip style, then open a trip for full details and booking.', 'yatra'); ?></p>
81 <?php elseif (!empty($current_filter_name) || !empty($current_filter_slug)) : ?>
82 <p class="yatra-listing-archive-lede"><?php
83 printf(
84 esc_html__('Filtered by: %s', 'yatra'),
85 esc_html($current_filter_name !== '' ? $current_filter_name : (string) $current_filter_slug)
86 );
87 ?></p>
88 <?php endif; ?>
89 <p class="yatra-results-count">
90 <?php
91 if ($yatra_results['display_total'] > 0) {
92 echo sprintf(
93 __('Showing <strong>%d-%d</strong> of %d trips (Page %d of %d)', 'yatra'),
94 (int) $yatra_results['start_item'],
95 (int) $yatra_results['end_item'],
96 (int) $yatra_results['display_total'],
97 $trip_current_page,
98 $trip_total_pages
99 );
100 } else {
101 echo esc_html__('No trips found', 'yatra');
102 }
103 ?>
104 </p>
105 </div>
106 <div class="yatra-results-controls">
107 <div class="yatra-sort-control">
108 <label><?php esc_html_e('Sort by:', 'yatra'); ?></label>
109 <?php
110 ?>
111 <select id="yatra-sort-filter" class="yatra-sort-filter-select">
112 <?php foreach ($yatra_sort_options as $sort_opt) : ?>
113 <option value="<?php echo esc_attr(esc_url($sort_opt['url'])); ?>"<?php echo !empty($sort_opt['selected']) ? ' selected="selected"' : ''; ?>>
114 <?php echo esc_html($sort_opt['label']); ?>
115 </option>
116 <?php endforeach; ?>
117 </select>
118 </div>
119 <div class="yatra-view-toggle">
120 <button class="yatra-view-btn active" data-view="grid" title="<?php esc_attr_e('Grid View', 'yatra'); ?>">
121 <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
122 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z"/>
123 </svg>
124 </button>
125 <button class="yatra-view-btn" data-view="list" title="<?php esc_attr_e('List View', 'yatra'); ?>">
126 <svg width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
127 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"/>
128 </svg>
129 </button>
130 </div>
131 </div>
132 </div>
133
134 <div class="yatra-listing-layout">
135 <!-- Filter Sidebar - Comprehensive Filters -->
136 <aside class="yatra-filter-sidebar">
137 <div class="yatra-filter-header">
138 <h2><?php esc_html_e('Filters', 'yatra'); ?></h2>
139 <button type="button" class="yatra-clear-filters"><?php esc_html_e('Clear all', 'yatra'); ?></button>
140 </div>
141
142 <!-- Price Range -->
143 <?php
144 $price_stats = $filter_data['price_stats'] ?? $tripListingService->getPriceStats();
145
146 $min_price = $price_stats ? (int)$price_stats->min_price : 0;
147 $max_price = $price_stats ? (int)$price_stats->max_price : 10000;
148 $step = max(1, (int)($max_price / 100)); // Dynamic step based on price range
149 ?>
150 <div class="yatra-filter-section">
151 <div class="yatra-filter-title" data-toggle="price">
152 <div class="yatra-filter-title-content">
153 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
154 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/>
155 </svg>
156 <span><?php esc_html_e('Price Range', 'yatra'); ?></span>
157 </div>
158 <div class="yatra-filter-actions">
159 <span class="yatra-clear-section" data-section="price" title="<?php esc_attr_e('Clear price filters', 'yatra'); ?>">
160 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
161 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
162 </svg>
163 </span>
164 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
165 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
166 </svg>
167 </div>
168 </div>
169 <div class="yatra-filter-content">
170 <div class="yatra-price-range">
171 <div class="yatra-price-inputs">
172 <div class="yatra-price-input-group">
173 <label class="yatra-price-input-label"><?php esc_html_e('Min Price', 'yatra'); ?></label>
174 <input type="number" name="price_min" placeholder="<?php echo $min_price; ?>" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" value="<?php echo !empty($active_filters['price_min']) ? esc_attr($active_filters['price_min']) : ''; ?>" id="priceMin">
175 </div>
176 <div class="yatra-price-separator">—</div>
177 <div class="yatra-price-input-group">
178 <label class="yatra-price-input-label"><?php esc_html_e('Max Price', 'yatra'); ?></label>
179 <input type="number" name="price_max" placeholder="<?php echo $max_price; ?>" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" value="<?php echo !empty($active_filters['price_max']) ? esc_attr($active_filters['price_max']) : ''; ?>" id="priceMax">
180 </div>
181 </div>
182 <div class="yatra-price-slider">
183 <div class="yatra-price-slider-track" aria-hidden="true"></div>
184 <div class="yatra-price-slider-range" aria-hidden="true"></div>
185 <input type="range" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" step="<?php echo $step; ?>" value="<?php echo !empty($active_filters['price_min']) ? esc_attr($active_filters['price_min']) : $min_price; ?>" class="yatra-range-min" id="priceRangeMin" data-default="<?php echo $min_price; ?>" data-user-set="<?php echo !empty($active_filters['price_min']) ? 'true' : 'false'; ?>">
186 <input type="range" min="<?php echo $min_price; ?>" max="<?php echo $max_price; ?>" step="<?php echo $step; ?>" value="<?php echo !empty($active_filters['price_max']) ? esc_attr($active_filters['price_max']) : $max_price; ?>" class="yatra-range-max" id="priceRangeMax" data-default="<?php echo $max_price; ?>" data-user-set="<?php echo !empty($active_filters['price_max']) ? 'true' : 'false'; ?>">
187 </div>
188 <div class="yatra-price-display"><?php echo yatra_format_price($min_price); ?> - <?php echo yatra_format_price($max_price); ?></div>
189 </div>
190 </div>
191 </div>
192
193 <!-- Trip Type Filter -->
194 <div class="yatra-filter-section">
195 <div class="yatra-filter-title" data-toggle="trip-type">
196 <div class="yatra-filter-title-content">
197 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
198 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
199 </svg>
200 <span><?php esc_html_e('Trip Type', 'yatra'); ?></span>
201 </div>
202 <div class="yatra-filter-actions">
203 <span class="yatra-clear-section" data-section="trip-type" title="<?php esc_attr_e('Clear trip type filter', 'yatra'); ?>">
204 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
205 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
206 </svg>
207 </span>
208 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
209 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
210 </svg>
211 </div>
212 </div>
213 <div class="yatra-filter-content">
214 <div class="yatra-checkbox-group">
215 <?php
216 // Get trip type options from service
217 $trip_type_options = $filter_data['trip_types'] ?? [];
218
219 foreach ($trip_type_options as $type_option) :
220 ?>
221 <label class="yatra-checkbox-label">
222 <input type="radio" name="trip_type" value="<?php echo esc_attr($type_option->value); ?>" <?php echo ($active_filters['trip_type'] === $type_option->value) ? 'checked' : ''; ?>>
223 <span><?php echo esc_html($type_option->label); ?></span>
224 <span class="yatra-filter-count">(<?php echo (int)$type_option->count; ?>)</span>
225 </label>
226 <?php endforeach; ?>
227
228 <!-- All Types Option -->
229 <label class="yatra-checkbox-label">
230 <input type="radio" name="trip_type" value="" <?php echo empty($active_filters['trip_type']) ? 'checked' : ''; ?>>
231 <span><?php esc_html_e('All Types', 'yatra'); ?></span>
232 </label>
233 </div>
234 </div>
235 </div>
236
237 <!-- Difficulty Level -->
238 <?php
239 $difficulty_levels = $filter_data['difficulty_levels'] ?? [];
240 if (!empty($difficulty_levels)) :
241 ?>
242 <div class="yatra-filter-section">
243 <div class="yatra-filter-title" data-toggle="difficulty">
244 <div class="yatra-filter-title-content">
245 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
246 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/>
247 </svg>
248 <span><?php esc_html_e('Difficulty Level', 'yatra'); ?></span>
249 </div>
250 <div class="yatra-filter-actions">
251 <span class="yatra-clear-section" data-section="difficulty" title="<?php esc_attr_e('Clear difficulty filters', 'yatra'); ?>">
252 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
253 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
254 </svg>
255 </span>
256 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
257 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
258 </svg>
259 </div>
260 </div>
261 <div class="yatra-filter-content">
262 <?php
263 $yatra_sidebar_cb_rows = [];
264 foreach ($difficulty_levels as $level) {
265 $yatra_sidebar_cb_rows[] = [
266 'value' => $level->id,
267 'label' => $level->name,
268 'count' => (int) $level->count,
269 ];
270 }
271 $yatra_sidebar_cb_input_name = 'difficulty[]';
272 $yatra_sidebar_cb_active = $active_filters['difficulty'] ?? [];
273 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
274 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
275 ?>
276 </div>
277 </div>
278 <?php endif; ?>
279
280 <!-- Rating -->
281 <div class="yatra-filter-section">
282 <div class="yatra-filter-title" data-toggle="rating">
283 <div class="yatra-filter-title-content">
284 <svg class="yatra-filter-icon" width="18" height="18" fill="#fbbf24" viewBox="0 0 24 24">
285 <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"/>
286 </svg>
287 <span><?php esc_html_e('Rating', 'yatra'); ?></span>
288 </div>
289 <div class="yatra-filter-actions">
290 <span class="yatra-clear-section" data-section="rating" title="<?php esc_attr_e('Clear rating filters', 'yatra'); ?>">
291 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
292 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
293 </svg>
294 </span>
295 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
296 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
297 </svg>
298 </div>
299 </div>
300 <div class="yatra-filter-content">
301 <div class="yatra-rating-filter">
302 <?php
303 $rating_options = $filter_data['ratings'] ?? [];
304
305 foreach ($rating_options as $option) :
306 // Show all rating options, even with 0 count for better UX
307 ?>
308 <label class="yatra-rating-option">
309 <input type="checkbox" name="rating[]" value="<?php echo esc_attr($option->rating); ?>" <?php echo in_array($option->rating, $active_filters['rating'] ?? []) ? 'checked' : ''; ?>>
310 <div class="yatra-stars-display">
311 <?php for ($i = 1; $i <= 5; $i++) : ?>
312 <svg class="yatra-star <?php echo $i <= $option->rating ? 'filled' : 'empty'; ?>" width="16" height="16" viewBox="0 0 24 24">
313 <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" fill="<?php echo $i <= $option->rating ? '#fbbf24' : '#e5e7eb'; ?>"/>
314 </svg>
315 <?php endfor; ?>
316 <span class="yatra-rating-label"><?php echo esc_html($option->label); ?></span>
317 <span class="yatra-filter-count">(<?php echo (int)$option->count; ?>)</span>
318 </div>
319 </label>
320 <?php endforeach; ?>
321 </div>
322 </div>
323 </div>
324
325 <!-- Trip Categories -->
326 <?php
327 $categories = $filter_data['categories'] ?? [];
328 if (!empty($categories)) :
329 ?>
330 <div class="yatra-filter-section">
331 <div class="yatra-filter-title" data-toggle="categories">
332 <div class="yatra-filter-title-content">
333 <svg class="yatra-filter-icon" width="18" height="18" fill="currentColor" viewBox="0 0 20 20">
334 <path fill-rule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 10a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H4a1 1 0 01-1-1v-6zM14 9a1 1 0 00-1 1v6a1 1 0 001 1h2a1 1 0 001-1v-6a1 1 0 00-1-1h-2z" clip-rule="evenodd" />
335 </svg>
336 <span><?php esc_html_e('Categories', 'yatra'); ?></span>
337 </div>
338 <div class="yatra-filter-actions">
339 <span class="yatra-clear-section" data-section="categories" title="<?php esc_attr_e('Clear category filters', 'yatra'); ?>">
340 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
341 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
342 </svg>
343 </span>
344 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
345 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
346 </svg>
347 </div>
348 </div>
349 <div class="yatra-filter-content">
350 <?php
351 $yatra_sidebar_cb_rows = [];
352 foreach ($categories as $category) {
353 $yatra_sidebar_cb_rows[] = [
354 'value' => $category->id,
355 'label' => $category->name,
356 'count' => (int) $category->count,
357 ];
358 }
359 $yatra_sidebar_cb_input_name = 'categories[]';
360 $yatra_sidebar_cb_active = $active_filters['categories'] ?? [];
361 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
362 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
363 ?>
364 </div>
365 </div>
366 <?php endif; ?>
367
368 <!-- Destinations -->
369 <?php
370 $destinations = $filter_data['destinations'] ?? [];
371 if (!empty($destinations)) :
372 ?>
373 <div class="yatra-filter-section">
374 <div class="yatra-filter-title" data-toggle="destinations">
375 <div class="yatra-filter-title-content">
376 <svg class="yatra-filter-icon" width="18" height="18" fill="currentColor" viewBox="0 0 20 20">
377 <path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd" />
378 </svg>
379 <span><?php esc_html_e('Destinations', 'yatra'); ?></span>
380 </div>
381 <div class="yatra-filter-actions">
382 <span class="yatra-clear-section" data-section="destinations" title="<?php esc_attr_e('Clear destination filters', 'yatra'); ?>">
383 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
384 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
385 </svg>
386 </span>
387 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
388 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
389 </svg>
390 </div>
391 </div>
392 <div class="yatra-filter-content">
393 <?php
394 $yatra_sidebar_cb_rows = [];
395 foreach ($destinations as $destination) {
396 $yatra_sidebar_cb_rows[] = [
397 'value' => $destination->id,
398 'label' => $destination->name,
399 'count' => (int) $destination->count,
400 ];
401 }
402 $yatra_sidebar_cb_input_name = 'destinations[]';
403 $yatra_sidebar_cb_active = $active_filters['destinations'] ?? [];
404 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
405 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
406 ?>
407 </div>
408 </div>
409 <?php endif; ?>
410
411 <!-- Activities -->
412 <?php
413 $activities = $filter_data['activities'] ?? [];
414 if (!empty($activities)) :
415 ?>
416 <div class="yatra-filter-section">
417 <div class="yatra-filter-title" data-toggle="activities">
418 <div class="yatra-filter-title-content">
419 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
420 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
421 </svg>
422 <span><?php esc_html_e('Activities', 'yatra'); ?></span>
423 </div>
424 <div class="yatra-filter-actions">
425 <span class="yatra-clear-section" data-section="activities" title="<?php esc_attr_e('Clear activity filters', 'yatra'); ?>">
426 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
427 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
428 </svg>
429 </span>
430 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
431 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
432 </svg>
433 </div>
434 </div>
435 <div class="yatra-filter-content">
436 <?php
437 $yatra_sidebar_cb_rows = [];
438 foreach ($activities as $activity) {
439 $yatra_sidebar_cb_rows[] = [
440 'value' => $activity->id,
441 'label' => $activity->name,
442 'count' => (int) $activity->count,
443 ];
444 }
445 $yatra_sidebar_cb_input_name = 'activities[]';
446 $yatra_sidebar_cb_active = $active_filters['activities'] ?? [];
447 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
448 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
449 ?>
450 </div>
451 </div>
452 <?php endif; ?>
453
454 <!-- Accommodation Type -->
455 <?php
456 // Get accommodation types from service
457 $accommodation_types = $filter_data['accommodations'] ?? [];
458
459 if (!empty($accommodation_types)) :
460 ?>
461 <div class="yatra-filter-section">
462 <div class="yatra-filter-title" data-toggle="accommodation">
463 <div class="yatra-filter-title-content">
464 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
465 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"/>
466 </svg>
467 <span><?php esc_html_e('Accommodation', 'yatra'); ?></span>
468 </div>
469 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
470 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
471 </svg>
472 </div>
473 <div class="yatra-filter-content">
474 <?php
475 $yatra_sidebar_cb_rows = [];
476 foreach ($accommodation_types as $accommodation) {
477 $yatra_sidebar_cb_rows[] = [
478 'value' => $accommodation->name,
479 'label' => ucwords(str_replace(['_', '-'], ' ', $accommodation->name)),
480 'count' => (int) $accommodation->trip_count,
481 ];
482 }
483 $yatra_sidebar_cb_input_name = 'accommodation[]';
484 $yatra_sidebar_cb_active = $active_filters['accommodation'] ?? [];
485 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
486 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
487 ?>
488 </div>
489 </div>
490 <?php endif; ?>
491
492 <!-- Included Services -->
493 <?php
494 // Get included services from service
495 $included_services = $filter_data['included_services'] ?? [];
496
497 if (!empty($included_services)) :
498 ?>
499 <div class="yatra-filter-section">
500 <div class="yatra-filter-title" data-toggle="services">
501 <div class="yatra-filter-title-content">
502 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
503 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z"/>
504 </svg>
505 <span><?php esc_html_e('Included Services', 'yatra'); ?></span>
506 </div>
507 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
508 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
509 </svg>
510 </div>
511 <div class="yatra-filter-content">
512 <?php
513 $yatra_sidebar_cb_rows = [];
514 foreach ($included_services as $service) {
515 $yatra_sidebar_cb_rows[] = [
516 'value' => $service->service_name,
517 'label' => $service->service_name,
518 'count' => (int) $service->trip_count,
519 ];
520 }
521 $yatra_sidebar_cb_input_name = 'services[]';
522 $yatra_sidebar_cb_active = $active_filters['services'] ?? [];
523 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
524 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
525 ?>
526 </div>
527 </div>
528 <?php endif; ?>
529
530 <!-- Special Offers -->
531 <?php
532 // Get special offers from service
533 $special_offers = $filter_data['special_offers'] ?? [];
534
535 if (!empty($special_offers)) :
536 ?>
537 <div class="yatra-filter-section">
538 <div class="yatra-filter-title" data-toggle="offers">
539 <div class="yatra-filter-title-content">
540 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
541 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v13m0-13V6a2 2 0 112 2h-2zm0 0V5.5A2.5 2.5 0 109.5 8H12zm-7 4h14M5 12a2 2 0 110-4h14a2 2 0 110 4M5 12v7a2 2 0 002 2h10a2 2 0 002-2v-7"/>
542 </svg>
543 <span><?php esc_html_e('Special Offers', 'yatra'); ?></span>
544 </div>
545 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
546 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
547 </svg>
548 </div>
549 <div class="yatra-filter-content">
550 <?php
551 $yatra_sidebar_cb_rows = [];
552 foreach ($special_offers as $offer) {
553 $yatra_sidebar_cb_rows[] = [
554 'value' => $offer->value,
555 'label' => $offer->label,
556 'count' => (int) $offer->count,
557 ];
558 }
559 $yatra_sidebar_cb_input_name = 'offers[]';
560 $yatra_sidebar_cb_active = $active_filters['offers'] ?? [];
561 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
562 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
563 ?>
564 </div>
565 </div>
566 <?php endif; ?>
567
568 <!-- Booking Options -->
569 <?php
570 // Get booking options from service
571 $booking_options = $filter_data['booking_options'] ?? [];
572
573 if (!empty($booking_options)) :
574 ?>
575 <div class="yatra-filter-section">
576 <div class="yatra-filter-title" data-toggle="booking">
577 <div class="yatra-filter-title-content">
578 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
579 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
580 </svg>
581 <span><?php esc_html_e('Booking Options', 'yatra'); ?></span>
582 </div>
583 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
584 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
585 </svg>
586 </div>
587 <div class="yatra-filter-content">
588 <?php
589 $yatra_sidebar_cb_rows = [];
590 foreach ($booking_options as $option) {
591 $yatra_sidebar_cb_rows[] = [
592 'value' => $option->value,
593 'label' => $option->label,
594 'count' => (int) $option->count,
595 ];
596 }
597 $yatra_sidebar_cb_input_name = 'booking[]';
598 $yatra_sidebar_cb_active = $active_filters['booking'] ?? [];
599 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
600 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
601 ?>
602 </div>
603 </div>
604 <?php endif; ?>
605
606 <!-- Age Suitability -->
607 <?php
608 // Get age restrictions from service
609 $age_options = $filter_data['age_restrictions'] ?? [];
610
611 if (!empty($age_options)) :
612 ?>
613 <div class="yatra-filter-section">
614 <div class="yatra-filter-title" data-toggle="age">
615 <div class="yatra-filter-title-content">
616 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
617 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
618 </svg>
619 <span><?php esc_html_e('Age Suitability', 'yatra'); ?></span>
620 </div>
621 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
622 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
623 </svg>
624 </div>
625 <div class="yatra-filter-content">
626 <?php
627 $yatra_sidebar_cb_rows = [];
628 foreach ($age_options as $option) {
629 $yatra_sidebar_cb_rows[] = [
630 'value' => $option->value,
631 'label' => $option->label,
632 'count' => (int) $option->count,
633 ];
634 }
635 $yatra_sidebar_cb_input_name = 'age[]';
636 $yatra_sidebar_cb_active = $active_filters['age'] ?? [];
637 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
638 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
639 ?>
640 </div>
641 </div>
642 <?php endif; ?>
643
644 <!-- Trip Attributes Filter -->
645 <?php if (is_array($yatra_trip_list) && !empty($yatra_trip_list['attributes'])) : ?>
646 <div class="yatra-filter-section">
647 <div class="yatra-filter-title" data-toggle="trip-attributes">
648 <div class="yatra-filter-title-content">
649 <svg class="yatra-filter-icon" width="18" height="18" fill="none" stroke="currentColor" viewBox="0 0 24 24">
650 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"/>
651 </svg>
652 <span><?php esc_html_e('Trip Attributes', 'yatra'); ?></span>
653 </div>
654 <div class="yatra-filter-actions">
655 <span class="yatra-clear-section" data-section="trip-attributes" title="<?php esc_attr_e('Clear trip attribute filters', 'yatra'); ?>">
656 <svg width="14" height="14" fill="none" stroke="currentColor" viewBox="0 0 24 24">
657 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
658 </svg>
659 </span>
660 <svg class="yatra-filter-arrow" width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
661 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
662 </svg>
663 </div>
664 </div>
665 <div class="yatra-filter-content">
666 <?php foreach ($yatra_trip_list['attributes'] as $attribute) : ?>
667 <?php
668 $attribute_filter_name = 'attributes[' . $attribute['id'] . ']';
669 $current_values = $active_filters['attributes'][$attribute['id']] ?? [];
670
671 $field_options = [];
672 if (!empty($attribute['field_options'])) {
673 $field_options = is_array($attribute['field_options']) ?
674 $attribute['field_options'] :
675 (json_decode($attribute['field_options'], true) ?: []);
676 }
677 ?>
678
679 <div class="yatra-attribute-item">
680 <div class="yatra-attribute-label">
681 <?php if (!empty($attribute['icon'])) : ?>
682 <?php
683 $icon_data = maybe_unserialize($attribute['icon']);
684 if (is_array($icon_data) && $icon_data['type'] === 'image' && !empty($icon_data['value'])) {
685 $image_url = '';
686 if (is_numeric($icon_data['value'])) {
687 $image_url = wp_get_attachment_image_url((int) $icon_data['value'], 'thumbnail');
688 } elseif (is_string($icon_data['value']) && filter_var($icon_data['value'], FILTER_VALIDATE_URL)) {
689 $image_url = $icon_data['value'];
690 }
691 if (!empty($image_url)) {
692 echo '<img class="yatra-attribute-icon" src="' . esc_url($image_url) . '" alt="' . esc_attr($attribute['name']) . '" width="16" height="16">';
693 }
694 } elseif (is_array($icon_data) && $icon_data['type'] === 'icon' && !empty($icon_data['value'])) {
695 echo '<span class="yatra-attribute-icon">' . yatra_svg_icon($icon_data['value'], '') . '</span>';
696 }
697 ?>
698 <?php endif; ?>
699 <span class="yatra-attribute-name"><?php echo esc_html($attribute['name']); ?></span>
700 </div>
701 <div class="yatra-attribute-content">
702 <?php if (($attribute['field_type'] === 'select' || $attribute['field_type'] === 'radio') && !empty($field_options)) : ?>
703 <?php
704 $yatra_sidebar_cb_rows = [];
705 foreach ($field_options as $option) {
706 $yatra_sidebar_cb_rows[] = [
707 'value' => $option['value'],
708 'label' => $option['label'],
709 ];
710 }
711 $yatra_sidebar_cb_input_name = $attribute_filter_name . '[]';
712 $yatra_sidebar_cb_active = $current_values;
713 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
714 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
715 ?>
716
717 <?php elseif ($attribute['field_type'] === 'checkbox' && !empty($field_options)) : ?>
718 <?php
719 $yatra_sidebar_cb_rows = [];
720 foreach ($field_options as $option) {
721 $yatra_sidebar_cb_rows[] = [
722 'value' => $option['value'],
723 'label' => $option['label'],
724 ];
725 }
726 $yatra_sidebar_cb_input_name = $attribute_filter_name . '[]';
727 $yatra_sidebar_cb_active = is_array($current_values) ? $current_values : [];
728 include __DIR__ . '/partials/listing-sidebar-collapsible-checkboxes.php';
729 unset($yatra_sidebar_cb_rows, $yatra_sidebar_cb_input_name, $yatra_sidebar_cb_active);
730 ?>
731
732 <?php elseif ($attribute['field_type'] === 'checkbox') : ?>
733 <div class="yatra-checkbox-group">
734 <label class="yatra-checkbox-label">
735 <input
736 type="checkbox"
737 name="<?php echo esc_attr($attribute_filter_name); ?>"
738 value="1"
739 <?php echo in_array('1', (array) $current_values, true) ? 'checked' : ''; ?>
740 >
741 <span><?php _e('Yes', 'yatra'); ?></span>
742 </label>
743 </div>
744
745 <?php elseif ($attribute['field_type'] === 'number') : ?>
746 <div class="yatra-input-group">
747 <input
748 type="number"
749 name="<?php echo esc_attr($attribute_filter_name); ?>[min]"
750 placeholder="<?php esc_attr_e('Min', 'yatra'); ?>"
751 value="<?php echo esc_attr($current_values['min'] ?? ''); ?>"
752 class="yatra-filter-input"
753 >
754 <input
755 type="number"
756 name="<?php echo esc_attr($attribute_filter_name); ?>[max]"
757 placeholder="<?php esc_attr_e('Max', 'yatra'); ?>"
758 value="<?php echo esc_attr($current_values['max'] ?? ''); ?>"
759 class="yatra-filter-input"
760 >
761 </div>
762
763 <?php elseif ($attribute['field_type'] === 'date') : ?>
764 <div class="yatra-input-group">
765 <input
766 type="date"
767 name="<?php echo esc_attr($attribute_filter_name); ?>[from]"
768 value="<?php echo esc_attr($current_values['from'] ?? ''); ?>"
769 class="yatra-filter-input"
770 >
771 <input
772 type="date"
773 name="<?php echo esc_attr($attribute_filter_name); ?>[to]"
774 value="<?php echo esc_attr($current_values['to'] ?? ''); ?>"
775 class="yatra-filter-input"
776 >
777 </div>
778
779 <?php else : ?>
780 <input
781 type="text"
782 name="<?php echo esc_attr($attribute_filter_name); ?>"
783 placeholder="<?php esc_attr_e('Type to filter…', 'yatra'); ?>"
784 value="<?php echo esc_attr(implode(', ', $current_values)); ?>"
785 class="yatra-filter-input"
786 >
787 <?php endif; ?>
788 </div>
789 </div>
790 <?php endforeach; ?>
791 </div>
792 </div>
793 <?php endif; ?>
794
795 </aside>
796
797 <!-- Main Content Area -->
798 <main class="yatra-listing-content">
799 <?php if (count($trips_source) > 0) : ?>
800 <div class="yatra-trip-grid" id="trip-grid">
801 <?php foreach ($trips_source as $trip) : ?>
802 <!-- Use the reusable trip-listing-card.php component -->
803 <?php include(dirname(__FILE__) . '/trip-listing-card.php'); ?>
804 <?php endforeach; ?>
805 </div>
806 <?php else : ?>
807 <div class="yatra-empty-state text-center py-12">
808 <svg class="mx-auto h-8 w-8 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
809 <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
810 </svg>
811 <h3 class="mt-2 text-lg font-medium text-gray-900 dark:text-gray-100"><?php esc_html_e('No trips found', 'yatra'); ?></h3>
812 <p class="mt-1 text-gray-500 dark:text-gray-400"><?php esc_html_e('Try adjusting your search or filter to find what you\'re looking for.', 'yatra'); ?></p>
813 </div>
814 <?php endif; ?>
815
816 <div class="yatra-listing-pagination yatra-listing-pagination--trip-content">
817 <?php
818 $prev_url = $yatra_pagination['prev_url'] ?? null;
819 $next_url = $yatra_pagination['next_url'] ?? null;
820 $prev_disabled = empty($prev_url);
821 $next_disabled = empty($next_url);
822 ?>
823 <a class="yatra-pagination-btn <?php echo $prev_disabled ? 'disabled' : ''; ?>" href="<?php echo $prev_disabled ? 'javascript:void(0);' : esc_url($prev_url); ?>">
824 <?php echo yatra_svg_icon('chevron-left', 'yatra-btn-icon'); ?>
825 <span><?php esc_html_e('Previous', 'yatra'); ?></span>
826 </a>
827 <?php foreach (($yatra_pagination['items'] ?? []) as $pitem) : ?>
828 <?php if (($pitem['type'] ?? '') === 'ellipsis') : ?>
829 <span class="yatra-pagination-ellipsis">...</span>
830 <?php elseif (($pitem['type'] ?? '') === 'page') : ?>
831 <a class="yatra-pagination-btn <?php echo !empty($pitem['is_current']) ? 'active' : ''; ?>" href="<?php echo esc_url((string) ($pitem['url'] ?? '')); ?>">
832 <?php echo esc_html((string) ($pitem['page'] ?? '')); ?>
833 </a>
834 <?php endif; ?>
835 <?php endforeach; ?>
836 <a class="yatra-pagination-btn <?php echo $next_disabled ? 'disabled' : ''; ?>" href="<?php echo $next_disabled ? 'javascript:void(0);' : esc_url($next_url); ?>">
837 <span><?php esc_html_e('Next', 'yatra'); ?></span>
838 <?php echo yatra_svg_icon('chevron-right', 'yatra-btn-icon'); ?>
839 </a>
840 </div>
841 </main>
842 </div>
843 </div>
844 </div>
845 </div>
846
847 <?php
848 yatra_get_footer();
849 ?>
850