Neste tutorial, veremos como exibir uma etiqueta que calcula a porcentagem de desconto quando um produto tiver um preço original e um preço promocional, tanto no detalhe do produto quanto na lista:
Essa porcentagem é calculada quando o usuário altera uma variável nos detalhes do produto para casos em que eles têm um preço diferente.
HTML
A primeira coisa que vamos fazer é criar o tpl geral para todas as etiquetas relacionadas a um produto: desconto, frete grátis e sem estoque. Se você não precisa de tudo, você pode excluir o código que não precisa.
1. Adicione o arquivo labels.tpl à pasta snipplets
Vamos notar duas coisas importantes aqui:
- O condicional {% if product_detail%} que usamos ao incluir o snipplet para perguntar se ele se aplica ao detalhe do produto ou não, dessa forma podemos usar as classes “js -...”
- A variável price_discount_percentage que faz a conta para calcular qual é a porcentagem de desconto.
{% if product.compare_at_price > product.price %} {% set price_discount_percentage = ((product.compare_at_price) - (product.price)) * 100 / (product.compare_at_price) %} {% endif %} {% if not product.has_stock or product.free_shipping or product.compare_at_price %} <div class="labels"> {% if not product.has_stock %} <div class="{% if product_detail %}js-stock-label {% endif %}label label-default">{{ "Sin stock" | translate }}</div> {% else %} {% if product.compare_at_price %} <div class="js-offer-label label label-primary" {% if (not product.compare_at_price) or not product.display_price %}style="display:none;"{% endif %}> <span {% if product_detail %}class="js-offer-percentage"{% endif %}>{{ price_discount_percentage |round }}</span>% OFF </div> {% endif %} {% if product.free_shipping %} <div class="label label-secondary">{{ "Envío gratis" | translate }}</div> {% endif %} {% endif %} </div> {% endif %}
2. Com labels.tpl criado, temos que incluí-lo no detalhe do produto e na lista de produtos.
Para o item na lista nós o incluímos no item snipplet.tpl dentro da pasta snipplets/grid, pode ser que no seu layout este snipplet seja chamado single_product.tpl.
Chamamos o snipplet da seguinte maneira (idealmente dentro do componente de imagem do produto):
{% include 'snipplets/labels.tpl' %}
Incluiremos o mesmo snipplet nos detalhes do produto. No layout Base, fazemos isso no arquivo product-image.tpl na pasta snipplets/product, no seu caso você pode ter que incluí-lo no template product.tpl. O importante é que esteja dentro do contexto da imagem do produto, já que o componente da etiqueta tem uma posição absoluta no CSS.
{% include 'snipplets/labels.tpl' with {'product_detail': true} %}
3. Continuando com os detalhes do produto, aplicamos as seguintes alterações:
No modelo product.tpl no div principal que engloba todo o conteúdo desta página adicionamos os seguintes IDs e seletores “js -...”, sendo os seguintes:
<div id="single-product" class=”js-product-detail js-product-container" data-variants="{{product.variants_object | json_encode }}" itemscope itemtype="http://schema.org/Product"> … </div>
Depois substituímos o HTML que mostra o preço e o preço promocional dentro do snipplet product-form.tpl ou, talvez, no seu caso ele esteja no product.tpl, com o seguinte código:
{# Product price #} <div class="price-container text-center text-sm-left" itemprop="offers" itemscope itemtype="http://schema.org/Offer"> <span class="d-inline-block"> <h4 id="compare_price_display" class="js-compare-price-display price-compare" {% if not product.compare_at_price or not product.display_price %}style="display:none;"{% else %} style="display:block;"{% endif %}>{% if product.compare_at_price and product.display_price %}{{ product.compare_at_price | money }}{% endif %}</h4> </span> <spa class="d-inline-block"> <h4 class="js-price-display" id="price_display" itemprop="price"{% if product.display_price %} content="{{ product.price / 100 }}"{% endif %} {% if not product.display_price %}style="display:none;"{% endif %}>{% if product.display_price %}{{ product.price | money }}{% endif %}</h4> </span> <meta itemprop="priceCurrency" content="{{ product.currency }}" /> {% if product.stock_control %} <meta itemprop="inventoryLevel" content="{{ product.stock }}" /> <meta itemprop="availability" href="http://schema.org/{{ product.stock ? 'InStock' : 'OutOfStock' }}" content="{{ product.stock ? 'In stock' : 'Out of stock' }}" /> {% endif %} </div>
Por último adicionamos a classe js-variation-option dentro do select das variantes do detalhe do produto. No layout Base, isso está no tpl product-variants.tpl dentro da pasta snipplets/product. Em seu layout, esse arquivo pode ser chamado de variants.tpl ou talvez você deva aplicar a alteração diretamente no template product.tpl
CSS
Requisito:
Ter adicionado helper classes em seu layout. Você pode seguir este pequeno tutorial para fazer isso (é só copiar e colar algumas classes, não leva mais que 1 minuto).
1. Adicionamos o seguinte SASS de cores em style-colors.scss.tpl (ou no stylesheet do seu layout que possui as cores e fontes da loja). Lembre-se de que as variáveis de cores e fontes podem variar em relação ao seu design:
{# /* // Labels */ #} .label { background: darken($main-background, 1%); &.label-primary{ background: $main-foreground; color: $main-background; } }
2. Adicione os estilos no arquivo static/style-critical.tpl
{# /* // Labels */ #} .labels { position: absolute; top: 0; z-index: 9; } .label { margin-bottom: 10px; padding: 5px 10px; font-size: 12px; text-align: left; }
JS
⚠️ A partir do dia 30 de janeiro de 2023, a biblioteca jQuery será removida do código de nossas lojas, portanto, a função "$" não poderá ser utilizada.
O JavaScript deve ser adicionado no arquivo store.js.tpl (ou onde você tem suas funções JS). Adicionamos o seguinte código para para executar a mudança de variante (e labels do produto):
jQueryNuvem(document).on("change", ".js-variation-option", function(e) { var $parent = jQueryNuvem(this).closest(".js-product-variants"); var $variants_group = jQueryNuvem(this).closest(".js-product-variants-group"); var $quickshop_parent_wrapper = jQueryNuvem(this).closest(".js-quickshop-container"); {# If quickshop is used from modal, use quickshop-id from the item that opened it #} if($quickshop_parent_wrapper.hasClass("js-quickshop-modal")){ var quick_id = jQueryNuvem(".js-quickshop-opened .js-quickshop-container").data("quickshopId"); }else{ var quick_id = $quickshop_parent_wrapper.data("quickshopId"); } if($parent.hasClass("js-product-quickshop-variants")){ var $quickshop_parent = jQueryNuvem(this).closest(".js-item-product"); {# Target visible slider item if necessary #} if($quickshop_parent.hasClass("js-item-slide")){ var $quickshop_variant_selector = '.js-swiper-slide-visible .js-quickshop-container[data-quickshop-id="'+quick_id+'"]'; }else{ var $quickshop_variant_selector = '.js-quickshop-container[data-quickshop-id="'+quick_id+'"]'; } LS.changeVariant(changeVariant, $quickshop_variant_selector); } else { LS.changeVariant(changeVariant, '#single-product'); } {# Offer and discount labels update #} var $this_product_container = jQueryNuvem(this).closest(".js-product-container"); if($this_product_container.hasClass("js-quickshop-container")){ var this_quickshop_id = $this_product_container.attr("data-quickshop-id"); var $this_product_container = jQueryNuvem('.js-product-container[data-quickshop-id="'+this_quickshop_id+'"]'); } var $this_compare_price = $this_product_container.find(".js-compare-price-display"); var $this_price = $this_product_container.find(".js-price-display"); var $installment_container = $this_product_container.find(".js-product-payments-container"); var $installment_text = $this_product_container.find(".js-max-installments-container"); var $this_add_to_cart = $this_product_container.find(".js-prod-submit-form"); // Get the current product discount percentage value var current_percentage_value = $this_product_container.find(".js-offer-percentage"); // Get the current product price and promotional price var compare_price_value = $this_compare_price.html(); var price_value = $this_price.html(); // Calculate new discount percentage based on difference between filtered old and new prices const percentageDifference = window.moneyDifferenceCalculator.percentageDifferenceFromString(compare_price_value, price_value); if(percentageDifference){ $this_product_container.find(".js-offer-percentage").text(percentageDifference); $this_product_container.find(".js-offer-label").css("display" , "table"); } if ($this_compare_price.css("display") == "none" || !percentageDifference) { $this_product_container.find(".js-offer-label").hide(); } if ($this_add_to_cart.hasClass("nostock")) { $this_product_container.find(".js-stock-label").show(); } else { $this_product_container.find(".js-stock-label").hide(); } if ($this_price.css('display') == 'none'){ $installment_container.hide(); $installment_text.hide(); }else{ $installment_text.show(); } });
Pronto, você já tem em sua loja a funcionalidade aplicada.