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.