Calculadora de frete

No tutorial a seguir explicamos como adicionar o calculador de frete e as lojas físicas em seu layout:

O código neste tutorial inclui:

  • A calculador de frete, tanto no detalhe do produto como no carrinho
  • O filtro entre opções de envio semelhantes. Isso destaca a melhor opção de envio e oculta o restante em um link "Ver mais opções". Não se aplica a meios de envio personalizados.
  • Datas exatas de envio em vez do tempo estimado em dias
  • Select de lojas físicas (somente para lojas não brasileiras)
  • Mensagem sobre frete grátis (aplica-se apenas a lojas no Brasil que usam o meio de envio Correios)

Abaixo do subtotal você pode ver um exemplo da calculadora

À esquerda, as opções de envio exibidas e à direita as opções menos relevantes, visíveis clicando em "Ver mais opções".

HTML

A primeira coisa que vamos fazer é criar os tpls necessários para a funcionalidade.

1. Adicionamos a pasta com o nome shipping dentro da pasta snipplets

2. Dentro desta pasta, criamos os seguintes arquivos, cada um com seu respectivo código. É importante manter os IDs e classes "js -..." para garantir sua operação quando adicionamos JavaScript.

branches.tpl

Esse arquivo representa o seletor de lojas físicas que são visíveis apenas para lojas não brasileiras. O código é o seguinte:

<div class="js-toggle-branches w-100">
    <span class="form-row">
        <div class="col-auto">
            {% include "snipplets/svg/store.tpl" with {svg_custom_class: "icon-inline icon-lg link-module-icon svg-icon-text"} %}
        </div>
        <div class="col-6">
            <div class="mb-1"> 
                {% if store.branches|length > 1 %}
                    {{ 'Retirá gratis en nuestros locales' | translate }}
                {% else %}
                    {{ 'Retirá gratis en nuestro local' | translate }}
                {% endif %}
            </div>
            <div class="btn-link float-left">
                {% if product_detail %}
                    <span class="js-see-branches">
                        {% if store.branches|length > 1 %}
                            {{ 'Ver locales' | translate }}
                        {% else %}
                            {{ 'Ver local' | translate }}
                        {% endif %}
                    </span>
                {% else %}
                    <span>
                        {{ 'Elegir local' | translate }}
                    </span>
                {% endif %}
                {% include "snipplets/svg/chevron-down.tpl" with {svg_custom_class: "js-see-branches icon-inline ml-1"} %}


                <span class="js-hide-branches" style="display: none;">
                    {% if product_detail %}
                        {% if store.branches|length > 1 %}
                            {{ 'Ocultar locales' | translate }}
                        {% else %}
                            {{ 'Ocultar local' | translate }}
                        {% endif %}
                    {% endif %}
                    {% include "snipplets/svg/chevron-up.tpl" with {svg_custom_class: "icon-inline ml-1"} %}
                </span>
            </div>
        </div>
    </span>
</div>


{# Store branches #}


{% if not product_detail %}
    
    <ul class="js-store-branches-container list-unstyled radio-button-container mt-3" style="display: none;">


        {# Selectable branches #}


        {% for branch in store.branches %}
            <li class="radio-button-item">
                <label class="js-shipping-radio js-branch-radio radio-button" data-loop="branch-radio-{{loop.index}}">
                <input 
                    class="js-branch-method {% if cart.shipping_data.code == branch.code %} js-selected-shipping-method {% endif %} shipping-method" 
                    data-price="0" 
                    {% if cart.shipping_data.code == branch.code %}checked{% endif %} type="radio" 
                    value="{{branch.code}}" 
                    data-name="{{ branch.name }} - {{ branch.extra }}"
                    data-code="{{branch.code}}" 
                    data-cost="{{ 'Gratis' | translate }}"
                    name="option" 
                    style="display:none">
                    <span class="shipping-option row-fluid radio-button-content">
                       <span class="radio-button-icons">
                            <span class="radio-button-icon unchecked"></span>
                            <span class="radio-button-icon checked"></span>
                            <span class="radio-button-icon checked checked-invert"></span>
                        </span>
                        <span class="radio-button-label">
                            <h6 class="text-primary mb-1 d-inline-block">{{ 'Gratis' | translate }}</h6>
                            <span class="radio-button-text">
                                {{ branch.name }} - {{ branch.extra }}
                            </span>
                        </span>
                    </span>
                </label>
            </li>
        {% endfor %}
    </ul>
{% else %}
    <ul class="js-store-branches-container list-unstyled list mt-3" style="display: none;">
        {% for branch in store.branches %}
            <li class="list-item">
                <span class="list-item-content">
                    <h6 class="text-primary mb-1">{{ 'Gratis' | translate }}</h6>
                    <div>{{ branch.name }} - {{ branch.extra }}</div>
                </span>
            </li>
        {% endfor %}
    </ul>
{% endif %}

shipping-calculator.tpl

É o componente da calculadora de frete. Inclui um input, um botão, a mensagem de erro e uma mensagem que mostra o valor mínimo para obter frete grátis, bem como uma mensagem notificando que o frete grátis foi atingido quando excedido esse valor (isso se aplica somente a lojas que usam Correios).

{% if shipping_calculator_show %}
    <div class="{% if product_detail %}product-shipping-calculator{% endif %} {% if store.branches and store.country != 'BR' %}mb-4{% else %}mb-2{% endif %}">
        <div class="js-shipping-calculator-form">


            {# Shipping calcualtor input #}
            
            {% embed "snipplets/forms/form-input.tpl" with{type_tel: true, input_value: cart.shipping_zipcode, input_name: 'zipcode', input_custom_class: 'js-shipping-input', input_placeholder: "Código postal" | translate, input_label: false, input_append_content: true, input_group_custom_class: 'form-row align-items-center mb-3', form_control_container_custom_class: 'col-5'} %}
                {% block input_prepend_content %}
                    <div class="col-12 mb-2">


                        {% include "snipplets/svg/truck.tpl" with {svg_custom_class: "icon-inline icon-w-18 icon-lg svg-icon-text mr-2"} %}


                        {# Free shipping achieved label #}


                        <span class="js-free-shipping-message" {% if not free_shipping.cart_has_free_shipping %}style="display: none;"{% endif %}>
                            {{ "¡Genial! <strong class='text-primary'>Tenés envío gratis</strong> en esta compra" | translate }}
                        </span>


                        {# Free shipping with min price label #}


                        <span class="js-shipping-calculator-label" {% if free_shipping.cart_has_free_shipping or not free_shipping.min_price_free_shipping.min_price %}style="display: none;"{% endif %}>
                            {{ "<strong class='text-primary'>Envío gratis</strong> superando los" | translate }} <span>{{ free_shipping.min_price_free_shipping.min_price }}</span>
                        </span>


                        {# Shipping default label #}


                        <span class="js-shipping-calculator-label-default" {% if free_shipping.cart_has_free_shipping or free_shipping.min_price_free_shipping.min_price %}style="display: none;"{% endif %}>


                            {# Regular shipping calculator label #}
                            
                            {{ 'Costos de envío' | translate }}
                        </span>
                    </div>
                {% endblock input_prepend_content %}
                {% block input_form_alert %}
                <div class="col-12">
                    <div class="js-ship-calculator-error invalid-zipcode alert alert-danger" style="display: none;">{{ "No encontramos este código postal. ¿Está bien escrito?" | translate }}</div>
                    <div class="js-ship-calculator-error js-ship-calculator-common-error alert alert-danger" style="display: none;">{{ "Ocurrió un error al calcular el envío. Por favor intentá de nuevo en unos segundos." | translate }}</div>
                    <div class="js-ship-calculator-error js-ship-calculator-external-error alert alert-danger" style="display: none;">{{ "El calculo falló por un problema con el medio de envío. Por favor intentá de nuevo en unos segundos." | translate }}</div>
                </div>
                {% endblock input_form_alert %}
                {% block input_append_content %}
                <span class="col-6">
                    <button class="js-calculate-shipping btn btn-default btn-block">    
                        <span class="js-calculate-shipping-wording">{{ "Calcular" | translate }}</span>
                        <span class="js-calculating-shipping-wording" style="display: none;">{{ "Calculando" | translate }}</span>
                        <span class="loading" style="display: none;">
                            {% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline svg-icon-text icon-spin"} %}
                        </span>
                    </button>
                    {% if shipping_calculator_variant %}
                        <input type="hidden" name="variant_id" id="shipping-variant-id" value="{{ shipping_calculator_variant.id }}">
                    {% endif %}
                </span>
                {% endblock input_append_content %}
            {% endembed %}
        </div>
        <div class="js-shipping-calculator-response mb-3 float-left w-100 {% if product_detail %}list{% endif %}" style="display: none;"></div>
    </div>
{% endif %}

shipping-calculator-item.tpl

Este é o item na lista de opções de envio. Dentro disso você pode mostrar:

Variável
Descrição
option.short_nameNome do meio de envío utilizando option.short_name
option.costPreço com option.cost, se option.cost == 0 é exibido como gratis.
option.old_costO preço antigo quando é uma opção de Correios com frete grátis, con option.old_cost
option.timeTempo formatado em dias, por exemplo, "5 dias úteis"
option.timeTempo formatado em datas, por exemplo “Chega entre terça-feira 07/08 e quarta-feira 09/08”. Recomendamos usar essa opção, pois é mais fácil para o usuário entender.
option.payment_rulesUma mensagem se o meio de envio estiver disponível apenas para um determinado meio de pagamento usando option.payment_rules

Se o meio de envio tiver subopções, incluímos o tpl da pasta shipping_suboptions (que adicionaremos mais tarde). Aplica-se apenas a lojas na Argentina com o meio de remessa OCA por enquanto.

Também tem uma mensagem de alerta no caso de precisarmos mostrar alguma condição extra no meio de envio. Isso é definido a partir do PHP Nuvemshop.

Além disso o condicional feature_option no radio button. Isso serve para diferenciar as opções de frete pendentes da menor prioridade ao incluí-las no tpl shipping_options.tpl (que serão incluídas posteriormente). Lembre-se de que essa filtragem não inclui meios de entrega locais ou personalizados.

O código é o seguinte:

<li class="js-shipping-list-item radio-button-item">
    <label class="js-shipping-radio radio-button list-item" data-loop="shipping-radio-{{loop.index}}">
        <input 
        id="{% if featured_option %}featured-{% endif %}shipping-{{loop.index}}" 
        class="js-shipping-method {% if not featured_option %}js-shipping-method-hidden{% endif %} shipping-method" 
        data-price="{{option.cost.value}}" 
        data-code="{{option.code}}" 
        data-name="{{option.name}}" 
        data-cost="{% if option.show_price %} {% if option.cost.value == 0  %}{{ 'Gratis' | translate }}{% else %}{{option.cost}}{% endif %}{% else %} {{ 'A convenir' | translate }} {% endif %}" 
        type="radio" 
        value="{{option.code}}" 
        {% if featured_option and loop.first %}checked="checked"{% endif %} name="option" 
        style="display:none" />
        <span class="radio-button-content">
            <span class="radio-button-icons">
                <span class="radio-button-icon unchecked"></span>
                <span class="radio-button-icon checked"></span>
            </span>
            <span class="radio-button-label">


                {# Improved shipping option with no carrier img and ordered shipping info #}
                
                <div class="radio-button-text"> 
                    {% if option.show_price %} 
                        <div class="mb-1 d-inline-block">
                            <span class="text-primary h6">
                                {% if option.cost.value == 0  %}
                                    {{ 'Gratis' | translate }}
                                {% else %}
                                    {{option.cost}}
                                {% endif %}
                            </span>
                            {% if option.cost.value == 0 and option.old_cost.value %}
                                <span class="price-compare text-foreground font-small ml-1">{{option.old_cost}}</span>
                            {% endif %}
                        </div>
                    {% endif %}
                    {% if option.time %}
                        <div>
                            <strong>
                            {% if store.has_smart_dates %}
                                {{option.dates}}
                            {% else %}
                                {{option.time}}
                            {% endif %}
                            </strong>
                        </div>
                    {% endif %}
                </div>
                <div class="radio-button-text">
                    {{option.short_name}} {{ option.method == 'branch'  ? option.extra.extra  :  '' }}
                </div>
                {% if option.payment_rules %}
                    <div>
                        {% include "snipplets/svg/info-circle.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
                        <i>{{option.payment_rules}}</i>
                    </div>
                {% endif %}


                {% if option.suboptions is not empty %}
                    {% include "snipplets/shipping_suboptions/#{option.suboptions.type}.tpl" with {'suboptions': option.suboptions} %}
                {% endif %}


                {% if option.warning['enable'] %}
                    <div class="alert alert-warning">
                      <p>{{ option.warning['message'] }}</p>
                    </div>
                {% endif %}
            </span>
        </span>
    </label>
</li>

3. Criamos o arquivo shipping_options.tpl dentro da pasta snipplets. Você não deve mudar seu nome ou localização, já que usamos o Nuvemshop PHP para exibi-lo dentro do div com a classe js-shipping-calculator-response na tpl shipping-calculator.tpl

Dentro deste snipplet são construídas as duas listas de opções de envio, a priorizada e a oculta no link “Ver mais opções”.

{% if options %}
    {% if store.has_smart_dates and show_time %}
        <div class="radio-group-label mb-3">{{"El tiempo de entrega no considera feriados." | translate}}</div>
    {% endif %}
    <ul class="list-unstyled">


        {# Smart shipping hides similar shipping options on a toggle div and also shows an improved shipping item #}


        {# Check if smart shipping is needed #}


        {% set has_options_to_hide = false %}


        {% for option in options_to_hide %}
            {% if options_to_hide|length >= 1 %}
                {% set has_options_to_hide = true %}
            {% endif %}
        {% endfor %}


        {% for option in options_to_show if store.country == 'BR' or option.img_code != "branch" %}
            {% include "snipplets/shipping/shipping-calculator-item.tpl" with {'featured_option': true} %}
        {% endfor %}


        {% if has_options_to_hide %}
            <div class="js-show-more-shipping-options d-inline-block w-100 mt-3 text-center">
                <a href="#" class="btn-link">
                    <span class="js-shipping-see-more">
                        {{ 'Ver más opciones' | translate }}
                        {% include "snipplets/svg/chevron-down.tpl" with {svg_custom_class: "icon-inline ml-1"} %}
                    </span>
                    <span class="js-shipping-see-less" style="display: none;">{{ 'Ver menos opciones' | translate }}
                        {% include "snipplets/svg/chevron-up.tpl" with {svg_custom_class: "icon-inline ml-1"} %}
                    </span>
                </a>
            </div>
            <div class="js-other-shipping-option w-100 mt-3" style="display: none;">
                {% for option in options_to_hide if store.country == 'BR' or option.img_code != "branch" %}
                    {% include "snipplets/shipping/shipping-calculator-item.tpl" %}
                {% endfor %}
                </div>
        {% endif %}
    </ul>


    <div class="js-product-shipping-label font-small mt-3 pull-left" style="display: none;">
        <span class="js-shipping-filled-cart js-visible-on-cart-filled" {% if cart.items_count == 0 %}style="display:none;"{% endif%}>
            {% include "snipplets/svg/info-circle.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
            <span>{{ 'El precio de envío incluye este producto y todos los que agregaste al carrito.' | translate }}</span>
        </span>
    </div>
{% else %}
<span>{{"No hay costos de envío para el código postal dado." | translate}}</span>
{% endif %}


{# Don't remove this #}
<input type="hidden" name="after_calculation" value="1"/>
<input type="hidden" name="zipcode" value="{{zipcode}}"/>

4. Adicionamos a pasta shipping_suboptions dentro da pasta snipplet e finalmente criamos um tpl chamado select.tpl.

Isso mostra subopções na forma de um select para os meios de frete que precisam ser exibidos. Por enquanto, ela só se aplica a agências OCA.

{% set selected_option = loop.first or cart.shipping_option == option.name %}
<div class="js-shipping-suboption {{suboptions.name}}">
    {% if suboptions.options %}


        <p class="js-shipping-suboption-product mb-1" style="display: none;">{{ 'Podrás elegir alguna de las siguientes opciones antes de finalizar la compra:' | translate }}</p>


        {# Read only suboptions #}
        <ul class="js-shipping-suboption-list" name="{{suboptions.name}}" style="display: none;">
            {% for option in suboptions.options %}
                <li class="text-capitalize">{{ option.name | lower }}</li>
            {% endfor %}
        </ul>


        {# Select suboptions for cart page #}


        <div class="js-shipping-suboption-select" style="display:none;">
        {% embed "snipplets/forms/form-select.tpl" with{ select_name: suboptions.name, select_group_custom_class: 'm-0'} %}
            {% block select_options %}
               <option {% if not suboptions.selected %}selected{% endif %} disabled>{{ suboptions.default_option | translate }}</option>
                {% for option in suboptions.options %}
                    <option value="{{option.value}}">{{ option.name | lower }}</option>
                {% endfor %}
            {% endblock select_options%}
        {% endembed %}
        </div>


    {% else %}
        <input type="hidden" name="{{suboptions.name}}"/>
        <div>{{ suboptions.no_options_message | translate }}</div>
    {% endif %}
</div>

5. Agora precisamos chamar a calculadora de remessa e as lojas no carrinho e no detalhe do produto.

Para o detalhe do produto, adicionamos o seguinte código no product-form.tpl ou no arquivo em que você tem o formulário do produto:

{% if settings.shipping_calculator_product_page and not product.free_shipping %}

        {# Shipping calculator and branch link #}


        <div id="product-shipping-container" class="product-shipping-calculator list" {% if not product.display_price or not product.has_stock %}style="display:none;"{% endif %}>


            {# Shipping Calculator #}
            
            {% if store.has_shipping %}
                {% include "snipplets/shipping/shipping-calculator.tpl" with {'shipping_calculator_show': settings.shipping_calculator_cart_page and not product.free_shipping, 'shipping_calculator_variant' : product.selected_or_first_available_variant} %}
            {% endif %}


            {% if store.branches and store.country != 'BR' %}
                
                {# Link for branches #}
                {% include "snipplets/shipping/branches.tpl" with {'product_detail': true} %}
            {% endif %}
        </div>
{% endif %} 

Em seguida, temos que adicionar a calculadora no carrinho, no layout Base é no snipplet cart-totals.tpl mas em seu projeto pode ser em cart.tpl ou cart-panel-ajax.tpl

{% if settings.shipping_calculator_cart_page %}
  <div class="js-visible-on-cart-filled divider" {% if cart.items_count == 0 %}style="display:none;"{% endif %}></div>


  <div class="js-visible-on-cart-filled js-has-new-shipping js-shipping-calculator-container container-fluid">


    {# Saved shipping not available #}


    <div class="js-shipping-method-unavailable alert alert-warning row" style="display: none;">
      <div>
        <strong>{{ 'El medio de envío que habías elegido ya no se encuentra disponible ' | translate }}</strong>{{ 'porque el total de los items del carrito superan el peso máximo.' | translate }}
      </div>
      <div>
        {{ '¡No te preocupes! Podés elegir otro medio de envío.' | translate}}
      </div>
    </div>


    {# Shipping calculator and branch link #}


    <div id="cart-shipping-container" class="row" {% if cart.items_count == 0 %} style="display: none;"{% endif %} data-shipping-url="{{ store.shipping_calculator_url }}">


      {# Used to save shipping #}


      <span id="cart-selected-shipping-method" data-code="{{ cart.shipping_data.code }}" class="hidden">{{ cart.shipping_data.name }}</span>


      {# Shipping Calculator #}


      {% if store.has_shipping %}
        {% include "snipplets/shipping/shipping-calculator.tpl" with {'shipping_calculator_show': settings.shipping_calculator_cart_page, 'product_detail': false} %}
      {% endif %}


      {# Store branches #}


      {% if store.branches and store.country != 'BR' %}


        {# Link for branches #}


        {% include "snipplets/shipping/branches.tpl" with {'product_detail': false} %}
      {% endif %}
    </div>
  </div>


  <div class="js-visible-on-cart-filled divider {% if not store.branches or store.country == 'BR' %} mt-0{% endif %}" {% if cart.items_count == 0 %}style="display:none;"{% endif %}></div>


{% endif %}

6. Precisamos adicionar no template product.tpl no div pai de todo o detalhe do producto, o ID “single-product” e as classes js-has-new-shipping js-product-detail js-product-container, js-shipping-calculator-container. Ficando da seguinte maneira:

<div id="single-product" class="js-has-new-shipping js-product-detail js-product-container js-shipping-calculator-container" data-variants="{{product.variants_object | json_encode }}" itemscope itemtype="http://schema.org/Product">
HTML do detalhe de produto
</div>

7. Criamos a pasta forms dentro da pasta snipplets. Aqui precisamos adicionar um novo arquivo com o nome form-input.tpl que usaremos para o input do calculador.

{# /*============================================================================
  #Form input
==============================================================================*/


#Properties


#Group
    //input_group_custom_class for custom CSS classes
#Label 
    // input_label_id for ID
    // input_for for label for
    // input_label_custom_class for custom CSS classes
    // input_label_text for label text
#Prepend
    // input_prepend_content to add content before input
#Container (Only if has prepend or append)
    // form_control_container_custom_class for container custom class. E.g: col
#Input 
    // Can be text_area or input
    // input_type to define type (text, tel, number or passowrd)
    // input_id for id
    // input_name for name
    // input_value for val
    // input_placeholder for placeholder
    // input_custom_class for custom CSS classes 
    // input_rows for textarea rows
    // input_data_attr for data attributes
    // input_data_val for input_data_attr value
#Append
    // input_append_content to add content after input
#Alerts 
    // input_form_alert to insert alerts


#}


<div class="form-group {{ input_group_custom_class }}">
    {% if input_label_text %}
        <label {% if input_label_id %}id="{{ input_label_id }}"{% endif %} class="form-label {{ input_label_custom_class }}" {% if input_for %}for="{{ input_name }}"{% endif %}>{{ input_label_text }}</label>
    {% endif %}
    {% block input_prepend_content %}
    {% endblock input_prepend_content %}
    {% if input_append_content or input_prepend_content %}
    <div class="form-control-container {{ form_control_container_custom_class }}">
    {% endif %}
    {% if text_area %}
        <textarea
            {% if input_id %}id="{{ input_id }}"{% endif %}
            class="form-control form-control-area {{ input_custom_class }} {% if input_append_content %}form-control-inline{% endif %}" 
            autocorrect="off" 
            autocapitalize="off" 
            {% if input_name %}name="{{ input_name }}"{% endif %}
            {% if input_value %}value="{{ input_value }}"{% endif %}
            {% if input_rows %}rows="{{ input_rows }}"{% endif %}
            {% if input_placeholder %}placeholder="{{ input_placeholder }}"{% endif %}
            {% if input_data_attr %}data-{{ input_data_attr }}="{{ input_data_val }}"{% endif %}></textarea>
    {% else %}
        <input 
            type="{% if type_text %}text{% elseif type_number %}number{% elseif type_tel %}tel{% elseif type_password %}password{% elseif type_hidden %}hidden{% endif %}"
            {% if input_id %}id="{{ input_id }}"{% endif %}
            class="form-control {{ input_custom_class }} {% if input_append_content %}form-control-inline{% endif %}" 
            autocorrect="off" 
            autocapitalize="off" 
            {% if type_password %}autocomplete="off"{% endif %}
            {% if input_name %}name="{{ input_name }}"{% endif %}
            {% if input_value %}value="{{ input_value }}"{% endif %}
            {% if input_min %}min="{{ input_min }}"{% endif %}
            {% if input_placeholder %}placeholder="{{ input_placeholder }}"{% endif %}
            {% if input_data_attr %}data-{{ input_data_attr }}="{{ input_data_val }}"{% endif %}/>
    {% endif %}
    {% if input_append_content or input_prepend_content %}
    </div>
    {% endif %}
    {% block input_append_content %}
    {% endblock input_append_content %}
    {% if input_help %}
    <div class="mt-4 text-center">
        <a href="{{ input_help_link }}" class="btn-link {{ input_link_class }}">{% block input_help_text %}{% endblock input_help_text %}</a>
    </div>
    {% endif %}
    {% block input_form_alert %}
    {% endblock input_form_alert %}
</div>

8. Finalmente, para a parte HTML, precisamos adicionar uma pasta SVG dentro da pasta snipplets. Aqui vamos adicionar os SVGs que usamos para os ícones na calculadora.

store.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 616 512"><path d="M602 118.6L537.1 15C531.3 5.7 521 0 510 0H106C95 0 84.7 5.7 78.9 15L14 118.6c-29.6 47.2-10 110.6 38 130.8v227.4c0 19.4 14.3 35.2 32 35.2h448c17.7 0 32-15.8 32-35.2V249.4c48-20.2 67.6-83.6 38-130.8zM516 464H100v-96h416zm-.2-144.2H100v-64.7c24-3.3 45.1-15.2 60.3-32.2 18 20.1 44.3 33.1 73.8 33.1 29.6 0 55.8-13 73.8-33.1 18 20.1 44.3 33.1 73.8 33.1 29.6 0 55.8-13 73.8-33.1 15.3 17 36.3 28.9 60.3 32.2zm47.9-133c-3.2 6.8-10.9 18.6-27 20.8-2.4.3-4.8.5-7.2.5-14.7 0-28.2-6.1-38.1-17.2L455.7 151 420 190.8c-9.9 11.1-23.5 17.2-38.1 17.2s-28.2-6.1-38.1-17.2L308 151l-35.7 39.8c-9.9 11.1-23.5 17.2-38.1 17.2-14.7 0-28.2-6.1-38.1-17.2L160.3 151l-35.7 39.8c-9.9 11.1-23.5 17.2-38.1 17.2-2.5 0-4.9-.2-7.2-.5-16-2.2-23.8-13.9-27-20.8-5-10.8-7.1-27.6 2.3-42.6L114.8 48h386.3l60.2 96.1c9.5 15.1 7.5 31.9 2.4 42.7z"/></svg>

chevron-down.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M441.9 167.3l-19.8-19.8c-4.7-4.7-12.3-4.7-17 0L224 328.2 42.9 147.5c-4.7-4.7-12.3-4.7-17 0L6.1 167.3c-4.7 4.7-4.7 12.3 0 17l209.4 209.4c4.7 4.7 12.3 4.7 17 0l209.4-209.4c4.7-4.7 4.7-12.3 0-17z"/></svg>

chevron-up.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M6.101 359.293L25.9 379.092c4.686 4.686 12.284 4.686 16.971 0L224 198.393l181.13 180.698c4.686 4.686 12.284 4.686 16.971 0l19.799-19.799c4.686-4.686 4.686-12.284 0-16.971L232.485 132.908c-4.686-4.686-12.284-4.686-16.971 0L6.101 342.322c-4.687 4.687-4.687 12.285 0 16.971z"/></svg>

info-circle.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 448c-110.532 0-200-89.431-200-200 0-110.495 89.472-200 200-200 110.491 0 200 89.471 200 200 0 110.53-89.431 200-200 200zm0-338c23.196 0 42 18.804 42 42s-18.804 42-42 42-42-18.804-42-42 18.804-42 42-42zm56 254c0 6.627-5.373 12-12 12h-88c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h12v-64h-12c-6.627 0-12-5.373-12-12v-24c0-6.627 5.373-12 12-12h64c6.627 0 12 5.373 12 12v100h12c6.627 0 12 5.373 12 12v24z"/></svg>

truck.tpl

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M624 368h-16V251.9c0-19-7.7-37.5-21.1-50.9L503 117.1C489.6 103.7 471 96 452.1 96H416V56c0-30.9-25.1-56-56-56H56C25.1 0 0 25.1 0 56v304c0 30.9 25.1 56 56 56h8c0 53 43 96 96 96s96-43 96-96h128c0 53 43 96 96 96s96-43 96-96h48c8.8 0 16-7.2 16-16v-16c0-8.8-7.2-16-16-16zm-464 96c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48zm208-96H242.7c-16.6-28.6-47.2-48-82.7-48s-66.1 19.4-82.7 48H56c-4.4 0-8-3.6-8-8V56c0-4.4 3.6-8 8-8h304c4.4 0 8 3.6 8 8v312zm48-224h36.1c6.3 0 12.5 2.6 17 7l73 73H416v-80zm64 320c-26.5 0-48-21.5-48-48s21.5-48 48-48 48 21.5 48 48-21.5 48-48 48zm80-100.9c-17.2-25.9-46.6-43.1-80-43.1-24.7 0-47 9.6-64 24.9V272h144v91.1z"/></svg>

sync-alt.tpl 

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M483.515 28.485L431.35 80.65C386.475 35.767 324.485 8 256 8 123.228 8 14.824 112.338 8.31 243.493 7.971 250.311 13.475 256 20.301 256h28.045c6.353 0 11.613-4.952 11.973-11.294C66.161 141.649 151.453 60 256 60c54.163 0 103.157 21.923 138.614 57.386l-54.128 54.129c-7.56 7.56-2.206 20.485 8.485 20.485H492c6.627 0 12-5.373 12-12V36.971c0-10.691-12.926-16.045-20.485-8.486zM491.699 256h-28.045c-6.353 0-11.613 4.952-11.973 11.294C445.839 370.351 360.547 452 256 452c-54.163 0-103.157-21.923-138.614-57.386l54.128-54.129c7.56-7.56 2.206-20.485-8.485-20.485H20c-6.627 0-12 5.373-12 12v143.029c0 10.691 12.926 16.045 20.485 8.485L80.65 431.35C125.525 476.233 187.516 504 256 504c132.773 0 241.176-104.338 247.69-235.493.339-6.818-5.165-12.507-11.991-12.507z"/></svg>

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 na 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 layout:

{# This mixin adds browser prefixes to a CSS property #}


@mixin prefix($property, $value, $prefixes: ()) {
  @each $prefix in $prefixes {
      #{'-' + $prefix + '-' + $property}: $value;
  }
    #{$property}: $value;
}


{# /* // Buttons */ #}


.btn{
  text-decoration: none;
  text-align: center;
  border: 0;
  cursor: pointer;
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  text-transform: uppercase;
  background: none;
  @include prefix(transition, all 0.4s ease, webkit ms moz o);
  &:hover,
  &:focus{
    outline: 0;
    opacity: 0.8;
  }
  &[disabled],
  &[disabled]:hover{
    opacity: 0.5;
    cursor: not-allowed;
    outline: 0;
  }
  &-default{
    padding: 10px 15px; 
    background-color: rgba($main-foreground, .2);
    color: $main-foreground;
    fill: $main-foreground;
    font-weight: bold;
  }
  &-primary{
    padding: 15px;
    background-color: $primary-color;
    color: $main-background;
    fill: $main-background;
    letter-spacing: 4px;
    @extend %body-font;
    &:hover{
      color: $main-background;
      fill: $main-background;
    }
  }
  &-secondary{
    padding: 10px 15px; 
    background-color: $main-background;
    color: $main-foreground;
    fill: $main-foreground;
    border: 1px solid $main-foreground;
  }
  &-block{
    float: left;
    width: 100%;
  }
}


{# /* // Links */ #}


.btn-link{
  color: $primary-color;
  fill: $primary-color;
  text-transform: uppercase;
  border-bottom: 1px solid;
  font-weight: bold;
  cursor: pointer;
  &:hover,
  &:focus{
    color: rgba($primary-color, .5);
    fill: rgba($primary-color, .5);
  }
}


{# /* // Forms */ #}


input,
textarea {
  font-family: $body-font;
}


.form-control {
  display: block;
  padding: 10px 8px;
  width: 100%;
  border: 0;
  border-bottom: 1px solid rgba($main-foreground, .5);
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  color: $main-foreground;
  background-color: $main-background;
  &:focus{
    outline: 0;
  }
  &-inline{
    display: inline;
  }
}


.form-control::-webkit-input-placeholder { 
  color: $main-foreground;
}
.form-control:-moz-placeholder {
  color: $main-foreground;
}
.form-control::-moz-placeholder {
  color: $main-foreground;
}
.form-control:-ms-input-placeholder {
  color: $main-foreground;
}


.radio-button {
  input[type="radio"]{
    & +  .radio-button-content .unchecked{
      border:2px solid $main-foreground;
    }
    & +  .radio-button-content .checked{
      background-color: $main-foreground;
    }
  }
}

2. Adicione os estilos no arquivo static/style-critical.tpl

Se em seu layout você usar um stylesheet para o CSS crítico, precisaremos do seguinte código dentro dele, do contrário, você pode unificar o CSS dos passos 2 e 3 em um único arquivo.

{# /* // Forms */ #}


.form-group {
  position: relative;
  width: 100%;
}
.form-group .form-select-icon{
  position: absolute;
  bottom: 12px;
  right: 0;
  pointer-events: none;
}
.form-row {
  width: auto;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
  flex-wrap: wrap;
  margin-right: -5px;
  margin-left: -5px;
  clear: both;
}


.form-row > .col,
.form-row > [class*=col-]{
  padding-right: 5px;
  padding-left: 5px;
}


.form-label {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
}

3. Adicione os estilos no arquivo static/style-async.tpl

Se em seu layout você usar um stylesheet CSS assíncrono, precisaremos do seguinte código dentro dela, do contrário, você pode unificar o CSS dos passos 2 e 3 em um único arquivo.

{# /* // Margin and Padding */ #}


%section-margin {
  margin-bottom: 70px;
}
%element-margin {
  margin-bottom: 35px;
}
%element-margin-small {
  margin-bottom: 20px;
}


{# /* // Mixins */ #}


{# This mixin adds browser prefixes to a CSS property #}


@mixin prefix($property, $value, $prefixes: ()) {
  @each $prefix in $prefixes {
    #{'-' + $prefix + '-' + $property}: $value;
  }
  #{$property}: $value;
}


{# /* // Forms */ #}


.form-group{
  @extend %element-margin;
  .form-label{
    float: left;
    width: 100%;
    margin-bottom: 10px;
  }
  .alert{
    margin: 10px 0 0 0;
  }
}


.radio-button{
  width: 100%;
  float: left;
  clear: both;
  text-align: left;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  @extend %element-margin-small;
  cursor: pointer;
  &.disabled{
    opacity: 0.6;
    cursor: not-allowed;
    input[type="radio"] {
      cursor: not-allowed;
    }
  }
  &-icons{
    position: relative;
    float: left;
    display: table;
    width: 20px;
    margin:0 5px 0 0;
  }
  &-icon{
    border-radius: 50%;
    width: 18px;
    height: 18px;
  }
  input[type="radio"]{
    display: none;
    & +  .radio-button-content .unchecked{
      float: left;
    }
    & +  .radio-button-content .checked{
      position: absolute;
      left:9px;
      top:9px;
      width:0;
      height: 0;      
      @include prefix(transform, translate(-50%,-50%), webkit ms moz o);
      @include prefix(transition, all 0.2s , webkit ms moz o);
    }
    &:checked + .radio-button-content .checked{
      width: 6px;
      height: 6px;
    }
  }
  &-label{
    display: table;
    padding-top: 1px;
  }
  &-text{
    display: table;
    margin-bottom: 2px;
  }
}


.radio-button-item:last-of-type .radio-button{
  margin-bottom: 0;
}


.form-select {
  display: block;
  width: 100%;
  &:focus{
    outline:0;
  }
  &::-ms-expand {
    display: none;
  }
}


{# /* Disabled controls */ #}


input,
select,
textarea{
  &[disabled],
  &[disabled]:hover,
  &[readonly],
  &[readonly]:hover{
    background-color: #DDD;
    cursor: not-allowed; 
  }
}

JS

1. JavaScript precisam ser adicionados no arquivo store.js.tpl (ou onde você tem suas funções JS). O código que precisamos é o seguinte:

/* // Select and save shipping function */ 


    selectAndSaveShippingOption = function(elem){
        $(".js-shipping-method, .js-branch-method").removeClass('js-selected-shipping-method');
        $(elem).addClass('js-selected-shipping-method');
        LS.saveCalculatedShipping(true);
        var $closest_shipping_container = $(elem).closest(".js-shipping-calculator-container");
        if($(elem).hasClass("js-shipping-method-hidden")){
            $closest_shipping_container.find(".js-shipping-see-more").hide();
            $closest_shipping_container.find(".js-shipping-see-less").show();
            $closest_shipping_container.find(".js-other-shipping-options").show();
        }
    };


    /* // Calculate shipping function */ 


    $(".js-calculate-shipping").click(function (e) {
        e.preventDefault();


            {# Take the Zip code to all shipping calculators on screen #}
            let shipping_input_val = $(this).closest(".js-shipping-calculator-form").find(".js-shipping-input").val();
            if (shipping_input_val.length != 0){
                $(".js-shipping-input").val(shipping_input_val);
            }
            
        LS.calculateShippingAjax(
            $(this).closest(".js-shipping-calculator-container").find(".js-shipping-input").val(),
            '{{ store.shipping_calculator_url | escape('js') }}',
            $(this).closest(".js-shipping-calculator-container")
        );
    });


    /* // Calculate shipping by submit */ 


    $(".js-shipping-input").keydown(function (e) {
        var key = e.which ? e.which : e.keyCode;
        var enterKey = 13;
        if (key === enterKey) {
            e.preventDefault();
            $(this).closest(".js-shipping-calculator-form").find(".js-calculate-shipping").click();
            if ($(window).width() < 768) {
                $(this).blur();
            }
        }
    });


     /* // Shipping and branch click */ 


    $(document).on("change", ".js-shipping-method, .js-branch-method", function () {
        selectAndSaveShippingOption(this);
        $(".js-shipping-method-unavailable").hide();
    });


    /* // Select shipping first option on results */


    $('.js-shipping-method:checked').livequery(function () {
        let shippingPrice = $(this).attr("data-price");
        LS.addToTotal(shippingPrice);
        selectAndSaveShippingOption(this);
    });


   /* // Toggle branches link */


    $(document).on("click", ".js-toggle-branches", function (e) {
        e.preventDefault();
        $(this).next().slideToggle("fast");
        $(this).find(".js-see-branches, .js-hide-branches").toggle();
    });


    /* // Toggle more shipping options */


    $(document).on("click", ".js-show-more-shipping-options", function(e) {
        e.preventDefault();
        $(this).next().slideToggle("fast");
        $(this).find(".js-shipping-see-more, .js-shipping-see-less").toggle();
    });


    /* // Calculate shipping on page load */


    {# Only shipping input has value, cart has saved shipping and there is no branch selected #}


    if($("#cart-shipping-container .js-shipping-input").val() && !$(".js-branch-method").hasClass('js-selected-shipping-method') && $(".js-cart-total").hasClass('js-cart-saved-shipping')){
       
        // If user already had calculated shipping: recalculate shipping
       
       setTimeout(function() { 
            LS.calculateShippingAjax(
                $('#cart-shipping-container').find(".js-shipping-input").val(), 
                '{{store.shipping_calculator_url | escape('js')}}',
                $("#cart-shipping-container").closest(".js-shipping-calculator-container") );
        }, 100);
    }else if($(".js-branch-method").hasClass('js-selected-shipping-method')){
        $("#cart-shipping-container .js-toggle-branches").click();


        // Trigger function only for free pickup stores
        LS.saveCalculatedShipping(false);
    }


    /* // Shipping provinces */


    {% if provinces_json %}
        $('select[name="country"]').change(function () {
            var provinces = {{ provinces_json | default('{}') | raw }};
            LS.swapProvinces(provinces[$(this).val()]);
        }).change();
    {% endif %}

2. Depois temos que adicionarno arquivo external.js.tpl ou no arquivo onde você tem os plugins do seu layout, o plugin Livequery

/*! jquery.livequery - v1.3.6 - 2013-08-26
* Copyright (c)
*  (c) 2010, Brandon Aaron (http://brandonaaron.net)
*  (c) 2012 - 2013, Alexander Zaytsev (http://hazzik.ru/en)
* Dual licensed under the MIT (MIT_LICENSE.txt)
* and GPL Version 2 (GPL_LICENSE.txt) licenses. 
*/
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?a(require("jquery")):a(jQuery)}(function(a,b){function c(a,b,c,d){return!(a.selector!=b.selector||a.context!=b.context||c&&c.$lqguid!=b.fn.$lqguid||d&&d.$lqguid!=b.fn2.$lqguid)}a.extend(a.fn,{livequery:function(b,e){var f,g=this;return a.each(d.queries,function(a,d){return c(g,d,b,e)?(f=d)&&!1:void 0}),f=f||new d(g.selector,g.context,b,e),f.stopped=!1,f.run(),g},expire:function(b,e){var f=this;return a.each(d.queries,function(a,g){c(f,g,b,e)&&!f.stopped&&d.stop(g.id)}),f}});var d=a.livequery=function(b,c,e,f){var g=this;return g.selector=b,g.context=c,g.fn=e,g.fn2=f,g.elements=a([]),g.stopped=!1,g.id=d.queries.push(g)-1,e.$lqguid=e.$lqguid||d.guid++,f&&(f.$lqguid=f.$lqguid||d.guid++),g};d.prototype={stop:function(){var b=this;b.stopped||(b.fn2&&b.elements.each(b.fn2),b.elements=a([]),b.stopped=!0)},run:function(){var b=this;if(!b.stopped){var c=b.elements,d=a(b.selector,b.context),e=d.not(c),f=c.not(d);b.elements=d,e.each(b.fn),b.fn2&&f.each(b.fn2)}}},a.extend(d,{guid:0,queries:[],queue:[],running:!1,timeout:null,registered:[],checkQueue:function(){if(d.running&&d.queue.length)for(var a=d.queue.length;a--;)d.queries[d.queue.shift()].run()},pause:function(){d.running=!1},play:function(){d.running=!0,d.run()},registerPlugin:function(){a.each(arguments,function(b,c){if(a.fn[c]&&!(a.inArray(c,d.registered)>0)){var e=a.fn[c];a.fn[c]=function(){var a=e.apply(this,arguments);return d.run(),a},d.registered.push(c)}})},run:function(c){c!==b?a.inArray(c,d.queue)<0&&d.queue.push(c):a.each(d.queries,function(b){a.inArray(b,d.queue)<0&&d.queue.push(b)}),d.timeout&&clearTimeout(d.timeout),d.timeout=setTimeout(d.checkQueue,20)},stop:function(c){c!==b?d.queries[c].stop():a.each(d.queries,d.prototype.stop)}}),d.registerPlugin("append","prepend","after","before","wrap","attr","removeAttr","addClass","removeClass","toggleClass","empty","remove","html","prop","removeProp"),a(function(){d.play()})});

Configurações

No arquivo config/settings.txt, adicionaremos um checkbox para ativar ou desativar a calculadora e as lojas físicas na seção Personalizar meu layout atual no Administrador nuvem

Na seção Detalhe do produto, adicionamos o seguinte:

    title
        title = Medios de envío
    checkbox_global
        name = shipping_calculator_product_page
        description = Mostrar calculador de costos de envío en la página de producto

E fazemos o mesmo para a seção de Carrinho de compras

    title
        title = Medios de envío
    checkbox_global
        name = shipping_calculator_cart_page
        description = Mostrar calculador de costos de envío en el carrito

Traduções

Nesta etapa adicionamos os textos para as traduções no arquivo config/translations.txt

--- Shipping ---


es "Formas de envío"
pt "Formas de envio"
en "Shipping methods"
es_mx "Opciones de envío"


es "FORMAS DE ENVÍO"
pt "FORMAS DE ENVIO"
en "SHIPPING METHODS"
es_mx "OPCIONES DE ENVÍO"


es "Ejemplos de formas de envío"
pt "Exemplos de formas de envio"
en "Shipping methods examples"
es_mx "Ejemplos de opciones de envío"


es "Ingrese aquí su código postal para calcular su costo de envío"
pt "Digite aqui o seu CEP para calcular o frete"
en "Enter your zipcode to calculate your shipping cost"
es_mx "Ingresa tu código postal para calcular el costo de envío"


es "Calculá el costo de tu envío"
pt "Cálculo de frete"
en "Enter your zipcode to calculate your shipping cost"
es_mx "Calcula el costo de tu envío"


es "Calcular envío"
pt "Calcular frete"
en "Calculate shipping"
es_mx "Calcular envío"


es "Código postal"
pt "CEP"
en "Zipcode"
es_mx "Código postal"


es "Calcular costo de envío"
pt "Calcular Frete"
en "Calculate shipping"
es_mx "Calcular costo de envío"


es "El código postal es inválido."
pt "O CEP está inválido."
en "The zipcode is not valid."
es_mx "El código postal es inválido."


es " (sin envío)"
pt " (sem frete)"
en " (without shipping cost)"
es_mx " (sin envío)"


es "El código postal es inválido. Por favor intentá de nuevo usando otro."
pt "CEP inválido. Por favor, digite novamente ou informe outro."
en "The zipcode is not valid. Please try again using another."
es_mx "El código postal es inválido. Intenta de nuevo ingresando otro."


es "Ocurrió un error al calcular el envío. Por favor intentá de nuevo en unos segundos."
pt "Erro no cálculo. Por favor, tente novamente em alguns segundos."
en "An error ocurred while calculating the shipping. Please try again in a few seconds."
es_mx "Hubo un error al calcular el envío. Intenta de nuevo en unos segundos."


es "El calculo falló por un problema con el medio de envío. Por favor intentá de nuevo en unos segundos."
pt "Erro no meio de envio. Por favor, tente novamente em alguns segundos."
en "The calculation failed due to a problem with the shipping method. Please try again in a few seconds."
es_mx "El cálculo falló por un problema con el forma de envío. Intenta de nuevo en unos segundos."


es "Vea las opciones de envío para su código postal abajo"
pt "Veja os valores para o seu CEP abaixo"
en "Your shipping options are the following"
es_mx "Conoce las opciones de entrega para tu código postal"


es "No hay costos de envío para el código postal dado."
pt "Não há frete disponível para o CEP informado"
en "Shipping is not available for your zipcode."
es_mx "No hay costos de envío para ese código postal."


es "Retirá gratis en nuestros locales"
pt "Retire grátis em nossas lojas físicas"
en "Free pickup on our stores"
es_mx "Recoge gratis en nuestras tiendas"


es "Retirá gratis en nuestro local"
pt "Retire grátis em nossa loja física"
en "Free pickup on our store"
es_mx "Recoge gratis en nuestra tienda"


es "Ver locales"
pt "Ver lojas físicas"
en "See our stores"
es_mx "Ver tiendas"


es "Ver local"
pt "Ver loja física"
en "See our store"
es_mx "Ver tienda"


es "Elegir local"
pt "Escolher loja física"
en "Select store"
es_mx "Elegir una tienda"


es "Conocé nuestras opciones de envío"
pt "Conheça nossas opções de frete"
en "See our shipping options"
es_mx "Conoce nuestras opciones de entrega"


es "Elegí nuestras opciones de envío"
pt "Escolha a opção de frete"
en "Choose our shipping options"
es_mx "Conoce las opciones de entrega"


es "Calculando"
pt "Calculando"
en "Calculating"
es_mx "Calculando"


es "El medio de envío que habías elegido ya no se encuentra disponible "
pt "O frete escolhido não está mais disponível "
en "The shipping method selected is no longer available "
es_mx "La forma de envío que elegiste ya no está disponible "


es "porque el total de los items del carrito superan el peso máximo."
pt "porque o total de itens no carrinho excede o peso máximo."
en "because the total of the items in the cart surpass the maximum weight."
es_mx "porque el peso total del carrito supera el peso máximo."


es "¡No te preocupes! Podés elegir otro medio de envío."
pt "Mas não se preocupe! Você pode escolher outro meio de envio."
en "Do not worry! You can select another method."
es_mx "¡No te preocupes! Puedes elegir otra forma de envío."


es "Ocultar locales"
pt "Esconder lojas físicas"
en "Hide our stores"
es_mx "Ocultar tiendas"


es "Ocultar local"
pt "Esconder loja física"
en "Hide our store"
es_mx "Ocultar tienda"


es "Seguí acá"
pt "Acompanhe aqui"
en "Track here"
es_mx "Sigue aquí"


es "tu última compra"
pt "seu último pedido"
en "your last order"
es_mx "tu última compra"


es "El precio de envío incluye este producto y todos los que agregaste al carrito."
pt "O custo de frete inclui este produto e outros adicionados ao carrinho."
en "The shipping cost includes this product and all the products added to the cart."
es_mx "El precio de envío incluye este producto y todos los que has agregado al carrito."


es "Podrás elegir alguna de las siguientes opciones antes de finalizar la compra:"
pt "Você pode escolher uma das seguintes opções antes de finalizar a compra"
en "You will be able to choose some of the following options before ending the purchase"
es_mx "Podrás elegir alguna de las siguientes opciones antes de finalizar la compra:"


es "No encontramos este código postal. ¿Está bien escrito?"
pt "Não conseguimos encontrar esse CEP. Está bem escrito?"
en "We couldn&#39;t find this zipcode. Is it written right?"
es_mx "No encontramos este código postal. ¿Está bien escrito?"


es "El tiempo de entrega no considera feriados."
pt "O prazo de entrega não contabiliza feriados."
en "The delivery time does not consider holidays."
es_mx "El tiempo de entrega no considera feriados."


es "Ingresa aquí tu código postal para calcular tu costo de envío"
pt "Digite aqui o seu CEP para calcular o frete"
en "Enter your zipcode to calculate your shipping cost"
es_mx "Ingresa aquí tu código postal para calcular tu costo de envío"


es "Costos de envío"
pt "Custos de frete"
en "Shipping costs"
es_mx "Costos de envío"


es "Calcular"
pt "Calcular"
en "Calculate"
es_mx "Calcular"


es "Envío:"
pt "Frete:"
en "Shipping:"
es_mx "Envío:"


es "Calcular para ver"
pt "Calcule para visualizar"
en "Calculate to view"
es_mx "Calcular para ver"


es "El costo del envío se calculará después."
pt "O frete será calculado depois."
en "Shipping cost will be calculated at checkout"
es_mx "El costo del envío se calculará después."


es "<strong>Tenés envío gratis</strong> en esta compra. ¡Aprovechalo!"
pt "Você ganhou <strong>frete grátis</strong> para esta compra. Aproveite!"
en "You have <strong>free shipping</strong> in this order. Go for it!"
es_mx "<strong>Tienes envío gratis</strong> en esta compra. ¡Aprovéchalo!"


es "¡Genial! <strong class='text-primary'>Tenés envío gratis</strong> en esta compra"
pt "Sucesso! Você <strong class='text-primary'>tem frete grátis</strong> para esta compra."
en "You have <strong class='text-primary'>free shipping</strong> in this order."
es_mx "¡Genial! <strong class='text-primary'>Tienes envío gratis</strong> en esta compra"


es "¡Estas a <strong class='js-cart-free-shipping-amount'></strong> de tener <strong class='text-primary m-quarter-bottom'>envío gratis</strong> en tu compra!"
pt "<strong>Ganhe frete grátis</strong> com mais <strong class='js-cart-free-shipping-amount'></strong> em compras"
en "You need <strong class='js-cart-free-shipping-amount'></strong> to have <strong class='text-primary m-quarter-bottom'>free shipping</strong> on your order"
es_mx "¡Estas a <strong class='js-cart-free-shipping-amount'></strong> de tener <strong class='text-primary m-quarter-bottom'>envío gratis</strong> en tu compra!"


es "Ver más productos"
pt "Escolher mais produtos"
en "See more products"
es_mx "Ver más productos"


es "¡Todos los productos de esta categoría <strong>tienen envío gratis!</strong>"
pt "Todos os produtos desta categoria <strong>tienen envío gratis!</strong>"
en "All the products in this category <strong>have free shipping!</strong>"
es_mx "¡Todos los productos de esta categoría <strong>tienen envío gratis!</strong>"


es "<strong class='text-primary'>Envío gratis</strong> superando los"
pt "<strong class='text-primary'>Frete grátis</strong> para compras acima de"
en "<strong class='text-primary'>Free shipping</strong> buying more than"
es_mx "<strong class='text-primary'>Envío gratis</strong> superando los"


es "<strong class='text-primary'>¡Envío gratis!</strong> con todos los medios de envío"
pt "<strong class='text-primary'>Frete grátis!</strong> com todos os meios de envio"
en "<strong class='text-primary'>Free shipping!</strong> with all shipping options"
es_mx "<strong class='text-primary'>¡Envío gratis!</strong> con todos los medios de envío"




--- --- Shipping and Payments


es "Medios de envío"
pt "Opções de frete"
en "Shipping Methods"
es_mx "Opciones de envío"


es "Mostrar calculador de costos de envío en la página de producto"
pt "Mostrar o Cálculo de Frete na página de produto"
en "Show shipping cost calculator on product page"
es_mx "Mostrar el calculador de costos de envío en la página de producto"


es "Mostrar calculador de costos de envío en el carrito"
pt "Mostrar o Cálculo de Frete no carrinho"
en "Show shipping cost calculator to cart"
es_mx "Mostrar el calculador de costos de envío en el carrito"


es "Mostrar medios de envío en tu tienda"
pt "Mostrar as opções de frete na sua loja"
en "Show Shipping Methods in your store"
es_mx "Mostrar las opciones de envío en tu sitio"


es "Mostrar medios de pago en tu tienda"
pt "Mostrar as opções de pagamento na sua loja"
en "Show payment methods in your store"
es_mx "Mostrar los métodos de pago en tu sitio"

Ativação

Você pode ativar a calculadora n detalhe do produto e no carrinho através do Administrador Nuvem, na seção Personalizar meu  layout atual nas seções Detalhes do produto e Carrinho de compras:


Pronto, você já tem em seu layout a funcionalidade aplicada.