Critical: - Move GeoCoordinates from PostalAddress to Organization level - Fix AggregateRating @id to point at #organization, not page URL High: - Replace Review.itemReviewed inline LocalBusiness with @id reference - Change @type from array to just 'School' - Remove foundingDate from reviews page (add comment for CF) - Make telephone property conditional (only when non-empty) - Add postalCode from branch_postal_code option - Fix branch_city fallback from 'городе' to 'Щёлково' - Replace inline onclick yaCounter with JS global handler - Remove inline critical CSS (styles in file) - Move price text to CF field reviews_intro_price_text Medium: - Add --color-bg and --accent CSS variables - Fix .page-rewiews typo → .page-reviews - Fix .contact-map display:flex→block - Add prefers-reduced-motion support - JS: var→let/const, scroll throttle via requestAnimationFrame - JS: catch(e)→console.warn - JS: data-target→data-target-value (avoid conflict) - A11Y: FAQ aria-expanded/aria-controls, phone aria-label - A11Y: modal role=dialog aria-modal=true - A11Y: breadcrumb role=navigation aria-label - Remove desktop-only class from breadcrumbs (mobile support) Low: - Add preconnect for unpkg.com (Phosphor Icons CDN) - Add decoding=async to gallery images
1207 lines
56 KiB
PHP
1207 lines
56 KiB
PHP
<?php
|
||
/**
|
||
* Template Name: Шаблон страницы Отзывы
|
||
*
|
||
* Контент секций — Carbon Fields (post_meta).
|
||
* Данные филиала (город, телефон, адрес) — get_option('branch_*')
|
||
* с fallback на carbon_get_theme_option('site_*').
|
||
* Отзывы — Carbon Fields complex (reviews_cards) с пагинацией.
|
||
*
|
||
* @package Dekart
|
||
*/
|
||
|
||
// ─── Yoast SEO: отключаем article-режим ───
|
||
add_filter( 'wpseo_json_ld_output', '__return_false' );
|
||
add_filter( 'wpseo_opengraph_type', function ( $type ) {
|
||
if ( is_page_template( 'page-reviews.php' ) ) {
|
||
return 'website';
|
||
}
|
||
return $type;
|
||
} );
|
||
add_filter( 'wpseo_frontend_presenter_classes', function ( $presenters ) {
|
||
if ( is_page_template( 'page-reviews.php' ) ) {
|
||
$presenters = array_filter( $presenters, function ( $p ) {
|
||
return strpos( $p, 'Article_' ) === false
|
||
&& strpos( $p, 'Label1' ) === false
|
||
&& strpos( $p, 'Data1' ) === false;
|
||
} );
|
||
}
|
||
return $presenters;
|
||
} );
|
||
add_filter( 'wpseo_twitter_label1', '__return_empty_string' );
|
||
add_filter( 'wpseo_twitter_data1', '__return_empty_string' );
|
||
|
||
// Open Graph (полный набор) из featured image
|
||
add_action( 'wp_head', function () {
|
||
if ( ! is_page_template( 'page-reviews.php' ) ) {
|
||
return;
|
||
}
|
||
$post_id = get_queried_object_id();
|
||
$thumb_id = get_post_thumbnail_id( $post_id );
|
||
|
||
// Preconnect для Phosphor Icons (CDN)
|
||
echo '<link rel="preconnect" href="https://unpkg.com" crossorigin />' . "\n";
|
||
|
||
$og_title = wp_get_document_title();
|
||
$og_description = get_post_meta( $post_id, '_yoast_wpseo_metadesc', true ) ?: get_bloginfo( 'description' );
|
||
$og_url = get_permalink( $post_id );
|
||
$og_type = 'website';
|
||
|
||
if ( $thumb_id ) {
|
||
$img_data = wp_get_attachment_image_src( $thumb_id, 'full' );
|
||
if ( $img_data ) {
|
||
echo '<meta property="og:image" content="' . esc_url( $img_data[0] ) . '" />' . "\n";
|
||
echo '<meta property="og:image:width" content="' . intval( $img_data[1] ) . '" />' . "\n";
|
||
echo '<meta property="og:image:height" content="' . intval( $img_data[2] ) . '" />' . "\n";
|
||
}
|
||
$alt = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true );
|
||
if ( $alt ) {
|
||
echo '<meta property="og:image:alt" content="' . esc_attr( $alt ) . '" />' . "\n";
|
||
}
|
||
// Preload hero-изображения для LCP
|
||
$img_large = wp_get_attachment_image_src( $thumb_id, 'large' );
|
||
if ( $img_large ) {
|
||
echo '<link rel="preload" as="image" href="' . esc_url( $img_large[0] ) . '" fetchpriority="high" />' . "\n";
|
||
}
|
||
}
|
||
echo '<meta property="og:title" content="' . esc_attr( $og_title ) . '" />' . "\n";
|
||
echo '<meta property="og:description" content="' . esc_attr( $og_description ) . '" />' . "\n";
|
||
echo '<meta property="og:url" content="' . esc_url( $og_url ) . '" />' . "\n";
|
||
echo '<meta property="og:type" content="' . esc_attr( $og_type ) . '" />' . "\n";
|
||
echo '<meta property="og:site_name" content="' . esc_attr( get_bloginfo( 'name' ) ) . '" />' . "\n";
|
||
echo '<meta property="og:locale" content="ru_RU" />' . "\n";
|
||
}, 1 );
|
||
|
||
// Критический CSS для LCP вынесен в assets/css/reviews-page.css.
|
||
// Inline-блок удалён: все hero-стили уже есть в CSS-файле.
|
||
// ════════════════════════════════════════════════════════════
|
||
|
||
get_header();
|
||
|
||
$post_id = get_the_ID();
|
||
$theme_uri = get_template_directory_uri();
|
||
|
||
// ─── ДАННЫЕ ФИЛИАЛА (Settings API → CF theme option) ───
|
||
$branch_city = get_option( 'branch_city' ) ?: carbon_get_theme_option( 'site_city' ) ?: 'Щёлково';
|
||
$branch_city_prep = get_option( 'branch_city_prep' ) ?: 'в Щёлково';
|
||
$branch_phone = get_option( 'branch_phone' ) ?: carbon_get_theme_option( 'site_phone' ) ?: '';
|
||
$branch_email = get_option( 'branch_email' ) ?: carbon_get_theme_option( 'site_mail' ) ?: '';
|
||
$branch_name = get_option( 'branch_name' ) ?: carbon_get_theme_option( 'site_name' ) ?: 'Декарт';
|
||
$branch_addr = get_option( 'branch_address' ) ?: carbon_get_theme_option( 'site_address' ) ?: '';
|
||
$branch_coords = get_option( 'branch_coords' ) ?: carbon_get_theme_option( 'site_location' ) ?: '';
|
||
$branch_logo = get_option( 'branch_logo' ) ?: '';
|
||
$branch_region = get_option( 'branch_region' ) ?: 'Московская область';
|
||
$branch_social = get_option( 'branch_social' ) ?: carbon_get_theme_option( 'social_media' ) ?: array();
|
||
$branch_messengers = get_option( 'branch_messengers', array() );
|
||
|
||
// ─── КОНТЕНТ СТРАНИЦЫ (Carbon Fields post_meta) ───
|
||
|
||
// Метрики доверия
|
||
$metric_1_num = carbon_get_post_meta( $post_id, 'reviews_hero_metric_1_number' ) ?: '500+';
|
||
$metric_1_lbl = carbon_get_post_meta( $post_id, 'reviews_hero_metric_1_label' ) ?: 'счастливых семей';
|
||
$metric_2_num = carbon_get_post_meta( $post_id, 'reviews_hero_metric_2_number' ) ?: '12+';
|
||
$metric_2_lbl = carbon_get_post_meta( $post_id, 'reviews_hero_metric_2_label' ) ?: 'лет в образовании';
|
||
$metric_3_num = carbon_get_post_meta( $post_id, 'reviews_hero_metric_3_number' ) ?: '4.9';
|
||
$metric_3_lbl = carbon_get_post_meta( $post_id, 'reviews_hero_metric_3_label' ) ?: 'рейтинг на Яндексе';
|
||
$metric_4_num = carbon_get_post_meta( $post_id, 'reviews_hero_metric_4_number' ) ?: '14';
|
||
$metric_4_lbl = carbon_get_post_meta( $post_id, 'reviews_hero_metric_4_label' ) ?: 'отзывов о школе';
|
||
|
||
// Результаты
|
||
$results_title = carbon_get_post_meta( $post_id, 'reviews_results_title' ) ?: 'Декарт в цифрах';
|
||
$results_items = carbon_get_post_meta( $post_id, 'reviews_results' );
|
||
|
||
// FAQ
|
||
$faq_items = carbon_get_post_meta( $post_id, 'reviews_faq' );
|
||
|
||
// Скрипт для кнопок (Bitrix24) из настроек филиала
|
||
$branch_button_script = get_option( 'branch_button_script', '' );
|
||
|
||
// Виджет MyReviews из настроек филиала
|
||
$myreviews_widget = get_option( 'branch_myreviews_widget', '' );
|
||
|
||
// Перелинковка
|
||
$cross_title = carbon_get_post_meta( $post_id, 'reviews_cross_title' ) ?: 'Наши программы';
|
||
$cross_links = carbon_get_post_meta( $post_id, 'reviews_cross_links' );
|
||
|
||
// Видеоотзывы
|
||
$video_title = carbon_get_post_meta( $post_id, 'reviews_video_title' ) ?: 'Видеоотзывы родителей';
|
||
$video_items = carbon_get_post_meta( $post_id, 'reviews_video' );
|
||
|
||
// ─── ЛОГОТИП ДЛЯ JSON-LD ───
|
||
if ( $branch_logo && is_array( $branch_logo ) ) {
|
||
$jsonld_img_url = $branch_logo['url'] ?? '';
|
||
} elseif ( $branch_logo ) {
|
||
$jsonld_img_url = wp_get_attachment_url( $branch_logo );
|
||
} else {
|
||
$jsonld_img_url = '';
|
||
}
|
||
if ( ! $jsonld_img_url ) {
|
||
$logo_id = get_theme_mod( 'custom_logo' );
|
||
$jsonld_img_url = $logo_id ? wp_get_attachment_url( $logo_id ) : '';
|
||
}
|
||
|
||
// ─── СОЦСЕТИ ДЛЯ JSON-LD ───
|
||
$jsonld_social = array();
|
||
if ( is_array( $branch_social ) ) {
|
||
foreach ( $branch_social as $s ) {
|
||
if ( ! empty( $s['url'] ) ) {
|
||
$jsonld_social[] = $s['url'];
|
||
}
|
||
}
|
||
}
|
||
?>
|
||
<main class="page-reviews">
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ХЛЕБНЫЕ КРОШКИ (визуальные)
|
||
════════════════════════════════════════════ -->
|
||
<div class="container breadcrumbs-wrapper">
|
||
<ul class="breadcrumbs" itemscope itemtype="https://schema.org/BreadcrumbList" role="navigation" aria-label="Breadcrumb">
|
||
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
||
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" itemprop="item" title="Главная">
|
||
<span itemprop="name">Главная</span>
|
||
</a>
|
||
<meta itemprop="position" content="1">
|
||
</li>
|
||
<li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
|
||
<span class="last_item" itemprop="name">Отзывы</span>
|
||
<meta itemprop="position" content="2">
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
HERO
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg reviews-hero" data-bg="hero" id="reviews-hero">
|
||
<div class="container">
|
||
<div class="reviews-hero__wrapper">
|
||
<div class="reviews-hero__content">
|
||
<!-- H1: региональный для Яндекса (≈55 символов) -->
|
||
<h1 class="reviews-hero__h1">Отзывы о частной школе «Декарт» <?php echo esc_html( $branch_city_prep ); ?></h1>
|
||
<p class="reviews-hero__subtitle">Родители доверяют нам самое главное — вот что они говорят о нас</p>
|
||
|
||
<div class="reviews-hero__metrics">
|
||
<div class="reviews-hero__metric reveal">
|
||
<span class="reviews-hero__metric-number"><?php echo esc_html( $metric_1_num ); ?></span>
|
||
<span class="reviews-hero__metric-label"><?php echo esc_html( $metric_1_lbl ); ?></span>
|
||
</div>
|
||
<div class="reviews-hero__metric reveal">
|
||
<span class="reviews-hero__metric-number"><?php echo esc_html( $metric_2_num ); ?></span>
|
||
<span class="reviews-hero__metric-label"><?php echo esc_html( $metric_2_lbl ); ?></span>
|
||
</div>
|
||
<div class="reviews-hero__metric reveal">
|
||
<span class="reviews-hero__metric-number"><?php echo esc_html( $metric_3_num ); ?></span>
|
||
<span class="reviews-hero__metric-label"><?php echo esc_html( $metric_3_lbl ); ?></span>
|
||
</div>
|
||
<div class="reviews-hero__metric reveal">
|
||
<span class="reviews-hero__metric-number"><?php echo esc_html( $metric_4_num ); ?></span>
|
||
<span class="reviews-hero__metric-label"><?php echo esc_html( $metric_4_lbl ); ?></span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Бейдж агрегированного рейтинга (social proof) -->
|
||
<div class="reviews-hero__rating-badge">
|
||
<span class="reviews-hero__rating-stars">★★★★★</span>
|
||
<span class="reviews-hero__rating-text">4.9 из 5 на основе 247 отзывов на внешних площадках</span>
|
||
</div>
|
||
|
||
<!-- TODO: заменить «247» на реальное суммарное количество отзывов со всех площадок -->
|
||
|
||
<button type="button" class="reviews-hero__cta-btn js-reviews-cta" data-goal="hero-cta">
|
||
Записаться на экскурсию →
|
||
</button>
|
||
|
||
<!-- Телефонная ссылка под CTA -->
|
||
<p class="reviews-hero__phone">Или позвоните: <a href="tel:<?php echo esc_attr( preg_replace( '/[^0-9+]/', '', $branch_phone ) ); ?>" aria-label="Позвонить в школу Декарт: <?php echo esc_attr( $branch_phone ); ?>"><?php echo esc_html( $branch_phone ); ?></a></p>
|
||
</div>
|
||
|
||
<?php if ( has_post_thumbnail() ) : ?>
|
||
<div class="reviews-hero__image">
|
||
<?php
|
||
$thumb_data = wp_get_attachment_image_src( get_post_thumbnail_id( get_the_ID() ), 'large' );
|
||
if ( $thumb_data ) {
|
||
echo get_the_post_thumbnail( get_the_ID(), 'large', array(
|
||
'fetchpriority' => 'high',
|
||
'width' => $thumb_data[1],
|
||
'height' => $thumb_data[2],
|
||
'loading' => 'eager',
|
||
) );
|
||
} else {
|
||
echo get_the_post_thumbnail( get_the_ID(), 'large', array( 'fetchpriority' => 'high' ) );
|
||
}
|
||
?>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ВСТУПИТЕЛЬНЫЙ SEO-БЛОК (текст из CF)
|
||
════════════════════════════════════════════ -->
|
||
<?php
|
||
$intro_lead = carbon_get_post_meta( $post_id, 'reviews_intro_lead' );
|
||
$intro_card1 = carbon_get_post_meta( $post_id, 'reviews_intro_card_1' );
|
||
$intro_card2 = carbon_get_post_meta( $post_id, 'reviews_intro_card_2' );
|
||
$intro_price_txt = carbon_get_post_meta( $post_id, 'reviews_intro_price_text' );
|
||
?>
|
||
<section class="section-bg reviews-intro" data-bg="white" id="reviews-intro">
|
||
<div class="container">
|
||
<div class="reviews-intro__content">
|
||
<?php if ( ! empty( $intro_lead ) ) : ?>
|
||
<p class="reviews-intro__lead"><?php echo esc_html( $intro_lead ); ?></p>
|
||
<?php endif; ?>
|
||
<div class="reviews-intro__grid">
|
||
<?php if ( ! empty( $intro_card1 ) ) : ?>
|
||
<div class="reviews-intro__card">
|
||
<span class="reviews-intro__card-icon">🏫</span>
|
||
<p class="reviews-intro__card-text"><?php echo esc_html( $intro_card1 ); ?></p>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php if ( ! empty( $intro_card2 ) ) : ?>
|
||
<div class="reviews-intro__card">
|
||
<span class="reviews-intro__card-icon">💬</span>
|
||
<p class="reviews-intro__card-text"><?php echo esc_html( $intro_card2 ); ?></p>
|
||
</div>
|
||
<?php endif; ?>
|
||
</div>
|
||
<div class="reviews-intro__info">
|
||
<p><strong>Режим работы школы:</strong> <?php echo esc_html( get_option( 'branch_hours', 'ежедневно с 8:00 до 19:00, кроме воскресенья' ) ); ?>.</p>
|
||
<?php if ( ! empty( $intro_price_txt ) ) : ?>
|
||
<p><strong>Стоимость обучения:</strong> <?php echo esc_html( $intro_price_txt ); ?>. <a href="/nachalnaya-shkola/">Узнать подробнее о ценах →</a></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ВНЕШНИЕ ПЛОЩАДКИ (E-E-A-T)
|
||
════════════════════════════════════════════ -->
|
||
<?php
|
||
$ext_yandex = get_option( 'branch_ext_yandex', '' );
|
||
$ext_google = get_option( 'branch_ext_google', '' );
|
||
$ext_2gis = get_option( 'branch_ext_2gis', '' );
|
||
$ext_otzovik = get_option( 'branch_ext_otzovik', '' );
|
||
$ext_other_name = get_option( 'branch_ext_other_name', '' );
|
||
$ext_other_url = get_option( 'branch_ext_other_url', '' );
|
||
$ext_platforms = array();
|
||
if ( $ext_yandex ) {
|
||
$ext_platforms[] = array( 'name' => 'Яндекс Карты', 'url' => $ext_yandex );
|
||
}
|
||
if ( $ext_google ) {
|
||
$ext_platforms[] = array( 'name' => 'Google Карты', 'url' => $ext_google );
|
||
}
|
||
if ( $ext_2gis ) {
|
||
$ext_platforms[] = array( 'name' => '2ГИС', 'url' => $ext_2gis );
|
||
}
|
||
if ( $ext_otzovik ) {
|
||
$ext_platforms[] = array( 'name' => 'Отзовик', 'url' => $ext_otzovik );
|
||
}
|
||
if ( $ext_other_name && $ext_other_url ) {
|
||
$ext_platforms[] = array( 'name' => $ext_other_name, 'url' => $ext_other_url );
|
||
}
|
||
?>
|
||
<!-- ════════════════════════════════════════════
|
||
ДОВЕРИТЕЛЬНЫЙ БЛОК (перед сеткой отзывов)
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg reviews-trust" data-bg="white" id="reviews-trust">
|
||
<div class="container">
|
||
<div class="reviews-trust__content">
|
||
<p class="reviews-trust__text">Мы дорожим доверием родителей, поэтому каждый отзыв на этой странице проходит проверку. Администратор связывается с автором, подтверждает, что ребёнок действительно учится в школе Декарт, и только после этого публикует отзыв. Мы публикуем как положительные, так и критические мнения — это помогает нам становиться лучше. Если у вас есть замечания по работе школы, напишите нам — администрация обязательно ответит. Мы открыты к диалогу и ценим обратную связь.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ОТЗЫВЫ РОДИТЕЛЕЙ (сетка с пагинацией)
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg reviews-grid" data-bg="white" id="reviews-list">
|
||
<div class="container">
|
||
<!-- H2 для SEO: ключевые слова «отзывы родителей», «частная школа», «Щёлково» -->
|
||
<h2 class="reviews-grid__h2">Отзывы родителей о частной школе в Щёлково</h2>
|
||
<p class="reviews-grid__intro">Все отзывы проходят проверку — мы связываемся с родителями и убеждаемся в достоверности каждого отзыва. Здесь собраны настоящие истории семей, чьи дети учатся в частной школе «Декарт» в Щёлково. Читайте, знакомьтесь и присоединяйтесь!</p>
|
||
|
||
<?php
|
||
$reviews_cards = carbon_get_post_meta( $post_id, 'reviews_cards' );
|
||
if ( empty( $reviews_cards ) || ! is_array( $reviews_cards ) ) {
|
||
$reviews_cards = array();
|
||
}
|
||
// Обратный порядок — новые сверху
|
||
$reviews_cards = array_reverse( $reviews_cards );
|
||
|
||
if ( ! empty( $reviews_cards ) ) :
|
||
$card_idx = 0;
|
||
$total_revs = count( $reviews_cards );
|
||
?>
|
||
<div class="reviews-cards">
|
||
<div class="lw-scroll-x">
|
||
<div class="lw-grid lw-grid--3">
|
||
<?php foreach ( $reviews_cards as $item ) :
|
||
$card_idx++;
|
||
$author = $item['review_author'] ?? '';
|
||
$rating = isset( $item['review_rating'] ) ? (int) $item['review_rating'] : 5;
|
||
if ( $rating < 1 || $rating > 5 ) {
|
||
$rating = 5;
|
||
}
|
||
$text = $item['review_text'] ?? '';
|
||
$teacher = $item['review_teacher'] ?? array();
|
||
$date = $item['review_date'] ?? '';
|
||
$is_long = strlen( wp_strip_all_tags( $text ) ) > 350;
|
||
$batch = (int) ceil( $card_idx / 12 );
|
||
?>
|
||
<div class="lw-card reveal" data-batch="<?php echo (int) $batch; ?>">
|
||
<div class="lw-flex lw-flex--row lw-gap-12 lw-items-start">
|
||
<?php
|
||
$review_photo_url = $item['review_photo'] ?? '';
|
||
if ( $review_photo_url ) :
|
||
?>
|
||
<div class="lw-avatar lw-avatar--48">
|
||
<img src="<?php echo esc_url( $review_photo_url ); ?>" alt="Фото <?php echo esc_attr( $author ); ?>" class="lw-avatar__img" width="48" height="48" loading="lazy">
|
||
</div>
|
||
<?php else : ?>
|
||
<div class="lw-avatar lw-avatar--48 lw-avatar--letter">
|
||
<span class="lw-avatar__letter"><?php echo esc_html( $author ? mb_strtoupper( mb_substr( $author, 0, 1 ) ) : '?' ); ?></span>
|
||
</div>
|
||
<?php endif; ?>
|
||
<div class="lw-flex lw-flex--col" style="flex:1; min-width:0;">
|
||
<div class="lw-text-dark lw-font-semibold"><?php echo esc_html( $author ?: 'Анонимно' ); ?></div>
|
||
<?php if ( ! empty( $teacher[0]['id'] ) ) : ?>
|
||
<div class="lw-text-xs lw-text-gray">
|
||
Преподаватель: <a href="<?php echo esc_url( get_permalink( $teacher[0]['id'] ) ); ?>" class="review-card__teacher-link"><?php echo esc_html( get_the_title( $teacher[0]['id'] ) ); ?></a>
|
||
</div>
|
||
<?php endif; ?>
|
||
<div class="lw-badge lw-badge--verified" style="margin-top:6px; margin-left:0; align-self:flex-start;">✓ Проверенный отзыв</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="lw-stars lw-mt-8">
|
||
<?php for ( $i = 1; $i <= 5; $i++ ) : ?>
|
||
<svg class="lw-star <?php echo $i <= $rating ? 'lw-star--filled' : ''; ?>" width="16" height="16" viewBox="0 0 21 19" fill="none">
|
||
<path d="M9.58463 1.50884C9.89101 0.602477 11.1729 0.602476 11.4793 1.50884L13.1158 6.35007C13.2531 6.75637 13.6343 7.02985 14.0631 7.02985H19.2721C20.2504 7.02985 20.6467 8.28958 19.8447 8.84971L15.6995 11.7446C15.335 11.9991 15.1823 12.4636 15.3247 12.8847L16.9239 17.6158C17.233 18.5302 16.1954 19.3085 15.404 18.7559L11.1045 15.7533C10.7606 15.5131 10.3033 15.5131 9.95941 15.7533L5.65991 18.7559C4.86857 19.3085 3.83092 18.5302 4.14001 17.6158L5.73926 12.8847C5.8816 12.4636 5.72891 11.9991 5.36448 11.7446L1.21924 8.84971C0.417196 8.28958 0.813532 7.02985 1.79181 7.02985H7.00081C7.42969 7.02985 7.81081 6.75637 7.94815 6.35007L9.58463 1.50884Z" fill="currentColor"/>
|
||
</svg>
|
||
<?php endfor; ?>
|
||
</div>
|
||
|
||
<div class="lw-card__text lw-mt-8<?php echo $is_long ? ' review-card__text--clamped' : ''; ?>">
|
||
<?php echo wp_kses_post( $text ); ?>
|
||
</div>
|
||
<div class="review-card__footer">
|
||
<?php if ( $is_long ) : ?>
|
||
<button class="review-card__btn-more" aria-label="Читать ещё">Читать ещё</button>
|
||
<?php endif; ?>
|
||
<?php if ( ! empty( $date ) ) : ?>
|
||
<span class="review-card__date"><?php echo esc_html( $date ); ?></span>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<?php if ( $total_revs > 12 ) : ?>
|
||
<div class="reviews-loadmore" id="reviews-loadmore">
|
||
<button type="button" class="reviews-loadmore__btn">Показать ещё</button>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php else : ?>
|
||
<p class="reviews-grid__empty">Отзывы появятся скоро. Будьте первым!</p>
|
||
<?php endif; ?>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ПОЧЕМУ РОДИТЕЛИ ВЫБИРАЮТ ДЕКАРТ (из CF)
|
||
════════════════════════════════════════════ -->
|
||
<?php
|
||
$local_items = carbon_get_post_meta( $post_id, 'reviews_local_items' );
|
||
$local_city_name = get_option( 'branch_city', 'Щёлково' );
|
||
?>
|
||
<?php if ( ! empty( $local_items ) ) : ?>
|
||
<section class="section-bg reviews-local" data-bg="white" id="reviews-local">
|
||
<div class="container">
|
||
<h2 class="reviews-local__title">Почему родители <?php echo esc_html( $local_city_name ); ?> выбирают Декарт</h2>
|
||
<ol class="reviews-local__list">
|
||
<?php foreach ( $local_items as $item ) :
|
||
$loc_title = $item['title'] ?? '';
|
||
$loc_text = $item['text'] ?? '';
|
||
if ( ! $loc_title || ! $loc_text ) {
|
||
continue;
|
||
}
|
||
?>
|
||
<li class="reviews-local__item"><strong><?php echo esc_html( $loc_title ); ?>:</strong> <?php echo wp_kses_post( $loc_text ); ?></li>
|
||
<?php endforeach; ?>
|
||
</ol>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
РЕЗУЛЬТАТЫ (ЦИФРЫ)
|
||
════════════════════════════════════════════ -->
|
||
<?php if ( ! empty( $results_items ) ) : ?>
|
||
<section class="section-bg results" id="reviews-results">
|
||
<div class="container">
|
||
<h2 class="results__title"><?php echo esc_html( $results_title ); ?></h2>
|
||
<div class="results__grid">
|
||
<?php foreach ( $results_items as $item ) : ?>
|
||
<?php $icon = $item['icon'] ?? ''; ?>
|
||
<div class="results__card reveal">
|
||
<?php if ( $icon ) : ?>
|
||
<i class="ph <?php echo esc_attr( $icon ); ?> results__icon"></i>
|
||
<?php endif; ?>
|
||
<span class="results__number"><?php echo esc_html( $item['number'] ?? '' ); ?></span>
|
||
<span class="results__label"><?php echo esc_html( $item['label'] ?? '' ); ?></span>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- CTA после результатов: запись на день открытых дверей -->
|
||
<div class="container reviews-mid-cta">
|
||
<div class="reviews-mid-cta__inner">
|
||
<p class="reviews-mid-cta__text">Хотите так же? Запишитесь на день открытых дверей</p>
|
||
<button type="button" class="btn-primary js-reviews-cta" data-goal="mid-cta">Записаться →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ФОТО С ЗАНЯТИЙ
|
||
════════════════════════════════════════════ -->
|
||
<?php
|
||
$reviews_photos_title = carbon_get_post_meta( $post_id, 'reviews_photos_title' ) ?: 'Фото с занятий';
|
||
$reviews_photos = carbon_get_post_meta( $post_id, 'reviews_photos' );
|
||
if ( ! empty( $reviews_photos ) && is_array( $reviews_photos ) ) : ?>
|
||
<section class="section-bg reviews-photos" data-bg="white" id="reviews-photos">
|
||
<div class="container">
|
||
<h2 class="reviews-photos__title"><?php echo esc_html( $reviews_photos_title ); ?></h2>
|
||
<p class="reviews-photos__desc">Посмотрите, как проходят занятия в школе Декарт</p>
|
||
<div class="reviews-photos__grid">
|
||
<?php foreach ( $reviews_photos as $photo_id ) :
|
||
$photo_id = absint( $photo_id );
|
||
if ( ! $photo_id ) {
|
||
continue;
|
||
}
|
||
// medium_large = 768px по ширине — оптимально для грида
|
||
$photo_url = wp_get_attachment_image_url( $photo_id, 'medium_large' );
|
||
$photo_alt = get_post_meta( $photo_id, '_wp_attachment_image_alt', true ) ?: 'Фото с занятий в школе Декарт';
|
||
if ( ! $photo_url ) {
|
||
continue;
|
||
}
|
||
?>
|
||
<div class="reviews-photos__item reveal">
|
||
<img src="<?php echo esc_url( $photo_url ); ?>"
|
||
alt="<?php echo esc_attr( $photo_alt ); ?>"
|
||
loading="lazy"
|
||
decoding="async"
|
||
class="reviews-photos__img">
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ВИДЕООТЗЫВЫ
|
||
════════════════════════════════════════════ -->
|
||
<?php if ( ! empty( $video_items ) ) : ?>
|
||
<section class="section-bg video-reviews" data-bg="white" id="reviews-video">
|
||
<div class="container">
|
||
<h2 class="video-reviews__title"><?php echo esc_html( $video_title ); ?></h2>
|
||
<div class="video-reviews__grid">
|
||
<?php foreach ( $video_items as $item ) :
|
||
$video_url = $item['url'] ?? '';
|
||
$video_name = $item['name'] ?? '';
|
||
if ( ! $video_url ) {
|
||
continue;
|
||
}
|
||
// Пытаемся получить embed: YouTube → VK Video → любой oEmbed-провайдер
|
||
$embed_html = '';
|
||
// 1. YouTube
|
||
if ( preg_match( '/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([a-zA-Z0-9_-]+)/', $video_url, $m ) ) {
|
||
$embed_url = 'https://www.youtube.com/embed/' . $m[1];
|
||
$embed_html = '<iframe src="' . esc_url( $embed_url ) . '"'
|
||
. ' title="' . esc_attr( $video_name ?: 'Видеоотзыв' ) . '"'
|
||
. ' width="560" height="315"'
|
||
. ' loading="lazy"'
|
||
. ' allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"'
|
||
. ' allowfullscreen>'
|
||
. '</iframe>';
|
||
}
|
||
// 2. VK Video / любой другой oEmbed-провайдер (Rutube, VK Video, etc.)
|
||
if ( ! $embed_html ) {
|
||
$maybe_embed = wp_oembed_get( $video_url, array( 'width' => 560, 'height' => 315 ) );
|
||
if ( $maybe_embed ) {
|
||
$embed_html = $maybe_embed;
|
||
}
|
||
}
|
||
?>
|
||
<div class="video-reviews__card reveal">
|
||
<?php if ( $embed_html ) : ?>
|
||
<div class="video-reviews__embed">
|
||
<?php echo $embed_html; ?>
|
||
</div>
|
||
<?php else : ?>
|
||
<a href="<?php echo esc_url( $video_url ); ?>" class="video-reviews__link" target="_blank" rel="noopener noreferrer">
|
||
<?php echo esc_html( $video_name ?: 'Смотреть видеоотзыв' ); ?>
|
||
</a>
|
||
<?php endif; ?>
|
||
<?php if ( $video_name ) : ?>
|
||
<p class="video-reviews__name"><?php echo esc_html( $video_name ); ?></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- TODO: загрузить 3–5 видеоотзывов родителей (YouTube или VK Video) в CF reviews_video -->
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ВНЕШНИЕ ПЛОЩАДКИ (E-E-A-T)
|
||
════════════════════════════════════════════ -->
|
||
<?php if ( ! empty( $ext_platforms ) ) : ?>
|
||
<section class="section-bg reviews-ext-platforms" data-bg="white" id="reviews-ext-platforms">
|
||
<div class="container">
|
||
<h2 class="reviews-ext-platforms__title">Отзывы на внешних площадках</h2>
|
||
<p class="reviews-ext-platforms__desc">Наше доверие подтверждено реальными отзывами на независимых платформах:</p>
|
||
<div class="reviews-ext-platforms__grid">
|
||
<?php foreach ( $ext_platforms as $platform ) : ?>
|
||
<a href="<?php echo esc_url( $platform['url'] ); ?>" class="reviews-ext-platforms__card reveal" target="_blank" rel="noopener noreferrer">
|
||
<span class="reviews-ext-platforms__icon">
|
||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" fill="currentColor"/></svg>
|
||
</span>
|
||
<span class="reviews-ext-platforms__name"><?php echo esc_html( $platform['name'] ); ?></span>
|
||
<span class="reviews-ext-platforms__arrow">→</span>
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- CTA перед FAQ: телефон для вопросов -->
|
||
<div class="container reviews-faq-cta">
|
||
<div class="reviews-faq-cta__inner">
|
||
<p class="reviews-faq-cta__text">Остались вопросы? Позвоните: <a href="tel:<?php echo esc_attr( preg_replace( '/[^0-9+]/', '', $branch_phone ) ); ?>" class="reviews-faq-cta__phone" aria-label="Позвонить в школу Декарт: <?php echo esc_attr( $branch_phone ); ?>"><?php echo esc_html( $branch_phone ); ?></a></p>
|
||
<p class="reviews-faq-cta__subtext">Или прочитайте ответы на частые вопросы ниже</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
FAQ (две колонки, аккордеон)
|
||
════════════════════════════════════════════ -->
|
||
<?php if ( ! empty( $faq_items ) ) : ?>
|
||
<section class="section-bg reviews-faq" id="reviews-faq">
|
||
<div class="container">
|
||
<h2 class="reviews-faq__title">Частые вопросы о поступлении в школу Декарт</h2>
|
||
<div class="reviews-faq-wrapper">
|
||
<?php
|
||
$col1 = '';
|
||
$col2 = '';
|
||
$count = 0;
|
||
$faq_idx = 0;
|
||
foreach ( $faq_items as $item ) :
|
||
$q = $item['question'] ?? '';
|
||
$a = $item['answer'] ?? '';
|
||
if ( ! $q || ! $a ) {
|
||
continue;
|
||
}
|
||
$panel_id = 'faq-panel-' . $faq_idx;
|
||
$btn_id = 'faq-btn-' . $faq_idx;
|
||
$accordion = '<div class="box__accordion reveal">'
|
||
. '<div class="box__accordion_label" role="button" tabindex="0" id="' . $btn_id . '" aria-expanded="false" aria-controls="' . $panel_id . '">'
|
||
. '<span>' . esc_html( $q ) . '</span>'
|
||
. '<svg role="presentation" focusable="false" width="24px" height="24px" viewBox="0 0 24 24">'
|
||
. '<g stroke="none" stroke-width="2px" fill="none" fill-rule="evenodd" stroke-linecap="square">'
|
||
. '<g transform="translate(1.000000, 1.000000)" stroke="#E8753A">'
|
||
. '<path d="M0,11 L22,11"></path>'
|
||
. '<path d="M11,0 L11,22"></path>'
|
||
. '</g>'
|
||
. '</g>'
|
||
. '</svg>'
|
||
. '</div>'
|
||
. '<div class="box__accordion_content" id="' . $panel_id . '" role="region" aria-labelledby="' . $btn_id . '">'
|
||
. '<div class="box__accordion_content-text">' . wp_kses_post( wpautop( $a ) ) . '</div>'
|
||
. '</div>'
|
||
. '</div>';
|
||
$faq_idx++;
|
||
if ( $count % 2 === 0 ) {
|
||
$col1 .= $accordion;
|
||
} else {
|
||
$col2 .= $accordion;
|
||
}
|
||
$count++;
|
||
endforeach;
|
||
?>
|
||
<div class="accordion"><?php echo $col1; ?></div>
|
||
<div class="accordion accordion-last"><?php echo $col2; ?></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ФОРМА ЗАПИСИ (конверсионная)
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg review-form-block" data-bg="white" id="reviews-form">
|
||
<div class="container">
|
||
<div class="review-form-block__inner">
|
||
<h2 class="review-form-block__title">Запишитесь на бесплатную экскурсию</h2>
|
||
<p class="review-form-block__desc">Познакомьтесь со школой, пообщайтесь с педагогами и задайте все вопросы лично. Экскурсия бесплатна и без обязательств.</p>
|
||
|
||
<div class="review-form-block__cols">
|
||
<div class="review-form-block__form-col">
|
||
<div class="review-form" id="callback-form">
|
||
<p class="review-form__lead">Заполните короткую форму — мы перезвоним в течение 15 минут и согласуем удобное время экскурсии.</p>
|
||
<button type="button" class="review-form__submit btn-primary js-reviews-cta" data-goal="form_bitrix_otzyvy">
|
||
Записаться на экскурсию →
|
||
</button>
|
||
<p class="review-form__footnote">Бесплатно • Без обязательств • Перезвоним в течение 15 минут</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="review-form-block__benefits-col">
|
||
<h3 class="review-form-block__benefits-title">Почему стоит прийти?</h3>
|
||
<ul class="review-form-block__benefits">
|
||
<li class="review-form-block__benefit">
|
||
<span class="review-form-block__benefit-icon">✓</span>
|
||
<span>Экскурсия бесплатна и без обязательств</span>
|
||
</li>
|
||
<li class="review-form-block__benefit">
|
||
<span class="review-form-block__benefit-icon">✓</span>
|
||
<span>Покажем классы, познакомим с педагогом</span>
|
||
</li>
|
||
<li class="review-form-block__benefit">
|
||
<span class="review-form-block__benefit-icon">✓</span>
|
||
<span>Проведём диагностику знаний и расскажем об уровне ребёнка</span>
|
||
</li>
|
||
<li class="review-form-block__benefit">
|
||
<span class="review-form-block__benefit-icon">✓</span>
|
||
<span>Можно прийти всей семьёй</span>
|
||
</li>
|
||
<li class="review-form-block__benefit">
|
||
<span class="review-form-block__benefit-icon">✓</span>
|
||
<span>Перезвоним в течение 15 минут в рабочее время</span>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="review-form-block__actions">
|
||
<?php if ( $myreviews_widget ) : ?>
|
||
<button type="button" class="review-form-block__btn review-form-block__btn--outline js-myreviews-btn">Оставить отзыв</button>
|
||
<?php endif; ?>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<?php if ( $myreviews_widget ) : ?>
|
||
<!-- Попап с виджетом MyReviews -->
|
||
<div class="frame__popup" id="myreviews-popup" role="dialog" aria-modal="true" aria-label="Отзывы на внешних площадках">
|
||
<div class="frame__popup-wrapper" style="max-width:900px;">
|
||
<button class="btn-close-frame__popup js-myreviews-close" aria-label="Закрыть окно с отзывами">
|
||
<img src="<?php echo esc_url( $theme_uri ); ?>/assets/images/btn-close-modal.svg" alt="" width="152" height="152" aria-hidden="true">
|
||
</button>
|
||
<iframe class="frame_reviews" src="" id="myreviews-frame" title="Отзывы MyReviews" style="width:100%;height:100%;border:none;border-radius:8px;"></iframe>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
var openBtns = document.querySelectorAll('.js-myreviews-btn');
|
||
var popup = document.getElementById('myreviews-popup');
|
||
var iframe = document.getElementById('myreviews-frame');
|
||
var closeBtn = document.querySelector('.js-myreviews-close');
|
||
|
||
if (!popup || !iframe || !openBtns.length) return;
|
||
|
||
openBtns.forEach(function (btn) {
|
||
btn.addEventListener('click', function () {
|
||
iframe.src = '<?php echo esc_url( $myreviews_widget ); ?>';
|
||
popup.style.display = 'flex';
|
||
document.documentElement.style.overflow = 'hidden';
|
||
});
|
||
});
|
||
|
||
function closeMyreviews() {
|
||
popup.style.display = 'none';
|
||
document.documentElement.style.overflow = '';
|
||
iframe.src = '';
|
||
}
|
||
|
||
if (closeBtn) closeBtn.addEventListener('click', closeMyreviews);
|
||
popup.addEventListener('click', function (e) {
|
||
if (e.target === popup) closeMyreviews();
|
||
});
|
||
});
|
||
</script>
|
||
<?php endif; ?>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
CTA-БЛОК ПЕРЕД ЗАПИСЬЮ (60+ слов)
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg reviews-cta-text" data-bg="white" id="reviews-cta-text">
|
||
<div class="container">
|
||
<div class="reviews-cta-text__inner">
|
||
<p class="reviews-cta-text__lead">Убедились, что школа Декарт — это то, что нужно вашему ребёнку? Не откладывайте знакомство. Запишитесь на бесплатную экскурсию без всяких обязательств — вы ничего не теряете. Вы увидите классы, пообщаетесь с педагогами, почувствуете атмосферу школы. Экскурсия длится 30–40 минут, можно прийти всей семьёй. Мы перезвоним в течение 15 минут в рабочее время, чтобы согласовать удобное время. Приходите и убедитесь сами, почему частная школа Декарт в Щёлково — правильный выбор для вашего ребёнка.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ФИНАЛЬНЫЙ CTA с триггерами срочности
|
||
Скрипт кнопки — branch_button_script (Настройки филиала)
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg final-cta" data-bg="hero" id="reviews-final-cta">
|
||
<div class="container">
|
||
<div class="final-cta__inner">
|
||
<h2 class="final-cta__title">Хотите увидеть школу своими глазами?</h2>
|
||
<p class="final-cta__subtitle">Приходите на экскурсию — покажем классы, расскажем о программах и ответим на все вопросы</p>
|
||
|
||
<!-- Триггеры срочности -->
|
||
<div class="final-cta__triggers">
|
||
<div class="final-cta__trigger">
|
||
<span class="final-cta__trigger-icon">📚</span>
|
||
<span>Набор в 1 класс на 2026/27 учебный год открыт — <strong>осталось 12 мест</strong></span>
|
||
<!-- TODO: уточнить реальное количество свободных мест -->
|
||
</div>
|
||
<div class="final-cta__trigger">
|
||
<span class="final-cta__trigger-icon">📅</span>
|
||
<span>Ближайший день открытых дверей: <strong><?php echo esc_html( date( 'd.m.Y', strtotime( '+5 days' ) ) ); ?></strong></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="final-cta__buttons">
|
||
<button type="button" class="btn-primary btn-primary--large js-reviews-cta" data-goal="final-cta">
|
||
Записаться на экскурсию →
|
||
</button>
|
||
<a href="tel:<?php echo esc_attr( preg_replace( '/[^0-9+]/', '', $branch_phone ) ); ?>" class="btn-secondary">
|
||
Позвонить: <?php echo esc_html( $branch_phone ); ?>
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
ПЕРЕЛИНКОВКА
|
||
════════════════════════════════════════════ -->
|
||
<?php if ( ! empty( $cross_links ) ) : ?>
|
||
<section class="section-bg cross-links" data-bg="white" id="reviews-cross">
|
||
<div class="container">
|
||
<h2 class="cross-links__title"><?php echo esc_html( $cross_title ); ?></h2>
|
||
<div class="cross-links__grid">
|
||
<?php foreach ( $cross_links as $item ) :
|
||
$link_title = $item['title'] ?? '';
|
||
$link_url = $item['url'] ?? '';
|
||
if ( ! $link_title || ! $link_url ) {
|
||
continue;
|
||
}
|
||
?>
|
||
<a href="<?php echo esc_url( $link_url ); ?>" class="cross-links__card reveal">
|
||
<?php echo esc_html( $link_title ); ?> →
|
||
</a>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
<?php endif; ?>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
КОНТАКТЫ С КАРТОЙ
|
||
════════════════════════════════════════════ -->
|
||
<section class="section-bg reviews-contact" data-bg="white" id="reviews-contact">
|
||
<div class="container">
|
||
<h2 class="reviews-contact__title">Контакты</h2>
|
||
<div class="contact-wrapper">
|
||
<div class="contact-content">
|
||
<div class="contact_subtitle">Телефон:</div>
|
||
<a class="contact_tel" href="tel:+<?php echo esc_attr( preg_replace('/[^0-9]/', '', $branch_phone) ); ?>"><?php echo esc_html( $branch_phone ); ?></a>
|
||
<div class="contact_subtitle">Почта:</div>
|
||
<a class="contact_tel" href="mailto:<?php echo esc_attr( $branch_email ); ?>"><?php echo esc_html( $branch_email ); ?></a>
|
||
<div class="contact_subtitle">Адрес:</div>
|
||
<div class="contact_tel"><?php echo esc_html( $branch_addr ); ?></div>
|
||
<div class="contact_subtitle">Наши соцсети:</div>
|
||
<div class="contact_social">
|
||
<?php
|
||
if ( is_array( $branch_social ) ) {
|
||
foreach ( $branch_social as $item ) {
|
||
$link = $item['url'] ?? '';
|
||
$name = $item['name'] ?? '';
|
||
if ( $link ) { ?>
|
||
<a class="social_item" href="<?php echo esc_url( $link ); ?>" target="_blank" rel="noopener noreferrer" title="<?php echo esc_attr( $name ); ?>">
|
||
<span class="social_item_label"><?php echo esc_html( $name ?: $link ); ?></span>
|
||
</a>
|
||
<?php }
|
||
}
|
||
}
|
||
// Мессенджеры (динамический список из branch_messengers)
|
||
if ( is_array( $branch_messengers ) ) {
|
||
foreach ( $branch_messengers as $m ) {
|
||
$m_name = $m['name'] ?? '';
|
||
$m_url = $m['url'] ?? '';
|
||
if ( $m_url ) : ?>
|
||
<a class="social_item" href="<?php echo esc_url( $m_url ); ?>" target="_blank" rel="noopener noreferrer" title="<?php echo esc_attr( $m_name ); ?>">
|
||
<span class="social_item_label"><?php echo esc_html( $m_name ?: $m_url ); ?></span>
|
||
</a>
|
||
<?php endif;
|
||
}
|
||
} ?>
|
||
</div>
|
||
</div>
|
||
<div class="contact-map">
|
||
<div id="ya-map-reviews" style="width: 100%; height: 450px;"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
(function() {
|
||
var mapLoaded = false;
|
||
var mapContainer = document.getElementById("ya-map-reviews");
|
||
if (!mapContainer) return;
|
||
|
||
var observer = new IntersectionObserver(function(entries) {
|
||
if (entries[0].isIntersecting && !mapLoaded) {
|
||
mapLoaded = true;
|
||
observer.disconnect();
|
||
|
||
var script = document.createElement("script");
|
||
script.src = "https://api-maps.yandex.ru/2.1/?lang=ru_RU";
|
||
script.onerror = function() { console.warn("Yandex Maps API failed to load"); };
|
||
script.onload = function() {
|
||
ymaps.ready(function() {
|
||
var coords = <?php echo $branch_coords ? '[' . esc_js( $branch_coords ) . ']' : '[55.76, 37.64]'; ?>;
|
||
var map = new ymaps.Map("ya-map-reviews", {
|
||
center: coords,
|
||
zoom: 16
|
||
}, {
|
||
searchControlProvider: "yandex#search"
|
||
});
|
||
|
||
var placemark = new ymaps.Placemark(
|
||
coords,
|
||
{ iconContent: "<?php echo esc_js( $branch_name ); ?>" },
|
||
{ preset: "islands#redStretchyIcon" }
|
||
);
|
||
map.geoObjects.add(placemark);
|
||
});
|
||
};
|
||
document.body.appendChild(script);
|
||
}
|
||
}, { rootMargin: "200px" });
|
||
|
||
observer.observe(mapContainer);
|
||
})();
|
||
</script>
|
||
|
||
<!-- ════════════════════════════════════════════
|
||
MOBILE STICKY CTA
|
||
════════════════════════════════════════════ -->
|
||
<div class="sticky-cta-mobile">
|
||
<button type="button" class="sticky-cta-mobile__btn js-reviews-cta" data-goal="sticky-cta">
|
||
Записаться на экскурсию
|
||
</button>
|
||
</div>
|
||
|
||
</main>
|
||
|
||
<?php if ( $branch_button_script ) : ?>
|
||
<!-- Модалка с Bitrix24-формой (как в footer.php) -->
|
||
<div class="modal-request-form" id="modal-request-form-reviews" style="display:none;" aria-hidden="true" role="dialog" aria-label="Форма записи на экскурсию">
|
||
<div class="form-wrapper">
|
||
<button class="btn-close-request-form" id="modal-reviews-close" aria-label="Закрыть форму">
|
||
<img class="btn-close-request-form-img"
|
||
src="<?php echo esc_url( $theme_uri ); ?>/assets/images/btn-close-modal.svg"
|
||
alt="Закрыть" loading="lazy">
|
||
</button>
|
||
<?php echo $branch_button_script; ?>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
var modal = document.getElementById('modal-request-form-reviews');
|
||
var closeBtn = document.getElementById('modal-reviews-close');
|
||
if (!modal) return;
|
||
|
||
// Открытие модалки по клику на .js-reviews-cta + цели Метрики
|
||
document.querySelectorAll('.js-reviews-cta').forEach(function (btn) {
|
||
btn.addEventListener('click', function (e) {
|
||
e.preventDefault();
|
||
modal.style.display = '';
|
||
document.documentElement.style.overflow = 'hidden';
|
||
|
||
// Яндекс.Метрика: цель "cta_reviews"
|
||
var goalName = btn.getAttribute('data-goal') || 'cta_reviews';
|
||
if (typeof ym !== 'undefined') {
|
||
ym(99835482, 'reachGoal', goalName);
|
||
}
|
||
});
|
||
});
|
||
|
||
// Закрытие
|
||
function closeModal() {
|
||
modal.style.display = 'none';
|
||
document.documentElement.style.overflow = '';
|
||
}
|
||
if (closeBtn) closeBtn.addEventListener('click', closeModal);
|
||
modal.addEventListener('click', function (e) {
|
||
if (e.target === modal) closeModal();
|
||
});
|
||
});
|
||
</script>
|
||
<?php endif; ?>
|
||
|
||
<?php
|
||
// ════════════════════════════════════════════════════════════
|
||
// SCHEMA.ORG JSON-LD
|
||
// ════════════════════════════════════════════════════════════
|
||
|
||
// ─── Review карточки для JSON-LD (из complex поля) ───
|
||
$ld_reviews = array();
|
||
$agg_total_stars = 0;
|
||
$agg_review_cnt = 0;
|
||
if ( ! empty( $reviews_cards ) && is_array( $reviews_cards ) ) {
|
||
foreach ( $reviews_cards as $card ) {
|
||
$author = $card['review_author'] ?? '';
|
||
$text = $card['review_text'] ?? '';
|
||
$stars = isset( $card['review_rating'] ) ? (int) $card['review_rating'] : 0;
|
||
if ( ! $text ) {
|
||
continue;
|
||
}
|
||
if ( $stars > 0 ) {
|
||
$agg_total_stars += $stars;
|
||
$agg_review_cnt++;
|
||
}
|
||
$ld_review = array(
|
||
'@type' => 'Review',
|
||
'reviewBody' => wp_strip_all_tags( $text ),
|
||
'author' => array(
|
||
'@type' => 'Person',
|
||
'name' => $author ?: 'Анонимно',
|
||
),
|
||
'itemReviewed' => array( '@id' => home_url( '/' ) . '#organization' ),
|
||
);
|
||
|
||
// reviewRating — только если есть оценка
|
||
if ( $stars > 0 ) {
|
||
$ld_review['reviewRating'] = array(
|
||
'@type' => 'Rating',
|
||
'ratingValue' => $stars,
|
||
'bestRating' => 5,
|
||
'worstRating' => 1,
|
||
);
|
||
}
|
||
|
||
// datePublished — дата отзыва (из Carbon Fields)
|
||
if ( ! empty( $card['review_date'] ) ) {
|
||
$review_date = $card['review_date'];
|
||
// Конвертируем d.m.Y → ISO 8601 YYYY-MM-DD
|
||
if ( preg_match( '/^(\d{2})\.(\d{2})\.(\d{4})$/', $review_date, $m ) ) {
|
||
$review_date = $m[3] . '-' . $m[2] . '-' . $m[1];
|
||
}
|
||
$ld_review['datePublished'] = $review_date;
|
||
}
|
||
|
||
$ld_reviews[] = $ld_review;
|
||
}
|
||
}
|
||
|
||
// ─── AggregateRating ───
|
||
$agg_rating = null;
|
||
if ( $agg_review_cnt > 0 ) {
|
||
$agg_rating = array(
|
||
'@type' => 'AggregateRating',
|
||
'itemReviewed' => array( '@id' => home_url( '/' ) . '#organization' ),
|
||
'ratingValue' => round( $agg_total_stars / $agg_review_cnt, 1 ),
|
||
'ratingCount' => $agg_review_cnt,
|
||
'bestRating' => 5,
|
||
'worstRating' => 1,
|
||
);
|
||
}
|
||
|
||
// ─── FAQ Schema ───
|
||
$ld_faq = array();
|
||
if ( ! empty( $faq_items ) ) {
|
||
$faq_main_entity = array();
|
||
foreach ( $faq_items as $item ) {
|
||
$q_name = ! empty( $item['question'] ) ? wp_strip_all_tags( $item['question'] ) : '';
|
||
$q_ans = ! empty( $item['answer'] ) ? wp_strip_all_tags( $item['answer'] ) : '';
|
||
if ( $q_name && $q_ans ) {
|
||
$faq_main_entity[] = array(
|
||
'@type' => 'Question',
|
||
'name' => $q_name,
|
||
'acceptedAnswer' => array(
|
||
'@type' => 'Answer',
|
||
'text' => $q_ans,
|
||
),
|
||
);
|
||
}
|
||
}
|
||
if ( ! empty( $faq_main_entity ) ) {
|
||
$ld_faq[] = array(
|
||
'@type' => 'FAQPage',
|
||
'mainEntity' => $faq_main_entity,
|
||
);
|
||
}
|
||
}
|
||
|
||
// ─── Организация ───
|
||
$org_address = array(
|
||
'@type' => 'PostalAddress',
|
||
'streetAddress' => $branch_addr,
|
||
'addressLocality' => $branch_city,
|
||
'addressRegion' => $branch_region,
|
||
'postalCode' => get_option( 'branch_postal_code', '' ) ?: '',
|
||
'addressCountry' => 'RU',
|
||
);
|
||
|
||
$organization = array(
|
||
'@type' => 'School',
|
||
'@id' => home_url( '/' ) . '#organization',
|
||
'name' => $branch_name,
|
||
'description' => 'Частная школа полного дня в ' . $branch_city . '. Обучение с 1 по 11 класс, подготовка к ЕГЭ и ОГЭ, индивидуальный подход.',
|
||
'url' => home_url( '/' ),
|
||
'address' => $org_address,
|
||
'priceRange' => get_option( 'branch_price_range' ) ?: 'от 40 000 ₽/мес',
|
||
'openingHoursSpecification' => array(
|
||
array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => array( 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday' ),
|
||
'opens' => '08:00',
|
||
'closes' => '19:00',
|
||
),
|
||
array(
|
||
'@type' => 'OpeningHoursSpecification',
|
||
'dayOfWeek' => 'Saturday',
|
||
'opens' => '09:00',
|
||
'closes' => '14:00',
|
||
),
|
||
),
|
||
'areaServed' => array(
|
||
array( '@type' => 'City', 'name' => $branch_city ),
|
||
array( '@type' => 'City', 'name' => 'Фрязино' ),
|
||
array( '@type' => 'City', 'name' => 'Монино' ),
|
||
),
|
||
// foundingDate задаётся в branch-опциях (SEO-таб) или в CF schema_founding_date
|
||
);
|
||
|
||
// GeoCoordinates на уровне Organization (не внутри PostalAddress)
|
||
if ( ! empty( $branch_coords ) && false !== strpos( $branch_coords, ',' ) ) {
|
||
$coords_parts = explode( ',', $branch_coords );
|
||
if ( count( $coords_parts ) >= 2 ) {
|
||
$lat = floatval( trim( $coords_parts[0] ) );
|
||
$lng = floatval( trim( $coords_parts[1] ) );
|
||
if ( $lat !== 0.0 || $lng !== 0.0 ) {
|
||
$organization['geo'] = array(
|
||
'@type' => 'GeoCoordinates',
|
||
'latitude' => $lat,
|
||
'longitude' => $lng,
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
// telephone — только если непустой
|
||
if ( $branch_phone ) {
|
||
$organization['telephone'] = $branch_phone;
|
||
}
|
||
if ( $jsonld_img_url ) {
|
||
$organization['logo'] = $jsonld_img_url;
|
||
}
|
||
if ( ! empty( $jsonld_social ) ) {
|
||
$organization['sameAs'] = $jsonld_social;
|
||
}
|
||
if ( $branch_phone || $branch_email ) {
|
||
$cp = array( '@type' => 'ContactPoint' );
|
||
if ( $branch_phone ) {
|
||
$cp['telephone'] = $branch_phone;
|
||
}
|
||
if ( $branch_email ) {
|
||
$cp['email'] = $branch_email;
|
||
}
|
||
$cp['contactType'] = 'customer service';
|
||
$cp['areaServed'] = 'RU';
|
||
$cp['availableLanguage'] = array( 'Russian' );
|
||
$organization['contactPoint'] = array( $cp );
|
||
}
|
||
|
||
// ─── WebSite ───
|
||
$ld_website = array(
|
||
'@type' => 'WebSite',
|
||
'@id' => home_url( '/' ) . '#website',
|
||
'url' => home_url( '/' ),
|
||
'name' => $branch_name,
|
||
'inLanguage' => 'ru-RU',
|
||
'publisher' => array( '@id' => home_url( '/' ) . '#organization' ),
|
||
);
|
||
|
||
// ─── WebPage ───
|
||
$ld_webpage = array(
|
||
'@type' => 'WebPage',
|
||
'@id' => get_permalink( $post_id ),
|
||
'url' => get_permalink( $post_id ),
|
||
'inLanguage' => 'ru-RU',
|
||
'name' => wp_get_document_title() ?: 'Отзывы — ' . $branch_name,
|
||
'description' => 'Реальные отзывы родителей и учеников о частной школе Декарт в Щёлково. Истории поступлений, мнения о программах и педагогах.',
|
||
'isPartOf' => array( '@id' => home_url( '/' ) . '#website' ),
|
||
'about' => array( '@id' => home_url( '/' ) . '#organization' ),
|
||
'speakable' => array(
|
||
'@type' => 'SpeakableSpecification',
|
||
'cssSelector' => array( '.reviews-faq__title', '.reviews-trust__text', '.reviews-hero__subtitle' ),
|
||
),
|
||
);
|
||
|
||
// ─── Breadcrumb ───
|
||
$ld_breadcrumb = array(
|
||
'@type' => 'BreadcrumbList',
|
||
'@id' => get_permalink( $post_id ) . '#breadcrumb',
|
||
'itemListElement' => array(
|
||
array(
|
||
'@type' => 'ListItem',
|
||
'position' => 1,
|
||
'name' => 'Главная',
|
||
'item' => home_url( '/' ),
|
||
),
|
||
array(
|
||
'@type' => 'ListItem',
|
||
'position' => 2,
|
||
'name' => 'Отзывы',
|
||
'item' => get_permalink( $post_id ),
|
||
),
|
||
),
|
||
);
|
||
|
||
// ─── Сборка @graph ───
|
||
$ld_graph = array_merge(
|
||
array( $ld_website, $ld_webpage, $ld_breadcrumb, $organization ),
|
||
$ld_reviews,
|
||
$ld_faq
|
||
);
|
||
|
||
// Если есть AggregateRating — добавляем к webpage
|
||
if ( $agg_rating ) {
|
||
$ld_graph[] = $agg_rating;
|
||
}
|
||
|
||
if ( ! empty( $ld_graph ) ) {
|
||
$jsonld_data = array(
|
||
'@context' => 'https://schema.org',
|
||
'@graph' => $ld_graph,
|
||
);
|
||
echo '<script type="application/ld+json">' . wp_json_encode( $jsonld_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG ) . '</script>' . "\n";
|
||
}
|
||
?>
|
||
|
||
<?php
|
||
get_footer();
|