dev_10_fixbugs #34

Merged
Andrei-10 merged 5 commits from dev_10_fixbugs into master 2 months ago
  1. 131
      wp-content/themes/cosmopet/global-functions/multisite-functions.php
  2. 32
      wp-content/themes/cosmopet/modules/footer/assets/css/gp-style-tablet.css
  3. 0
      wp-content/themes/cosmopet/modules/forms/assets/css/forms.css
  4. 71
      wp-content/themes/cosmopet/modules/layout/assets/css/gp-style-core.css
  5. 39
      wp-content/themes/cosmopet/modules/shop/components/cart/assets/js/cart.js
  6. 2
      wp-content/themes/cosmopet/modules/shop/components/catalog/component-controller.php
  7. 5
      wp-content/themes/cosmopet/static/css/forms.css
  8. 27
      wp-content/themes/cosmopet/static/css/front-page.css
  9. 55
      wp-content/themes/cosmopet/temp-functions/woocommerce-logic.php
  10. 11
      wp-content/themes/cosmopet/templates/_blocks/shop/archive-product-tease.twig
  11. 49
      wp-content/themes/cosmopet/templates/_pages/shop/archive-product.twig
  12. 7
      wp-content/themes/cosmopet/templates/archive-product/archive-product-tease.twig
  13. 157
      wp-content/themes/cosmopet/templates/archive-product/archive-product.twig
  14. 3
      wp-content/themes/cosmopet/templates/layout.twig
  15. 44
      wp-content/themes/cosmopet/woocommerce/assets/css/gp-style-core.css
  16. 101
      wp-content/themes/cosmopet/woocommerce/assets/css/gp-style-desktop.css

@ -275,137 +275,6 @@ add_action('wp_footer', 'add_facebook_pixel_events');
}
}
// Ваш код для custom_enqueue_ajax_add_to_cart остается без изменений
add_action('wp_enqueue_scripts', 'custom_enqueue_ajax_add_to_cart');
function custom_enqueue_ajax_add_to_cart() {
// Подключаем скрипт только на странице товара
if (is_product()) {
// Убедимся, что jQuery подключен
wp_enqueue_script('jquery');
// Inline JavaScript с поддержкой jQuery.noConflict
$ajax_script = "
jQuery(document).ready(function($) {
console.log('AJAX Add to Cart script loaded'); // Отладка: проверяем загрузку скрипта
// Перехват клика по кнопке
$('.single_add_to_cart_button').on('click', function(e) {
e.preventDefault();
e.stopPropagation(); // Предотвращаем всплытие события
console.log('Add to cart button clicked'); // Отладка: клик по кнопке
var \$button = $(this);
var \$form = \$button.closest('form.cart');
var product_id = \$button.val(); // Извлекаем product_id из value кнопки
var quantity = \$form.find('input[name=\"quantity\"]').val() || 1;
// Проверка на корректность product_id
if (!product_id || isNaN(product_id)) {
console.log('Invalid product_id:', product_id); // Отладка
console.log('Error: Неверный ID товара');
\$button.removeClass('loading').prop('disabled', false); // Разблокируем кнопку
return;
}
// Блокируем кнопку
\$button.addClass('loading').prop('disabled', true);
console.log('Sending AJAX request for product_id: ' + product_id + ', quantity: ' + quantity); // Отладка
// Подготовка данных
var data = {
action: 'woocommerce_ajax_add_to_cart',
product_id: product_id,
quantity: quantity
};
// Добавляем поле url, если есть
var urlField = \$form.find('input[name=\"url\"]');
if (urlField.length) {
data.url = urlField.val();
}
$.ajax({
type: 'POST',
url: ajax_object.ajax_url,
data: data,
dataType: 'json',
success: function(response) {
console.log('AJAX response:', response); // Отладка
if (response.success) {
console.log('Товар добавлен в корзину'); // Уведомление в консоли
// Обновляем фрагменты корзины
if (response.data.fragments) {
$.each(response.data.fragments, function(key, value) {
console.log('Updating fragment:', key); // Отладка
$(key).replaceWith(value);
});
}
$(document.body).trigger('wc_fragment_refresh');
$(document.body).trigger('added_to_cart', [response.data.fragments, response.data.cart_hash]);
// Сбрасываем форму
\$form[0].reset();
console.log('Form reset after successful add to cart'); // Отладка
} else {
console.log('Error: ' + (response.data.message || 'Ошибка при добавлении товара в корзину')); // Уведомление в консоли
}
},
error: function(xhr, status, error) {
console.error('AJAX error:', status, error); // Отладка
console.log('Error: Произошла ошибка при добавлении товара: ' + error);
},
complete: function() {
console.log('AJAX request completed'); // Отладка
\$button.removeClass('loading').prop('disabled', false); // Разблокируем кнопку
}
});
});
// Перехват отправки формы
$('form.cart').on('submit', function(e) {
e.preventDefault();
e.stopPropagation(); // Предотвращаем всплытие
console.log('Form submit prevented'); // Отладка
});
});
";
wp_add_inline_script('jquery', $ajax_script);
// Передаем AJAX URL
wp_localize_script('jquery', 'ajax_object', array(
'ajax_url' => admin_url('admin-ajax.php')
));
// Inline CSS
wp_enqueue_style('woocommerce-custom-styles', get_template_directory_uri() . '/style.css', array(), '1.0');
$custom_css = "
.single_add_to_cart_button.loading {
opacity: 0.5;
cursor: not-allowed;
position: relative;
}
.single_add_to_cart_button.loading:after {
content: '';
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid #fff;
border-radius: 50%;
border-top-color: transparent;
animation: spin 1s linear infinite;
position: absolute;
right: 10px;
}
@keyframes spin {
100% {
transform: rotate(360deg);
}
}
";
wp_add_inline_style('woocommerce-custom-styles', $custom_css);
}
}
// Отключаем кэширование для страниц товаров
add_action('template_redirect', function() {
if (is_product()) {

@ -1,4 +1,34 @@
/* Стили для планшетов */
@media only screen and (max-width: 992px) {
@media (min-width: 769px) and (max-width: 1200px) {
.footer__wrapper {
width: 100%!important;
display: flex;
flex-direction: column;
}
.footer-bottom {
flex-direction: column;
}
.footer-content__wrap {
flex-direction: column;
}
.footer-content__wrap {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 20px;
width: 100%;
}
}
@media(max-width:768px){
.footer-top {
flex-direction: column;
}
.footer-bottom {
flex-direction: column;
}
.footer-content__wrap {
flex-direction: column;
}
}

@ -2283,3 +2283,74 @@ textarea{
padding: 24px 16px!important;
}
}
.woocommerce-notices-wrapper{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
margin-bottom: 0 !important;
z-index: 10000;
}
.woocommerce-error,.woocommerce-info,.woocommerce-message {
padding: 1em 2em 1em 3.5em;
margin: 0 0 0em;
position: relative;
background-color: #f6f5f8;
color: #515151;
border-top: 3px solid #720eec;
list-style: none outside;
width: auto;
word-wrap: break-word
}
.woocommerce-error::after,.woocommerce-error::before,.woocommerce-info::after,.woocommerce-info::before,.woocommerce-message::after,.woocommerce-message::before {
content: " ";
display: table
}
.woocommerce-error::after,.woocommerce-info::after,.woocommerce-message::after {
clear: both
}
.woocommerce-error::before,.woocommerce-info::before,.woocommerce-message::before {
font-family: WooCommerce;
content: "\e028";
content: "\e028"/"";
display: inline-block;
position: absolute;
top: 1em;
left: 1.5em
}
.woocommerce-error .button,.woocommerce-info .button,.woocommerce-message .button {
float: right
}
.woocommerce-error li,.woocommerce-info li,.woocommerce-message li {
list-style: none outside!important;
padding-left: 0!important;
margin-left: 0!important
}
.woocommerce-message {
border-top-color: #8fae1b
}
.woocommerce-message::before {
content: "\e015";
color: #8fae1b
}
.woocommerce-info {
border-top-color: #1e85be
}
.woocommerce-info::before {
color: #1e85be
}
.woocommerce-error {
border-top-color: #b81c23
}
.woocommerce-error::before {
content: "\e016";
color: #b81c23
}

@ -99,6 +99,7 @@ jQuery(document).ready(function($) {
// Все элементы обработаны
localStorage.removeItem(removedItemsStorageKey);
updateCartFragment();
updateNotices();
$('#modal-basket').removeClass('loading');
return;
}
@ -166,6 +167,7 @@ jQuery(document).ready(function($) {
localStorage.setItem(removedItemsStorageKey, JSON.stringify(updatedItems));
updateCartFragment();
updateNotices();
// $('[data-key="' + key + '"]').remove()
}
}
@ -203,6 +205,7 @@ jQuery(document).ready(function($) {
$('.proceed-to-checkout').css('display', '');
updateCartFragment();
updateNotices();
}
}
});
@ -266,6 +269,7 @@ jQuery(document).ready(function($) {
// Обновление корзины при добавлении товара
$(document.body).on('added_to_cart', function() {
updateCartFragment();
updateNotices();
openBasketOnFirstAdd();
});
@ -288,6 +292,7 @@ jQuery(document).ready(function($) {
success: function(response) {
if (response.success) {
updateCartFragment(update_full);
updateNotices();
} else {
console.error('Ошибка при обновлении корзины');
}
@ -335,6 +340,33 @@ jQuery(document).ready(function($) {
});
}
function updateNotices() {
$.ajax({
type: 'POST',
url: woocommerce_params.ajax_url,
data: {
action: 'get_wc_notices'
},
beforeSend: function() {
console.log('Загрузка уведомлений...');
},
success: function(response) {
if (response.success && response.data && response.data.html) {
$('.woocommerce-notices-wrapper').html(response.data.html)
setTimeout(function(){
$('.woocommerce-notices-wrapper').html('')
}, 5000)
} else {
console.warn('Нет уведомлений');
}
},
error: function(xhr, status, error) {
console.error('Ошибка AJAX:', error);
}
});
}
// Добавляем спиннер на кнопку 'Добавить в корзину' в корзине
$('body').on('click', '.add_to_cart_button', function() {
var btn = $(this);
@ -379,6 +411,7 @@ jQuery(document).ready(function($) {
}
updateCartFragment();
updateNotices();
openBasketOnFirstAdd();
},
error: function(xhr) {
@ -421,4 +454,10 @@ jQuery(function($){
}
});
});
});

@ -28,7 +28,7 @@ function get_active_woobewoo_filters_for_twig() {
$raw_taxonomy = str_replace('wpf_filter_', '', $key);
error_log("→ Обнаружен фильтр: $raw_taxonomy");
$slugs = is_array($value) ? $value : explode('|', $value);
$slugs = is_array($value) ? $value : preg_split('/[\|,]/', $value);
error_log("→ Slugs: " . implode(', ', $slugs));
$taxonomy = taxonomy_exists('pa_' . $raw_taxonomy) ? 'pa_' . $raw_taxonomy : $raw_taxonomy;

@ -438,3 +438,8 @@
.discount_block{
padding-bottom: 80px;
}
.form-textarea{
font-family: inherit;
}

@ -3520,24 +3520,6 @@ color: #f4f1f0;
.reviews_item .swiper-fade .swiper-slide {
width:100%!important;
}
.footer__wrapper {
width: 100%!important;
display: flex;
flex-direction: column;
}
.footer-bottom {
flex-direction: column;
}
.footer-content__wrap {
flex-direction: column;
}
.footer-content__wrap {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 20px;
width: 100%;
}
.reviews_item.reviews_item2 {
position: absolute;
max-width: 500px;
@ -3553,15 +3535,6 @@ color: #f4f1f0;
}
@media(max-width:768px){
.footer-top {
flex-direction: column;
}
.footer-bottom {
flex-direction: column;
}
.footer-content__wrap {
flex-direction: column;
}
.home__title.invisible {
font-size:28px;
}

@ -295,3 +295,58 @@ function custom_remove_woocommerce_styles_on_checkout( $enqueue_styles ) {
return $enqueue_styles;
}
add_filter( 'woocommerce_enqueue_styles', 'custom_remove_woocommerce_styles_on_checkout' );
// Перехватываем валидацию и заменяем поведение
add_filter('woocommerce_add_to_cart_validation', 'custom_limit_stock_add_to_cart_behavior', 10, 5);
function custom_limit_stock_add_to_cart_behavior($passed, $product_id, $quantity, $variation_id = 0, $variations = []) {
$product = wc_get_product($variation_id ?: $product_id);
if (!$passed || !$product || !$product->managing_stock()) {
return $passed;
}
$stock = $product->get_stock_quantity();
$in_cart = WC()->cart->get_cart_item_quantities();
$already_in_cart = $in_cart[$product->get_id()] ?? 0;
$total = $already_in_cart + $quantity;
if ($total > $stock) {
$can_add = max($stock - $already_in_cart, 0);
if ($can_add > 0) {
// Добавим максимум
WC()->cart->add_to_cart($product_id, $can_add, $variation_id, $variations);
wc_add_notice(sprintf(
__('Вы запросили %d шт., но доступно только %d. Добавлено максимально возможное количество.', 'woocommerce'),
$quantity, $can_add
), 'notice');
} else {
wc_add_notice(__('Вы не можете добавить больше — товар закончился на складе.', 'woocommerce'), 'error');
}
// Возвращаем false, чтобы остановить оригинальное добавление
return false;
}
return $passed;
}
// Убираем редирект на страницу товара при неудаче добавления
add_filter('woocommerce_cart_redirect_after_error', '__return_false');
add_action('wp_ajax_get_wc_notices', 'custom_get_wc_notices');
add_action('wp_ajax_nopriv_get_wc_notices', 'custom_get_wc_notices');
function custom_get_wc_notices() {
ob_start();
wc_print_notices(); // выводим уведомления, если они есть
$html = ob_get_clean();
wp_send_json_success([
'html' => $html,
]);
}

@ -33,11 +33,18 @@
<div class="product-item__price">
<p>{{ post._price() }} {{ fn('get_woocommerce_currency_symbol') }}</p>
</div>
{% set stock_status = post.meta('_stock_status') == 'instock' %}
{% if stock_status == 'instock' %}
<div class="product-item__bye">
<button class="button button--white button--100-perc open-overlay">
{{ function('pll_e', 'Купить') }}
</button>
</div>
{% else %}
<button data-pname="{{ post.title }}" class="to-know button--100-perc open-to-know">
<p>{{ function('pll_e', 'Узнать о поступлении') }}</p>
</button>
{% endif %}
</div>
<div class="product-item__overlay">
<div class="product-item-overlay__header">
@ -72,6 +79,9 @@
{% set weight = function('get_product_info', sibling.ID, 'weight') %}
{% set s_product = TimberPost(sibling.ID) %}
{% set s_in_stock = s_product.meta('_stock_status') == 'instock' %}
{% if s_in_stock %}
{% set class = '' %}
{% if weight == cur_weight %}
{% set class = 'active' %}
@ -81,6 +91,7 @@
{{ weight }}
</button>
</li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>

@ -103,35 +103,48 @@ document.addEventListener("DOMContentLoaded", () => {
});
});
// Обработка клика на отдельные теги активных фильтров
const activeFilterTags = document.querySelectorAll('.active-filter-tag');
activeFilterTags.forEach(tag => {
tag.addEventListener('click', () => {
const slug = tag.dataset.filterSlug;
const taxonomy = tag.dataset.filterTaxonomy;
// Убираем префикс pa_ если есть для формирования параметра URL
const rawTaxonomy = taxonomy.replace('pa_', '');
const param = 'wpf_filter_' + rawTaxonomy;
// Обработка клика на теги активных фильтров
document.querySelectorAll('.active-filter-tag').forEach(tag => {
tag.addEventListener('click', function(e) {
e.preventDefault();
const slug = this.dataset.filterSlug;
const taxonomy = this.dataset.filterTaxonomy;
const urlParam = 'wpf_filter_' + taxonomy.replace('pa_', '');
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
if (params.has(param)) {
let values = params.get(param).split(',');
values = values.filter(v => v !== slug);
if (params.has(urlParam)) {
const currentValue = params.get(urlParam);
if (values.length > 0) {
params.set(param, values.join(','));
// Разделяем значения, учитывая как закодированные, так и обычные разделители
let values = currentValue.split(/\||%7C|,/);
// Декодируем и фильтруем значения
const newValues = values.filter(v => {
return decodeURIComponent(v.trim()) !== slug.trim();
});
// Обновляем URL параметры
if (newValues.length > 0) {
// Используем | как разделитель (можно заменить на ',', если нужно)
params.set(urlParam, newValues.join('|'));
} else {
params.delete(param);
params.delete(urlParam);
// Дополнительно очищаем связанные параметры
if (urlParam.includes('price')) {
params.delete('wpf_min_price');
params.delete('wpf_max_price');
}
params.delete('wpf_fbv');
}
// Обновляем URL и перезагружаем страницу
url.search = params.toString();
window.location.href = url.toString();
});
window.location.href = url.href;
}
});
});
// Обработка кнопки "Очистить все"
const clearAllBtn = document.querySelector('.active-filters__clear');

@ -33,11 +33,18 @@
<div class="product-item__price">
<p>{{ post._price() }} {{ fn('get_woocommerce_currency_symbol') }}</p>
</div>
{% set stock_status = fn('wc_get_product_stock_status', post.id) %}
{% if stock_status == 'instock' %}
<div class="product-item__bye">
<button class="button button--white button--100-perc open-overlay">
{{ function('pll_e', 'Купить') }}
</button>
</div>
{% else %}
<button data-pname="{{ post.title }}" class="to-know button--100-perc open-to-know">
<p>{{ function('pll_e', 'Узнать о поступлении') }}</p>
</button>
{% endif %}
</div>
<div class="product-item__overlay">
<div class="product-item-overlay__header">

@ -1,157 +0,0 @@
{% set bodyClass = 'bg-white' %}
{% set mainClass = 'wrapper' %}
{% extends 'layout.twig' %}
{% block content %}
{% if site_region == 'ru' %}
<style>
.product-item-overlay__price::after{
content: '₽';
}
</style>
{% endif %}
<div class="breadcrumbs">
<a href="/" class="breadcrumbs__item">
{{ function('pll_e', 'Главная') }}
</a>
<a href="/shop" class="breadcrumbs__item">
{{ function('pll_e', 'Продукция') }}
</a>
{% if category %}
<a href="{{ category_link }}" class="breadcrumbs__item">
{{ category_title }}
</a>
{% endif %}
</div>
<div class="product">
<div class="product__header">
<h1 class="product__title">
{% if category %}
{{ category.name }}
{% else %}
{{ function('pll_e', 'Продукция') }}
{% endif %}
</h1>
<button class="button button--gradient button--high button--icon button--filter">
{{ function('pll_e', 'Фильтры') }}
</button>
</div>
{% if active_filters|length > 0 %}
<div class="active-filters">
{% if active_filters is not empty %}
<div class="active-filters">
{% for filter in active_filters %}
<span class="active-filter-tag" data-filter-id="{{ filter.id }}" data-filter-slug="{{ filter.slug }}" data-filter-taxonomy="{{ filter.taxonomy }}">
{{ filter.name }} ×
</span>
{% endfor %}
</div>
{% endif %}
<button class="active-filters__clear button button--white">
{{ function('pll_e', 'Очистить все') }}
</button>
</div>
{% endif %}
<div class="product__main">
{% for post in posts %}
{% include 'archive-product/archive-product-tease.twig' with {post: post} %}
{% endfor %}
</div>
<div class="product__footer product__footer--error">
{% if posts_per_page < count %}
<button class="button button--white" id="load-more-products" data-category_id="{{ category_id }}" data-category_type="{{ category_type }}">
{{ function('pll_e', 'Загрузить еще') }}
</button>
{% endif %}
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
const filterButtons = document.querySelectorAll('.product-tagitem');
filterButtons.forEach(button => {
button.addEventListener('click', () => {
const slug = button.dataset.slug;
const taxonomy = button.dataset.taxonomy;
const param = 'wpf_filter_' + taxonomy;
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
if (params.has(param)) {
let values = params.get(param).split(',');
values = values.filter(v => v !== slug);
if (values.length > 0) {
params.set(param, values.join(','));
} else {
params.delete(param);
}
url.search = params.toString();
window.location.href = url.toString();
}
});
});
// Обработка клика на отдельные теги активных фильтров
const activeFilterTags = document.querySelectorAll('.active-filter-tag');
activeFilterTags.forEach(tag => {
tag.addEventListener('click', () => {
const slug = tag.dataset.filterSlug;
const taxonomy = tag.dataset.filterTaxonomy;
// Убираем префикс pa_ если есть для формирования параметра URL
const rawTaxonomy = taxonomy.replace('pa_', '');
const param = 'wpf_filter_' + rawTaxonomy;
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
if (params.has(param)) {
let values = params.get(param).split(',');
values = values.filter(v => v !== slug);
if (values.length > 0) {
params.set(param, values.join(','));
} else {
params.delete(param);
}
}
url.search = params.toString();
window.location.href = url.toString();
});
});
// Обработка кнопки "Очистить все"
const clearAllBtn = document.querySelector('.active-filters__clear');
if (clearAllBtn) {
clearAllBtn.addEventListener('click', () => {
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);
for (const key of Array.from(params.keys())) {
if (key.startsWith('wpf_')) {
params.delete(key);
}
}
url.search = params.toString();
window.location.href = url.toString();
});
}
});
</script>
{% endblock %}

@ -12,6 +12,9 @@
<body class="{{bodyClass}}">
{% include 'header.twig' %}
<main class="{{ mainClass }}">
<div class="woocommerce-notices-wrapper">
{{ fn('wc_print_notices') }}
</div>
{% block content %}
{% endblock %}
{% include 'modal.twig' %}

@ -1262,3 +1262,47 @@ button{
background-repeat: no-repeat;
background-position: center;
}
.wpfFilterWrapper ul:not(.wpfButtonsFilter) li{
min-width: 50%;
}
.to-know{
width: 100%;
padding: 12px;
display: flex;
justify-content: center;
border: none;
transition: opacity .2s ease-out;
text-transform: uppercase;
}
.to-know:hover{
opacity: .8;
}
.to-know p{
padding-bottom: 4px;
font-family: var(--font-family);
font-weight: 700;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
border-bottom: 1px var(--text-black) solid;
cursor: pointer;
}
.to-know--background-none{
background: none;
}

@ -704,107 +704,6 @@ main{
} */
/* modal */
/* footer */
.footer{
margin-top: 80px;
padding: 40px 24px;
background: var(--background-black);
}
.footer__wrapper{
width: 100%;
display: flex;
}
.footer__content{
width: calc(100% - 364px);
}
.footer__logo{
width: 187px;
height: 43px;
}
.footer__address{
margin-top: 24px;
font-family: var(--font-family);
font-weight: 500;
font-size: 24px;
line-height: 133%;
color: var(--text-white);
font-style: normal;
}
.footer__list{
margin: 28px -12px -12px -12px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.footer-list__item{
margin: 12px;
width: calc(50% - 24px);
display: flex;
flex-direction: column;
}
.footer-list__item:nth-child(even){
width: 322px;
}
.footer-list__item .button{
border-radius: 24px;
}
.footer-list__title{
font-family: var(--font-family);
font-weight: 700;
font-size: 16px;
line-height: 125%;
color: var(--text-white);
}
.footer-list__link{
margin-top: 4px;
font-family: var(--font-family);
font-weight: 500;
font-size: 24px;
line-height: 133%;
color: var(--text-white);
text-decoration: none;
}
.footer__form{
margin-left: 48px;
width: 364px;
}
.footer__about{
margin-top: 16px;
padding-top: 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid var(--text-white);
}
.footer-about__text{
font-family: var(--font-family);
font-weight: 500;
font-size: 20px;
line-height: 120%;
text-align: right;
color: var(--text-white);
opacity: 0.6;
text-decoration: none;
}
.footer__social-media{
display: none;
}
/* footer */
/* detail */
.detail{
margin: 48px 24px 24px 24px;

Loading…
Cancel
Save