single product page

task_4097
GP_DV 3 months ago
parent 38bec6349a
commit a332e5b62a
  1. 155
      wp-content/themes/cosmopet/functions.php
  2. 552
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/css/gp-style-core.css
  3. 722
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/css/gp-style-desktop.css
  4. 38
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/css/gp-style-mobile.css
  5. 348
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/css/gp-style-tablet.css
  6. 3
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/img/svg/main/arrow-breadcrumbs.svg
  7. 5
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/img/svg/main/arrow-left.svg
  8. 5
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/img/svg/main/arrow-right.svg
  9. 11
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/img/svg/main/black-x.svg
  10. 348
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/js/gp-main.js
  11. 110
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/js/gp-product.js
  12. 67
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/js/tabs.js
  13. 89
      wp-content/themes/cosmopet/modules/shop/components/single-product/assets/js/toggle.js
  14. 74
      wp-content/themes/cosmopet/modules/shop/components/single-product/component-controller.php
  15. 447
      wp-content/themes/cosmopet/modules/shop/components/single-product/component-template.twig
  16. 56
      wp-content/themes/cosmopet/modules/shop/module-controller.php
  17. 60
      wp-content/themes/cosmopet/single-product.php
  18. 5
      wp-content/themes/cosmopet/static/shop/img/svg/main/arrow-left.svg
  19. 5
      wp-content/themes/cosmopet/static/shop/img/svg/main/arrow-right.svg
  20. 11
      wp-content/themes/cosmopet/static/shop/img/svg/main/black-x.svg
  21. 63
      wp-content/themes/cosmopet/templates/shop/single-product.php
  22. 198
      wp-content/themes/cosmopet/woocommerce/archive-product/archive-product-tease.twig
  23. 19
      wp-content/themes/cosmopet/woocommerce/single-product.php

@ -535,12 +535,19 @@ function get_products() {
}
function get_product_info ($id, $type) {
$product = wc_get_product( $id );
if (!$id) {
return '';
}
$product = wc_get_product($id);
if (!$product) {
return '';
}
if ($type == 'price') {
return $product->get_price();
} elseif ($type == 'weight') {
return $product->get_weight() . ' кг';
return $product->get_weight() ? $product->get_weight() . ' кг' : '';
}
return '';
}
function get_add_to_cart_button ($id) {
@ -550,6 +557,10 @@ function get_add_to_cart_button ($id) {
}
function get_collection_siblings ($term) {
if (!$term) {
return [];
}
$args = array(
'posts_per_page' => -1,
'post_type' => 'product',
@ -782,3 +793,143 @@ function create_likes_table() {
dbDelta($sql);
}
add_action('after_switch_theme', 'create_likes_table');
add_filter('woocommerce_product_data_tabs', function($tabs) {
$tabs['composition_tab'] = array(
'label' => 'Состав',
'target' => 'composition_product_data',
'class' => array('composition_tab'),
'priority' => 60,
);
$tabs['feeding_tab'] = array(
'label' => 'Рекомендации по кормлению',
'target' => 'feeding_product_data',
'class' => array('feeding_tab'),
'priority' => 61,
);
$tabs['important_tab'] = array(
'label' => 'Важно',
'target' => 'important_product_data',
'class' => array('important_tab'),
'priority' => 62,
);
return $tabs;
});
add_action('woocommerce_product_data_panels', function() {
global $post;
$composition = get_post_meta($post->ID, '_composition', true);
echo '<div id="composition_product_data" class="panel woocommerce_options_panel">';
woocommerce_wp_textarea_input([
'id' => '_composition',
'label' => 'Состав',
'desc_tip' => true,
'description' => 'Введите состав товара',
'value' => $composition
]);
echo '</div>';
});
add_action('woocommerce_product_data_panels', function() {
global $post;
$feeding = get_post_meta($post->ID, '_feeding_recommendations', true);
echo '<div id="feeding_product_data" class="panel woocommerce_options_panel">';
woocommerce_wp_textarea_input([
'id' => '_feeding_recommendations',
'label' => 'Рекомендации по кормлению',
'desc_tip' => true,
'description' => 'Введите рекомендации по кормлению',
'value' => $feeding
]);
echo '</div>';
});
add_action('woocommerce_product_data_panels', function() {
global $post;
$important = get_post_meta($post->ID, '_important', true);
echo '<div id="important_product_data" class="panel woocommerce_options_panel">';
woocommerce_wp_textarea_input([
'id' => '_important',
'label' => 'Важно',
'desc_tip' => true,
'description' => 'Введите важную информацию',
'value' => $important
]);
echo '</div>';
});
add_action('woocommerce_process_product_meta', function($post_id) {
if (isset($_POST['_composition'])) {
update_post_meta($post_id, '_composition', sanitize_textarea_field($_POST['_composition']));
}
if (isset($_POST['_feeding_recommendations'])) {
update_post_meta($post_id, '_feeding_recommendations', sanitize_textarea_field($_POST['_feeding_recommendations']));
}
if (isset($_POST['_important'])) {
update_post_meta($post_id, '_important', sanitize_textarea_field($_POST['_important']));
}
});
// Добавление поля для выбора рекомендуемых товаров
function register_recommended_products_acf_field() {
if (function_exists('acf_add_local_field_group')) {
acf_add_local_field_group(array(
'key' => 'group_recommended_products',
'title' => 'Рекомендуемые товары',
'fields' => array(
array(
'key' => 'field_recommended_products',
'label' => 'Выберите рекомендуемые товары',
'name' => 'recommended_products',
'type' => 'relationship',
'instructions' => 'Выберите товары, которые будут отображаться в секции "вашему питомцу может понравиться"',
'required' => 0,
'conditional_logic' => 0,
'post_type' => array(
0 => 'product',
),
'filters' => array(
0 => 'search',
1 => 'taxonomy',
),
'return_format' => 'object',
'min' => '',
'max' => 8,
),
),
'location' => array(
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'product',
),
),
),
'menu_order' => 0,
'position' => 'normal',
'style' => 'default',
'label_placement' => 'top',
'instruction_placement' => 'label',
'hide_on_screen' => '',
));
}
}
add_action('acf/init', 'register_recommended_products_acf_field');
add_action('wp_footer', 'remove_view_cart_button_js');
function remove_view_cart_button_js() {
?>
<script>
jQuery(document).ready(function($) {
$(document).on('added_to_cart', function() {
$('.added_to_cart.wc-forward').remove();
});
});
</script>
<?php
}

@ -0,0 +1,552 @@
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Переменные, шрифты, UI kit */
/*
700 - Bold
600 - SemiBold / Demi
500 - Medium
400 - Regular
*/
a{
cursor: pointer;
}
/* Craftwork Grotesk */
@font-face {
font-family: "Craftwork Grotesk";
src: local("Craftwork Grotesk Bold"),
url("../fonts/craftwork/CraftworkGrotesk-SemiBold.woff2") format("woff2"),
url("../fonts/craftwork/CraftworkGrotesk-Bold.woff") format("woff"),
url("../fonts/craftwork/craftwork-grotesk-bold.ttf") format("ttf");
font-weight: 700;
}
@font-face {
font-family: "Craftwork Grotesk";
src: local("Craftwork Grotesk SemiBold"),
url("../fonts/craftwork/CraftworkGrotesk-SemiBold.woff2") format("woff2"),
url("../fonts/craftwork/CraftworkGrotesk-SemiBold.woff") format("woff"),
url("../fonts/craftwork/craftwork-grotesk-semi-bold.ttf") format("ttf");
font-weight: 600;
}
@font-face {
font-family: "Craftwork Grotesk";
src: local("Craftwork Grotesk Medium"),
url("../fonts/craftwork/CraftworkGrotesk-Medium.woff2") format("woff2"),
url("../fonts/craftwork/CraftworkGrotesk-Medium.woff") format("woff"),
url("../fonts/craftwork/craftwork-grotesk-medium.ttf") format("ttf");
font-weight: 500;
}
@font-face {
font-family: "Craftwork Grotesk";
src: local("Craftwork Grotesk Regular"),
url("../fonts/craftwork/CraftworkGrotesk-Regular.woff2") format("woff2"),
url("../fonts/craftwork/CraftworkGrotesk-Regular.woff") format("woff"),
url("../fonts/craftwork/craftwork-grotesk-regular.ttf") format("ttf");
font-weight: 400;
}
/* Craftwork Grotesk */
/* din 2014 */
@font-face {
font-family: "DIN 2014 Rounded";
src: local("DIN 2014 Rounded Demi"),
url("../fonts/din-2014/din-2014-rounded-demi.woff2") format("woff2"),
url("../fonts/din-2014/din-2014-rounded-demi.woff") format("woff"),
url("../fonts/din-2014/din-2014-rounded-demi.ttf") format("ttf");
font-weight: 600;
}
@font-face {
font-family: "DIN 2014 Rounded";
src: local("DIN 2014 Rounded Regular"),
url("../fonts/din-2014/din-2014-rounded-regular.woff2") format("woff2"),
url("../fonts/din-2014/din-2014-rounded-regular.woff") format("woff"),
url("../fonts/din-2014/din-2014-rounded-regular.ttf") format("ttf");
font-weight: 400;
}
/* din 2014 */
/* roboto */
@font-face {
font-family: "Roboto";
src: local("Roboto Medium"),
url("../fonts/roboto/Roboto-Medium.woff2") format("woff2"),
url("../fonts/roboto/Roboto-Medium.woff") format("woff"),
url("../fonts/roboto/roboto-medium.ttf") format("ttf");
font-weight: 500;
}
@font-face {
font-family: "Roboto";
src: local("Roboto Regular"),
url("../fonts/roboto/Roboto-Regular.woff2") format("woff2"),
url("../fonts/roboto/Roboto-Regular.woff") format("woff"),
url("../fonts/roboto/roboto-medium.ttf") format("ttf");
font-weight: 400;
}
/* roboto */
/* Глобальные переменные: */
:root {
/* fonts */
--font-family: "Craftwork Grotesk", sans-serif;
--second-family: "DIN 2014 Rounded", sans-serif;
--third-family: "Roboto", sans-serif;
/* color */
/* text */
--text-white: #fff;
--text-black: #121212;
--text-dark: #2b2b3b;
--text-grey: #999;
--text-red: #fa0505;
--text-green: #2ED15D;
--text-0: #000;
--text-3: #333;
--text-6: #666;
--text-9: #999;
/* background */
--background-white: #fff;
--background-black: #121212;
--background-grey: #f2f2f2;
--background-green: #2ED15D;
--background-green-white: #f4fff0;
--background-9: #999;
/* gradient */
--gradient-blue: radial-gradient(346.57% 244.17% at 149.73% -58.39%, rgb(15, 88, 129) 0%, rgb(30, 164, 156) 51.21689438819885%, rgb(118, 206, 117) 80.70731163024902%, rgb(236, 243, 159) 91.14583134651184%);
--gradient-turquoise: radial-gradient(346.57% 244.17% at 149.73% -58.39%, rgb(117, 196, 240) 0%, rgb(126, 231, 225) 51.21689438819885%, rgb(181, 228, 180) 80.70731163024902%, rgb(237, 244, 164) 91.14583134651184%);
--gradient-red: linear-gradient(22deg, #f44242 0%, #569ef0 100%);
}
/* общие */
button{
cursor: pointer;
}
.wrapper{
margin: 0 auto;
max-width: 1600px;
}
/* компоненты */
/* lang*/
/* lang */
/* mini-profile */
/* mini-profile */
/* main-menu */
/* main-menu */
/* form */
/* .form-input-radio__ */
/* form */
/* social media */
/* social media */
/* breadcrumbs */
.breadcrumbs{
margin: 24px;
display: flex;
align-items: center;
}
.breadcrumbs__item{
display: block;
padding: 0px 16px;
font-weight: 700;
font-size: 16px;
line-height: 125%;
color: var(--text-6);
text-decoration: none;
position: relative;
}
.breadcrumbs__item:first-child{
padding-left: 0;
}
/* breadcrumbs */
/* compound */
.compound{
margin: -5px;
min-height: 33.95px;
display: flex;
align-items: start;
}
.compound__item{
margin: 5px;
padding: 4px 8px;
font-weight: 700;
font-size: 12px;
line-height: 133%;
color: var(--text-black);
border-radius: 16px;
background-color: var(--background-white);
display: block;
text-decoration: none;
}
.compound__item:first-child{
margin-left: 0;
}
/* compound */
/* button */
.button{
font-weight: 600;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
border-radius: 20px;
cursor: pointer;
}
.button--100-perc{
width: 100%;
}
.button--white{
padding: 11px 24px;
text-align: center;
background-color: var(--background-white);
border: 1px solid var(--background-black);
transition: opacity .2s ease-out;
}
.button--white:hover{
opacity: .8;
}
.button--gradient{
background: var(--gradient-turquoise);
border: none;
transition: opacity .2s ease-out;
}
.button--gradient:hover{
opacity: .8;
}
.button--high{
height: 56px;
padding: 16px 24px 24px 24px;
font-weight: 700;
text-align: center;
position: relative;
}
.button--red-48-px{
border-radius: 48px;
}
.to-know{
/* width: 100%; */
padding: 12px 24px 7px 24px;
display: flex;
justify-content: center;
border: none;
transition: opacity .2s ease-out;
text-decoration: none;
}
.to-know:hover{
opacity: .8;
}
.to-know p{
padding-bottom: 4px;
font-weight: 700;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
border-bottom: 1px var(--text-black) solid;
cursor: pointer;
}
.back{
margin-top: 16px;
margin-left: 16px;
padding: 8px;
padding-left: 32px;
background: none;
border: none;
font-weight: 600;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
text-decoration: none;
position: relative;
}
.back::before{
content: '';
position: absolute;
top: 8px;
left: 0;
margin-right: 8px;
width: 24px;
height: 24px;
background-image: url(../img/svg/main/arrow-back.svg);
}
.back::after{
content: '';
position: absolute;
bottom: 6px;
left: 0;
width: calc(100% - 8px);
height: 1px;
background: var(--text-black);
}
/* button */
/* select */
.select{
max-width: 144px;
position: relative;
}
.select__state{
width: 100%;
padding: 11px 47px 11px 13px;
/* pointer-events:none; */
border: 1px solid var(--background-black);
border-radius: 20px;
font-weight: 400;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
cursor: pointer;
position: relative;
transition: opacity .2s ease-out;
}
.select:hover .select__state{
opacity: .8;
}
.select::after{
content: '';
position: absolute;
top: 20.5px;
right: 21.5px;
width: 17px;
height: 10px;
background-image: url(../img/svg/main/arrow-black.svg);
background-repeat: no-repeat;
background-size: contain;
pointer-events: none;
}
.state__block{
position: absolute;
top: 48px;
left: 0;
width: 100%;
height: 0;
overflow: hidden;
transition: height .2s ease-out;
}
.state__content{
padding: 8px;
border-radius: 6px;
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1), 0 0 2px 0 rgba(0, 0, 0, 0.2);
background-color: var(--background-white);
list-style-type: none;
}
.state__content li{
margin-top: 8px;
}
.state__content li:first-child{
margin-top: 0;
}
.state__button{
width: 100%;
padding: 4px 32px 4px 4px;
background: none;
border: none;
font-weight: 400;
font-size: 20px;
line-height: 120%;
color: var(--text-dark);
text-align: start;
border-radius: 6px;
transition: background-color .2s ease-out;
position: relative;
}
.state__button:hover{
background-color: var(--background-grey);
}
/* select */
/* counter */
.counter{
display: flex;
align-items: center;
}
.counter__input{
width: 48px;
font-weight: 600;
font-size: 20px;
line-height: 120%;
text-align: center;
color: var(--text-black);
pointer-events: none;
background: none;
border: none;
}
.counter__button{
width: 48px;
height: 48px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--text-3);
border-radius: 24px;
background: var(--background-white);
transition: opacity .2s ease-out;
}
.counter__button:hover{
opacity: .8;
}
/* counter */
/* modal */
/* modal */
/* toggle */
.toggle{
padding-top: 26px;
padding-bottom: 25px;
border-bottom: 1px solid var(--text-3);
position: relative;
}
.toggle::after{
content: '';
position: absolute;
top: 24px;
right: 0;
width: 24px;
aspect-ratio: 1;
background-image: url(../img/svg/main/black-x.svg);
transform: rotate(45deg);
transition: transform .2s;
pointer-events: none;
}
.toggle__title{
padding-right: 30px;
font-weight: 700;
font-size: 16px;
line-height: 125%;
color: var(--text-black);
cursor: pointer;
}
.toggle__block-content{
height: 0;
overflow: hidden;
transition: height .2s ease-out;
}
.toggle__content{
padding-top: 24px;
}
.toggle__text{
font-weight: 400;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
}
/* toggle */
/* checkbox */
/* checkbox */
/* radio */
/* radio */

@ -0,0 +1,722 @@
/* Основные стили для компьютера */
/* header start */
.detail-block-form__item a{
display: block;
}
.detail-block-form__items{
margin-top: 12px;
}
.detail-block-form__item a {
margin: 8px;
}
/* header end */
/* product */
.product__item{
margin: 12px;
width: calc(25% - 24px);
display: flex;
flex-direction: column;
justify-content: space-between;
background-color: var(--background-grey);
border-radius: 24px;
overflow: hidden;
position: relative;
}
.product__item::before{
content: '';
position: absolute;
top: 0;
left: 0;
width: calc(100% - 2px);
height: calc(100% - 2px);
border: 1px solid #000;
border-radius: 24px;
pointer-events: none;
transition: opacity .2s ease-out;
opacity: 0;
}
.product__item:hover::before{
opacity: 1;
}
.product-item__label{
position: absolute;
top: 16px;
left: 16px;
margin: -2px;
display: flex;
align-items: center;
z-index: 10;
}
.product-item-label__tag{
margin: 2px;
padding: 4px 8px;
font-weight: 700;
font-size: 12px;
line-height: 133%;
color: #f4f1f0;
border-radius: 16px;
display: block;
text-decoration: none;
}
.product-item-label__tag--new{
background: var(--gradient-blue);
}
.product-item-label__tag--sale{
background: var(--gradient-red);
}
.product-item-label__tag--black{
background: var(--background-black);
color: var(--text-white);
}
.product-item-label__tag--title{
padding: 4px 2px;
font-size: 16px;
line-height: 125%;
color: var(--text-black);
display: flex;
align-items: center;
}
.product-item__product-card{
height: 274px;
display: flex;
justify-content: center;
align-items: center;
}
.product-item__images{
height: 242px;
object-fit: contain;
}
.product-item__content-card{
padding: 15.5px;
}
.product-item__title{
margin-top: 8px;
font-weight: 500;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
text-decoration: none;
display: block;
}
.product-item__title:first-child{
margin-top: 0;
}
.product-item__price{
margin-top: 8px;
display: flex;
align-items: center;
}
.product-item__price p{
font-weight: 700;
font-size: 20px;
line-height: 200%;
text-transform: uppercase;
color: var(--text-black);
}
.product-item__price p::after{
content: '₽';
padding-left: 5px;
}
.product-item__bye{
margin-top: 8px;
}
.product-item__overlay{
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 100%;
padding: 24px;
display: flex;
flex-direction: column;
justify-content: space-between;
border-radius: 24px;
backdrop-filter: blur(25px);
background-color: rgba(242, 242, 242, 0.8);
z-index: 10;
transition: top .4s ease-out;
}
.product-item-overlay__header{}
.product-item-overlay__tags{
margin: 4px -6px -6px -6px;
font-weight: 500;
font-size: 12px;
line-height: 133%;
color: var(--text-3);
display: flex;
flex-wrap: wrap;
list-style-type: none;
}
.product-item-overlay__tags li{
margin: 4px 6px;
position: relative;
}
.product-item-overlay__tags li:nth-child(n+1)::after{
content: '';
position: absolute;
top: 6px;
right: -8px;
width: 4px;
aspect-ratio: 1;
background-color: var(--text-3);
border-radius: 50%;
}
.product-item-overlay__tags li:last-child::after,
.product-item-overlay__tags li:last-child::before{
display: none;
}
.product-item-overlay__price{
margin-top: 32px;
font-weight: 700;
font-size: 24px;
line-height: 100%;
text-transform: uppercase;
text-align: right;
color: var(--text-black);
}
.product-item-overlay__price::after{
content: '₽';
}
.product-item-overlay__block-button{
margin-top: 32px;
}
.product-item-overlay__button{
margin-top: 16px;
}
.product-item-overlay__button:first-child{
margin-top: 0;
}
.product-item-overlay__input-block{
}
.product-item-overlay__field{
margin-top: 24px;
display: flex;
justify-content: space-between;
align-items: center;
}
.product-item-overlay__field:first-child{
margin-top: 0;
}
.product-item-overlay-field__title{
font-weight: 700;
font-size: 16px;
line-height: 125%;
color: var(--text-0);
}
.product-item__form{
}
/* product */
/* modal */
/* .modal__button .to-know{
display: none;
} */
/* modal */
/* footer */
/* footer */
/* detail */
.detail{
margin: 48px 24px 24px 24px;
display: flex;
align-items: start;
flex-wrap: wrap;
}
.detail__images{
margin: -12px;
width: calc(50% - 24px);
display: flex;
flex-wrap: wrap;
}
.detail__image{
margin: 12px;
border-radius: 24px;
display: flex;
align-items: center;
justify-content: center;
background: var(--background-grey);
cursor: pointer;
}
.detail__content{
margin-left: 48px;
width: calc(50% - 24px);
}
.detail__label{
margin: -2px;
display: flex;
align-items: center;
}
.detail__label .product-item-label__tag:last-child{
margin-left: auto;
}
.detail__label .product-item-label__tag:first-child{
margin-left: 0;
}
.detail__title{
margin-top: 8px;
font-weight: 700;
font-size: 36px;
line-height: 111%;
text-transform: uppercase;
color: var(--text-black);
}
.detail__block-price{
margin-top: 24px;
display: flex;
align-items: center;
}
.detail-block-price__price{
font-weight: 700;
font-size: 36px;
line-height: 111%;
text-transform: uppercase;
}
.detail-block-price__price::after{
content: '₽';
}
.detail-block-price__sale{
margin-left: 22px;
display: flex;
align-items: center;
}
.detail-block-price-sale__text{
font-weight: 700;
font-size: 20px;
line-height: 120%;
text-transform: uppercase;
text-decoration: line-through;
color: var(--text-6);
}
.detail-block-price-sale__text::after{
content: '₽';
}
.detail-block-price-sale__perc{
margin-left: 9px;
font-weight: 500;
font-size: 12px;
line-height: 133%;
color: var(--text-red);
}
.detail-block-price-sale__perc::before{
content: '-';
}
.detail-block-price-sale__perc::after{
content: '%';
}
.detail-block__form{
margin-top: 48px;
display: flex;
flex-direction: column;
}
.detail-block-form__item{
margin-top: 24px;
min-width: 345.89px;
display: flex;
align-items: center;
flex-wrap: wrap;
}
.detail-block-form__item--radio{
margin: 16px -8px -8px -8px;
}
.detail-block-form__item:first-child{
margin-top: 0;
}
.detail-block-form__submit{
min-width: 345.89px;
}
.detail__warning{
padding: 3px;
border-radius: 24px;
background: var(--gradient-turquoise);
}
.detail-warning__content{
padding: 26px;
border-radius: 22px;
background: var(--background-white);
}
.detail-warning__title{
font-weight: 700;
font-size: 24px;
line-height: 100%;
text-transform: uppercase;
color: var(--text-black);
}
.detail-warning__text{
margin-top: 16px;
font-weight: 400;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
}
.detail__toggle{
margin-top: 48px;
margin-bottom: 48px;
}
.detail__wrapper-catalot{
margin-top: 64px;
width: calc(100% + 16px);
overflow: hidden;
position: relative;
}
.detail__catalot{
}
.detail-catalot__header{
padding-right: 16px;
display: flex;
justify-content: space-between;
align-items: center;
}
.detail-catalot__control{
display: flex;
align-items: center;
}
.detail-catalot-control__button{
margin-left: 24px;
width: 48px;
aspect-ratio: 1;
border-radius: 50%;
border: 1px solid var(--background-black);
background: none;
display: flex;
justify-content: center;
align-items: center;
}
.detail-catalot__title{
font-weight: 700;
font-size: 24px;
line-height: 100%;
text-transform: uppercase;
text-align: start;
color: var(--text-0);
}
.detail-catalot__content{
margin: 12px -12px -12px -12px;
width: 100%;
display: flex;
}
.detail__catalot .product__item{
width: calc(100% - 24px);
}
.detail__images-phone{
display: none;
}
.back-detail{
display: none;
}
.toggle__table{
margin-top: 32px;
display: flex;
flex-wrap: wrap;
}
.toggle__table:first-child{
margin-top: 0;
}
.toggle__table--three .toggle-table__block:nth-child(1){
width: 40%;
}
.toggle__table--three .toggle-table__block:nth-child(2){
width: 40%;
}
.toggle__table--three .toggle-table__block:nth-child(3){
width: 20%;
}
.toggle__table--two .toggle-table__block{
width: calc(50% - 20px);
}
.toggle__table--two .toggle-table__block:nth-child(even){
margin-left: 40px;
}
.toggle-table__block{
}
.toggle-table__item{
margin-top: 8px;
width: 100%;
display: flex;
justify-content: space-between;
}
.toggle-table__item p{
display: block;
font-weight: 400;
font-size: 20px;
line-height: 120%;
color: var(--text-black);
flex-shrink: 0;
}
.toggle-table__item .warning{
width: 100%;
}
.toggle-table__item .warning p{
font-weight: 600;
font-size: 20px;
line-height: 120%;
text-align: center;
}
.toggle-table__title{
margin-bottom: 16px;
font-weight: 700;
font-size: 16px;
line-height: 125%;
color: var(--text-black);
}
.toggle-table__title--center{
text-align: center;
}
.toggle-table-item__line{
margin: 23px 8px 0 8px;
width: 100%;
height: 1px;
background: linear-gradient(to right, transparent 50%, #fff 50%), linear-gradient(to right, #333, #333);
background-size: 4px 2px, 100% 2px;
opacity: .6;
}
.radio-button{
}
.radio-button__input{
display: none;
}
/* detail */
/* gallery */
.gallery{
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 24px;
display: flex;
align-items: center;
background: var(--background-white);
pointer-events: none;
opacity: 0;
transition: opacity .2s ease-out;
z-index: 300;
}
.gallery__close{
position: absolute;
top: 24px;
right: 24px;
z-index: 10;
}
.gallery__pagination{
margin: -12px;
}
.gallery-pagination__item{
margin: 12px;
width: 134px;
height: 136px;
display: flex;
justify-content: center;
align-items: center;
border: none;
border-radius: 16px;
background: var(--background-grey);
}
.gallery-pagination__item img{
width: 90%;
max-height: 90%;
object-fit: contain;
}
.gallery__slider{
margin-left: 48px;
padding: 100px;
}
.gallery__slider{
width: 100%;
}
.gallery__slider .swiper-pagination{
display: none;
}
.gallery__slider .swiper-button-next::after,
.gallery__slider .swiper-button-prev::after{
display: none;
}
.gallery-button{
width: 48px;
height: 48px;
display: flex;
justify-content: center;
align-items: center;
border: 1px solid var(--background-black);
border-radius: 20px;
background: none;
}
.gallery__slider .swiper-slide{
display: flex;
justify-content: center;
align-items: center;
}
.gallery__block{
width: 600px;
height: 774px;
display: flex;
justify-content: center;
align-items: center;
background: var(--background-grey);
border-radius: 24px;
}
.gallery__block img{
width: 90%;
max-height: 90%;
object-fit: contain;
}
.gallery__wrapper{
margin: 0 auto;
max-width: 1600px;
display: flex;
align-items: center;
}
/* .swiper {
width: 600px;
height: 300px;
} */
/* gallery */
/* cabinet */
/* .cabinet-card-no-orders__ */
/* cabinet */
@media only screen and (max-width: 1600px) {
.wrapper{
max-width: 1280px;
}
.product__item{
margin: 12px;
width: calc(33.3% - 24px);
}
.gallery__wrapper{
max-width: 1280px;
}
}
@media only screen and (max-width: 1365px) {
.gallery__wrapper{
max-width: 100%;
}
}

@ -0,0 +1,38 @@
/* Стили для мобильных устройств */
@media only screen and (max-width: 720px) {
/* product */
.product__item{
width: calc(100% - 24px);
}
/* product */
}
/* detail */
.toggle__table--two .toggle-table__block{
width: 100%;
}
.toggle__table--two .toggle-table__block:nth-child(even){
margin-top: 32px;
margin-left: 0;
}
.toggle__table--three .toggle-table__block:nth-child(1){
width: 31%;
}
/* detail */
@media only screen and (max-width: 576px) {
/* header */
/* header */
/* product */
.product__header{
flex-direction: column;
align-items: start;
}
.product__header .button{
margin-top: 48px;
}
/* product */
}

@ -0,0 +1,348 @@
/* Стили для планшетов */
@media only screen and (max-width: 1200px) {
/* header */
main{
padding-top: 64px;
}
.main-menu{
display: none;
}
.header__open-menu{
display: block;
}
.lang{
display: none;
}
.header__logo{
width: 136px;
height: 29px;
}
.header__content{
height: auto;
padding: 8px 16px;
}
.mini-profile__item:nth-child(2){
margin-left: 0;
}
.header::after{
left: 0;
width: 100%;
}
.header__pc-menu{
display: none;
}
.header__phone-menu{
display: block;
}
.header__menu-block{
top: 56px;
}
.header__content::after{
left: 0;
right: 0;
width: 100%;
}
/* header */
/* footer */
.footer{
margin-top: 0;
padding: 24px 16px;
}
/* footer */
/* breadcrumbs */
.breadcrumbs{
display: none;
}
/* breadcrumbs */
/* product */
.product{
padding: 12px;
padding-top: 20px;
}
.product__title{
font-weight: 700;
font-size: 26px;
line-height: 123%;
text-transform: uppercase;
}
.to-know p {
font-size: 18px;
}
.toggle-table__title{
font-weight: 700;
font-size: 12px;
line-height: 133%;
}
.toggle-table__item p{
font-weight: 500;
font-size: 12px;
line-height: 133%;
}
.toggle-table-item__line{
margin-top: 12px;
}
.detail{
margin: 24px 16px;
}
.back-detail{
display: inline;
}
.detail-catalot__title{
font-size: 22px;
}
.product__footer--error{
margin: 48px 0px 24px;
}
/* product */
/* modal */
.modal{
padding: 0;
}
.modal__text{
padding-right: 0;
}
.form__button-pc{
display: none;
}
.form__button-mobile{
display: block;
}
.modal-form{
/* min-height: 100%;
width: 100%;
border-radius: 0;
border: none; */
}
.modal__notification{
margin: 24px;
}
.form-input-phone__list{
left: 0;
}
.modal-form-content__line--two{
flex-wrap: wrap;
}
.modal-form-content__line--two .modal-form-content-line__element{
margin-top: 24px;
width: 100%;
}
.modal-form-content__line--two .modal-form-content-line__element:first-child{
margin-top: 0;
}
.modal-map{
width: 100%;
flex-direction: column;
border-radius: 0;
}
.modal-map__left, .modal-map__right{
width: 100%;
}
.modal-map__map iframe {
width: 100%;
height: 528px;
}
.modal-map-form__button{
display: none;
}
.modal-map-form__sub-button{
margin-top: 64px;
padding: 0 24px;
display: flex;
}
/* modal */
/* cabinet */
.cabinet{
flex-direction: column;
position: relative;
}
.cabinet__control{
display: flex;
position: relative;
}
.cabinet__orders, .cabinet__profile{
width: calc(100% - 48px);
}
.cabinet__orders, .cabinet__profile{
position: absolute;
opacity: 0;
transition: opacity .2s ease-out;
}
.cabinet-content{
pointer-events:none;
}
.cabinet__orders.active, .cabinet__profile.active{
opacity: 1;
}
.cabinet__orders.hide, .cabinet__profile.hide{
position: static;
display: block;
pointer-events:auto;
width: 100%;
}
.cabinet__subscription-pc{
display: none;
}
.cabinet__subscription-mobile{
display: block;
margin: 24px 24px 0 24px;
}
.cabinet__orders .cabinet-card:nth-child(2){
margin-top: 0;
}
.cabinet__orders--no-cab .cabinet-card:nth-child(2){
margin-top: 32px;
}
/* cabinet */
}
@media only screen and (max-width: 980px) {
/* product */
.product__item{
width: calc(50% - 24px);
}
/* product */
/* detail */
.detail{
flex-direction: column;
}
.detail__images{
display: none;
}
.detail__content{
width: 100%;
}
.detail__content{
margin-left: 0;
}
.detail__images-phone{
display: block;
margin-top: 48px;
margin-bottom: 48px;
position: relative;
overflow: hidden;
}
.detail__images-phone .swiper-slide{
display: flex;
justify-content: center;
}
.detail-images-phone__image-block{
width: 100%;
aspect-ratio: 1;
max-width: 500px;
display: flex;
justify-content: center;
align-items: center;
background: var(--background-grey);
border-radius: 16px;
}
.detail__images-phone .swiper-pagination-bullet{
width: 8px;
height: 8px;
border-radius: 50%;
border: 1px solid #666;
background-color: #666;
opacity: 1;
}
.detail__images-phone .swiper-pagination-bullet.swiper-pagination-bullet-active{
background-color: var(--background-white);
}
.detail__images-phone .swiper-pagination{
margin-bottom: 19px;
}
.detail__title{
font-size: 26px;
line-height: 123%;
}
.gallery__slider .swiper-pagination {
display: block;
}
.gallery__pagination{
display: none;
}
.gallery__slider .swiper-pagination-bullet{
width: 8px;
height: 8px;
border-radius: 50%;
border: 1px solid #666;
background-color: #666;
opacity: 1;
}
.gallery__wrapper .gallery-button{
display: none;
}
.gallery__slider .swiper-pagination-bullet.swiper-pagination-bullet-active{
background-color: var(--background-white);
}
.gallery__slider{
margin-left:0;
padding: 0px 0px 50px 0px;
/* padding: 40px; */
}
.gallery__block {
width: 100%;
aspect-ratio: 1;
height: auto;
}
/* detail */
}
@media only screen and (max-width: 750px) {
/* cabinet */
.cabinet-card-order__open-detail{
margin-top: 144px;
}
.cabinet-card-order__detail-short{
right: auto;
left: 0;
bottom: 48px;
}
.cabinet-card-order-detail-short__item{
margin-left: -27px;
}
.cabinet-card-order-detail-short__item:first-child{
margin-left: 0;
}
.cabinet-card__order.active .cabinet-card-order__open-detail{
margin-top: 24px;
}
.cabinet-card-order__link{
margin-top: 144px;
}
/* cabinet */
}

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.7369 3.29777C11.1247 3.15233 11.557 3.34884 11.7025 3.73668L14.7025 11.7367C14.7661 11.9065 14.7661 12.0936 14.7025 12.2634L11.7025 20.2634C11.557 20.6512 11.1247 20.8477 10.7369 20.7023C10.349 20.5568 10.1525 20.1245 10.298 19.7367L13.1992 12L10.298 4.26336C10.1525 3.87552 10.349 3.44321 10.7369 3.29777Z" fill="#666666"/>
</svg>

After

Width:  |  Height:  |  Size: 481 B

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 16.4854H28" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 16.4854L14.4853 24.9706" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 16.4854L14.4853 8.00007" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 456 B

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26 16.4854H4" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 16.4854L17.5147 24.9706" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 16.4854L17.5147 8.00007" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 458 B

@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1_2483)">
<path d="M18 6L6 18" stroke="#121212" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 6L18 18" stroke="#121212" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_1_2483">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 455 B

@ -0,0 +1,348 @@
'use strict';
// header
toggleOpenX('.lang', '.lang__open', '.lang__list', '.lang__content', false);
toggleHeader('#pc-menu','.header__menu-block','.header__pc-menu', '.white', 'white');
toggleHeader('#phone-menu','.header__menu-block','.header__phone-menu', '.white', 'white');
// header
// modal
modalOpen('.button--filter', '.modal__filter');
modalOpen('.basket-open', '.modal__basket');
modalOpen('.open-to-know', '.modal__to-know');
modalClose('.modal__close');
let modal = document.querySelector('.modal');
modal.onclick = function (event) {
let target = event.target;
if (target.classList.contains('modal')) {
let aside = target.querySelector('.modal__aside'),
modalItem = target.querySelector('.modal__item.active');
aside.style.width = '0px';
setTimeout(() => {
modalItem.style.cssText = '';
modalItem.classList.remove('active');
target.classList.remove('active');
}, 300);
}
}
// modal
// toggle
toggleOpenX('.toggle', '.toggle__title', '.toggle__content', '.toggle__block-content', true);
// toggle
// // radio-button
// let radioButtons = document.querySelectorAll('.radio-button');
// radioButtons.forEach(radioBlock => {
// let buttons = radioBlock.querySelectorAll('.button');
// buttons.forEach(button => {
// let input = radioBlock.querySelector('.radio-button__input');
// button.onclick = function (e) {
// e.preventDefault();
// buttons.forEach(thisButton => {
// if (thisButton.classList.contains('active')) {
// thisButton.classList.remove('active')
// }
// })
// let text = button.textContent.trim();
// button.classList.toggle('active');
// input.value = text;
// }
// })
// })
// // radio-button
// overlay
let products = document.querySelectorAll('.product__item');
products.forEach(productItem => {
let button = productItem.querySelector('.open-overlay'),
overlay = productItem.querySelector('.product-item__overlay');
if (button) {
button.onclick = function (e) {
document.querySelectorAll('.product__item').forEach(e => {
if (e.classList.contains('active')) {
e.classList.remove('active');
}
});
document.querySelectorAll('.product-item__overlay').forEach(e => {
if (e.classList.contains('active')) {
e.classList.remove('active');
}
});
productItem.classList.toggle('active');
overlay.classList.toggle('active');
}
}
})
// overlay
// select
toggleOpenX('.select', '.select__state' , '.state__content', '.state__block', true);
let selects = document.querySelectorAll('.select');
selects.forEach(select => {
let state = select.querySelector('.select__state'),
content = select.querySelector('.state__block'),
buttons = select.querySelectorAll('.state__button');
buttons.forEach(e => {
let button = e;
e.onclick = function (event) {
event.preventDefault();
buttons.forEach(element => {
if (element.classList.contains('active')) {
element.classList.remove('active');
}
})
let text = e.textContent.trim();
state.value = text;
button.classList.add('active');
content.style.height = 0;
select.classList.remove('active');
}
})
})
// select
// counter
let counters = document.querySelectorAll('.counter');
counters.forEach(e => {
let minus = e.querySelector('.minus'),
plus = e.querySelector('.plus'),
input = e.querySelector('.counter__input');
minus.onclick = function (e) {
e.preventDefault();
let number = input.value;
if (number >= 2){
input.value = Number(number) - 1;
}
}
plus.onclick = function (e) {
e.preventDefault();
let number = input.value;
if (number <= 99) {
input.value = Number(number) + 1;
}
}
})
// counter
// checkbox
let checkbox = document.querySelectorAll('.checkbox');
checkbox.forEach(e => {
e.onclick = function (event) {
let input = e.querySelector('.checkbox__input');
if (!e.classList.contains('active')) {
input.checked = 1;
}else{
input.checked = 0;
}
e.classList.toggle('active');
}
})
// checkbox
// function
function modalOpen(buttonElement, contentElement){
let modal = document.querySelector('.modal'),
aside = document.querySelector('.modal__aside'),
elements = document.querySelectorAll(buttonElement),
device = window.screen.width;
elements.forEach(e => {
let thisContentElement = document.querySelector(contentElement);
e.onclick = function () {
modal.classList.add('active');
thisContentElement.classList.add('active');
let width = thisContentElement.clientWidth;
setTimeout(() => {
if (device <= 720) {
aside.style.width = `${device}px`;
thisContentElement.style.opacity = 1;
thisContentElement.style.filter = 'blur(0px)';
}else{
aside.style.width = `${width}px`;
thisContentElement.style.opacity = 1;
thisContentElement.style.filter = 'blur(0px)';
}
}, 10);
}
})
}
function modalClose(buttonElement) {
let modal = document.querySelector('.modal'),
aside = document.querySelector('.modal__aside'),
asideItems = document.querySelectorAll('.modal__item'),
elements = document.querySelectorAll(buttonElement);
elements.forEach(e => {
e.onclick = function () {
aside.style.width = '0px';
asideItems.forEach(e => {
if (e.classList.contains('active')) {
e.style.filter = 'blur(10px)';
}
});
setTimeout(() => {
asideItems.forEach(e => {
if (e.classList.contains('active')) {
e.classList.remove('active');
}
});
modal.classList.remove('active');
}, 300);
}
})
}
function toggleOpenX(mainElement, buttonElement ,heightElement, contentElement, close) {
let elements = document.querySelectorAll(mainElement);
elements.forEach(e => {
let thisMainElement = e,
thisButtonElement = e.querySelector(buttonElement),
thisHeightElement = e.querySelector(heightElement),
thisContentElement = e.querySelector(contentElement);
thisButtonElement.onclick = function (e) {
let height = thisHeightElement.clientHeight;
if (close == true && !thisMainElement.classList.contains('active')) {
elements.forEach(e => {
if (e.classList.contains('active')) {
e.classList.remove('active');
e.querySelector(contentElement).style.height = null
}
})
}
if (!thisMainElement.classList.contains('active')) {
thisContentElement.style.height = `${height}px`;
thisMainElement.classList.add('active');
}else{
thisContentElement.style.height = null;
thisMainElement.classList.remove('active');
}
}
});
}
function toggleHeader(button, content, blockheight, removeBlock, removeClass) {
let thisButton = document.querySelector(button),
thisContent = document.querySelector(content),
thisRemoveBlock = document.querySelector(removeBlock) || '',
thisBlockheight = document.querySelector(blockheight);
thisButton.onclick = function () {
let height = thisBlockheight.clientHeight;
if (!thisContent.classList .contains('open')) {
thisContent.style.height = `${height}px`;
thisContent.classList .add('open');
if (removeBlock) {
thisRemoveBlock.classList.remove(removeClass);
}
}else{
thisContent.style.height = null;
thisContent.classList .remove('open');
if (removeBlock) {
if (window.scrollY <= 25) {
thisRemoveBlock.classList.add(removeClass);
}
}
}
}
}
// function
// resize
window.addEventListener('resize', (e) => {
let width = window.screen.width;
// media
modalOpen('.button--filter', '.modal__filter');
modalOpen('.basket-open', '.modal__basket');
modalOpen('.open-to-know', '.modal__to-know');
modalClose('.modal__close');
let modalItem = document.querySelectorAll('.modal__item');
// if (width <= 720) {
modalItem.forEach(modal => {
if (modal.classList.contains('active')) {
let aside = document.querySelector('.modal__aside');
if (width <= 720) {
aside.style.width = `${width}px`
}else{
let openAside = document.querySelector('.modal__item.active'),
newWidth = openAside.clientWidth;
aside.style.width = `${newWidth}px`
}
}
})
// }
});
// resize
// scroll
if (document.querySelector('.header').classList.contains('white')) {
window.addEventListener("scroll", function (e) {
let header = document.querySelector('.header');
let scroll = window.scrollY;
if (scroll >= 25) {
header.classList.remove('white')
}else{
header.classList.add('white')
}
});
}
// scroll

@ -0,0 +1,110 @@
'use strict';
// slider gallery modal
const gallery = new Swiper('.gallery__slider', {
spaceBetween: 100,
pagination: {
el: '.swiper-pagination',
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
scrollbar: {
el: '.swiper-scrollbar',
},
});
let paginationButtons = document.querySelectorAll('.gallery-pagination__item');
paginationButtons.forEach(button => {
let index = button.dataset.countImg;
button.onclick = function () {
gallery.slideTo(index);
}
})
// open gallery
let detailImage= document.querySelectorAll('.detail__image');
detailImage.forEach(button => {
let index = button.dataset.countImg;
button.onclick = function () {
gallery.slideTo(index);
document.querySelector('.gallery').classList.add('active');
}
})
// close gallery
document.querySelector('.gallery__close').onclick = function () {
document.querySelector('.gallery').classList.remove('active');
}
// slider gallery modal
// slider gallery main phone
// createGalleryPhone('.detail__images', '.detail-images__wrapper', '.detail__image', 980);
const detailPhone = new Swiper('.detail__images-phone', {
spaceBetween: 100,
pagination: {
el: '.swiper-pagination',
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
scrollbar: {
el: '.swiper-scrollbar',
},
});
let detailImagesPhones = document.querySelectorAll('.detail-images-phone__image-block');
detailImagesPhones.forEach(button => {
button.onclick = function (e) {
let index = button.dataset.countImg;
gallery.slideTo(index);
document.querySelector('.gallery').classList.add('active');
}
})
// slider gallery main phone
// detail catalog
const detailCatalot = new Swiper('.detail__catalot', {
// Navigation arrows
navigation: {
nextEl: '.detail-catalot-control__button.next',
prevEl: '.detail-catalot-control__button.prev',
},
breakpoints: {
1600: {
slidesPerView: 4,
},
1200: {
slidesPerView: 3,
},
780: {
slidesPerView: 2,
},
100: {
slidesPerView: 1.1,
spaceBetween: 20
},
}
});
// detail catalog

@ -0,0 +1,67 @@
const rootSelectorTabs = '[data-js-tabs]';
class Tabs{
// элементы для поиска
selectors = {
root: rootSelectorTabs,
button: '[data-js-tabs-button]',
content: '[data-js-tabs-content]',
}
// класс отображения состояния
stateClasses = {
isActive: 'active',
}
constructor(rootElement){
this.rootElement = rootElement;
this.buttonElements = this.rootElement.querySelectorAll(this.selectors.button);
this.contentElements = this.rootElement.querySelectorAll(this.selectors.content);
this.state = {
activeMenuIndex: [...this.buttonElements]
.findIndex((buttonElement) => buttonElement.classList.contains(this.stateClasses.isActive)),
};
this.limitTabsIndex = this.buttonElements.length - 1;
this.bindEvents();
}
updateUI(){
const { activeMenuIndex } = this.state;
this.buttonElements.forEach((buttonElement, index) => {
const isActive = index === activeMenuIndex;
buttonElement.classList.toggle(this.stateClasses.isActive, isActive);
})
this.contentElements.forEach((contentElement, index) => {
const isActive = index === activeMenuIndex;
contentElement.classList.toggle(this.stateClasses.isActive, isActive);
})
}
onButtonClick(buttonIndex){
this.state.activeMenuIndex = buttonIndex;
this.updateUI();
}
bindEvents(){
this.buttonElements.forEach((buttonElement, index) => {
buttonElement.addEventListener('click', () => this.onButtonClick(index))
})
}
}
class TabsCollection {
constructor(){
this.init();
}
init(){
document.querySelectorAll(rootSelectorTabs).forEach((element) => {
new Tabs(element);
});
}
}
export default TabsCollection;

@ -0,0 +1,89 @@
const rootSelectorToggles = '[data-js-toggle]';
class Toggle{
// элементы для поиска
selectors = {
root: rootSelectorToggles,
button: '[data-js-toggle-button]',
wrapper: '[data-js-toggle-wrapper]',
content: '[data-js-toggle-content]',
}
// класс отображения состояния
stateClasses = {
isActive: 'active',
}
constructor(rootElement){
this.rootElement = rootElement;
this.buttonElements = this.rootElement.querySelectorAll(this.selectors.button);
this.wrapperElements = this.rootElement.querySelectorAll(this.selectors.wrapper);
this.contentElements = this.rootElement.querySelectorAll(this.selectors.content);
this.state = {
activeToggleIndex: [...this.buttonElements]
.findIndex((buttonElement) => buttonElement.classList.contains(this.stateClasses.isActive)),
};
this.bindEvents();
}
updateUI(newHeight){
const { activeToggleIndex } = this.state;
this.buttonElements.forEach((buttonElement, index) => {
const isActive = index === activeToggleIndex;
buttonElement.classList.toggle(this.stateClasses.isActive, isActive);
})
this.wrapperElements.forEach((wrapperElement, index) => {
const isActive = index === activeToggleIndex,
newHeight = this.contentElements[index].offsetHeight;
wrapperElement.classList.toggle(this.stateClasses.isActive, isActive);
if (isActive) {
wrapperElement.style.height = `${newHeight}px`;
setTimeout(() => {
if (wrapperElement.classList.contains('active')) {
wrapperElement.style.height = `auto`;
}
}, 300);
}else{
wrapperElement.style.height = `${newHeight}px`;
setTimeout(() => {
if (!wrapperElement.classList.contains('active')) {
wrapperElement.style.height = `${0}px`;
}
}, 10);
}
})
}
onButtonClick(buttonIndex){
this.state.activeToggleIndex = (buttonIndex === this.state.activeToggleIndex) ? -1 : buttonIndex;
this.updateUI();
}
bindEvents(){
this.buttonElements.forEach((buttonElement, index) => {
buttonElement.addEventListener('click', () => this.onButtonClick(index))
})
}
}
class TogglesCollection{
constructor(){
this.init();
}
init(){
document.querySelectorAll(rootSelectorToggles).forEach((element) => {
new Toggle(element);
});
}
}
export default TogglesCollection;

@ -0,0 +1,74 @@
<?php
add_filter('timber/context', function($context) {
if (function_exists('is_product') && is_product()) {
$product_id = get_the_ID();
$product = wc_get_product($product_id);
if ($product) {
$attributes = [];
$product_attributes = $product->get_attributes();
if (!empty($product_attributes)) {
foreach ($product_attributes as $taxonomy => $attribute) {
if ($attribute->is_taxonomy()) {
$terms = wc_get_product_terms($product_id, $taxonomy, ['fields' => 'all']);
if (!empty($terms)) {
$attr_values = [];
foreach ($terms as $term) {
$attr_values[] = [
'name' => $term->name,
'slug' => $term->slug,
'term_id' => $term->term_id,
'link' => get_term_link($term->term_id, $taxonomy),
];
}
$attributes[wc_attribute_label($taxonomy)] = $attr_values;
}
} else {
$attributes[wc_attribute_label($taxonomy)] = $attribute->get_options();
}
}
}
$context['product_attributes'] = $attributes;
if ($product->is_type('variable')) {
$available_variations = $product->get_available_variations();
$variations_data = [];
foreach ($available_variations as $variation) {
$variation_id = $variation['variation_id'];
$variation_obj = wc_get_product($variation_id);
$variations_data[] = [
'variation_id' => $variation_id,
'price' => $variation_obj->get_price(),
'regular_price' => $variation_obj->get_regular_price(),
'sale_price' => $variation_obj->get_sale_price(),
'attributes' => $variation['attributes']
];
}
$context['variations'] = $variations_data;
}
$meta_fields = [
'composition' => get_post_meta($product_id, '_composition', true),
'feeding_recommendations' => get_post_meta($product_id, '_feeding_recommendations', true),
'feeding_recommendations_table' => get_field('feeding_recommendations_table', $product_id),
'nutritional_value' => get_post_meta($product_id, '_nutritional_value', true),
'vitamins' => get_post_meta($product_id, '_vitamins', true),
'additives' => get_post_meta($product_id, '_additives', true),
'energy_value' => get_post_meta($product_id, '_energy_value', true),
'important' => get_post_meta($product_id, '_important', true),
];
$context['product_meta'] = $meta_fields;
}
}
return $context;
});

@ -0,0 +1,447 @@
{% set bodyClass = 'bg-white' %}
{% set mainClass = 'wrapper' %}
{% extends 'layout.twig' %}
{% block content %}
<div class="wrapper">
<div class="breadcrumbs">
{% if wc_breadcrumbs %}
{% for crumb in wc_breadcrumbs %}
<a href="{{ crumb.url }}" class="breadcrumbs__item">
{{ crumb.text }}
</a>
{% endfor %}
{% endif %}
</div>
<a href="{{ fn('get_permalink', fn('wc_get_page_id', 'shop')) }}" class="back back-detail">
{{ function('pll_e', 'к каталогу') }}
</a>
<div class="detail">
<div class="detail__images">
{% for image in gallery_images %}
<div class="detail__image detail__image--width-perc-{% if loop.index == 1 or loop.index == 4 %}100{% else %}50{% endif %}" data-count-img="{{ loop.index0 }}">
<img src="{{ image.src }}" alt="{{ image.alt }}" class="">
</div>
{% endfor %}
<div class="swiper-pagination"></div>
</div>
<div class="detail__content">
<div class="detail__label">
{% if product_attributes.Flavor is defined and product_attributes.Flavor|length > 0 %}
<div class="product-item-label__tag product-item-label__tag--black">
{{ product_attributes.Flavor[0].name }}
</div>
{% endif %}
{% if product_attributes.Вкус is defined and product_attributes.Вкус|length > 0 %}
<div class="product-item-label__tag product-item-label__tag--black">
<a href="{{ product_attributes.Вкус[0].link }}">{{ product_attributes.Вкус[0].name }}</a>
</div>
{% endif %}
{% if product_attributes.Тег is defined and product_attributes.Тег|length > 0 %}
<div class="product-item-label__tag product-item-label__tag--title">
<a href="{{ product_attributes.Тег[0].link }}">{{ product_attributes.Тег[0].name }}</a>
</div>
{% endif %}
{% if product.is_on_sale() %}
<div class="product-item-label__tag product-item-label__tag--sale">
{{ function('pll_e', 'Распродажа') }} %
</div>
{% endif %}
</div>
<p class="detail__title">
{{ product.get_title }}
</p>
<div class="detail__images-phone">
<div class="swiper-wrapper">
{% for image in gallery_images %}
<div class="swiper-slide">
<div class="detail-images-phone__image-block" data-count-img="{{ loop.index0 }}">
<img src="{{ image.src }}" alt="{{ image.alt }}">
</div>
</div>
{% endfor %}
</div>
<div class="swiper-pagination"></div>
</div>
<div class="detail__block-price">
<p class="detail-block-price__price">
{{ product.get_price }}
</p>
{% if product.is_on_sale() %}
<div class="detail-block-price__sale">
<p class="detail-block-price-sale__text">
{{ product.get_regular_price }}
</p>
<p class="detail-block-price-sale__perc">
{{ ((product.get_regular_price - product.get_price) / product.get_regular_price * 100)|round }}
</p>
</div>
{% endif %}
</div>
<form action="" class="detail-block__form" data-product-id="{{ product.id }}">
{% set collection = fn('wc_get_product_terms', product.id, 'pa_collection') %}
{% if collection %}
{% set siblings = function('get_collection_siblings', collection[0].term_id) %}
{% if siblings %}
<div class="detail-block-form__item detail-block-form__item--radio radio-button">
{% for sibling in siblings %}
{% set weight = sibling.post_title|split(', ')|last %}
{% set current_weight = function('get_product_info', product.id, 'weight') %}
{% set class = weight == current_weight ? 'active' : '' %}
<a href="{{ function('get_permalink', sibling.ID) }}" class="button button--white button--red-48-px {{ class }}" data-product_id="{{ sibling.ID }}" data-product_price="{{ function('get_product_info', sibling.ID, 'price') }}">
{{ weight|upper }}
</a>
{% endfor %}
<input type="text" class="radio-button__input" value="{{ current_weight|upper }}" readonly>
</div>
{% endif %}
{% endif %}
<div class="detail-block-form__items">
<input type="submit" value="{{ function('pll_e', 'Добавить в корзину') }}" class="button button--gradient button--high detail-block-form__submit">
</div>
</form>
<div class="detail__toggle">
<div class="toggle">
<p class="toggle__title">
{{ function('pll_e', 'ОПИСАНИЕ') }}
</p>
<div class="toggle__block-content">
<div class="toggle__content">
<p class="toggle__text">
{{ product.get_description() }}
</p>
</div>
</div>
</div>
{% if product_meta.composition %}
<div class="toggle">
<p class="toggle__title">
{{ function('pll_e', 'СОСТАВ') }}
</p>
<div class="toggle__block-content">
<div class="toggle__content">
<p class="toggle__text">
{{ product_meta.composition }}
</p>
</div>
</div>
</div>
{% endif %}
{% if product_meta.feeding_recommendations_table %}
<div class="toggle">
<p class="toggle__title">
{{ function('pll_e', 'РЕКОМЕНДАЦИИ ПО КОРМЛЕНИЮ') }}
</p>
<div class="toggle__block-content">
<div class="toggle__content">
<div class="toggle__table toggle__table--three">
{% if product_meta.feeding_recommendations_table.header %}
<div class="toggle-table__block">
<p class="toggle-table__title">{{ product_meta.feeding_recommendations_table.header.0 is iterable ? product_meta.feeding_recommendations_table.header.0|join(', ') : product_meta.feeding_recommendations_table.header.0 }}</p>
{% for row in product_meta.feeding_recommendations_table.body %}
<div class="toggle-table__item">
<p>{{ row.0 is iterable ? row.0|join(', ') : row.0 }}</p>
<div class="toggle-table-item__line"></div>
</div>
{% endfor %}
</div>
<div class="toggle-table__block">
<p class="toggle-table__title">{{ product_meta.feeding_recommendations_table.header.1 is iterable ? product_meta.feeding_recommendations_table.header.1|join(', ') : product_meta.feeding_recommendations_table.header.1 }}</p>
{% for row in product_meta.feeding_recommendations_table.body %}
<div class="toggle-table__item">
<p>{{ row.1 is iterable ? row.1|join(', ') : row.1 }}</p>
<div class="toggle-table-item__line"></div>
</div>
{% endfor %}
</div>
<div class="toggle-table__block">
<p class="toggle-table__title">{{ product_meta.feeding_recommendations_table.header.2 is iterable ? product_meta.feeding_recommendations_table.header.2|join(', ') : product_meta.feeding_recommendations_table.header.2 }}</p>
{% for row in product_meta.feeding_recommendations_table.body %}
<div class="toggle-table__item">
<p>{{ row.2 is iterable ? row.2|join(', ') : row.2 }}</p>
</div>
{% endfor %}
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% elseif product_meta.feeding_recommendations %}
<div class="toggle">
<p class="toggle__title">
{{ function('pll_e', 'РЕКОМЕНДАЦИИ ПО КОРМЛЕНИЮ') }}
</p>
<div class="toggle__block-content">
<div class="toggle__content">
{{ product_meta.feeding_recommendations }}
</div>
</div>
</div>
{% endif %}
{% if product_meta.nutritional_value or product_meta.vitamins or product_meta.additives or product_meta.energy_value %}
<div class="toggle">
<p class="toggle__title">
{{ function('pll_e', 'ПИЩЕВАЯ ЦЕННОСТЬ') }}
</p>
<div class="toggle__block-content">
<div class="toggle__content">
{% if product_meta.nutritional_value and product_meta.vitamins %}
<div class="toggle__table toggle__table--two">
<div class="toggle-table__block ">
<p class="toggle-table__title toggle-table__title--center">{{ function('pll_e', 'ПИЩЕВАЯ ЦЕННОСТЬ') }}</p>
{{ product_meta.nutritional_value }}
</div>
<div class="toggle-table__block ">
<p class="toggle-table__title toggle-table__title--center">{{ function('pll_e', 'ВИТАМИНЫ НА КГ') }}</p>
{{ product_meta.vitamins }}
</div>
</div>
{% endif %}
{% if product_meta.additives or product_meta.energy_value %}
<div class="toggle__table toggle__table--two">
{% if product_meta.additives %}
<div class="toggle-table__block ">
<p class="toggle-table__title toggle-table__title--center">{{ function('pll_e', 'ПИТАТЕЛЬНЫЕ ДОБАВКИ НА КГ') }}</p>
{{ product_meta.additives }}
</div>
{% endif %}
{% if product_meta.energy_value %}
<div class="toggle-table__block ">
<p class="toggle-table__title toggle-table__title--center">{{ function('pll_e', 'ЭНЕРГЕТИЧЕСКАЯ ЦЕННОСТЬ НА 100 ГРАММ') }}</p>
<div class="toggle-table__item">
<div class="detail__warning warning">
<div class="detail-warning__content">
<p class="detail-warning__title">{{ product_meta.energy_value }}</p>
</div>
</div>
</div>
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
</div>
{% endif %}
</div>
<div class="detail__warning">
<div class="detail-warning__content">
<p class="detail-warning__title">{{ function('pll_e', 'Важно') }}</p>
<p class="detail-warning__text">
{{ product_meta.important }}
</p>
</div>
</div>
</div>
{% set recommended_products = function('get_field', 'recommended_products', product.id) %}
{% set related_products = recommended_products ? recommended_products : function('wc_get_related_products', product.id, 4) %}
{% if related_products %}
<div class="detail__wrapper-catalot">
<div class="detail__catalot">
<div class="detail-catalot__header">
<p class="detail-catalot__title">
{{ function('pll_e', 'вашему питомцу может понравиться') }}
</p>
<div class="detail-catalot__control">
<button class="detail-catalot-control__button prev">
<img src="{{ theme.uri }}/static/shop/img/svg/main/arrow-left.svg" alt="">
</button>
<button class="detail-catalot-control__button next">
<img src="{{ theme.uri }}/static/shop/img/svg/main/arrow-right.svg" alt="">
</button>
</div>
</div>
<div class="detail-catalot__content swiper-wrapper">
{% for related_product in related_products %}
<div class="swiper-slide">
{% set post_id = related_product.ID is defined ? related_product.ID : related_product %}
{% set wc_product = fn('wc_get_product', post_id) %}
{% if wc_product %}
<div class="product__item">
<div class="product-item__label">
{% if wc_product.get_date_created|date('Y-m-d') >= criteria_for_new_product %}
<span href="#" class="product-item-label__tag product-item-label__tag--new">
{{ function('pll_e', 'Новинка') }}
</span>
{% endif %}
{% if wc_product.is_on_sale() %}
<span href="#" class="product-item-label__tag product-item-label__tag--sale">
{{ function('pll_e', 'Распродажа %') }}
</span>
{% endif %}
</div>
<a href="{{ wc_product.get_permalink() }}" class="product-item__product-card">
<img src="{{ fn('wp_get_attachment_url', wc_product.get_image_id()) }}" alt="{{ wc_product.get_name() }}" class="product-item__images">
</a>
<div class="product-item__content-card">
<div class="compound">
{% set compound = fn('wc_get_product_terms', post_id, 'pa_compound') %}
{% for option in compound %}
{% set term = get_term(option) %}
<a href="/compound/{{ term.slug }}" class="compound__item">{{ term.name }}</a>
{% endfor %}
</div>
<a href="{{ wc_product.get_permalink() }}" class="product-item__title">{{ wc_product.get_name() }}</a>
<div class="product-item__price">
<p>{{ wc_product.get_price() }}</p>
</div>
<div class="product-item__bye">
<button class="button button--white button--100-perc open-overlay">
{{ function('pll_e', 'Купить') }}
</button>
</div>
</div>
<div class="product-item__overlay">
<div class="product-item-overlay__header">
<a href="{{ wc_product.get_permalink() }}" class="product-item__title">{{ wc_product.get_name() }}</a>
<ul class="product-item-overlay__tags">
{% set features = fn('wc_get_product_terms', post_id, 'pa_features') %}
{% for option in features %}
{% set term = get_term(option) %}
<li>{{ term.name }}</li>
{% endfor %}
</ul>
</div>
<form class="product-item__form" method="post" action="/send-telegram.php">
<div class="product-item-overlay__input-block">
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Объем</p>
<div class="select">
{% set cur_weight = function('get_product_info', post_id, 'weight') %}
<input type="text" class="select__state" value="{{ cur_weight }}" readonly data-product_id="{{ post_id }}" data-product_price="{{ wc_product.get_price() }}">
<div class="state__block">
<ul class="state__content">
{% set collection = fn('wc_get_product_terms', post_id, 'pa_collection') %}
{% for option in collection %}
{% set term = get_term(option) %}
{% if term %}
{% set siblings = function('get_collection_siblings', term.term_id) %}
{% for sibling in siblings %}
{% set weight = function('get_product_info', sibling.ID, 'weight') %}
{% set class = '' %}
{% if weight == cur_weight %}
{% set class = 'active' %}
{% endif %}
<li>
<button class="state__button {{ class }}" data-product_id="{{ sibling.ID }}" data-product_price="{{ function('get_product_info', sibling.ID, 'price') }}">
{{ weight }}
</button>
</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Количество</p>
<div class="counter">
<button class="counter__button minus">
<img src="{{ theme.uri }}/woocommerce/assets/img/svg/main/minus.svg" alt="">
</button>
<input type="text" class="counter__input" value="1">
<button class="counter__button plus">
<img src="{{ theme.uri }}/woocommerce/assets/img/svg/main/plus.svg" alt="">
</button>
</div>
</div>
</div>
<p class="product-item-overlay__price">
{{ wc_product.get_price() }}
</p>
<div class="product-item-overlay__block-button">
<div class="product-item-overlay__button">
{{ function('get_add_to_cart_button', post_id) }}
</div>
<div class="product-item-overlay__more_button">
<a class="to-know button--100-perc" href="{{ wc_product.get_permalink() }}">
<p>{{ function('pll_e', 'Подробнее') }}</p>
</a>
</div>
</div>
</form>
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
{% endif %}
</div>
<div class="gallery">
<button class="gallery__close gallery-button">
<img src="{{ theme.uri }}/static/shop/img/svg/main/black-x.svg" alt="">
</button>
<div class="gallery__wrapper">
<div class="gallery__pagination">
{% for image in gallery_images %}
<button class="gallery-pagination__item" data-count-img="{{ loop.index0 }}">
<img src="{{ image.src }}" alt="{{ image.alt }}">
</button>
{% endfor %}
</div>
<div class="gallery__slider swiper">
<div class="swiper-wrapper">
{% for image in gallery_images %}
<div class="swiper-slide">
<div class="gallery__block">
<img src="{{ image.src }}" alt="{{ image.alt }}">
</div>
</div>
{% endfor %}
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev gallery-button">
<img src="{{ theme.uri }}/static/shop/img/svg/main/arrow-left.svg" alt="">
</div>
<div class="swiper-button-next gallery-button">
<img src="{{ theme.uri }}/static/shop/img/svg/main/arrow-right.svg" alt="">
</div>
</div>
</div>
</div>
</div>
{% endblock %}

@ -0,0 +1,56 @@
<?php
add_filter('timber/context', function($context) {
if (function_exists('is_product') && is_product()) {
$product_id = get_the_ID();
$product = wc_get_product($product_id);
if ($product) {
$context['product'] = $product;
$context['product_id'] = $product_id;
$terms = get_the_terms($product_id, 'product_cat');
if ($terms && !is_wp_error($terms)) {
$context['product_categories'] = $terms;
}
$attachment_ids = $product->get_gallery_image_ids();
$gallery_images = [];
$main_image_id = $product->get_image_id();
if ($main_image_id) {
$gallery_images[] = [
'id' => $main_image_id,
'src' => wp_get_attachment_image_url($main_image_id, 'full'),
'alt' => get_post_meta($main_image_id, '_wp_attachment_image_alt', true)
];
}
foreach ($attachment_ids as $attachment_id) {
$gallery_images[] = [
'id' => $attachment_id,
'src' => wp_get_attachment_image_url($attachment_id, 'full'),
'alt' => get_post_meta($attachment_id, '_wp_attachment_image_alt', true)
];
}
$context['gallery_images'] = $gallery_images;
$related_products_ids = wc_get_related_products($product_id, 5);
if (!empty($related_products_ids)) {
$related_products = [];
foreach ($related_products_ids as $related_id) {
$related_product = wc_get_product($related_id);
if ($related_product) {
$related_products[] = $related_product;
}
}
$context['related_products'] = $related_products;
}
}
}
return $context;
});

@ -0,0 +1,60 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if (is_product()) {
include_module('shop');
include_component('shop', 'single-product');
$context = Timber::get_context();
$post = Timber::get_post();
$context['post'] = $post;
$context['wc_breadcrumbs'] = array();
if (function_exists('woocommerce_breadcrumb')) {
$args = array(
'delimiter' => '',
'wrap_before' => '',
'wrap_after' => '',
'before' => '',
'after' => '',
'home' => _x('Home', 'breadcrumb', 'woocommerce'),
);
$breadcrumbs = new WC_Breadcrumb();
$breadcrumbs->generate();
$formatted_breadcrumbs = array();
foreach ($breadcrumbs->get_breadcrumb() as $crumb) {
$formatted_breadcrumbs[] = array(
'text' => $crumb[0],
'url' => $crumb[1]
);
}
$context['wc_breadcrumbs'] = $formatted_breadcrumbs;
}
$product_id = get_the_ID();
$product = wc_get_product($product_id);
$context['product'] = $product;
$context['related_products'] = array();
$related_products_ids = wc_get_related_products($product_id, 5);
if ($related_products_ids) {
foreach ($related_products_ids as $related_id) {
$related_product = wc_get_product($related_id);
if ($related_product) {
$context['related_products'][] = $related_product;
}
}
}
Timber::render('modules/shop/components/single-product/component-template.twig', $context);
}

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 16.4854H28" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 16.4854L14.4853 24.9706" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 16.4854L14.4853 8.00007" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 456 B

@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26 16.4854H4" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 16.4854L17.5147 24.9706" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M26 16.4854L17.5147 8.00007" stroke="#666666" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 458 B

@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1_2483)">
<path d="M18 6L6 18" stroke="#121212" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 6L18 18" stroke="#121212" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_1_2483">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 455 B

@ -0,0 +1,63 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if (is_product()) {
include_module('shop');
include_component('shop', 'single-product');
$context = Timber::get_context();
$post = Timber::get_post();
$context['post'] = $post;
$context['wc_breadcrumbs'] = array();
if (function_exists('woocommerce_breadcrumb')) {
$args = array(
'delimiter' => '',
'wrap_before' => '',
'wrap_after' => '',
'before' => '',
'after' => '',
'home' => _x('Home', 'breadcrumb', 'woocommerce'),
);
$breadcrumbs = new WC_Breadcrumb();
$breadcrumbs->generate();
$formatted_breadcrumbs = array();
foreach ($breadcrumbs->get_breadcrumb() as $crumb) {
$formatted_breadcrumbs[] = array(
'text' => $crumb[0],
'url' => $crumb[1]
);
}
$context['wc_breadcrumbs'] = $formatted_breadcrumbs;
}
$product_id = get_the_ID();
$product = wc_get_product($product_id);
$context['product'] = $product;
$context['related_products'] = array();
$related_products_ids = wc_get_related_products($product_id, 5);
if ($related_products_ids) {
foreach ($related_products_ids as $related_id) {
$related_product = wc_get_product($related_id);
if ($related_product) {
$context['related_products'][] = $related_product;
}
}
}
Timber::render('modules/shop/components/single-product/component-template.twig', $context);
}

@ -1,115 +1,117 @@
{% set cur_product = fn('wc_get_product', product.id) %}
{% set attrs = post.product.get_attributes() %}
{% set cur_weight = function('get_product_info', post.id, 'weight') %}
{% if post.id is defined and post.id %}
{% set cur_product = fn('wc_get_product', post.id) %}
{% set attrs = post.product.get_attributes() %}
{% set cur_weight = function('get_product_info', post.id, 'weight') %}
<div class="product__item">
<div class="product-item__label">
{% if post.date('Y-m-d') >= criteria_for_new_product %}
<span href="#" class="product-item-label__tag product-item-label__tag--new">
{{ function('pll_e', 'Новинка') }}
</span>
{% endif %}
<div class="product__item">
<div class="product-item__label">
{% if post.date('Y-m-d') >= criteria_for_new_product %}
<span href="#" class="product-item-label__tag product-item-label__tag--new">
{{ function('pll_e', 'Новинка') }}
</span>
{% endif %}
{% if post._sale_price %}
<span href="#" class="product-item-label__tag product-item-label__tag--sale">
{{ function('pll_e', 'Распродажа %') }}
</span>
{% endif %}
</div>
<a href="{{ post.link }}" class="product-item__product-card">
<img src="{{ post.thumbnail.src('shop_single') }}" alt="{{ post.title }}" class="product-item__images">
</a>
<div class="product-item__content-card">
<div class="compound">
{% set compound = fn('wc_get_product_terms', post.id, 'pa_compound') %}
{% for option in compound %}
{% set term = get_term(option) %}
<a href="/compound/{{ term.slug }}" class="compound__item">{{ term.name }}</a>
{% endfor %}
</div>
<a href="#" class="product-item__title">{{ post.title }}</a>
<div class="product-item__price">
<p>{{ post._price() }}</p>
{% if post._sale_price %}
<span href="#" class="product-item-label__tag product-item-label__tag--sale">
{{ function('pll_e', 'Распродажа %') }}
</span>
{% endif %}
</div>
<div class="product-item__bye">
<button class="button button--white button--100-perc open-overlay">
{{ function('pll_e', 'Купить') }}
</button>
</div>
</div>
<div class="product-item__overlay">
<div class="product-item-overlay__header">
<a href="#" class="product-item__title">{{ post.title }}</a>
<ul class="product-item-overlay__tags">
{% set features = fn('wc_get_product_terms', post.id, 'pa_features') %}
{% for option in features %}
<a href="{{ post.link }}" class="product-item__product-card">
<img src="{{ post.thumbnail.src('shop_single') }}" alt="{{ post.title }}" class="product-item__images">
</a>
<div class="product-item__content-card">
<div class="compound">
{% set compound = fn('wc_get_product_terms', post.id, 'pa_compound') %}
{% for option in compound %}
{% set term = get_term(option) %}
<li>{{ term.name }}</li>
<a href="/compound/{{ term.slug }}" class="compound__item">{{ term.name }}</a>
{% endfor %}
</ul>
</div>
<a href="#" class="product-item__title">{{ post.title }}</a>
<div class="product-item__price">
<p>{{ post._price() }}</p>
</div>
<div class="product-item__bye">
<button class="button button--white button--100-perc open-overlay">
{{ function('pll_e', 'Купить') }}
</button>
</div>
</div>
<form class="product-item__form" method="post" action="/send-telegram.php">
<div class="product-item-overlay__input-block">
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Объем</p>
<div class="product-item__overlay">
<div class="product-item-overlay__header">
<a href="#" class="product-item__title">{{ post.title }}</a>
<ul class="product-item-overlay__tags">
{% set features = fn('wc_get_product_terms', post.id, 'pa_features') %}
{% for option in features %}
{% set term = get_term(option) %}
<li>{{ term.name }}</li>
{% endfor %}
</ul>
</div>
<form class="product-item__form" method="post" action="/send-telegram.php">
<div class="product-item-overlay__input-block">
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Объем</p>
<div class="select">
<input type="text" class="select__state" value="{{ cur_weight }}" readonly data-product_id="{{post.id}}" data-product_price="{{ post._price() }}">
<div class="state__block">
<ul class="state__content">
{% set collection = fn('wc_get_product_terms', post.id, 'pa_collection') %}
{% for option in collection %}
{% set term = get_term(option) %}
{% set siblings = function('get_collection_siblings' , term.id) %}
<div class="select">
<input type="text" class="select__state" value="{{ cur_weight }}" readonly data-product_id="{{post.id}}" data-product_price="{{ post._price() }}">
<div class="state__block">
<ul class="state__content">
{% set collection = fn('wc_get_product_terms', post.id, 'pa_collection') %}
{% for option in collection %}
{% set term = get_term(option) %}
{% set siblings = function('get_collection_siblings' , term.id) %}
{% for sibling in siblings %}
{% for sibling in siblings %}
{% set weight = function('get_product_info', sibling.ID, 'weight') %}
{% set class = '' %}
{% if weight == cur_weight %}
{% set class = 'active' %}
{% endif %}
<li>
<button class="state__button {{ class }}" data-product_id="{{sibling.ID}}" data-product_price="{{ function('get_product_info', sibling.ID, 'price') }}">
{{ weight }}
</button>
</li>
{% set weight = function('get_product_info', sibling.ID, 'weight') %}
{% set class = '' %}
{% if weight == cur_weight %}
{% set class = 'active' %}
{% endif %}
<li>
<button class="state__button {{ class }}" data-product_id="{{sibling.ID}}" data-product_price="{{ function('get_product_info', sibling.ID, 'price') }}">
{{ weight }}
</button>
</li>
{% endfor %}
{% endfor %}
{% endfor %}
</ul>
</ul>
</div>
</div>
</div>
</div>
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Количество</p>
<div class="product-item-overlay__field">
<p class="product-item-overlay-field__title">Количество</p>
<div class="counter">
<button class="counter__button minus">
<img src="{{ theme.link }}/woocommerce/assets/img/svg/main/minus.svg" alt="">
</button>
<input type="text" class="counter__input" value="1">
<button class="counter__button plus">
<img src="{{ theme.link }}/woocommerce/assets/img/svg/main/plus.svg" alt="">
</button>
<div class="counter">
<button class="counter__button minus">
<img src="{{ theme.link }}/woocommerce/assets/img/svg/main/minus.svg" alt="">
</button>
<input type="text" class="counter__input" value="1">
<button class="counter__button plus">
<img src="{{ theme.link }}/woocommerce/assets/img/svg/main/plus.svg" alt="">
</button>
</div>
</div>
</div>
</div>
<p class="product-item-overlay__price">
{{ post._price() }}
</p>
<div class="product-item-overlay__block-button">
<div class="product-item-overlay__button">
{{ function('get_add_to_cart_button', post.id) }}
</div>
<div class="product-item-overlay__more_button">
<a class="to-know button--100-perc" href="{{ post.link }}">
<p>{{ function('pll_e', 'Подробнее') }}</p>
</a>
<p class="product-item-overlay__price">
{{ post._price() }}
</p>
<div class="product-item-overlay__block-button">
<div class="product-item-overlay__button">
{{ function('get_add_to_cart_button', post.id) }}
</div>
<div class="product-item-overlay__more_button">
<a class="to-know button--100-perc" href="{{ post.link }}">
<p>{{ function('pll_e', 'Подробнее') }}</p>
</a>
</div>
</div>
</div>
</form>
</form>
</div>
</div>
</div>
{% endif %}

@ -0,0 +1,19 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
get_header();
$template_path = 'templates/shop/single-product.php';
if (file_exists(get_template_directory() . '/' . $template_path)) {
include_once get_template_directory() . '/' . $template_path;
} else {
while (have_posts()) : the_post();
wc_get_template_part('content', 'single-product');
endwhile;
}
get_footer();
Loading…
Cancel
Save