File: /mnt/data/dreamstour-wp/wp-content/plugins/dreams-tour/templates/tour-grid_REMOTE_2679.php
<?php
/**
* Template Name: Tour Grid Template
* Template for displaying tour grid layout
*/
get_header();
?>
<div class="content">
<div class="container">
<!-- Loading Overlay -->
<div id="dt-loading-overlay" style="position:fixed;inset:0;display:none;z-index:9999;background:rgba(255,255,255,0.8);align-items:center;justify-content:center;">
<div class="spinner-border text-primary" role="status" aria-label="Loading">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<?php include(plugin_dir_path(__FILE__) . '/search-form.php'); ?>
<!-- Tour Types -->
<div class="mb-2">
<div class="mb-3">
<h5 class="mb-2"><?php esc_html_e('Choose type of Tours you are interested','dreams-tour');?></h5>
</div>
<div class="row" id="tour-categories-filter">
<?php
$tour_types = get_terms(array(
'taxonomy' => 'tour_category',
'hide_empty' => true,
'number' => 6
));
if (!empty($tour_types) && !is_wp_error($tour_types)) :
foreach ($tour_types as $type) :
$image_id = get_term_meta($type->term_id, 'dreamstour-category-image-id', true);
$image_url = $image_id ? wp_get_attachment_url($image_id) : get_template_directory_uri() . '/assets/images/placeholder.webp';
// Check if this category is currently active
$is_active = false;
if (isset($_GET['tour_category']) && !empty($_GET['tour_category'])) {
$selected_categories = (array)$_GET['tour_category'];
$is_active = in_array($type->term_id, $selected_categories);
}
?>
<div class="col-xxl-2 col-lg-3 col-md-4 col-sm-6">
<div class="d-flex align-items-center hotel-type-item mb-3 tour-category-filter <?php echo $is_active ? 'active' : ''; ?>" data-category-id="<?php echo esc_attr($type->term_id); ?>">
<a href="javascript:void(0);" class="avatar avatar-lg">
<img src="<?php echo esc_url($image_url); ?>" class="rounded-circle" alt="<?php echo esc_attr($type->name); ?>">
</a>
<div class="ms-2">
<h6 class="fs-16 fw-medium"><a href="javascript:void(0);"><?php echo esc_html($type->name); ?></a></h6>
<p class="fs-14"><?php echo esc_html($type->count); ?> <?php esc_html_e('Tours','dreams-tour');?></p>
</div>
</div>
</div>
<?php endforeach;
endif; ?>
</div>
</div>
<!-- /Tour Types -->
<div class="row">
<?php
// Include the filter sidebar
include(plugin_dir_path(__FILE__) . '/filter-sidebar.php');
?>
<div class="col-xl-9 col-lg-8 theiaStickySidebar">
<div class="d-flex align-items-center justify-content-between flex-wrap">
<?php
// Main query for tours
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'tour',
'posts_per_page' => 9,
'paged' => $paged,
'post_status' => 'publish'
);
// Add search query if exists
if (isset($_GET['search']) && !empty($_GET['search'])) {
$args['s'] = sanitize_text_field($_GET['search']);
}
// Add destination filter
if (isset($_GET['destination']) && !empty($_GET['destination'])) {
$args['meta_query'][] = array(
'key' => 'tour_destination',
'value' => sanitize_text_field($_GET['destination']),
'compare' => 'LIKE'
);
}
// Add check-in date filter
if (isset($_GET['check_in']) && !empty($_GET['check_in'])) {
$check_in_date = sanitize_text_field($_GET['check_in']);
$date_format_input = 'd-m-Y';
$date_format_output = 'Y-m-d';
$check_in_date_obj = DateTime::createFromFormat($date_format_input, $check_in_date);
if ($check_in_date_obj && $check_in_date_obj->format($date_format_input) === $check_in_date) {
$formatted_date = $check_in_date_obj->format($date_format_output);
$args['meta_query'][] = array(
'key' => 'tour_start_date',
'value' => $formatted_date,
'compare' => '>=',
'type' => 'DATE',
);
}
}
// Add duration filter
if (isset($_GET['tour_duration_days']) && !empty($_GET['tour_duration_days'])) {
$args['tax_query'][] = array(
'taxonomy' => 'tour_duration_days',
'field' => 'term_id',
'terms' => intval($_GET['tour_duration_days']),
'operator' => 'IN'
);
}
// Add traveler count filter
if (isset($_GET['travellers']) && !empty($_GET['travellers'])) {
$travellers_count = intval($_GET['travellers']);
$args['meta_query'][] = array(
'key' => 'tour_people_limit',
'value' => $travellers_count,
'type' => 'NUMERIC',
'compare' => '>='
);
}
// Add search query if exists
if (isset($_GET['search']) && !empty($_GET['search'])) {
$args['s'] = sanitize_text_field($_GET['search']);
}
// Add price range filter
if (isset($_GET['price_range']) && !empty($_GET['price_range'])) {
$price_range = explode(';', sanitize_text_field($_GET['price_range']));
if (count($price_range) === 2) {
$args['meta_query'][] = array(
'key' => 'tour_price',
'value' => array_map('intval', $price_range),
'type' => 'NUMERIC',
'compare' => 'BETWEEN'
);
}
}
// Add category filter
if (isset($_GET['tour_category']) && !empty($_GET['tour_category'])) {
$args['tax_query'][] = array(
'taxonomy' => 'tour_category',
'field' => 'term_id',
'terms' => array_map('intval', (array)$_GET['tour_category']),
'operator' => 'IN'
);
}
// Add rating filter
if (isset($_GET['rating']) && !empty($_GET['rating'])) {
$args['meta_query'][] = array(
'key' => 'tour_rating',
'value' => array_map('intval', (array)$_GET['rating']),
'type' => 'NUMERIC',
'compare' => 'IN'
);
}
// Ensure tax_query and meta_query are properly structured
if (!empty($args['tax_query'])) {
$args['tax_query']['relation'] = 'AND';
}
if (!empty($args['meta_query'])) {
$args['meta_query']['relation'] = 'AND';
}
// Add sorting
if (isset($_GET['sort']) && !empty($_GET['sort'])) {
switch ($_GET['sort']) {
case 'price_low':
$args['meta_key'] = 'tour_price';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'ASC';
break;
case 'price_high':
$args['meta_key'] = 'tour_price';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'newest':
$args['orderby'] = 'date';
$args['order'] = 'DESC';
break;
case 'rating':
$args['meta_key'] = 'tour_rating';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'reviews':
$args['meta_key'] = 'tour_reviews';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
default:
// Recommended - default ordering
break;
}
}
$tours_query = new WP_Query($args);
?>
<h6 class="mb-3" id="tour-count"><?php echo esc_html($tours_query->found_posts); ?> <?php esc_html_e('Tours Found','dreams-tour');?></h6>
<div class="d-flex align-items-center flex-wrap">
<div class="list-item d-flex align-items-center mb-3">
<?php
$tour_grid_page= dreamstour_fl_framework_getoptions( 'tour_grid_page' );
$tour_grid_page_url = get_permalink( $tour_grid_page ) ?: '#';
$tour_list_page= dreamstour_fl_framework_getoptions( 'tour_list_page' );
$tour_list_page_url = get_permalink( $tour_list_page ) ?: '#';
?>
<a href="<?php echo esc_url($tour_grid_page_url); ?>" class="list-icon me-2 active"><i class="isax isax-grid-1"></i></a>
<a href="<?php echo esc_url($tour_list_page_url); ?>" class="list-icon me-2"><i class="isax isax-firstline"></i></a>
</div>
<div class="dropdown mb-3">
<a href="javascript:void(0);" class="dropdown-toggle py-2" data-bs-toggle="dropdown" aria-expanded="false">
<span class="fw-medium text-gray-9"><?php esc_html_e('Sort By','dreams-tour');?> : </span><?php esc_html_e('Recommended','dreams-tour');?>
</a>
<div class="dropdown-menu dropdown-sm">
<form id="sort-form">
<h6 class="fw-medium fs-16 mb-3"><?php esc_html_e('Sort By','dreams-tour');?></h6>
<?php
$sort_options = array(
'recommended' => 'Recommended',
'price_low' => 'Price: low to high',
'price_high' => 'Price: high to low',
'newest' => 'Newest',
'rating' => 'Ratings',
'reviews' => 'Reviews'
);
$current_sort = isset($_GET['sort']) ? sanitize_text_field($_GET['sort']) : 'recommended';
foreach ($sort_options as $key => $label) :
?>
<div class="form-check d-flex align-items-center ps-0 mb-2">
<input class="form-check-input ms-0 mt-0" type="radio" name="sort" value="<?php echo esc_attr($key); ?>" id="sort-<?php echo esc_attr($key); ?>" <?php checked($current_sort, $key); ?>>
<label class="form-check-label ms-2" for="sort-<?php echo esc_attr($key); ?>"><?php echo esc_html($label); ?></label>
</div>
<?php endforeach; ?>
<!-- Preserve other filters -->
<?php if (isset($_GET['search'])) : ?>
<input type="hidden" name="search" value="<?php echo esc_attr($_GET['search']); ?>">
<?php endif; ?>
<?php if (isset($_GET['destination'])) : ?>
<input type="hidden" name="destination" value="<?php echo esc_attr($_GET['destination']); ?>">
<?php endif; ?>
<?php if (isset($_GET['tour_category'])) : ?>
<?php foreach ((array)$_GET['tour_category'] as $category) : ?>
<input type="hidden" name="tour_category[]" value="<?php echo esc_attr($category); ?>">
<?php endforeach; ?>
<?php endif; ?>
<?php if (isset($_GET['rating'])) : ?>
<?php foreach ((array)$_GET['rating'] as $rating) : ?>
<input type="hidden" name="rating[]" value="<?php echo esc_attr($rating); ?>">
<?php endforeach; ?>
<?php endif; ?>
<div class="d-flex align-items-center justify-content-end border-top pt-3 mt-3">
<a href="<?php echo get_permalink(); ?>" class="btn btn-light btn-sm me-2"><?php esc_html_e('Reset','dreams-tour');?></a>
<button type="submit" class="btn btn-primary btn-sm"><?php esc_html_e('Apply','dreams-tour');?></button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="row justify-content-space-between" id="tour-results">
<?php if ($tours_query->have_posts()) : ?>
<?php while ($tours_query->have_posts()) : $tours_query->the_post(); ?>
<?php
$tour_price = get_post_meta(get_the_ID(), 'tour_price', true);
$tour_offer_price = get_post_meta(get_the_ID(), 'tour_offer_price', true);
$tour_duration = get_post_meta(get_the_ID(), 'tour_duration', true);
$tour_guests = get_post_meta(get_the_ID(), 'tour_people_limit', true);
// Compute rating and review count from approved comments (like single-tour)
$comments = get_comments(array(
'post_id' => get_the_ID(),
'status' => 'approve',
'orderby' => 'comment_date',
'order' => 'DESC'
));
$tour_id = get_the_ID();
$tour_reviews = is_array($comments) ? count($comments) : 0;
$sum_ratings = 0;
$rated_count = 0;
if ($comments) {
foreach ($comments as $c) {
$r = get_comment_meta($c->comment_ID, 'rating', true);
if ($r) {
$sum_ratings += intval($r);
$rated_count++;
}
}
}
$tour_rating = $rated_count > 0 ? number_format($sum_ratings / $rated_count, 1) : '0.0';
$tour_destination = get_post_meta(get_the_ID(), 'tour_destination', true);
$tour_types = get_the_terms(get_the_ID(), 'tour_category');
$gallery = get_post_meta(get_the_ID(), 'tour_gallery', true);
$author_id = get_the_author_meta('ID');
$author_avatar = get_avatar_url($author_id, array('size' => 96));
// Get first image from gallery or featured image
$tour_image = '';
if (!empty($gallery) && is_array($gallery)) {
$tour_image = wp_get_attachment_url($gallery[0]);
}
if (!$tour_image && has_post_thumbnail()) {
$tour_image = get_the_post_thumbnail_url(get_the_ID(), 'large');
}
if (!$tour_image) {
$tour_image = plugin_dir_url(__FILE__) . 'assets/img/tours-07.jpg';
}
?>
<!-- Tour Card -->
<div class="col-xxl-4 col-md-6 d-flex">
<div class="place-item mb-4 flex-fill">
<div class="place-img">
<div class="img-slider image-slide owl-carousel nav-center">
<?php
$gallery = get_post_meta(get_the_ID(), 'tour_gallery', true); // Adjust meta key as needed
if ($gallery && is_array($gallery)) {
foreach ($gallery as $img_id) {
$img_url = wp_get_attachment_image_url($img_id, 'large');
if ($img_url) {
?>
<div class="slide-images">
<a href="<?php the_permalink(); ?>">
<img src="<?php echo esc_url($img_url); ?>" class="img-fluid" alt="<?php the_title_attribute(); ?>">
</a>
</div>
<?php
}
}
} else {
// Fallback to featured image
if (has_post_thumbnail()) {
?>
<div class="slide-images">
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('large', ['class' => 'img-fluid', 'alt' => get_the_title()]); ?>
</a>
</div>
<?php
}else{
// Fallback to a placeholder image
$placeholder_image = wc_placeholder_img_src(); ?>
<div class="slide-images">
<a href="<?php the_permalink(); ?>">
<img src="<?php echo esc_url($placeholder_image); ?>" class="img-fluid" alt="<?php the_title_attribute(); ?>">
</a>
</div>
<?php
}
}
?>
</div>
<div class="fav-item">
<?php $wishlist_active = is_user_logged_in() ? (function_exists('dreamstour_is_in_wishlist') ? dreamstour_is_in_wishlist(get_current_user_id(), $tour_id) : false) : false; ?>
<a href="javascript:void(0);" id="dt-wishlist-btn" data-tour-id="<?php echo (int) $tour_id; ?>" data-tour-title="<?php echo esc_attr(get_the_title($tour_id)); ?>" class="fav-icon <?php echo $wishlist_active ? 'selected' : ''; ?>">
<i class="isax isax-heart5"></i>
</a>
<span class="badge bg-info d-inline-flex align-items-center"><i class="isax isax-ranking me-1"></i><?php esc_html_e('Trending','dreams-tour');?></span>
</div>
</div>
<div class="place-content">
<div class="d-flex align-items-center justify-content-between mb-1">
<div class="d-flex flex-wrap align-items-center">
<span class="me-1"><i class="ti ti-receipt text-primary"></i></span>
<p class="fs-14 text-gray-9">
<?php
if ($tour_types && !is_wp_error($tour_types)) {
echo esc_html($tour_types[0]->name);
} else {
esc_html_e('Tour','dreams-tour');
}
?>
</p>
</div>
<span class="d-inline-block border vertical-splits">
<span class="bglight text-light d-flex align-items-center justify-content-center"></span>
</span>
<div class="d-flex align-items-center flex-wrap">
<span class="badge badge-warning badge-xs text-gray-9 fs-13 fw-medium me-1"><?php echo $tour_rating ? esc_html($tour_rating) : '0.0'; ?></span>
<p class="fs-14">(<?php echo $tour_reviews ? esc_html($tour_reviews) : '0'; ?> <?php esc_html_e('Reviews','dreams-tour');?>)</p>
</div>
</div>
<h5 class="mb-1 text-truncate"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h5>
<p class="d-flex align-items-center mb-3"><i class="isax isax-location5 me-2"></i><?php echo $tour_destination ? esc_html($tour_destination) : get_the_excerpt(); ?></p>
<div class="mb-3">
<h6 class="d-flex align-items-center text-gray-6 fs-14 fw-normal">
<?php esc_html_e('Starts From','dreams-tour');?>
<?php if ($tour_offer_price) : ?>
<span class="ms-1 fs-18 fw-semibold text-primary">
<?php echo get_woocommerce_currency_symbol(); ?><?php echo esc_html($tour_offer_price); ?>
</span>
<!-- Original Price (struck through) -->
<span class="ms-1 fs-18 fw-semibold text-gray-3 text-decoration-line-through">
<?php echo get_woocommerce_currency_symbol(); ?><?php echo esc_html($tour_price); ?>
</span>
<?php else : ?>
<!-- Regular Price only -->
<span class="ms-1 fs-18 fw-semibold text-primary">
<?php echo get_woocommerce_currency_symbol(); ?><?php echo esc_html($tour_price ? $tour_price : '0'); ?>
</span>
<?php endif; ?>
</h6>
</div>
<div class="d-flex align-items-center justify-content-between border-top pt-3">
<div class="d-flex flex-wrap align-items-center me-2">
<span class="me-1"><i class="isax isax-calendar-tick text-gray-6"></i></span>
<p class="fs-14 text-gray-9">
<?php
// Fetch "Day" and "Night" taxonomy terms
$days_terms = get_the_terms(get_the_ID(), 'tour_duration_days');
$nights_terms = get_the_terms(get_the_ID(), 'tour_duration_nights');
$days = ($days_terms && !is_wp_error($days_terms)) ? $days_terms[0]->name : '';
$nights = ($nights_terms && !is_wp_error($nights_terms)) ? $nights_terms[0]->name : '';
if ($days || $nights) {
echo esc_html(trim($days . ($days && $nights ? ', ' : '') . $nights));
} else {
esc_html_e('N/A','dreams-tour');
}
?>
</p>
</div>
<span class="d-inline-block border vertical-splits">
<span class="bglight text-light d-flex align-items-center justify-content-center"></span>
</span>
<div class="ms-2 d-flex align-items-center">
<p class="fs-14 text-gray-9 mb-0 text-truncate d-flex align-items-center">
<i class="isax isax-profile-2user me-1"></i><?php echo $tour_guests ? esc_html($tour_guests) : '0'; ?> <?php esc_html_e('Guests','dreams-tour');?>
</p>
<a href="javascript:void(0);" class="avatar avatar-sm ms-3">
<img src="<?php echo esc_url($author_avatar); ?>" class="rounded-circle" alt="<?php the_author(); ?>">
</a>
</div>
</div>
</div>
</div>
</div>
<!-- /Tour Card -->
<?php endwhile; ?>
<?php else : ?>
<div class="col-12">
<div class="alert alert-info"><?php esc_html_e('No tours found matching your criteria.','dreams-tour');?></div>
</div>
<?php endif;
wp_reset_postdata(); ?>
</div>
<!-- Pagination -->
<nav class="pagination-nav" id="tour-pagination">
<?php
$current_page = max(1, get_query_var('paged'));
$total_pages = $tours_query->max_num_pages;
if ($total_pages > 1) {
echo '<ul class="pagination justify-content-center">';
// Previous button
if ($current_page > 1) {
$prev_url = get_pagenum_link($current_page - 1);
echo '<li class="page-item">';
echo '<a class="page-link" href="' . esc_url($prev_url) . '" aria-label="Previous">';
echo '<span aria-hidden="true"><i class="fa-solid fa-chevron-left"></i></span>';
echo '</a>';
echo '</li>';
} else {
echo '<li class="page-item disabled">';
echo '<a class="page-link" href="javascript:void(0);" aria-label="Previous">';
echo '<span aria-hidden="true"><i class="fa-solid fa-chevron-left"></i></span>';
echo '</a>';
echo '</li>';
}
// Page numbers
for ($i = 1; $i <= $total_pages; $i++) {
$is_active = ($i == $current_page);
$page_url = get_pagenum_link($i);
echo '<li class="page-item' . ($is_active ? ' active' : '') . '">';
echo '<a class="page-link" href="' . esc_url($page_url) . '">' . $i . '</a>';
echo '</li>';
}
// Next button
if ($current_page < $total_pages) {
$next_url = get_pagenum_link($current_page + 1);
echo '<li class="page-item">';
echo '<a class="page-link" href="' . esc_url($next_url) . '" aria-label="Next">';
echo '<span aria-hidden="true"><i class="fa-solid fa-chevron-right"></i></span>';
echo '</a>';
echo '</li>';
} else {
echo '<li class="page-item disabled">';
echo '<a class="page-link" href="javascript:void(0);" aria-label="Next">';
echo '<span aria-hidden="true"><i class="fa-solid fa-chevron-right"></i></span>';
echo '</a>';
echo '</li>';
}
echo '</ul>';
}
?>
</nav>
<!-- /Pagination -->
</div>
</div>
</div>
</div>
<?php
// Enqueue scripts for AJAX functionality
// wp_enqueue_script('tour-ajax', get_template_directory_uri() . '/js/tour-ajax.js', array('jquery'), '1.0', true);
// wp_localize_script('tour-ajax', 'tour_ajax', array(
// 'ajax_url' => admin_url('admin-ajax.php'),
// 'nonce' => wp_create_nonce('tour_ajax_nonce')
// ));
// Inline script to handle loading overlay on navigation interactions
?>
<script>
(function($){
function showLoader(){
var $ov = $('#dt-loading-overlay');
if ($ov.length){ $ov.css('display','flex'); }
}
$(document).on('submit', '#tour-search-form, #tour-filter-form, #sort-form', function(){
showLoader();
});
$(document).on('click', '#tour-pagination a', function(){
// Only show for real links
var href = $(this).attr('href');
if (href && href !== '#') { showLoader(); }
});
// Also show when user clicks grid/list toggle
$(document).on('click', '.list-icon', function(){
var href = $(this).attr('href');
if (href && href !== '#') { showLoader(); }
});
// Category chips at the top
$(document).on('click', '#tour-categories-filter .tour-category-filter, #tour-categories-filter .tour-category-filter a', function(){
showLoader();
});
// General: any link inside results triggers loader
$(document).on('click', '#tour-results a', function(){
var target = $(this).attr('target');
var href = $(this).attr('href');
if (href && href.indexOf('javascript:') !== 0 && target !== '_blank') {
showLoader();
}
});
})(jQuery);
</script>
<?php
get_footer();
?>