Jamil-Abdullayev b8246597d4 Initial commit: orgsteklo WordPress theme
Custom WooCommerce theme for orgsteklo.ru including:
- Product catalog with category/subcategory hierarchy
- Custom checkout with delivery calculation
- Price calculator
- Admin settings panel
- Search functionality
- User account pages
2026-03-05 00:48:06 +04:00

474 lines
22 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
do_action( 'woocommerce_before_checkout_form', $checkout );
if ( ! $checkout->is_registration_enabled() && $checkout->is_registration_required() && ! is_user_logged_in() ) {
echo esc_html( apply_filters( 'woocommerce_checkout_must_be_logged_in_message', __( 'You must be logged in to checkout.', 'woocommerce' ) ) );
return;
}
?>
<section class="checkout">
<div class="checkout-container container">
<h1>Оформление заказа</h1>
<form name="checkout" method="post" class="woocommerce-checkout checkout-main" action="<?php echo esc_url( wc_get_checkout_url() ); ?>" enctype="multipart/form-data" aria-label="<?php echo esc_attr__( 'Checkout', 'woocommerce' ); ?>">
<div class="checkout-left">
<?php if ( $checkout->get_checkout_fields() ) : ?>
<?php do_action( 'woocommerce_checkout_before_customer_details' ); ?>
<?php do_action( 'woocommerce_checkout_billing' ); ?>
<?php if ( WC()->cart->needs_shipping() && WC()->cart->show_shipping() ) : ?>
<?php do_action( 'woocommerce_review_order_before_shipping' ); ?>
<?php wc_cart_totals_shipping_html(); ?>
<?php do_action( 'woocommerce_review_order_after_shipping' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_checkout_shipping' ); ?>
<?php do_action( 'woocommerce_checkout_after_customer_details' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_checkout_before_order_review_heading' ); ?>
<div class="checkout-col">
<div class="checkout-name">
<span>4</span>
<h3>Комментарий к заказу</h3>
</div>
<div class="checkout-block">
<div class="checkout-comment">
<div class="checkout-comment__col">
<textarea name="order_comments" id="order_comments" placeholder="Комментарий..."></textarea>
<p class="checkout-data__description"><?php echo nl2br( esc_html( orgsteklo_get_checkout_setting( 'comment_hint' ) ) ); ?></p>
</div>
<div class="checkout-comment__file">
<div class="checkout-comment__file-input">
<input type="file" id="checkout-file" name="checkout-file">
<label for="checkout-file">
<p>Прикрепить файл</p>
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_3029_15970)"><path d="M15.2986 6.89996C15.1735 6.77498 15.004 6.70477 14.8272 6.70477C14.6504 6.70477 14.4809 6.77498 14.3559 6.89996L7.09455 14.1926C6.78503 14.5022 6.41756 14.7478 6.01312 14.9153C5.60869 15.0829 5.17522 15.1691 4.73745 15.1692C3.85334 15.1692 3.00542 14.8181 2.38022 14.193C1.75501 13.5678 1.40374 12.72 1.40368 11.8359C1.40362 10.9518 1.75477 10.1038 2.37988 9.47863L9.41255 2.41729C9.78861 2.04722 10.2957 1.84074 10.8233 1.84283C11.3509 1.84491 11.8563 2.0554 12.2294 2.42843C12.6025 2.80147 12.8131 3.30683 12.8154 3.83443C12.8176 4.36204 12.6112 4.86915 12.2412 5.24529L5.20855 12.3066C5.08172 12.4281 4.91286 12.496 4.73722 12.496C4.56157 12.496 4.39272 12.4281 4.26588 12.3066C4.1409 12.1816 4.07069 12.0121 4.07069 11.8353C4.07069 11.6585 4.1409 11.489 4.26588 11.364L10.5272 5.07396C10.6487 4.94823 10.7159 4.77982 10.7143 4.60503C10.7128 4.43023 10.6427 4.26302 10.5191 4.13942C10.3955 4.01581 10.2283 3.9457 10.0535 3.94418C9.87869 3.94266 9.71029 4.00986 9.58455 4.13129L3.32322 10.4213C3.13746 10.607 2.99011 10.8275 2.88958 11.0702C2.78905 11.3129 2.73731 11.573 2.73731 11.8356C2.73731 12.0983 2.78905 12.3584 2.88958 12.6011C2.99011 12.8437 3.13746 13.0642 3.32322 13.25C3.7043 13.6136 4.2108 13.8165 4.73755 13.8165C5.2643 13.8165 5.7708 13.6136 6.15188 13.25L13.1839 6.18796C13.7959 5.56016 14.1359 4.71653 14.1303 3.83981C14.1247 2.96309 13.7739 2.12388 13.1539 1.50398C12.5339 0.884072 11.6946 0.533391 10.8179 0.527898C9.94118 0.522404 9.09759 0.862542 8.46988 1.47463L1.43722 8.53596C0.562003 9.41118 0.0703125 10.5982 0.0703125 11.836C0.0703125 13.0737 0.562003 14.2607 1.43722 15.136C2.31243 16.0112 3.49948 16.5029 4.73722 16.5029C5.97496 16.5029 7.162 16.0112 8.03722 15.136L15.2986 7.84529C15.3608 7.78334 15.4103 7.70969 15.444 7.62858C15.4777 7.54746 15.4951 7.46048 15.4951 7.37263C15.4951 7.28478 15.4777 7.1978 15.444 7.11668C15.4103 7.03556 15.3608 6.96191 15.2986 6.89996V6.89996Z" fill="white"/></g><defs><clipPath id="clip0_3029_15970"><rect width="16" height="16" fill="white" transform="translate(0 0.5)"/></clipPath></defs></svg>
</label>
</div>
<p class="checkout-data__description"><?php echo nl2br( esc_html( orgsteklo_get_checkout_setting( 'file_hint' ) ) ); ?></p>
</div>
</div>
</div>
</div>
<div class="checkout-col">
<div class="checkout-name">
<span>5</span>
<h3>Способ оплаты</h3>
</div>
<div class="checkout-block">
<div class="checkout-payments">
<div class="checkout-payment">
<input type="radio" id="checkout-payment-1" name="checkout-payments" checked="">
<label for="checkout-payment-1">Сформировать счет*</label>
</div>
<div class="checkout-payment">
<input type="radio" id="checkout-payment-2" name="checkout-payments">
<label for="checkout-payment-2">Оплата онлайн</label>
</div>
<p class="checkout-payments__description"><?php echo nl2br( esc_html( orgsteklo_get_checkout_setting( 'payment_description' ) ) ); ?></p>
<p class="checkout-payments__online-description" style="display:none;"><?php echo nl2br( esc_html( orgsteklo_get_checkout_setting( 'online_payment_description' ) ) ); ?></p>
</div>
</div>
</div>
</div>
<?php do_action( 'woocommerce_checkout_before_order_review' ); ?>
<div id="order_review" class="woocommerce-checkout-review-order checkout-right">
<div class="checkout-sidebar">
<h3>Ваша корзина</h3>
<div class="checkout-sidebar__col">
<?php
$count = WC()->cart->get_cart_contents_count();
function plural_form($number, $forms) {
$n = abs($number) % 100;
$n1 = $n % 10;
if ($n > 10 && $n < 20) return $forms[2];
if ($n1 > 1 && $n1 < 5) return $forms[1];
if ($n1 == 1) return $forms[0];
return $forms[2];
}
$word = plural_form($count, ['товар', 'товара', 'товаров']);
?>
<div class="checkout-sidebar__row">
<p>Количество товаров:</p>
<p><?php echo $count . ' ' . $word; ?></p>
</div>
<?php
$cart = WC()->cart;
$total_weight = 0;
foreach ( $cart->get_cart() as $item ) {
$product = $item['data'];
$qty = $item['quantity'];
$weight = (float) $product->get_weight();
$total_weight += $weight * $qty;
}
?>
<div class="checkout-sidebar__row">
<p>Вес заказа:</p>
<p><?php echo number_format($total_weight, 3, '.', ' '); ?> кг</p>
</div>
<?php
$cart = WC()->cart;
$items = $cart->get_cart();
$regular_total = 0;
$sale_total = 0;
foreach ( $items as $item ) {
$product = $item['data'];
$quantity = $item['quantity'];
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
if ( $sale_price === '' ) {
$sale_price = $regular_price;
}
$regular_total += $regular_price * $quantity;
$sale_total += $sale_price * $quantity;
}
$discount_total = $regular_total - $sale_total;
?>
<div class="checkout-sidebar__row">
<p>Стоимость товара без скидки:</p>
<p><?php echo wc_price($regular_total); ?></p>
</div>
<div class="checkout-sidebar__row">
<p>Скидка на товар:</p>
<p><?php echo wc_price($discount_total); ?></p>
</div>
<?php
$cart = WC()->cart;
$regular_total = 0;
$sale_total = 0;
foreach ( $cart->get_cart() as $item ) {
$product = $item['data'];
$qty = $item['quantity'];
$regular_price = $product->get_regular_price();
$sale_price = $product->get_sale_price();
if ( $sale_price === '' ) {
$sale_price = $regular_price;
}
$regular_total += $regular_price * $qty;
$sale_total += $sale_price * $qty;
}
$cart_discount = orgsteklo_calculate_cart_discount( $sale_total );
$final_total = $sale_total - $cart_discount['amount'];
?>
<?php if ( $cart_discount['percent'] > 0 ) : ?>
<div class="checkout-sidebar__row">
<p>Скидка от суммы заказа (<?php echo $cart_discount['percent']; ?>%):</p>
<p><?php echo wc_price( $cart_discount['amount'] ); ?></p>
</div>
<?php endif; ?>
<div class="checkout-sidebar__row" id="checkout-sidebar__delivery" style="display:none;">
<p>Стоимость доставки:</p>
<p id="checkout-delivery-price">0 ₽</p>
</div>
</div>
<div class="checkout-sidebar__price-col">
<p class="checkout-sidebar__price-title">Итоговая стоимость заказа:</p>
<div class="cart-total__price-row">
<p class="cart-total__price" id="checkout-final-total" data-base-total="<?php echo esc_attr($final_total); ?>" data-regular-total="<?php echo esc_attr($regular_total); ?>"><?php echo number_format($final_total, 0, ',', ' '); ?> <span>₽</span></p>
<?php if ( $regular_total > $final_total ) : ?>
<p class="cart-total__oldprice" id="checkout-old-total"><?php echo number_format($regular_total, 0, ',', ' '); ?> <span>₽</span></p>
<?php endif; ?>
</div>
</div>
<?php do_action( 'woocommerce_checkout_order_review' ); ?>
</div>
</div>
<?php do_action( 'woocommerce_checkout_after_order_review' ); ?>
</form>
</div>
</section>
<script>
document.addEventListener('DOMContentLoaded', function () {
const deliveryBlock = document.getElementById('checkout-sidebar__delivery');
const deliveryPriceEl = document.getElementById('checkout-delivery-price');
const shippingInputs = document.querySelectorAll('.shipping_method');
const kmRate = <?php echo intval( orgsteklo_get_checkout_setting( 'moscow_area_km_rate' ) ); ?>;
function updateDeliveryVisibility() {
const selected = document.querySelector('.shipping_method:checked');
if (! selected) return;
let cost = parseFloat( selected.dataset.cost || 0 );
const shippingId = selected.id || '';
// Для МО: базовая стоимость + N руб/км от МКАД
if ( shippingId === 'shipping_method_0_dostavka-po-moskovskoj-oblasti' ) {
const kmInput = document.getElementById('shipping_km_mkad');
const km = kmInput ? parseFloat(kmInput.value) || 0 : 0;
cost = cost + (kmRate * km);
}
if ( cost > 0 ) {
deliveryBlock.style.display = 'flex';
deliveryPriceEl.textContent = Math.round(cost).toLocaleString('ru-RU') + ' ₽';
} else {
deliveryBlock.style.display = 'none';
}
// Обновляем итоговую сумму с учётом доставки
const totalEl = document.getElementById('checkout-final-total');
const oldTotalEl = document.getElementById('checkout-old-total');
if ( totalEl ) {
const baseTotal = parseFloat(totalEl.dataset.baseTotal) || 0;
const regularTotal = parseFloat(totalEl.dataset.regularTotal) || 0;
const deliveryCost = cost > 0 ? cost : 0;
const newTotal = Math.round(baseTotal + deliveryCost);
totalEl.innerHTML = newTotal.toLocaleString('ru-RU') + ' <span>₽</span>';
if ( oldTotalEl && regularTotal > baseTotal ) {
const newOldTotal = Math.round(regularTotal + deliveryCost);
oldTotalEl.innerHTML = newOldTotal.toLocaleString('ru-RU') + ' <span>₽</span>';
}
}
}
shippingInputs.forEach(input => {
input.addEventListener('change', updateDeliveryVisibility);
});
// Пересчёт при вводе км от МКАД
document.addEventListener('input', function(e) {
if (e.target && e.target.id === 'shipping_km_mkad') {
updateDeliveryVisibility();
}
});
// Инициализация при загрузке страницы
updateDeliveryVisibility();
jQuery( document.body ).on( 'updated_checkout', updateDeliveryVisibility );
});
jQuery(document).ready(function($) {
function updateDeliveryBlock() {
// Сначала скрываем все возможные блоки
$('#checkout-delivery_pickup, #checkout-delivery_moscow, #checkout-delivery_moscow_area, #checkout-delivery_region, #checkout-delivery_pochta').hide();
// Находим выбранный метод
const selected = $('.shipping_method:checked').attr('id');
// Показываем нужный блок в зависимости от id
switch (selected) {
case 'shipping_method_0_samovyvoz':
$('#checkout-delivery_pickup').show();
break;
case 'shipping_method_0_dostavka-po-moskve':
$('#checkout-delivery_moscow').show();
break;
case 'shipping_method_0_dostavka-po-moskovskoj-oblasti':
$('#checkout-delivery_moscow_area').show();
break;
case 'shipping_method_0_v-drugoj-region':
$('#checkout-delivery_region').show();
break;
case 'shipping_method_0_v-drugoj-region-pochtoj-rossii':
$('#checkout-delivery_pochta').show();
break;
}
}
// При загрузке страницы
updateDeliveryBlock();
// При изменении метода доставки
$(document).on('change', '.shipping_method', function() {
updateDeliveryBlock();
});
// При AJAX-обновлении (если WooCommerce Checkout делает пересчёт)
$(document.body).on('updated_checkout', function() {
updateDeliveryBlock();
});
});
jQuery(document).ready(function($) {
function updateOrderButtonText(method) {
const $orderButton = $('#place_order');
if (method === 'cod') {
$orderButton.text('Отправить заказ для выставления счета');
$orderButton.val('Отправить заказ для выставления счета');
$orderButton.attr('data-value', 'Отправить заказ для выставления счета');
} else {
$orderButton.text('Оплатить заказ');
$orderButton.val('Оплатить заказ');
$orderButton.attr('data-value', 'Оплатить заказ');
}
}
function syncPaymentRadios() {
$('.checkout-payment input[type="radio"]').on('change', function() {
const customID = $(this).attr('id');
$('.wc_payment_methods input[name="payment_method"]').prop('checked', false);
if (customID === 'checkout-payment-1') {
$('#payment_method_cod').prop('checked', true).trigger('change');
updateOrderButtonText('cod');
} else if (customID === 'checkout-payment-2') {
$('#payment_method_bacs').prop('checked', true).trigger('change');
updateOrderButtonText('bacs');
}
});
$('.wc_payment_methods input[name="payment_method"]').on('change', function() {
const method = $(this).val();
if (method === 'cod') {
$('#checkout-payment-1').prop('checked', true);
} else if (method === 'bacs') {
$('#checkout-payment-2').prop('checked', true);
}
updateOrderButtonText(method);
});
}
// Инициализация
syncPaymentRadios();
// При загрузке страницы: установить текст в зависимости от выбранного способа оплаты
const initialMethod = $('.wc_payment_methods input[name="payment_method"]:checked').val();
updateOrderButtonText(initialMethod);
// При ajax-обновлении формы
$(document.body).on('updated_checkout', function() {
syncPaymentRadios();
const updatedMethod = $('.wc_payment_methods input[name="payment_method"]:checked').val();
updateOrderButtonText(updatedMethod);
});
});
/* ===== Управление видимостью способов оплаты ===== */
jQuery(document).ready(function($) {
window.updatePaymentMethodVisibility = function() {
var $paymentCod = $('#checkout-payment-1').closest('.checkout-payment');
var $paymentBacs = $('#checkout-payment-2').closest('.checkout-payment');
var $descCod = $('.checkout-payments__description');
var $descOnline = $('.checkout-payments__online-description');
// Определяем тип покупателя: 0 = физ. лицо, 1 = юр. лицо
var personTab = $('.checkout-data__tab.active').index();
// Определяем способ доставки
var shippingId = $('.shipping_method:checked').attr('id') || '';
var isRemote = (
shippingId === 'shipping_method_0_v-drugoj-region' ||
shippingId === 'shipping_method_0_v-drugoj-region-pochtoj-rossii'
);
if (isRemote) {
// Другой регион / Почта России → только "Сформировать счёт" для всех
$paymentCod.show();
$paymentBacs.hide();
$('#checkout-payment-1').prop('checked', true).trigger('change');
$descCod.show();
$descOnline.hide();
} else if (personTab === 1) {
// Юр. лицо + локальная доставка → оба способа
$paymentCod.show();
$paymentBacs.show();
// Показываем описание в зависимости от выбранного способа
if ($('#checkout-payment-2').is(':checked')) {
$descCod.hide();
$descOnline.show();
} else {
$descCod.show();
$descOnline.hide();
}
} else {
// Физ. лицо + локальная доставка → только "Оплата онлайн"
$paymentCod.hide();
$paymentBacs.show();
$('#checkout-payment-2').prop('checked', true).trigger('change');
$descCod.hide();
$descOnline.show();
}
};
// Переключение описаний при смене радиокнопки оплаты
$(document).on('change', '.checkout-payment input[type="radio"]', function() {
var $descCod = $('.checkout-payments__description');
var $descOnline = $('.checkout-payments__online-description');
if ($('#checkout-payment-2').is(':checked')) {
$descCod.hide();
$descOnline.show();
} else {
$descCod.show();
$descOnline.hide();
}
});
// Привязка к событиям
$(document).on('change', '.shipping_method', function() {
updatePaymentMethodVisibility();
});
$(document.body).on('updated_checkout', function() {
updatePaymentMethodVisibility();
});
// Инициализация при загрузке
updatePaymentMethodVisibility();
// Синхронизация кастомных полей с WooCommerce hidden fields
function syncBillingFields() {
var personTab = $('.checkout-data__tab.active').index();
if ( personTab === 0 ) {
// Физ. лицо
$('#billing_first_name_hidden').val( $('#billing_fio').val() );
$('#billing_phone_hidden').val( $('#billing_phone_phys').val() );
$('#billing_email_hidden').val( $('#billing_email_phys').val() );
$('#billing_person_type_hidden').val('physical');
// Очищаем юр. поля
$('#billing_company_name_hidden, #billing_inn_hidden, #billing_kpp_hidden, #billing_legal_address_hidden, #billing_actual_address_hidden').val('');
} else {
// Юр. лицо
$('#billing_first_name_hidden').val( $('#billing_contact_person').val() );
$('#billing_phone_hidden').val( $('#billing_phone_legal').val() );
$('#billing_email_hidden').val( $('#billing_email_legal').val() );
$('#billing_company_name_hidden').val( $('#billing_company_name').val() );
$('#billing_inn_hidden').val( $('#billing_inn').val() );
$('#billing_kpp_hidden').val( $('#billing_kpp').val() );
$('#billing_legal_address_hidden').val( $('#billing_legal_address').val() );
$('#billing_actual_address_hidden').val( $('#billing_actual_address').val() );
$('#billing_person_type_hidden').val('legal');
}
}
// Синхронизируем при любом вводе
$(document).on('input change', '.checkout-data input', syncBillingFields);
// Синхронизируем перед отправкой заказа
$(document.body).on('checkout_place_order', function() {
syncBillingFields();
});
// Валидация чекбокса согласия перед отправкой
$(document.body).on('checkout_place_order', function() {
if ( !$('#checkout-checkbox').is(':checked') ) {
if ( $('.checkout-checkbox-error').length === 0 ) {
$('.consult-checkbox').append(
'<p class="checkout-checkbox-error" style="color: #F02E13; font-size: 1.2rem; margin-top: 0.4rem;">Необходимо согласиться с политикой конфиденциальности и публичной офертой</p>'
);
}
$('html, body').animate({
scrollTop: $('.consult-checkbox').offset().top - 100
}, 300);
return false;
}
$('.checkout-checkbox-error').remove();
return true;
});
$('#checkout-checkbox').on('change', function() {
if ( $(this).is(':checked') ) {
$('.checkout-checkbox-error').remove();
}
});
});
</script>
<?php do_action( 'woocommerce_after_checkout_form', $checkout ); ?>