feat: tour page photos-first layout, mobile booking bar; board 1 fixes

Tour page (boards 2 and 3):
- Replace the blurred 'Welcome to {city}' hero with a breadcrumb and a photo
  gallery (1 large + 2, 'All N photos' opens the lightbox); the H1 title,
  rating with review count and facts follow; booking card stays sticky
- Phones/tablets: swipeable photos, name before price, 2x2 facts, and a
  fixed bottom bar with price + Check availability (vc-tour.css)

Board 1:
- Hide Viator internal tags ('Agent Low Quality Product'...) from the tour
  category, listing filter and activities section (VC_Tags, tested)
- Listings: run the query filter late and set posts_per_archive_page so
  pages show 12 tours as the count says
- Footer columns without a menu show default links (quick links, structure
  cities, contact/about/faq) instead of empty headings

Plugin 1.9.5, theme 1.0.13.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-29 21:01:13 +03:30
parent 2f1ecd99b4
commit de9814cf3d
15 changed files with 367 additions and 57 deletions

View File

@@ -34,7 +34,7 @@ class VC_Display {
// equal-specificity ties. Loading last makes our design win those ties.
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ), 100 );
add_action( 'template_redirect', array( __CLASS__, 'maybe_enrich_single' ) );
add_action( 'pre_get_posts', array( __CLASS__, 'filter_archive_query' ) );
add_action( 'pre_get_posts', array( __CLASS__, 'filter_archive_query' ), 999 );
add_filter( 'single_template', array( __CLASS__, 'single_template' ) );
add_filter( 'archive_template', array( __CLASS__, 'archive_template' ) );
add_filter( 'taxonomy_template', array( __CLASS__, 'taxonomy_template' ) );
@@ -164,6 +164,10 @@ class VC_Display {
}
wp_enqueue_style( 'vc-design', VC_PLUGIN_URL . 'assets/css/vc-design.css', $deps, VC_VERSION );
wp_add_inline_style( 'vc-design', self::astra_overrides() );
if ( $is_single ) {
// Tour page top section + mobile booking bar (after the overrides above).
wp_enqueue_style( 'vc-tour', VC_PLUGIN_URL . 'assets/css/vc-tour.css', array( 'vc-design' ), VC_VERSION );
}
// Front-end interactions: card rails, FAQ accordion, testimonials
// marquee, date field, and auto-submit on quick filter toggles.
@@ -318,6 +322,8 @@ class VC_Display {
* Apply the filter state to the main tours query (archive + taxonomy pages).
*/
public static function filter_archive_query( $query ) {
// Runs late (priority 999, see init) so another plugin/theme setting the
// page size can't leave the listing at 10 while it says "1–12".
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
@@ -346,7 +352,9 @@ class VC_Display {
*/
public static function build_query_vars( array $base_tax = array() ) {
$f = self::get_filter_state();
$vars = array( 'posts_per_page' => 12, 'ignore_sticky_posts' => true );
// posts_per_archive_page too: when set (Settings or another plugin), WP_Query
// uses it instead of posts_per_page on archives.
$vars = array( 'posts_per_page' => 12, 'posts_per_archive_page' => 12, 'ignore_sticky_posts' => true );
if ( '' !== $f['q'] ) {
$vars['s'] = $f['q'];
@@ -741,7 +749,7 @@ class VC_Display {
'viator_browse_activities'
);
$terms = self::get_section_terms( 'viator_tag', $atts['count'], $atts['ids'] );
$terms = VC_Tags::public_terms( self::get_section_terms( 'viator_tag', $atts['count'], $atts['ids'] ) );
if ( empty( $terms ) ) {
return '';
}

View File

@@ -34,6 +34,7 @@ final class VC_Plugin {
'includes/class-vc-cpt.php',
'includes/class-vc-taxonomies.php',
'includes/class-vc-structure.php',
'includes/class-vc-tags.php',
'includes/class-vc-api.php',
'includes/class-vc-importer.php',
'includes/class-vc-cron.php',

View File

@@ -0,0 +1,41 @@
<?php
defined( 'ABSPATH' ) || exit;
/**
* Viator attaches some internal, trade-only tags to products (e.g. "Agent Low
* Quality Product"). They are imported like any tag but must never be shown
* to visitors — not as a tour's category, not as a filter option.
*/
class VC_Tags {
/**
* Patterns (case-insensitive) that mark a tag as internal. Extend with the
* `vc_internal_tag_patterns` filter when WordPress is loaded.
*/
public static function patterns() {
$patterns = array( '/\bagent\b/i', '/\blow quality\b/i', '/\bquality product\b/i' );
return function_exists( 'apply_filters' ) ? (array) apply_filters( 'vc_internal_tag_patterns', $patterns ) : $patterns;
}
public static function is_internal( $name ) {
foreach ( self::patterns() as $pattern ) {
if ( preg_match( $pattern, (string) $name ) ) {
return true;
}
}
return false;
}
/**
* Drop internal tags from a list of term objects (keeps order).
*/
public static function public_terms( $terms ) {
return array_values(
array_filter(
(array) $terms,
function ( $term ) {
return is_object( $term ) && ! self::is_internal( $term->name );
}
)
);
}
}