переработал систему модалок и добавил блоки

This commit is contained in:
GP_DEV
2025-06-07 23:28:58 +03:00
parent decc7c470a
commit f23ac49f97
6 changed files with 224 additions and 171 deletions

View File

@@ -29,36 +29,57 @@ if (!function_exists('get_club_cards_for_current_language')) {
}
$cards = get_club_cards_for_current_language();
$heading = get_field('heading', $block['id']);
?>
<div id="<?php echo esc_attr($block_id); ?>" class="container mx-auto mt-[24px] <?php echo esc_attr($class_name); ?>">
<section id="<?php echo esc_attr($block_id); ?>" class="<?php echo esc_attr($class_name); ?>">
<div class="container mx-auto mt-[24px]">
<?php if ($heading) : ?>
<h2 class="text-[32px] font-bold mt-[24px]"><?php echo esc_html($heading); ?></h2>
<?php endif; ?>
<?php if ($cards): ?>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-[24px]">
<div class="mt-[24px] grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-[30px] max-[768px]:gap-[20px]">
<?php foreach ($cards as $card): ?>
<div class="club-card rounded-[8px] overflow-hidden border transition-shadow ">
<?php if (has_post_thumbnail($card->ID)): ?>
<div class="aspect-video overflow-hidden">
<?php echo get_the_post_thumbnail($card->ID, 'medium', ['class' => 'w-full h-full object-cover']); ?>
<div class="bg-[#ffffff] border-[1px] border-[#e5e7eb] rounded-[16px] overflow-hidden shadow-lg hover:shadow-xl transition-shadow ">
<?php
$card_image = get_field('image', $card->ID);
if ($card_image): ?>
<div class="overflow-hidden max-w-[60px] max-h-[60px] mx-auto mt-[22px] rounded-full">
<img src="<?php echo esc_url($card_image['url']); ?>"
alt="<?php echo esc_attr($card_image['alt']); ?>"
class="w-full h-full object-cover" />
</div>
<?php endif; ?>
<div class="p-[24px]">
<h3 class="text-[20px] font-semibold mb-[12px]">
<?php echo get_the_title($card->ID); ?>
<div class="p-[30px] max-[768px]:p-[20px]">
<?php $card_heading = get_field('heading', $card->ID); ?>
<?php if ($card_heading): ?>
<h3 class="text-[24px] max-[768px]:text-[20px] font-semibold text-[#1f2937] mb-[16px] text-center">
<?php echo esc_html($card_heading); ?>
</h3>
<?php endif; ?>
<?php if (get_the_excerpt($card->ID)): ?>
<div class="text-gray-600 mb-[16px]">
<?php echo get_the_excerpt($card->ID); ?>
<?php $card_description = get_field('description', $card->ID); ?>
<?php if ($card_description): ?>
<div class="text-[16px] max-[768px]:text-[14px] text-[#6b7280] leading-[150%] text-center mb-[16px]">
<?php echo wp_kses_post($card_description); ?>
</div>
<?php endif; ?>
<?php $card_price = get_field('price', $card->ID); ?>
<?php if ($card_price): ?>
<div class="text-[20px] max-[768px]:text-[18px] font-bold text-[#1f2937] text-center mb-[24px]">
<span>От</span> <?php echo esc_html($card_price); ?> Р.
</div>
<div class="text-center">
<?php endif; ?>
<div class="text-center mt-auto">
<?php $popup_button = get_field('popup_button', $card->ID); ?>
<button data-modal="club-card"
data-card-id="<?php echo $card->ID; ?>"
class="inline-block px-[24px] py-[12px] bg-blue-500 text-white rounded-[6px] hover:bg-blue-600 transition-colors ">
Подробнее
class="inline-block cursor-pointer px-[24px] py-[12px] bg-[#3b82f6] text-white rounded-[8px] hover:bg-[#2563eb] transition-colors ">
<?php echo $popup_button ? esc_html($popup_button) : 'Подробнее'; ?>
</button>
</div>
</div>
@@ -67,3 +88,4 @@ $cards = get_club_cards_for_current_language();
</div>
<?php endif; ?>
</div>
</section>

View File

@@ -31,7 +31,7 @@ $tiles_repeater = get_field('tiles_repeater');
<?php if ($tiles_repeater) : ?>
<div class="mt-[24px] grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-[30px] max-[768px]:gap-[20px]">
<?php foreach ($tiles_repeater as $tile) : ?>
<div class="bg-[#ffffff] border-[1px] border-[#e5e7eb] rounded-[16px] p-[30px] max-[768px]:p-[20px] shadow-lg hover:shadow-xl transition-shadow duration-300">
<div class="bg-[#ffffff] border-[1px] border-[#e5e7eb] rounded-[16px] p-[30px] max-[768px]:p-[20px] shadow-lg hover:shadow-xl transition-shadow ">
<?php if (!empty($tile['image'])) : ?>
<div class="w-[80px] h-[80px] rounded-full overflow-hidden mb-[20px] mx-auto bg-[#f3f4f6] flex items-center justify-center">

View File

@@ -73,6 +73,29 @@ function register_acf_blocks() {
),
));
acf_register_block_type(array(
'name' => 'form-block',
'title' => __('Блок формы'),
'description' => __('Блок формы обратной связи'),
'render_template' => 'template-parts/la-components/blocks/form-block/form-block.php',
'category' => 'theme-blocks',
'icon' => 'id-alt',
'keywords' => array('форма', 'форма записи', 'имя', 'телефон'),
'supports' => array(
'align' => array('wide', 'full'),
'anchor' => true,
'customClassName' => true,
),
'enqueue_assets' => function() {
wp_enqueue_style(
'form-block-css',
get_template_directory_uri() . '/template-parts/la-components/blocks/form-block/form-block.css',
[],
'1.0.0'
);
}
));
acf_register_block_type(array(
'name' => 'tiles-block',
'title' => __('Блок с плитками'),
@@ -88,6 +111,22 @@ function register_acf_blocks() {
),
));
acf_register_block_type(array(
'name' => 'advantages-block',
'title' => __('Блок преимуществ'),
'description' => __('Блок с преимуществами'),
'render_template' => 'template-parts/la-components/blocks/advantages-block/advantages-block.php',
'category' => 'theme-blocks',
'icon' => 'grid-view',
'keywords' => array('преимущества', 'карточки', 'advantages', 'преимущество'),
'supports' => array(
'align' => array('wide', 'full'),
'anchor' => true,
'customClassName' => true,
),
));
acf_register_block_type(array(
'name' => 'reviews-block',
'title' => __('Блок с отзывами'),

View File

@@ -5,15 +5,13 @@ function enqueue_theme_scripts() {
'modals-js',
get_template_directory_uri() . '/template-parts/la-components/js/modals.js',
array('jquery'),
'1.0.0',
'2.0.0',
true
);
}
add_action('wp_enqueue_scripts', 'enqueue_theme_scripts');
// Вывод всех модалок в футере
function modal_system_container() {
// Получаем список всех модалок
$modals_dir = get_template_directory() . '/template-parts/la-components/modals/';
$modals = array();
@@ -26,24 +24,17 @@ function modal_system_container() {
}
}
// общий контейнер
?>
<div id="modal-overlay" class="fixed inset-0 bg-[rgba(0,0,0,0.5)] backdrop-blur-sm z-50 flex items-center justify-center p-4 opacity-0 invisible transition-all duration-300">
<div class="bg-white rounded-lg shadow-2xl max-w-2xl w-full max-h-[90vh] relative transform scale-90 transition-transform duration-300 overflow-hidden">
<button id="modal-close" class="absolute top-4 right-4 z-10 w-8 h-8 flex items-center justify-center rounded-full hover:bg-gray-100 transition-colors text-gray-500 hover:text-gray-700">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
<!-- Контейнер для контента модалок -->
<div id="modal-content" class="overflow-y-auto max-h-[90vh]">
<div id="modal-content" class="overflow-y-auto max-h-[90vh]"></div>
</div>
</div>
</div>
<div id="modal-templates" class="hidden">
<?php foreach ($modals as $modal_name): ?>

View File

@@ -1,13 +1,13 @@
document.addEventListener('DOMContentLoaded', function() {
window.ModalSystem = {
const ModalSystem = {
overlay: null,
content: null,
container: null,
closeBtn: null,
isOpen: false,
currentModal: null,
modalStack: [],
init: function() {
init() {
this.overlay = document.getElementById('modal-overlay');
if (!this.overlay) return;
@@ -16,21 +16,20 @@ document.addEventListener('DOMContentLoaded', function() {
this.closeBtn = document.getElementById('modal-close');
this.bindEvents();
this.initFormHandling();
},
bindEvents: function() {
bindEvents() {
if (this.closeBtn) {
this.closeBtn.addEventListener('click', () => this.close());
}
this.overlay.addEventListener('click', (e) => {
if (e.target === this.overlay) {
this.close();
}
if (e.target === this.overlay) this.close();
});
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && this.isOpen) {
this.close();
}
if (e.key === 'Escape' && this.isOpen()) this.close();
});
document.addEventListener('click', (e) => {
@@ -38,7 +37,8 @@ document.addEventListener('DOMContentLoaded', function() {
if (modalTrigger) {
e.preventDefault();
const modalName = modalTrigger.getAttribute('data-modal');
this.open(modalName);
const cardId = modalTrigger.getAttribute('data-card-id');
this.open(modalName, { cardId });
}
});
@@ -50,71 +50,140 @@ document.addEventListener('DOMContentLoaded', function() {
});
},
initFormHandling() {
console.log('Form handling initialized');
open: function(modalName) {
if (this.isOpen) {
this.close();
document.addEventListener('fluentform_submission_success', (e) => {
const form = e.target.closest('.ff-el-form-wrapper form');
if (form) {
setTimeout(() => {
if (this.isOpen()) {
this.replace('form-success');
} else {
this.open('form-success');
}
}, 300);
}
}, true);
if (typeof jQuery !== 'undefined') {
jQuery(document).ajaxSuccess((event, xhr, settings) => {
if (settings.url && settings.url.includes('admin-ajax.php') &&
settings.data && settings.data.includes('fluentform_submit')) {
try {
const response = JSON.parse(xhr.responseText);
console.log('Response:', response);
if (response.success && response.data && response.data.insert_id) {
setTimeout(() => {
if (this.isOpen()) {
this.replace('form-success');
} else {
this.open('form-success');
}
}, 300);
}
} catch (e) {
}
}
});
} else {
}
},
open(modalName, params = {}) {
const template = document.getElementById(`modal-template-${modalName}`);
if (!template) return;
this.modalStack.push({
name: modalName,
params: params,
content: template.innerHTML
});
this.content.innerHTML = template.innerHTML;
if (this.modalStack.length === 1) {
this.show();
}
const template = document.getElementById(`modal-template-${modalName}`);
if (!template) {
console.error(`модальное окно ${modalName} не найдено`);
this.injectParams(params);
},
replace(modalName, params = {}) {
if (this.modalStack.length === 0) {
this.open(modalName, params);
return;
}
this.currentModal = modalName;
const template = document.getElementById(`modal-template-${modalName}`);
if (!template) return;
this.modalStack[this.modalStack.length - 1] = {
name: modalName,
params: params,
content: template.innerHTML
};
this.content.innerHTML = template.innerHTML;
this.show();
this.injectParams(params);
},
show: function() {
injectParams(params) {
if (params.cardId) {
setTimeout(() => {
const hiddenInput = this.content.querySelector('input[name="hidden"]');
if (hiddenInput && !hiddenInput.dataset.cardInjected) {
const currentValue = hiddenInput.value || '';
hiddenInput.value = currentValue + ` | Карта ID: ${params.cardId}`;
hiddenInput.dataset.cardInjected = 'true';
}
}, 100);
}
},
show() {
this.overlay.classList.remove('opacity-0', 'invisible');
this.overlay.classList.add('opacity-100', 'visible');
setTimeout(() => {
this.container.classList.remove('scale-90');
this.container.classList.add('scale-100');
}, 10);
this.isOpen = true;
setTimeout(() => {
this.closeBtn.focus();
if (this.closeBtn) this.closeBtn.focus();
}, 350);
},
close: function() {
if (!this.isOpen) return;
close() {
if (this.modalStack.length === 0) return;
this.modalStack.pop();
if (this.modalStack.length > 0) {
const prevModal = this.modalStack[this.modalStack.length - 1];
this.content.innerHTML = prevModal.content;
this.injectParams(prevModal.params);
} else {
this.hide();
}
},
hide() {
this.container.classList.remove('scale-100');
this.container.classList.add('scale-90');
this.overlay.classList.remove('opacity-100', 'visible');
this.overlay.classList.add('opacity-0', 'invisible');
this.isOpen = false;
this.currentModal = null;
this.modalStack = [];
},
getState: function() {
return {
isOpen: this.isOpen,
currentModal: this.currentModal
};
isOpen() {
return this.modalStack.length > 0;
}
};
ModalSystem.init();
window.openModal = function(modalName) {
ModalSystem.open(modalName);
};
window.closeModal = function() {
ModalSystem.close();
};
});

View File

@@ -1,90 +1,22 @@
<?php
<div class="bg-white max-w-lg w-full rounded-[8px]">
<div class="p-[24px]">
<h2 class="text-[24px] font-bold text-gray-900 mb-[16px]">
Заказать клубную карту
</h2>
$form_id = '4';
$form_title = 'Заявка на клубную карту';
<form class="space-y-[16px]">
<div>
<label for="name" class="block text-[14px] font-medium text-gray-700 mb-[8px]">
Имя *
</label>
<input type="text"
id="name"
name="name"
required
class="w-full px-[12px] py-[8px] border border-gray-300 rounded-[6px] focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
$current_url = home_url($_SERVER['REQUEST_URI']);
$page_title = get_the_title() ?: 'Главная страница';
<div>
<label for="email" class="block text-[14px] font-medium text-gray-700 mb-[8px]">
Email *
</label>
<input type="email"
id="email"
name="email"
required
class="w-full px-[12px] py-[8px] border border-gray-300 rounded-[6px] focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
$hidden_value = "Форма: {$form_title} | Страница: {$page_title} | URL: {$current_url}";
?>
<div>
<label for="phone" class="block text-[14px] font-medium text-gray-700 mb-[8px]">
Телефон *
</label>
<input type="tel"
id="phone"
name="phone"
required
class="w-full px-[12px] py-[8px] border border-gray-300 rounded-[6px] focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="p-[30px] max-[768px]:p-[20px]">
<h3 class="text-[24px] max-[768px]:text-[20px] font-bold text-[#1f2937] mb-[24px] text-center">
<?php echo esc_html($form_title); ?>
</h3>
<div>
<label for="card-type" class="block text-[14px] font-medium text-gray-700 mb-[8px]">
Тип карты
</label>
<select id="card-type"
name="card-type"
class="w-full px-[12px] py-[8px] border border-gray-300 rounded-[6px] focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">Выберите тип карты</option>
<option value="basic">Базовая</option>
<option value="premium">Премиум</option>
<option value="vip">VIP</option>
</select>
</div>
<div>
<label for="message" class="block text-[14px] font-medium text-gray-700 mb-[8px]">
Комментарий
</label>
<textarea id="message"
name="message"
rows="3"
class="w-full px-[12px] py-[8px] border border-gray-300 rounded-[6px] focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none"></textarea>
</div>
<div class="flex items-center">
<input type="checkbox"
id="agreement"
name="agreement"
required
class="mr-[8px] w-[16px] h-[16px] text-blue-600 border-gray-300 rounded focus:ring-blue-500">
<label for="agreement" class="text-[14px] text-gray-700">
Я согласен с обработкой персональных данных *
</label>
</div>
</form>
<div class="flex justify-end gap-[12px] mt-[24px]">
<button data-modal-close
type="button"
class="px-[24px] py-[12px] bg-gray-500 text-white rounded-[6px] hover:bg-gray-600 transition-colors duration-[300ms]">
Отмена
</button>
<button type="submit"
class="px-[24px] py-[12px] bg-blue-500 text-white rounded-[6px] hover:bg-blue-600 transition-colors duration-[300ms]">
Отправить заявку
</button>
</div>
<div class="form-block-wrapper"
data-form-id="<?php echo esc_attr($form_id); ?>"
data-hidden-value="<?php echo esc_attr($hidden_value); ?>">
<?php echo do_shortcode('[fluentform id="' . esc_attr($form_id) . '"]'); ?>
</div>
</div>