Snipplets

Los snipplets son la unidad mínima de HTML dentro de una plantilla y se encuentran dentro de la carpeta con su mismo nombre. 

Representan componentes aislados que pueden ser incluidos en uno o varios lugares de la tienda como por ejemplo el ítem de producto en el listado:

Pueden ser elementos genéricos como un simple input para un formulário

O algo específico de una funcionalidad como el calculador de envíos

Podés agregar todos los snipplets que necesites en tu diseño usando el nombre que creas mejor, lo importante es entender que cuanto más aislado esté el componente, más fácil va a ser su mantenimiento sin afectar otros archivos.

En las plantillas existen solo 4 snipplets que no pueden cambiar de ubicación ni nombre dentro de los archivos por razones de backend (es decir que son usados desde el PHP de Tiendanube)  :

  • product_grid.tpl → Se usa para cargar más productos en las páginas de categoría cuando el usuário llega al footer
  • shipping_options.tpl → Se usa para las opciones de envío
  • cart-item-ajax.tpl → Es el item del producto agregado al carrito
  • shipping_suboptions → es una carpeta que contiene solo un tpl que se usa cuando el medio de envío tiene más opciones, por ejemplo un desplegable para sucursales de OCA.

A continuación podrás ver en detalle algunos de los snipplets más importantes de una plantilla:

Grid

Dentro de la carpeta Grid tenemos todos los snipplets en relación a la grilla o listado de productos:

  • filters.tpl
  • sort-by.tpl
  • item.tpl

filters.tpl

En este snipplet encontrarás todo lo relacionado a los filtros de productos:

Separamos los filtros en 4 grupos:

  • Filtros de colores principales, los cuales se muestran con un botón circular con el fondo del color.
  • Filtros para colores secundarios, con los colores más específicos como “Salmón”. Estos se muestran con un botón normal cuyo texto será el nombre del color.
  • Filtros para talles
  • Otros filtros, para los más personalizados.

Usamos los filtros solamente para la página de categorías dentro del archivo category.tpl

{% set default_lang = current_language.lang %}
{% set filter_colors = insta_colors|length > 0 %}
{% set filter_more_colors = other_colors|length > 0 %}
{% set filter_sizes = size_properties_values|length > 0 %}
{% set filter_other = variants_properties|length > 0 %}


{% if default_lang == 'pt' %}
    {% set color_name = 'Cor' %}
    {% set size_name = 'Tamanho' %}
{% endif %}
{% if default_lang == 'es' %}
    {% set color_name = 'Color' %}
    {% set size_name = 'Talle' %}
{% endif %}
{% if default_lang == 'en' %}
    {% set color_name = 'Color' %}
    {% set size_name = 'Size' %}
{% endif %}
<div id="filters">
    {% if filter_colors %}
        <div class="mb-4">
            <h6 class="mb-2">{{ 'Color' | translate }}</h6>
            {% for name,color in insta_colors %}
                <button type="button" class="btn btn-secondary btn-circle mr-2 mb-2" style="background-color: {{ color[name] }};" title="{{ name }}" onclick="LS.urlAddParam('{{ color_name|replace("'","%27") }}', '{{ name|replace("'","%27") }}');">
                </button>
            {% endfor %}
        </div>
    {% endif %}
    {% if filter_more_colors %}
        <div class="mb-4">
            <h6 class="mb-2">
                {% if filter_colors %}
                    {{ 'Más colores' | translate }}
                {% else %}
                    {{ 'Color' | translate }}
                {% endif %}
            </h6>
            {% for color in other_colors %}
                <button type="button" class="btn btn-secondary mr-2 mb-2" onclick="LS.urlAddParam('{{ color_name|replace("'","%27") }}', '{{ color|replace("'","%27") }}');">{{ color }}
                </button>
            {% endfor %}
        </div>
    {% endif %}
    {% if filter_sizes %}
        <div class="mb-4">
            <h6 class="mb-2">{{ 'Talle' | translate }}</h6>
            {% for size in size_properties_values %}
                <button type="button" class="btn btn-secondary mr-2 mb-2" onclick="LS.urlAddParam('{{ size_name|replace("'","%27") }}', '{{ size|replace("'","%27") }}');">{{ size }}
                </button>
            {% endfor %}
        </div>
    {% endif %}


    {% for variants_property in variants_properties %}
        {% if filter_other %}
            <div class="mb-4">
                <h6 class="mb-2">{{ variants_property }}</h6>
                {% for value in variants_properties_values[variants_property] %}
                    <button type="button" class="btn btn-secondary mr-2 mb-2" onclick="LS.urlAddParam('{{ variants_property|replace("'","%27") }}', '{{ value|replace("'","%27") }}');">{{value}}
                    </button>
                {% endfor %}
            </div>
        {% endif %}
    {% endfor %}
</div>

Si no tenés esta funcionalidad en tu diseño y querés implementarla te sugerimos este tutorial.

sort-by.tpl

El sort-by.tpl sirve para ordenar los productos con los siguientes criterios:

  • Precio: mayor a menor y menor a mayor.
  • Alfabético: A -Z y Z - A.
  • Tiempo: más nuevo al más viejo y más viejo al más nuevo.
  • Más vendidos.

Usamos el sort by solamente para la página de categorías dentro del archivo category.tpl

{% set sort_text = {
'user': 'Destacado',
'price-ascending': 'Precio: Menor a Mayor',
'price-descending': 'Precio: Mayor a Menor',
'alpha-ascending': 'A - Z',
'alpha-descending': 'Z - A',
'created-ascending': 'Más Viejo al más Nuevo',
'created-descending': 'Más Nuevo al más Viejo',
'best-selling': 'Más Vendidos',
} %}
{% embed "snipplets/forms/form-select.tpl" with{select_label: false, select_custom_class: 'js-sort-by', select_group_custom_class: 'mb-0'} %}
    {% block select_options %}
        {% for sort_method in sort_methods %}
            {# This is done so we only show the user sorting method when the user chooses it #}
            {% if sort_method != 'user' or category.sort_method == 'user' %}
                <option value="{{ sort_method }}" {% if sort_by == sort_method %}selected{% endif %}>{{ sort_text[sort_method] | t }}</option>
            {% endif %}
        {% endfor %}
    {% endblock select_options%}
{% endembed %}

Si no tenés esta funcionalidad en tu diseño y querés implementarla te sugerimos este tutorial.

item.tpl

El item es el snipplet que representa al producto dentro del listado:

A través de este item mostramos información importante sobre el producto como:

  • Imagen
  • Nombre 
  • Precio
  • Cuotas

En algunos casos inclímos la funcionalidad de “Quickshop” o “Popup de compras rápida” así como una imágen secundaria cuando se hace hover sobre el item con el mouse en su versión de escritorio.

En este snipplet incuimos la implementación para lazy load con Lazysizes.

Incluimos el item en las siguientes partes del theme:

  • Productos destacados de la página de inicio.
  • Productos relacionados en el detalle del producto.
  • Listado en la página de categorías.
  • Listado en los resultados de búsqueda.
{# /*============================================================================
  #Item grid
==============================================================================*/

#Properties

#Slide Item

#}

{% set slide_item = slide_item | default(false) %}
{% set columns = settings.grid_columns %}

<div class="{% if slide_item %}swiper-slide{% else %}col{% if columns == 2 %}-6 col-md-3{% else %}-12 col-md-4{% endif %}{% endif %} item item-product{% if not product.display_price %} no-price{% endif %}">
    {% set product_url_with_selected_variant = has_filters ?  ( product.url | add_param('variant', product.selected_or_first_available_variant.id)) : product.url  %}
    <div class="item-image mb-2">
        <div style="padding-bottom: {{ product.featured_image.dimensions['height'] / product.featured_image.dimensions['width'] * 100}}%;" class="p-relative">
            <a href="{{ product_url_with_selected_variant }}" title="{{ product.name }}">
                <img alt="{{ product.featured_image.alt }}" data-sizes="auto" src="{{ 'images/empty-placeholder.png' | static_url }}" data-srcset="{{ product.featured_image | product_image_url('small')}} 240w, {{ product.featured_image | product_image_url('medium')}} 320w, {{ product.featured_image | product_image_url('large')}} 480w" class="lazyautosizes lazyload img-absolute img-absolute-centered" /> 


                {# Low quality img until final img is lazyloaded #}
                <img alt="{{ product.featured_image.alt }}" src="{{ product.featured_image | product_image_url('tiny')}}" class="img-absolute img-absolute-centered blur-up">
            </a>
            {% include 'snipplets/labels.tpl' %}
        </div>
    </div>
    <div class="item-description">
        <a href="{{ product_url_with_selected_variant }}" title="{{ product.name }}" class="item-link">
            <div itemprop="name" class="item-name mb-1">{{ product.name }}</div>
            <meta itemprop="url" content="{{ product.url }}" />
            {% if product.display_price %}
                <div class="item-price-container mb-1" itemprop="offers" itemscope itemtype="http://schema.org/Offer">
                    <meta itemprop="priceCurrency" content="{{ product.currency }}" />
                    {% if product.compare_at_price %}
                        <span class="price-compare">
                            {{ product.compare_at_price | money }}
                        </span>
                    {% endif %}
                    <span class="item-price" itemprop="price" content="{{ product.price / 100 }}">
                        {{ product.price | money }}
                    </span>
                </div>
            {% endif %}
        </a>
    </div>
    {% include 'snipplets/payments/installments.tpl' %}
</div>

product_grid.tpl

Aunque no incluyamos a este archivo dentro de la carpeta Grid (por razones de backend), es importante mencionarlo. 

Este tpl incluye al item.tpl para listar los items en las páginas de categorías y resultados de búsqueda, pero su rol principal es agregar más productos a medida que el usuario hace scroll en la pantalla. Es por esta funcionalidad que no debes modificar su nombre o ubicación dentro las carpetas del theme.

Incluimos este snipplet en:

  • La página de categorías
  • La página de resultados de búsqueda
{% if products and pages.is_last %}
    <div class="last-page" style="display:none;"></div>
{% endif %}
{% for product in products %}   
    {% include 'snipplets/grid/item.tpl' %}
{% endfor %}

Forms

Dentro de la carpeta Forms ubicamos todos los snipplets en relación los formulários:

form-input.tpl

Para cada input en un formulario usamos este snipplet, ya sea en la página de registro de un usuario o en el calculador de envíos.

Dentro del form-input.tpl podés elegir qué propiedades usar a la hora de incluirlo (usando un embed). Entre estas podés:

  • Usar clases personalizadas para el input
  • Mostrar o no un label arriba del input
  • Agregar contenido entre el label y el input
  • Definir si el input será un textarea o un input normal
  • Elegir que tipo de input será: number, text, password, etc

Para ver en detalles todas las propiedades de este snipplet podés guiarte mirando los comentarios en el código del mismo.

{# /*============================================================================
  #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>

Incluimos este snipplet en los snipplets newsletter.tpl, product-quantity.tpl, shipping-calculator.tpl y en los templates password.tpl, contact.tpl, reset.tpl, register.tpl, login.tpl, newpass.tpl, info.tpl  y address.tpl

form-select.tpl

Así como usamos el form-input.tpl para los inputs, tenemos el form-select.tpl para los select.

Con este snipplet también podés definir si mostrar o no un label ,o también agregar clases personalizadas, pero lo que lo hace diferente es la posibilidad de agregar opciones dentro del desplegable usando {% block select_options %}. Dentro de este tag de Twig es posible agregar cualquier opción.

Para más información sobre cómo usar un {% block %} te sugerimos que leas este artículo sobre Twig.

{# /*============================================================================
  #Form select
==============================================================================*/
#Properties
#Group
    //select_group_custom_class for custom CSS classes
#Label 
    // select_label_name for name
    // select_label_id for ID
    // select_for for label for
    // select_label_custom_class for custom CSS classes
#Select 
    // select_id for id
    // select_name for name
    // select_custom_class for custom CSS classes 
    // input_rows for textarea rows
    // select_options to insert select options
#}


<div class="form-group {{ select_group_custom_class }}">
    {% if select_label %}
        <label {% if select_label_id%}id="{{ select_label_id }}"{% endif %} class="form-label {{ select_label_custom_class }}" {% if select_for %}for="{{ select_for }}"{% endif %}>{{ select_label_name }}</label>
    {% endif %}
    <select 
        {% if select_id %}id="{{ select_id }}"{% endif %}
        class="form-select {{ select_custom_class }} {% if select_inline %}form-control-inline{% endif %}"
        {% if select_name %}name="{{ select_name }}"{% endif %}>
        {% block select_options %}
        {% endblock select_options %}
    </select>
    <div class="form-select-icon">
        {% include "snipplets/svg/chevron-down.tpl" with {svg_custom_class: "icon-inline icon-w-14 icon-lg svg-icon-text"} %}
    </div>
</div>

Incluimos este snipplet más que nada en el sort-by y en las variantes de productos.

form.tpl

Usamos el form.tpl para incluir un formulario clásico con el método “post” que por defecto muestra un botón para enviar.

Con este snipplet podés agregar los campos que necesites dentro del {% block form_body %} y elegir si mostrar o no un botón de “cancelar” usando la condición {% if cancel %}.

Para más información sobre cómo usar un {% block %} te sugerimos que leas este artículo sobre Twig.

{# /*============================================================================
  #Form
==============================================================================*/
#Properties
 
    // id
    // action
    // custom_class for custom CSS classes
    // Cancel if cancel button is needed
#}


<form id="{{ form_id }}" action="{{ form_action }}" method="post" class="form {{ form_custom_class }}">
    {% block form_body %}
    {% endblock%}
    {% if cancel %}
        <a href="#" class="{{ cancel_custom_class }} btn btn-default">{{ cancel_text }}</a>
    {% endif %}
    <input class="btn btn-primary {{ submit_custom_class }}" type="submit" value="{{ submit_text }}" name="{{ submit_name }}" />
</form>

Incluimos este snipplet en todos los formularios clásicos del theme como por ejemplo:

  • Login
  • Registro
  • Actualizar o crear datos de envío
  • Actualizar o crear datos de usuario
  • Contacto

Metas

Los metas son snipplets que usamos información a la hora de compartir un producto en Facebook y Twitter. 

facebook-category-og.tpl

Almacena la información de una categoría al ser compartida como el nombre, una url y una imágen destacada.

{{ category.url | og('url') }}
{{ category.name | og('title') }}
{{ category.description | og('description') }}
{{ ('http:' ~ category.featured_image | product_image_url('huge')) | og('image') }}
{{ ('https:' ~ category.featured_image | product_image_url('huge')) | og('image:secure_url') }}

facebook-og.tpl

Contiene la información general de una tienda como el nombre,  el logo y una url.

 {{ store.name | og('site_name') }}
{% if template == 'home' and store.logo %}
    {{ ('http:' ~ store.logo) | og('image') }}
    {{ ('https:' ~ store.logo) | og('image:secure_url') }}
{% endif %}

facebook-product-og.tpl

Tiene la información general de un producto como el nombre,  el precio, una descripción y una url.

{{ product.social_url | og('url') }}
{{ product.name | og('title') }}
{{ page_description | og('description') }}
{{ "#{fb_app.namespace}:product" | og('type') }}
{{ ('http:' ~ product.featured_image | product_image_url('huge')) | og('image') }}
{{ ('https:' ~ product.featured_image | product_image_url('huge')) | og('image:secure_url') }}
{% if product.display_price %}
    {{ (product.price / 100) | og_fb_app('price') }}
{% endif %}
{% if product.stock_control %}
    {{ product.stock | og_fb_app('stock') }}
{% endif %}

twitter-product-og.tpl

Muestra la información general de un producto como el nombre,  el precio, una descripción y una url.

<meta name="twitter:card" content="product">
<meta name="twitter:url" content="{{ product.social_url }}">
<meta name="twitter:image:src" content="{{ ('http:' ~ product.featured_image | product_image_url('huge')) }}">
{% if store.twitter_user %}
    <meta name="twitter:site" content="{{ store.twitter_user }}">
{% endif %}
<meta name="twitter:title" content="{{ product.name }}">
<meta name="twitter:data1" content="{{ product.display_price ? product.price | money_long : 'Consultar' | translate }}">
<meta name="twitter:label1" content="{{ 'Precio' | translate | upper }}">
<meta name="twitter:data2" content="{{ product.stock_control ? (product.stock > 0 ? product.stock : 'No' | translate) : 'Si' | translate }}">
<meta name="twitter:label2" content="{{ 'Stock' | translate | upper }}">

Incluimos todos los snipplets de Meta en el layout.tpl 

SVG

En la carpeta SVG tenemos todos los snipplets de iconos de la tienda. Estos son archivos SVG que al terminar con “.tpl” nos permiten usar twig para reemplazar la propiedad svg_custom_class por cualquier clase que necesitemos a la hora de incluirlo.




Un ejemplo de un snipplet de SVG es el ícono de la lupa para buscar:

<svg class="{{ svg_custom_class }}" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M508.5 468.9L387.1 347.5c-2.3-2.3-5.3-3.5-8.5-3.5h-13.2c31.5-36.5 50.6-84 50.6-136C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c52 0 99.5-19.1 136-50.6v13.2c0 3.2 1.3 6.2 3.5 8.5l121.4 121.4c4.7 4.7 12.3 4.7 17 0l22.6-22.6c4.7-4.7 4.7-12.3 0-17zM208 368c-88.4 0-160-71.6-160-160S119.6 48 208 48s160 71.6 160 160-71.6 160-160 160z"/></svg>

Que luego incluimos dentro del snipplet header-utilities.tpl

{% include "snipplets/svg/shopping-bag.tpl" with {svg_custom_class: "icon-inline icon-w-14 svg-icon-text"} %}
Siempre que usamos un ícono, lo incluimos de esta manera. Para más información sobre SVGs recomiendo que lean este artículo sobre performance.

Shipping

En esta carpeta ubicamos todos los snipplets en relación a uno de los puntos más críticos del flujo de compra, medios de envío. Recomendamos modificar lo menos posible estos archivos debido a su complejidad e importancia dentro del theme.

Además de los archivos de esta carpeta, por razones de backend tenemos por fuera de la carpeta Shipping:

  • La carpeta shipping_suboptions
  • El snipplet shipping_options.tpl
Todo el JavaScript en relación a shipping está en el archivo store.js.tpl 

branches.tpl

En este tpl listamos los locales físicos solo para las tiendas que no sean de Brasil, los cuales están visibles a modo informativo en el detalle del producto y luego se pueden seleccionar en el carrito. 








Estos locales podés configurarlos en el Administrador nube desde la sección Configuraciones/Envíos y Locales.

Si querés mostrar los locales en Brasil borrá el condicional store.country != 'BR' donde este snipplet sea incluído y también vas a tener que aplicar otro cambio explicado en el snipplet shipping_options.tpl
<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 %}

Incluimos este tpl en el snipplet product-form.tpl para el detalle del producto y cart-totals.tpl   para el carrito de compras.

shipping-calculator.tpl

El snipplet shipping-calculator.tpl representa al calculador de envíos tanto en el detalle del producto como en el carrito.





{% 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 %}
                    <span class="col-1">
                        {% include "snipplets/svg/truck.tpl" with {svg_custom_class: "icon-inline icon-w-18 icon-lg svg-icon-text"} %}
                     </span>
                {% 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 envío" | 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 %}

Incluimos este tpl en el snipplet product-form.tpl para el detalle del producto y cart-totals.tpl para el carrito de compras.


shipping_options.tpl

En este tpl llamamos al snipplet de la opción de envío, es el elemento padre del listado. A la hora de mostrar los resultados del cálculo de envío insertamos por backend este archivo dentro del div js-shipping-calculator-response ubicado en shipping-calculator.tpl. Es por este comportamiento que no podés cambiarle el nombre o cambiar su ubicación en el repositorio del theme.

Dentro del listado priorizamos primero los envíos más baratos y luego los más rápidos (siempre considerando la combinación de dos parámetros).

Además separamos entre envíos principales y secundarios cuando la tienda tiene medios de envío no personalizados que son similares, por ejemplo: una tienda de Argentina que tiene OCA con envío a domicilio y Correo Argentino con envío a domicilio. 

En este caso priorizamos el mejor de los dos para no confundir al usuario y el otro envío queda oculto bajo un link de “Ver más opciones”.

Esta funcionalidad de filtrado de opciones lo llamamos “Smart shipping”.

{% 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}}"/>

Incluimos este tpl usando backend luego de calcular envío dentro del div con la clase js-shipping-calculator-response en el shipping-calculator.tpl

shipping-calculator-item.tpl

Como su nombre lo indica, este snipplet lo usamos para mostrar cada opción de envío listada, en el detalle del producto son solo informativas mientras que en el carrito muestran un radiobutton para que el usuário pueda elegirla.

<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>

Incluimos este tpl en el snipplet shipping_options.tpl 

shipping_suboptions

Dentro de esta carpeta encontramos el archivo select.tpl que solo usamos para el medio de envío argentino OCA (por ahora), para listar sucursales de ese correo dentro de un select.

{% 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>

Incluimos este tpl en el snipplet shipping-calculator-item.tpl 


Payments

En la carpeta Payments tenemos todos los archivos en relación a medios de pago. Así como con la carpeta Shipping, recomendamos modificar lo menos posible estos archivos debido a su complejidad e importancia dentro del theme.

installments.tpl

Como su nombre en inglés lo indica, este snipplet lo usamos para mostrar las mejores cuotas ofrecidas por la tienda en el item del listado de productos, el detalle de productos y en el total del carrito de compras (solo en tiendas de Brasil).



Dentro de este snipplet usamos la condición {% if product %} para diferenciar entre las cuotas de cada producto y las cuotas del carrito. 

De la misma forma usamos {% if product_detail %} para diferenciar entre el detalle del producto y el item del listado, y así usar JavaScript a través de las clases “js-...” actualizando el valor de las cuotas cuando el usuario cambia de variante dentro del detalle de un producto.

En tiendas de Argentina solo mostramos la mejor posibilidad de cuotas sin especificar el valor exacto (excepto en el popup con el detalle, para más información sobre este leer los demás tpls de Payments) debido a la resolución de Precios Transparentes definida por el Gobierno

Por otro lado en tiendas que no son argentinas mostramos las cuotas con su valor exacto.

{% if product %}

  {# Product installments #}

  {% if product.show_installments and product.display_price %}

    {% set installments_info_base_variant = product.installments_info %}
    {% set installments_info = product.installments_info_from_any_variant %}

    {# If product detail installments, include container with "see installments" link #}

    {% if product_detail and installments_info %}
      <div data-toggle="#installments-modal" class="js-modal-open js-product-payments-container mb-2" {% if (not product.get_max_installments) and (not product.get_max_installments(false)) %}style="display: none;"{% endif %}>
    {% endif %}

    {% set product_can_show_installments = product.show_installments and product.display_price and product.get_max_installments.installment > 1 %}

    {% if product_can_show_installments %}

      {# If NOT product detail, just include installments alone without link or container #}
      <div class="{% if product_detail %}js-max-installments-container js-max-installments text-center text-md-left{% else %}item-installments{% endif %}">
        {% set max_installments_without_interests = product.get_max_installments(false) %}
        {% set max_installments_with_interests = product.get_max_installments %}
        {% if store.country == 'AR' %}
          {% if max_installments_with_interests %}
            <div>{{ "Hasta <strong class='installment-amount'>{1}</strong> cuotas" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</div>
          {% else %}
            <div style="display: none;">
            {% if product.max_installments_without_interests %}
              {{ "Hasta <strong class='js-installment-amount installment-amount'>{1}</strong> cuotas sin interés" | t(null, null) }}
            {% else %}
              {{ "Hasta <strong class='js-installment-amount installment-amount'>{1}</strong> cuotas sin interés" | t(null, null) }}
            {% endif %}
            </div>
          {% endif %}
        {% else %}
            {% if max_installments_without_interests and max_installments_without_interests.installment > 1 %}
              <div class="js-max-installments">{{ "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas sin interés de <strong class='js-installment-price installment-price'>{2}</strong>" | t(max_installments_without_interests.installment, max_installments_without_interests.installment_data.installment_value_cents | money) }}</div>
            {% else %}
              {% set max_installments_with_interests = product.get_max_installments %}
              {% if max_installments_with_interests %}
                <div class="js-max-installments">{{ "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas de <strong class='js-installment-price installment-price'>{2}</strong>" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</div>
              {% else %}
                <div class="js-max-installments" style="display: none;">
                  {% if product.max_installments_without_interests %}
                    {{ "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas sin interés de <strong class='js-installment-price installment-price'>{2}</strong>" | t(null, null) }}
                  {% else %}
                    {{ "<strong class='js-installment-amount installment-amount'>{1}</strong> cuotas de <strong class='js-installment-price installment-price'>{2}</strong>" | t(null, null) }}
                  {% endif %}
                </div>
              {% endif %}
            {% endif %}
        {% endif %}
      </div>
    {% endif %}

    {% if product_detail and installments_info %}
      <div class="form-row align-items-center align-items-start-md mb-4">
        {% set has_payment_logos = settings.payments %}
        {% if has_payment_logos %}
          <ul class="list-inline col col-md-auto text-center text-md-left mb-1">
            {% for payment in settings.payments %}
                {# Payment methods flags #}
                {% if store.country == 'BR' %}
                  {% if payment in ['visa', 'mastercard'] %}
                    <li>     
                      {{ payment | payment_new_logo | img_tag('',{class: 'card-img card-img-small lazyload'}) }}
                    </li>
                  {% endif %}
                {% else %}
                    {% if payment in ['visa', 'amex', 'mastercard'] %}
                      <li>
                        {{ payment | payment_new_logo | img_tag('',{class: 'card-img card-img-small lazyload'}) }}
                      </li>
                    {% endif %}
                {% endif %}
            {% endfor %}
              <li>
                {% include "snipplets/svg/credit-card-blank.tpl" with {svg_custom_class: "icon-inline icon-w-18 icon-2x svg-icon-text"} %}
              </li>
          </ul>
        {% endif %}
        <div class="col-12 col-md-auto text-center">
          <a id="btn-installments" class="btn-link" {% if (not product.get_max_installments) and (not product.get_max_installments(false)) %}style="display: none;"{% endif %}>
            {% set store_set_for_new_installments_view = store.is_set_for_new_installments_view %}
            {% if store_set_for_new_installments_view %}
                {{ "Ver medios de pago" | translate }}
            {% else %}
                {{ "Ver el detalle de las cuotas" | translate }}
            {% endif %}
          </a>
        </div>
      </div>
    </div>
    {% endif %}  
  {% endif %}
{% else %}

  {# Cart installments #}
  
  {% if store.country == 'BR' %}
  {% if cart.installments.max_installments_without_interest > 1 %}
    {% set installment =  cart.installments.max_installments_without_interest  %}
    {% set total_installment = cart.total %}
    {% set interest = false %}
    {% set interest_value = 0 %}
  {% else %}
    {% set installment = cart.installments.max_installments_with_interest  %}
    {% set total_installment = (cart.total * (1 + cart.installments.interest)) %}
    {% set interest = true %}
    {% set interest_value = cart.installments.interest %}
  {% endif %}
  <div {% if installment < 2 %} style="display: none;" {% endif %} data-interest="{{ interest_value }}" data-cart-installment="{{ installment }}" class="js-installments-cart-total text-right"> 
    {{ 'O hasta' | translate }}
    <span class="js-cart-installments-amount">{{ installment }}</span> 
    {{ 'cuotas de' | translate }} 
    <span class="js-cart-installments">{{ (total_installment / installment) | money }}</span> 
    <span {% if interest == true %} style="display: none;" {% endif %}class="js-installments-type-interest">{{ 'sin interés' | translate}}</span>
  </div>
  {% endif %}
{% endif %}

Incluimos este tpl en los snipplets cart-totals.tpl, item.tpl y product-form.tpl

payments.tpl

Este archivo es el componente padre del popup que muestra los detalles de cada medio de pago usando el embed para modals, modal.tpl

Cada medio de pago tiene una tab que al ser cliqueado por el usuario muestra el detalle del mismo.

En este archivo incluidmos los tpls payments-info-banks.tpl para mostrar información de pagos para cada banco (solo aplica a tiendas argentinas) y payments-info.tpl para mostrar información en medios de pago independiente de bancos como PayPal por ejemplo.

{% set installments_info_base_variant = product.installments_info %}
{% set installments_info = product.installments_info_from_any_variant %}
{% if installments_info %}
{% set gateways = installments_info | length %}
{% set store_set_for_new_installments_view = store.is_set_for_new_installments_view %}

    {% embed "snipplets/modal.tpl" with{modal_id: 'installments-modal', modal_position: 'bottom', modal_transition: 'slide', modal_header: true, modal_footer: true, modal_width: 'centered'  } %}
        {% block modal_head %}
            {{'Medios de pago' | translate }}
        {% endblock %}
        {% block modal_body %}

            {# Modal header and gateways tab links #}

            <div class="js-tab-container">
                <ul class="js-tab-group tab-group">
                    {% for method, installments in installments_info %}
                        <li id="method_{{ method }}" class="js-refresh-installment-data js-installments-gw-tab js-tab tab {% if loop.first %} active {% endif %}" data-code="{{ method }}">
                            <a href="#installment_{{ method }}_{{ installment }}" class="js-tab-link tab-link">{{ method == 'paypal_multiple' ? 'PAYPAL' : (method == 'itaushopline'? 'ITAU SHOPLINE' : method == 'boleto_paghiper'? 'BOLETO PAGHIPER' : method | upper) }}</a>
                        </li>

                        {# Custom payment method #}

                        {% if loop.last and custom_payment is not null %}
                            <li id="method_{{ custom_payment.code }}" class="js-refresh-installment-data js-installments-gw-tab js-tab tab" data-code="{{ custom_payment.code }}">
                                <a href="#installment_{{ custom_payment.code }}" class="js-tab-link tab-link">{{ custom_payment.name | upper }}</a>
                            </li>
                        {% endif %}
                    {% endfor %}
                </ul>

                {# Gateways tab content #}

                <div class="js-tabs-content tab-content">
                    {% for method, installments in installments_info %}
                        {% set discount = product.get_gateway_discount(method) %}
                        <div id="installment_{{ method }}_" class="js-tab-panel tab-panel {% if loop.first %} active {% endif %} js-gw-tab-pane">
                            <div>

                                {% if store_set_for_new_installments_view %}

                                    {# Payments info with readonly #}

                                    {% if method == 'mercadopago' and store.country == 'AR' %}

                                        {# Payments Gateways with banks: at the moment only MP AR #}

                                        {% include 'snipplets/payments/payments-info-banks.tpl' %}
                                    {% else %}

                                        {# Payments Gateways with cards only #}

                                        {% include 'snipplets/payments/payments-info.tpl' %}
                                    {% endif %}    

                                {% else %}

                                    {# Installments list for ROLA stores #}

                                    {% for installment, data_installment in installments %}
                                        <div id="installment_{{ method }}_{{ installment }}">
                                            {% set rounded_installment_value = data_installment.installment_value | round(2) %}
                                            {% set total_value = (data_installment.without_interests ? data_installment.total_value : installment * data_installment.installment_value) %}
                                            {% set total_value_in_cents = total_value  | round(2) * 100 %}
                                            <strong class="js-installment-amount">{{ installment }}</strong> {% if store.country != 'BR' %}cuota{% if installment > 1 %}s{% endif %} de{% else %}x{% endif %} <strong class="js-installment-price">{{ (rounded_installment_value * 100) | money }}</strong>
                                            {% if data_installment.without_interests %} {{ 'sin interés' | t }}{% endif %}
                                        </div>
                                    {% endfor %}

                                {% endif %}
                            </div>
                        </div>

                        {# Custom payment method #}

                        {% if loop.last and custom_payment is not null %}
                            <div class="js-tab-panel tab-panel js-gw-tab-pane" id="installment_{{ custom_payment.code }}">
                                <div class="box">

                                    {# Custom method instructions #}

                                    <h6 class="mb-1">{{ 'Cuando termines la compra vas a ver la información de pago en relación a esta opción.' | translate }}</h6>

                                    {# Price total #}

                                    <h4 class="mb-1 font-weight-normal">
                                        <span>{{ 'Total:' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
                                    </h4>

                                    {% if custom_payment.discount > 0 %}
                                        <div> {{ custom_payment.name }}: {{ 'tiene un' | translate }} <strong>{{ custom_payment.discount }}% {{'de descuento' | translate }}</strong> {{'que será aplicado sobre el costo total de la compra al finalizar la misma.' | translate }}</div>
                                    {% endif %}
                                
                                </div>
                            </div>
                        {% endif %}
                    {% endfor %}
                </div>
            </div>
            
        {% endblock %}
        {% block modal_foot %}
            <div class="text-right">
                <span class="js-modal-close btn-link pull-right">{{ 'Volver al producto' | translate }}</span>
            </div>
        {% endblock %}
    {% endembed %}

{% endif %}

Incluimos este tpl en el snipplet product-form.tpl

payments-info-banks.tpl

Representa la información de medios de pago para bancos, agrupados por cuotas sin interés (especificando el valor de las cuotas) y cuotas con interés (sin especificar el valor ya que no es la mejor alternativa de pago y el usuario podrá verlo a la hora de pagar) , la cual por el momento solo aplica a Mercado Pago en Argentina.

Además también mostramos en este tpl información sobre medios de pago en efectivo para Argentina.

{% set gateways = installmentsv2['methods'][method] %}

{# Gateways with banks #}

{# Credit cards #}
{% if gateways.cc is not null %}
  <h6 class="mb-1">{{'Tarjetas de crédito' | translate }}</h6>
  <div class="box">
    {# Installments without interest modules by groups, E.g: 3, 6, 9, 12 #}

    {% if gateways.cc is null or gateways.cc is empty is not null %}
      {% for installment, banks in gateways.cc.no_interest %}
        <div>

          {# Installment amount, cost, CFT, 1 payment info and total cost #}

          <h4 class="font-weight-normal mb-1">
            {{ installment }}
            {{ 'cuotas' | translate }}
            <span>{{ 'sin interés' | t }}</span>
            {{'de' | t}}
            <strong class="js-modal-installment-price" data-installment="{{installment}}"> {{ (product.price / installment) | money }}</strong>
          </h4>
          <h6 class="font-weight-normal mb-2">
            <span class="mr-1">
              <span>{{ 'CFT: ' | translate }}</span><strong>0,00%</strong>
            </span>
            <span class="mr-1">
              <span>{{ 'Total: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
            </span>
            <span>
              <span>{{ 'En 1 pago: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
            </span>
          </h6>

          {# Banks with installments without interest flags #}

          <div class="mb-3">
            {% for bank in banks %}
              <span>
                <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ bank | bank_code_by_name | payment_new_logo }}" class="card-img card-img-big lazyload" alt="{{ bank }}">
              </span>
            {% endfor %}
          </div>
          <div class="divider"></div>
        </div>
      {% endfor %}
    {% endif %}

    {# Installments with interest in one module #}

    {% if gateways.cc.interest is not null %}
      <div>

        {# Installment amount #}

        <h4 class="font-weight-normal mb-1">
          {{ gateways.max_with_interests ~ ' cuotas con otras tarjetas' | translate }}
        </h4>
        <h6 class="font-weight-normal mb-2">
          <span>{{ 'O en 1 pago de: ' | translate }}</span>
          <strong class="js-installments-one-payment">{{ product.price | money }}</strong>
        </h6>

        {# Banks with installments with interest flags #}

        {% for bank in gateways.cc.interest %}
          <span class="js-installments-flag-tab js-installments-cash-tab">
            <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ bank | bank_code_by_name | payment_new_logo }}" class="lazyload card-img card-img-big" alt="{{ bank }}">
          </span>
        {% endfor %}
        <div class="divider"></div>
      </div>
    {% endif %}
  </div>
{% endif %}

{# Cash methods #}

{% if gateways.debit is not null or gateways.cash is not null or gateways.transfer is not null %}
  <h6 class="mb-1">{{'Tarjeta de débito y efectivo' | translate }}</h6>
  <div class="box">

    {# Debit card #}

    {% if gateways.debit is not null %}

      {# Debit price #}

      <h4 class="font-weight-normal mb-1">{{ 'Débito' | translate }}</h4>
      <h6 class="font-weight-normal mb-2">
        <span>{{ 'Precio:' | translate }} </span><strong class="js-installments-one-payment"> {{ product.price | money }}</strong>
      </h6>

      {# Debit flags #}

      {% for logo in gateways.debit %}
        <span data-type="dd" data-code="{{ card }}">
          <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ logo | payment_new_logo }}" class="lazyload card-img card-img-big">
        </span>
      {% endfor %}

      <div class="divider"></div>

    {% endif %}

    {# Cash #}

    {% if gateways.cash is not null %}

      {# Cash price #}

      <h4 class="font-weight-normal mb-1">{{'Efectivo' | translate }}</h4>
      <h6 class="font-weight-normal mb-2">
        <span>{{ 'Precio:' | translate }} </span><strong class="js-installments-one-payment"> {{ product.price | money }}</strong>
      </h6>

      {# Cash flags #}

      {% for logo in gateways.cash %}
        <span data-type="dd" data-code="{{ card }}">
          <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ logo | payment_new_logo }}" class="lazyload card-img card-img-big">
        </span>
      {% endfor %}

      <div class="divider"></div>

    {% endif %}

    {# Wire transfer #}

    {% if gateways.transfer is not null %}

      {# Transfer price #}

      <h4 class="font-weight-normal mb-1 ">{{ 'Transferencia o déposito' | translate }}</h4>
      <h6 class="font-weight-normal mb-2">
        <span>{{ 'Precio:' | translate }} </span><span class="js-installments-one-payment"> {{ product.price | money }}</span>
      </h6>

      {# Transfer logos #}

      {% for logo in gateways.transfer %}
        <span class="js-installments-flag-tab js-installments-cash-tab" data-type="dd" data-code="{{ card }}">
          <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ logo | payment_new_logo }}" class="lazyload card-img card-img-big">
        </span>
      {% endfor %}

      <div class="divider"></div>

    {% endif %}
  </div>
{% endif %}

Incluimos este tpl en el snipplet payments.tpl


payments-info.tpl

Este tpl muestra información sobre medios de pago que no dependen de un banco en Argentina, y también incluye una tabla con el detalle de las cuotas para medios de pago de Brasil.

{% set installments_data = installmentsv2['methods'][method] %}

{# Gateways without banks: cards only #}

{% if installments_data['cards'] %}

    {# Credit cards #}

    <h6 class="mb-1">{{'Tarjetas de crédito' | translate }}</h6>
    <div id="installment-credit-card-option-{{ method }}" class="box">

        {# Credit cards max installments only for AR stores #}

        {% if store.country == 'AR' %}

            {% if installments_data['max_without_interests'] != '0' %}
                <h4 class="font-weight-normal mb-1">
                    {{ installments_data['max_without_interests'] }}
                    {{ 'cuotas' | translate }}
                    <span>{{ 'sin interés' | t }}</span>
                    {{'de' | t}}
                    <strong class="js-modal-installment-price" data-installment="{{ installments_data['max_without_interests'] }}"> {{ (product.price / installments_data['max_without_interests']) | money }}</strong>
                </h4>
                <h6 class="font-weight-normal mb-2">
                    <span class="mr-1">
                        <span>{{ 'CFT: ' | translate }}</span><strong>0,00%</strong>
                    </span>
                    <span class="mr-1">
                        <span>{{ 'Total: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
                    </span>
                    <span class="mr-1">
                        <span>{{ 'En 1 pago: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
                    </span>
                </h6>
            {% elseif installments_data['max_with_interests'] > 0 %}
                <h4 class="font-weight-normal mb-1">
                    {{ 'Hasta' | translate }}
                    {{ installments_data['max_with_interests'] }}
                    {{ 'cuotas' | translate }}
                </h4>
                <h6 class="font-weight-normal mb-2">
                    <span>
                        <span>{{ 'O en 1 pago de: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
                    </span>
                </h6>
            {% else %}
                <h4 class="font-weight-normal mb-1">
                    <span>{{ 'En 1 pago: ' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
                </h4>
            {% endif %}

        {% endif %}

        {# Credit cards flags #}

        {% for logo in installments_data['cards'] %}
            <span class="mb-3">
                <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ logo | payment_new_logo }}" class="lazyload card-img card-img-medium">
            </span>
        {% endfor %}

        {% if store.country != 'AR' %}

            {# Installments list for non AR stores #}

            <table class="table">
                <thead>
                    <tr>
                        <th colspan="2">{{ 'Cuotas ' | translate }}</th>
                        <th class="text-right">{{ 'Total' | translate }}</th>
                    </tr>
                </thead>
                <tbody>
                    {% for installment, data_installment in installments %}
                        {% set rounded_installment_value = data_installment.installment_value | round(2) %}
                        {% set total_value = (data_installment.without_interests ? data_installment.total_value : installment * data_installment.installment_value) %}
                        {% set total_value_in_cents = total_value  | round(2) * 100 %}
                        <tr id="installment_{{ method }}_{{ installment }}">

                            {# Installment amount #}

                            <td>
                                <strong><span class="js-installment-amount">{{ installment }}</span></strong>
                                </span>{% if installment > 1 %}{{ 'cuotas' | translate }}{% else %}{{ 'cuota' | translate }}{% endif %}</span>
                            </td>

                            {# Installment price #}

                            <td>
                                <span>{{ 'de ' | translate }}</span>
                                <strong><span class="js-installment-price">{{ (rounded_installment_value * 100) | money }}</span> </strong>


                                {% if data_installment.without_interests or installments_data['max_with_interests'] == 0 %}
                                    {{ 'sin interés' | t }}
                                {% endif %}
                            </td>

                            {# Total price #}


                            <td class="js-installment-total-price text-right">
                                {{ total_value_in_cents | money }}
                            </td>
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        {% endif %}
    </div>
{% endif %}

{# Cash methods #}

{% if installments_data['direct'] %}

    {# Cash module title #}

    <h6 class="mb-1">
        {% if store.country == 'BR' %}
            {% if wording_method_only_cash %}
                {{'Efectivo' | translate }}
            {% elseif wording_method_only_debit %}
                {{'Débito online' | translate }}
            {% else %}
                {{'Efectivo / Débito online' | translate }}
            {% endif %}
        {% else %}
            {{'Tarjeta de débito y efectivo' | translate }}
        {% endif %}
    </h6>

    {# If has debit card or cash #}

    <div id="installment-cash-option-{{ method }}" class="box">

        {# Cash flags #}

        <div class="">
            {% for logo in installments_data['direct'] %}
                <span>
                    <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ logo | payment_new_logo }}" class="lazyload card-img card-img-medium">
                </span>
            {% endfor %}
        </div>

        {# Cash total #}

        <h4 class="font-weight-normal mb-0">
            <span>{{ 'Total:' | translate }}</span><strong class="js-installments-one-payment">{{ product.price | money }}</strong>
        </h4>

        {# Boleto message #}

        {% if method in ['boleto_paghiper'] and discount > 0.0 %}
            <div> {{'Boleto Paghiper tiene un' | translate }} <strong>{{discount}}% {{'de descuento' | translate }}</strong> {{'que será aplicado sobre el costo total de la compra al finalizar la misma.' | translate }}</div>
        {% endif %}
    </div>
{% endif %}

Incluimos este tpl en el snipplet payments.tpl

Product

Dentro de la carpeta Product encontramos todos los snipplets en relación al detalle del producto.

product-form.tpl

En este snipplet está el código del formulario de producto donde incluimos:

  • El nombre
  • El precio
  • El texto de promociones
  • Las cuotas y el link para ver más sobre medios de pago
  • Las variantes
  • El botón de comprar
  • El calculador de envíos y los locales

Además de estos archivos, por fuera del formulario de HTML pero aún dentro de product-form.tpl también encontramos:

  • El popup con el detalle de medios de pago
  • Los links para compartir en redes sociales
  • La descripción del producto subida desde el Administrador nube.

El JavaScript en relación a este formulario podés encontrarlo dentro de store.js.tpl

{# Product name and breadcrumbs #}

<div itemprop="name">
    {% embed "snipplets/page-header.tpl" %}
        {% block page_header_text %}{{ product.name }}{% endblock page_header_text %}
    {% endembed %}
</div>

{# Product price #}

<div class="price-container text-center text-md-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 product_can_show_installments or (product.promotional_offer and not product.promotional_offer.script.is_percentage_off) %}mb-2{% endif %}" {% 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>
    <span class="d-inline-block">
        <h4 class="js-price-display {% if product_can_show_installments or (product.promotional_offer and not product.promotional_offer.script.is_percentage_off) %}mb-2{% endif %}" 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 }}" />
        {% set schema_org_availability = "http://schema.org/#{ product.stock ? 'InStock' : 'OutOfStock' }" %}
        <meta itemprop="availability" href="{{ schema_org_availability }}" content="{{ schema_org_availability }}" />
    {% endif %}
</div>

{# Promotional text #}

{% if product.promotional_offer and not product.promotional_offer.script.is_percentage_off and product.display_price %}
    <div class="js-product-promo-container text-center text-md-left">
        {% if product.promotional_offer.script.is_discount_for_quantity %}
            {% for threshold in product.promotional_offer.parameters %}
                <h4 class="mb-2"><strong>{{ "¡{1}% OFF comprando {2} o más!" | translate(threshold.discount_decimal_percentage * 100, threshold.quantity) }}</strong></h4>
            {% endfor %}
        {% else %}
            <h4 class="mb-2"><strong>{{ "¡Llevá {1} y pagá {2}!" | translate(product.promotional_offer.script.quantity_to_take, product.promotional_offer.script.quantity_to_pay) }}</strong></h4> 
        {% endif %}
        {% if product.promotional_offer.scope_type == 'categories' %}
            <p>{{ "Válido para" | translate }} {{ "este producto y todos los de la categoría" | translate }}:  
            {% for scope_value in product.promotional_offer.scope_value_info %}
               {{ scope_value.name }}{% if not loop.last %}, {% else %}.{% endif %}
            {% endfor %}</br>{{ "Podés combinar esta promoción con otros productos de la misma categoría." | translate }}</p>
        {% elseif product.promotional_offer.scope_type == 'all'  %}
            <p>{{ "Vas a poder aprovechar esta promoción en cualquier producto de la tienda." | translate }}</p>
        {% endif %}  
    </div> 
{% endif %}

{# Product installments #}

{% include "snipplets/payments/installments.tpl" with {'product_detail' : true} %}

{# Product form, includes: Variants, CTA and Shipping calculator #}

 <form id="product_form" class="js-product-form" method="post" action="{{ store.cart_url }}">
    <input type="hidden" name="add_to_cart" value="{{product.id}}" />
     {% if product.variations %}
        {% include "snipplets/product/product-variants.tpl" %}
    {% endif %}

    {% if product.available and product.display_price %}
        {% include "snipplets/product/product-quantity.tpl" %}
    {% endif %}
    {% set state = store.is_catalog ? 'catalog' : (product.available ? product.display_price ? 'cart' : 'contact' : 'nostock') %}
    {% set texts = {'cart': "Agregar al carrito", 'contact': "Consultar precio", 'nostock': "Sin stock", 'catalog': "Consultar"} %}
    <input type="submit" class="js-addtocart js-prod-submit-form btn btn-primary btn-block mb-4 {{ state }}" value="{{ texts[state] | translate }}" {% if state == 'nostock' %}disabled{% endif %} />

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

        <div class="divider"></div>

        {# 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>
        <div class="divider"></div>
    {% endif %} 
 </form>

{# Product payments details #}

{% include 'snipplets/payments/payments.tpl' %}

{# Product share #}

{% include 'snipplets/social/social-share.tpl' %}

{# Product description #}

{% if product.description is not empty %}
    <div class="product-description user-content">
        <h5 class="my-3">{{ "Descripción" | translate }}</h5>
        {{ product.description }}
    </div>
{% endif %}

Incluimos este tpl en el template product.tpl

product-image.tpl

Dentro de product-image.tpl está la imagen del producto, los carteles de oferta, stock y envío graits; y un placeholder de vectores que se muestra hasta que el slider que muestra la imagen esté cargado.

En este snipplet también incluimos las clases necesarias para el zoom con Fancybox así como la implementación para lazy load con Lazysizes.

El JavaScript en relación al slider y el zoom podés encontrarlo dentro de store.js.tpl

{% if product.images_count > 0 %}
    <div class="js-swiper-product nube-slider-product swiper-container" style="visibility:hidden; height:0;">
        {% include 'snipplets/labels.tpl' with {'product_detail': true} %}
        <div class="swiper-wrapper">
            {% for image in product.images %}
             <div class="swiper-slide js-product-slide slider-slide" data-image="{{image.id}}" data-image-position="{{loop.index0}}">
                 <a href="{{ image | product_image_url('huge') }}" data-fancybox="product-gallery" class="d-block p-relative" style="padding-bottom: {{ image.dimensions['height'] / image.dimensions['width'] * 100}}%;">
                     <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-srcset='{{  image | product_image_url('large') }} 480w, {{  image | product_image_url('huge') }} 640w' data-sizes="auto" class="js-product-slide-img product-slider-image img-absolute img-absolute-centered lazyautosizes lazyload" />
                     <img src="{{ image | product_image_url('tiny') }}" class="js-product-slide-img product-slider-image img-absolute img-absolute-centered blur-up" />
                </a>
             </div>
            {% endfor %}
        </div>
        <div class="js-swiper-product-pagination swiper-pagination swiper-pagination-white"></div>
        {% if product.images_count > 1 %}
            <div class="js-swiper-product-prev swiper-button-prev d-none d-md-block">{% include "snipplets/svg/chevron-left.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
            <div class="js-swiper-product-next swiper-button-next d-none d-md-block">{% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
        {% endif %}
    </div>
    {% snipplet 'placeholders/product-detail-image-placeholder.tpl' %}
{% endif %}

Incluimos este tpl en el template product.tpl


product-quantity.tpl

Como su nombre indica, en este tpl está el código para la cantidad de unidades a agregar al carrito.

El JavaScript en relación a la cantidad podes encontrarlo dentro de store.js.tpl

{# Product quantity #}
        
<div class="row">
    <div class="col col-md-4">
        {% embed "snipplets/forms/form-input.tpl" with{type_number: true, input_value: '1', input_name: 'quantity' ~ item.id, input_custom_class: 'js-quantity-input text-center', input_label: false, input_append_content: true, input_group_custom_class: 'js-quantity form-row align-items-center', form_control_container_custom_class: 'col-6', input_min: '1'} %}
            {% block input_prepend_content %}
                <span class="js-quantity-down col-3 text-center">
                    {% include "snipplets/svg/minus.tpl" with {svg_custom_class: "icon-inline icon-w-12 icon-lg svg-icon-text"} %}
                </span>
            {% endblock input_prepend_content %}
            {% block input_append_content %}
                <span class="js-quantity-up col-3 text-center">
                    {% include "snipplets/svg/plus.tpl" with {svg_custom_class: "icon-inline icon-w-12 icon-lg svg-icon-text"} %}
                </span>
            {% endblock input_append_content %}
        {% endembed %}
    </div>
</div>

Incluimos este tpl en el snipplet product-form.tpl

product-variants.tpl

En este archivo listamos todas las variantes de un producto (un máximo de 3) y sus propiedades en forma de un select.

El JavaScript en relación a la cantidad encontrarlo dentro de store.js.tpl

<div class="js-product-variants form-row">
    {% for variation in product.variations %}
        <div class="{% if loop.length == 3 %} col-12 col-md-4 {% elseif loop.length == 2 %} col-6 {% else %} col col-md-6{% endif %}">
            {% embed "snipplets/forms/form-select.tpl" with{select_label: true, select_label_name: '' ~ variation.name ~ '', select_for: 'variation_' ~ loop.index , select_id: 'variation_' ~ loop.index, select_name: 'variation' ~ '[' ~ variation.id ~ ']', select_custom_class: 'js-variation-option js-refresh-installment-data'} %}
                {% block select_options %}
                    {% for option in variation.options %}
                        <option value="{{ option.id }}" {% if product.default_options[variation.id] == option.id %}selected="selected"{% endif %}>{{ option.name }}</option>
                    {% endfor %}
                {% endblock select_options%}
            {% endembed %}
        </div>
    {% endfor %}
</div>

Incluimos este tpl en el snipplet product-form.tpl


product-related.tpl 

En este snipplet tenemos la funcionalidad de productos relacionados los cuales se muestran en un slider.

El JavaScript del slider de productos relacionados podés encontrarlo dentro de store.js.tpl

{# /*============================================================================
  #Product Related Grid
==============================================================================*/

#Properties

#Related Slider

#}

{% set related_products_ids = product.metafields.related_products.related_products_ids %}
{% if related_products_ids %}
    {% set related_products = related_products_ids | get_products %}
    {% set show = (related_products | length > 0) %}
{% endif %}
{% if not show %}
    {% set related_products = category.products | shuffle | take(8) %}
    {% set show = (related_products | length > 1) %}
{% endif %}

<section id="related-products" class="section-products-related">
    {% if show %}
        <div class="container">
            <div class="row">
                {% if settings.products_related_title %}
                    <div class="col-12 text-center">
                        <h3>{{ settings.products_related_title }}</h3>
                    </div>
                {% endif %}
                <div class="col-12">
                    <div class="js-swiper-related swiper-container">
                        <div class="swiper-wrapper">
                            {% for related in related_products %}
                                {% if product.id != related.id %}
                                    {% include 'snipplets/grid/item.tpl' with {'product': related, 'slide_item': true} %}
                                {% endif %}
                            {% endfor %}
                        </div>
                        {% if related_products | length < 4 %}
                        <div class="d-md-none">
                        {% endif %}
                            <div class="js-swiper-related-pagination swiper-pagination"></div>
                            <div class="js-swiper-related-prev swiper-button-prev">{% include "snipplets/svg/chevron-left.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
                            <div class="js-swiper-related-next swiper-button-next">{% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
                        {% if related_products | length < 4 %}
                        </div>
                        {% endif %}
                    </div>
                </div>
            </div>
        </div>
    {% endif %}
</section>

Incluimos este tpl en el snipplet product-form.tpl

Header

Dentro de la carpeta header están todos los archivos en relación al head de la tienda, es decir la parte donde están la navegación, el logo, el buscador y el ícono del carrito.

header.tpl

Este es el tpl “padre” del header de la tienda donde además de lo mencionado anteriormente también tenemos el modal que muestra el carrito de compras, cart-panel.tpl, el cual se incluye usando un embed.

{# Site Overlay #}
<div class="js-overlay site-overlay" style="display: none;"></div>

{# Header #}

{% set show_transparent_head = template == 'home' and settings.head_transparent and settings.slider and not settings.slider is empty %}

<header class="js-head-main head-main {% if show_transparent_head %}head-transparent{% endif %} head-{{ settings.head_background }} {% if settings.head_fix %}head-fix{% endif %}">

    {# Advertising #}
    
    {% if settings.ad_bar and settings.ad_text %}
        {% snipplet "header/header-advertising.tpl" %}
    {% endif %}

    <div class="container">
        <div class="row no-gutters align-items-center">
            <div class="col">{% snipplet "navigation/navigation.tpl" %}</div>
            <div class="col text-center">{% snipplet "header/header-logo.tpl" %}</div>
            <div class="col text-right">{% snipplet "header/header-utilities.tpl" %}</div>
        </div>
    </div>    
    {% include "snipplets/notification.tpl" with {order_notification: true, add_to_cart: true} %}
</header>

{# Hamburger panel #}

{% embed "snipplets/modal.tpl" with{modal_id: 'nav-hamburger',modal_class: 'nav-hamburger modal-docked-small', modal_position: 'left', modal_transition: 'fade', modal_width: 'full'  } %}
    {% block modal_body %}
        {% snipplet "navigation/navigation-panel.tpl" %}
    {% endblock %}
{% endembed %}

{# Modal Search #}


{% embed "snipplets/modal.tpl" with{modal_id: 'nav-search', modal_position: 'right', modal_transition: 'slide', modal_width: 'docked-md' } %}
    {% block modal_body %}
        {% snipplet "header/header-search.tpl" %}
    {% endblock %}
{% endembed %}

{% if not store.is_catalog %}           

    {# Cart Ajax #}

    {% embed "snipplets/modal.tpl" with{modal_id: 'modal-cart', modal_position: 'right', modal_transition: 'slide', modal_width: 'docked-md', modal_form_action: store.cart_url, modal_form_class: 'js-ajax-cart-panel' } %}
        {% block modal_head %}
            {% block page_header_text %}{{ "Carrito de Compras" | translate }}{% endblock page_header_text %}
        {% endblock %}
        {% block modal_body %}
            {% snipplet "cart-panel.tpl" %}
        {% endblock %}
    {% endembed %}

{% endif %}

Incluímos este tpl en el template layout.tpl

header-advertising.tpl

En este tpl tenemos el código en relación a una barra de anuncio donde la persona que administra la tienda puede agregar un texto con un link. 

<section class="section-advertising">
    <div class="container">
        <div class="row-fluid">
            <div class="col text-center">
                   {% if settings.ad_bar and settings.ad_text %}
                       {% if settings.ad_url %}
                        <a class="link-contrast" href="{{ settings.ad_url }}">
                    {% endif %}  
                        {% if settings.ad_text %}
                            {{ settings.ad_text }}
                        {% endif %} 
                    {% if settings.ad_url %}
                        </a>
                    {% endif %}  
                {% endif %}           
            </div>
        </div>
    </div>
</section>

Incluimos este tpl en el snipplet header.tpl

header-logo.tpl

En este archivo tenemos el logo de la tienda, tanto cuando la tienda tiene una imagen cargada como cuando no y mostramos su nombre. 

<div id="logo" class="logo-img-container {% if not has_logo %}hidden{% endif %}">
    {{ store.logo('medium') | img_tag(store.name, {class: 'logo-img  transition-soft-slow'}) | a_tag(store.url) }}
</div>
<div id="no-logo" class="logo-text-container {% if has_logo %} hidden{% endif %}">
    <a class="logo-text h1" href="{{ store.url }}">{{ store.name }}</a>
</div>

Incluimos este tpl en el snipplet header.tpl y en el template password.tpl

header-search-results.tpl

Este snipplet lo usamos para mostrar sugerencias cuando el usuario busca productos. Muestra imagen, nombre, precio y cuotas de los productos sugeridos; así como un link para ir a la página de resultados de búsqueda donde mostramos todos los resultados.

Mostramos hasta 6 sugerencias dentro de este archivo pero pueden modificarse cambiando la variable search_suggestions.

<ul class="search-suggest-list">
    {% set search_suggestions = products | take(6) %}
    {% for product in search_suggestions %}
        <li class="search-suggest-item container-fluid">
            <a href="{{ product.url }}" class="search-suggest-link row justify-content-md-center">
                <div class="search-suggest-image-container col-xs-auto">
                    {{ product.featured_image | product_image_url("tiny") | img_tag(product.featured_image.alt, {class: 'search-suggest-image'}) }}
                </div>
                <div class="search-suggest-text col">
                    <p class="search-suggest-name">
                        {{ product.name | highlight(query) }}
                    </p>
                    {% if product.display_price %}
                        <p>
                            {{ product.price | money }}

                            {% set product_can_show_installments = product.show_installments and product.display_price and product.get_max_installments.installment > 1 %}
                            {% if product_can_show_installments %}
                                {% set max_installments_without_interests = product.get_max_installments(false) %}
                                {% if store.country == 'AR' %}
                                    {% set max_installments_with_interests = product.get_max_installments %}
                                    {% if max_installments_with_interests %}
                                        <span>| {{ "Hasta <strong class='installment-amount'>{1}</strong> cuotas" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</span>
                                    {% endif %}
                                {% else %}
                                    {% if max_installments_without_interests and max_installments_without_interests.installment > 1 %}
                                        <span>| {{ "<strong class='installment-amount'>{1}</strong> cuotas sin interés de <strong class='installment-price'>{2}</strong>" | t(max_installments_without_interests.installment, max_installments_without_interests.installment_data.installment_value_cents | money) }}</span>
                                    {% else %}
                                        {% set max_installments_with_interests = product.get_max_installments %}
                                        {% if max_installments_with_interests %}
                                            <span>| {{ "<strong class='installment-amount'>{1}</strong> cuotas de <strong class='installment-price'>{2}</strong>" | t(max_installments_with_interests.installment, max_installments_with_interests.installment_data.installment_value_cents | money) }}</span>
                                        {% endif %}
                                    {% endif %}
                                {% endif %}
                            {% endif %}
                        </p>
                    {% endif %}
                </div>
                <div class="col-xs-auto">
                    {% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline search-suggest-icon"} %}
                </div>
            </a>
        </li>
    {% endfor %}
    <a href="#" class="js-search-suggest-all-link btn btn-primary d-block">{{ 'Ver todos los resultados' | translate }}</a>
</ul>

Es agregado dentro del div con la clase js-search-suggest usando JavaScript dentro del archivo store.js.tpl 

header-search.tpl

Este archivo representa al formulario de búsqueda que tiene un campo y un botón submit. Además de esto tiene un div con la clase js-search-suggest donde se inserta el tpl header-search-results.tpl que muestra las sugerencias de búsqueda.

<form class="js-search-container js-search-form" action="{{ store.search_url }}" method="get">
    <div class="form-group m-0">
        <input class="js-search-input form-control search-input" autocomplete="off" type="search" name="q" placeholder="{{ 'Buscar' | translate }}"/>
        <button type="submit" class="btn search-input-submit" value="">
            {% include "snipplets/svg/search.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
        </button>
    </div>
</form>
<div class="js-search-suggest search-suggest">
    {# AJAX container for search suggestions #}
</div>

Incluimos este tpl en el snipplet header.tpl

header-utilities.tpl

Dentro de este snipplet incluimos los iconos del head del theme, excepto el icono que abre la navegación (hamburger), ya que este está dentro del grupo de snipplets de la navegación.

<div class="utilities-container">
    <div class="utilities-item">
        <a href="#" class="js-modal-open js-toggle-search utilities-link" data-toggle="#nav-search">
            {% include "snipplets/svg/search.tpl" with {svg_custom_class: "icon-inline icon-w-16 svg-icon-text"} %}
        </a>
    </div>
    {% if not store.is_catalog %}    
    <div class="utilities-item">
        <div id="ajax-cart" class="cart-summary">
            <a href="#" {% if template != 'cart' %}class="js-modal-open js-toggle-cart"{% endif %} data-toggle="#modal-cart">
                {% include "snipplets/svg/shopping-bag.tpl" with {svg_custom_class: "icon-inline icon-w-14 svg-icon-text"} %}
                <span class="js-cart-widget-amount cart-widget-amount">{{ "{1}" | translate(cart.items_count ) }}</span>
            </a>
        </div>
    </div>
    {% endif %}
</div>

Incluimos este tpl en el snipplet header.tpl 

Footer

Footer.tpl

El footer del theme lo incluimos en este tpl, el cual incluye:

  • El formulario de newsletter, que es un snipplet en sí mismo
  • Los iconos (con links) de las redes sociales, que también tiene su propio snipplet
  • La navegación en el footer (contenido en su propio snipplet)
  • Los links de contacto (un snipplet usado también en la página de contacto)
  • Logos de medios de pago y envío
  • Información de copyright
  • Sellos personalizados, que son imágenes subidas por el administrador de la tienda en el footer

{% set has_social_network = store.facebook or store.twitter or store.google_plus or store.pinterest or store.instagram %} 
{% set has_footer_contact_info = store.phone or store.email or store.blog or store.address %}          


{% set has_footer_menu = settings.footer_menu %}
{% set has_payment_logos = settings.payments %}
{% set has_shipping_logos = settings.shipping %}
{% set has_shipping_payment_logos = has_payment_logos or has_shipping_logos %}
<footer class="js-hide-footer-while-scrolling display-when-content-ready">
    <div class="container">


        {% if template != 'password' %}


            {# Newsletter #}
            {% if settings.news_show %}
                {% include "snipplets/newsletter.tpl" %}
            {% endif %}

        {% endif %}
        
        {# Social #}
         {% if has_social_network %}
             <div class="row element-footer">
                 <div class="col text-center">{% include "snipplets/social/social-links.tpl" %}</div>
            </div>
        {% endif %}

        {% if template != 'password' %}

            {# Foot Nav #}
            {% if has_footer_menu %}
                <div class="row element-footer">
                     <div class="col text-center">{% include "snipplets/navigation/navigation-foot.tpl" %}</div>
                </div>
            {% endif %}

        {% endif %}

        {# Contact #}
         {% if has_footer_contact_info %}
             <div class="row element-footer">
                 <div class="col text-center">{% include "snipplets/contact-links.tpl" %}</div>
            </div>
        {% endif %}

        {# Logos Payments and Shipping #}
         {% if has_shipping_payment_logos %}
             <div class="row element-footer footer-payments-shipping-logos">
                 {% if has_payment_logos %}
                     <div class="col text-center">{% include "snipplets/logos-icons.tpl" with {'payments': true} %}</div>
                {% endif %}
                 <div class="w-100 my-2"></div>
                 {% if has_shipping_logos %}
                     <div class="col text-center">{% include "snipplets/logos-icons.tpl" with {'shipping': true} %}</div>
                 {% endif %}
            </div>
        {% endif %}

        <div class="row element-footer">
            <div class="col-md-6 text-center text-md-left">
                {#
                La leyenda que aparece debajo de esta linea de código debe mantenerse
                con las mismas palabras y con su apropiado link a Tienda Nube;
                como especifican nuestros términos de uso: http://www.tiendanube.com/terminos-de-uso .
                Si quieres puedes modificar el estilo y posición de la leyenda para que se adapte a
                tu sitio. Pero debe mantenerse visible para los visitantes y con el link funcional.
                Os créditos que aparece debaixo da linha de código deverá ser mantida com as mesmas
                palavras e com seu link para Nuvem Shop; como especificam nossos Termos de Uso:
                http://www.nuvemshop.com.br/termos-de-uso. Se você quiser poderá alterar o estilo
                e a posição dos créditos para que ele se adque ao seu site. Porém você precisa
                manter visivél e com um link funcionando.
                #}
                {{ new_powered_by_link }}
            </div>
            <div class="col-md-6 copyright text-center text-md-right pt-4 pt-md-0">
                {{ "Copyright {1} - {2}. Todos los derechos reservados." | translate( (store.business_name ? store.business_name : store.name) ~ (store.business_id ? ' - ' ~ store.business_id : ''), "now" | date('Y') ) }}
            </div>
        </div>

        {# AFIP - EBIT - Custom Seal #}
        {% if store.afip or ebit or settings.custom_seal_code or ("seal_img.jpg" | has_custom_image) %}
            {% if store.afip or ebit %}
                <div class="row element-footer">
                     <div class="col text-center">
                         {% if store.afip %}
                            <div class="footer-logo afip seal-afip">
                                {{ store.afip | raw }}
                            </div>
                        {% endif %}
                        {% if ebit %}
                            <div class="footer-logo ebit seal-ebit">
                                {{ ebit }}
                            </div>
                        {% endif %}
                     </div>
                 </div>
             {% endif %}
             {% if "seal_img.jpg" | has_custom_image or settings.custom_seal_code %}
                <div class="row element-footer">
                     <div class="col text-center">
                        {% if "seal_img.jpg" | has_custom_image %}
                            <div class="footer-logo custom-seal">
                                {% if settings.seal_url != '' %}
                                    <a href="{{ settings.seal_url }}" target="_blank">
                                {% endif %}
                                    <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ "seal_img.jpg" | static_url }}" class="custom-seal-img lazyload" alt="Empty placeholder"/>
                                {% if settings.seal_url != '' %}
                                    </a>
                                {% endif %}
                            </div>
                        {% endif %}
                        {% if settings.custom_seal_code %}
                            <div class="custom-seal custom-seal-code">
                                {{ settings.custom_seal_code | raw }}
                            </div>
                        {% endif %}
                    </div>
                </div>
            {% endif %}
        {% endif %}
    </div>
</footer>

Incluimos este tpl en los templates layout.tpl y password.tpl

Navigation

navigation.tpl

En este tpl incluimos el ícono que abre el modal de navegación

<div class="utilities-container">
    <div class="utilities-item">
        <a href="#" class="js-modal-open utilities-link" data-toggle="#nav-hamburger">
            {% include "snipplets/svg/bars.tpl" with {svg_custom_class: "icon-inline icon-w-14 svg-icon-text"} %}
        </a>
    </div>
</div>

Incluimos este tpl en el snipplet header.tpl 

navigation-panel.tpl

Este tpl muestra el contenido del modal donde tenemos los links a las páginas y categorías, para logearse, crear una cuenta y para cambiar el idioma de la tienda.

Dentro de este archivo llamamos al snipplet para el listado de links navigation-nav-list.tpl.

<div class="nav-primary">
    <ul class="nav-list">
        {% snipplet "navigation/navigation-nav-list.tpl" %}
    </ul>
</div>
<div class="nav-secondary">
    {% if languages | length > 1 %}
        <div class="languages">
            {% for language in languages %}
                {% set class = language.active ? "" : "opacity-50" %}
                <a href="{{ language.url }}" class="{{ class }}">{{ language.country | flag_url | img_tag(language.name) }}</a>
            {% endfor %}
        </div>
    {% endif %}
    <ul class="nav-account">
        {% if not customer %}
            {% if store.customer_accounts != 'mandatory' %}
            <li class="nav-accounts-item">{{ "Crear cuenta" | translate | a_tag(store.customer_register_url, '', 'nav-accounts-link') }}</li>
            {% endif %}
            <li class="nav-accounts-item">{{ "Iniciar sesión" | translate | a_tag(store.customer_login_url, '', 'nav-accounts-link') }}</li>
        {% else %}
            <li class="nav-accounts-item">{{ "Mi cuenta" | translate | a_tag(store.customer_home_url, '', 'nav-accounts-link') }}</li>
            <li class="nav-accounts-item">{{ "Cerrar sesión" | translate | a_tag(store.customer_logout_url, '', 'nav-accounts-link') }}</li>
        {% endif %}
    </ul>
</div>

Incluimos este tpl en el snippler header.tpl

navigation-nav-list.tpl

Este es el for que itera o recorre todos los links dentro del Menú Principal de una tienda. En este archivo mezclamos las dos cosas en un solo for, tanto páginas como categorías.

 

{% for item in navigation %}
    {% if item.subitems %}
        <li class="item-with-subitems">
            <div class="js-nav-list-toggle-accordion">
                <a class="nav-list-link" href="{{ item.url }}">{{ item.name }}</a>
                <span class="js-toggle-page-accordion nav-list-arrow transition-soft">
                    {% include "snipplets/svg/chevron-down.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
                </span>
            </div>
            <ul class="js-pages-accordion list-subitems nav-list-accordion" style="display:none;">
                {% snipplet "navigation/navigation-nav-list.tpl" with navigation = item.subitems %}
            </ul>
        </li>
    {% else %}
        <li>
            <a class="nav-list-link" href="{{ item.url }}">{{ item.name }}</a>
        </li>
    {% endif %}
{% endfor %}

Incluimos este tpl en el snipplet navigation-panel.tpl y dentro de si mismo navigation-nav-list.tpl

navigation-foot.tpl

Este snipplet muestra los links de la navegación del footer, la cual es elegida por el administrador de la tienda desde la sección de Personalizar el diseño actual.

<ul class="footer-menu m-0 p-0">
    {% for item in menus[settings.footer_menu] %}
        <li class="footer-menu-item my-4">
            <a class="footer-menu-link" href="{{ item.url }}" {% if item.url | is_external %}target="_blank"{% endif %}>{{ item.name }}</a>
        </li>
    {% endfor %}
</ul>

Incluimos este tpl en el snipplet footer.tpl 

Cart

cart-panel.tpl

Dentro de este archivo está el contenido del modal del carrito incluyendo el for que llama a los items del carrito, los mensajes para cuando el carrito está vacío o no hay más stock de un producto y se incluye el snipplet cart-totals.tpl

<div class="js-ajax-cart-list cart-row">
    {# Cart panel items #}
    {% if cart.items %}
      {% for item in cart.items %}
        {% include "snipplets/cart-item-ajax.tpl" %}
      {% endfor %}
    {% endif %}
</div>
<div class="js-empty-ajax-cart cart-row" {% if cart.items_count > 0 %}style="display:none;"{% endif %}>
     {# Cart panel empty #}
    <div class="alert alert-info">{{ "El carrito de compras está vacío." | translate }}</div>
</div>
<div id="error-ajax-stock" style="display: none;">
    <div class="alert alert-warning">
         {{ "¡Uy! No tenemos más stock de este producto para agregarlo al carrito. Si querés podés" | translate }}<a href="{{ store.products_url }}" class="btn-link ml-1">{{ "ver otros acá" | translate }}</a>
    </div>
</div>
<div class="cart-row">
    {% include "snipplets/cart-totals.tpl" %}
</div>

Incluimos este tpl en el snipplet header.tpl 

cart-item-ajax.tpl

Este es el item de cada producto que se agrega al carrito, no solo se usa para el carrito en su versión “popup”, sino también en la página de Carrito de compras. 

Si  bien el theme Base no muestra por defecto el carrito de compras en su versión “página”, tiene el template cart.tpl listo para ser usado. 

Este item muestra:

  • Una imágen del producto agregado
  • Su nombre y variante
  • Su precio
  • Un botón para removerlo del carrito
  • Los controles para aumentar o disminuir la cantidad

<div class="js-cart-item cart-item form-row" data-item-id="{{ item.id }}">

  {# Cart item image #}
  <div class="col-2 {% if cart_page %}col-md-1{% endif %}">
    <img src="{{ item.featured_image | product_image_url('medium') }}" class="img-fluid" />
  </div>
  <div class="col-10 {% if cart_page %}col-md-11{% endif %}">

    {# Cart item name #}
    <div class="cart-item-name">
      <a href="{{ item.url }}">
        {{ item.short_name }}
      </a>
      <small>{{ item.short_variant_name }}</small>
    </div>

    {# Cart item quantity controls #}
    <span class="pull-left">
      <button type="button" class="js-cart-quantity-btn cart-item-btn btn" onclick="LS.minusQuantity({{ item.id }}{% if not cart_page %}, true{% endif %})">
        {% include "snipplets/svg/minus.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
      </button>
      <span>
        <input type="number" name="quantity[{{ item.id }}]" data-item-id="{{ item.id }}" value="{{ item.quantity }}" class="js-cart-quantity-input cart-item-input form-control"/>
      </span>
      <span class="js-cart-input-spinner cart-item-spinner" style="display: none;">
        {% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-spin svg-icon-text"} %}
      </span>
      <button type="button" class="js-cart-quantity-btn cart-item-btn btn" onclick="LS.plusQuantity({{ item.id }}{% if not cart_page %}, true{% endif %})">
        {% include "snipplets/svg/plus.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
      </button>
    </span>

    {# Cart item subtotal mobile #}
    <h6 class="js-cart-item-subtotal cart-item-subtotal" data-line-item-id="{{ item.id }}">{{ item.subtotal | money }}</h6>
  </div>

  {# Cart item delete #}
  <div class="col-1 cart-item-delete text-right">
    <button type="button" class="btn" onclick="LS.removeItem({{ item.id }}{% if not cart_page %}, true{% endif %})">
      {% include "snipplets/svg/trash-alt.tpl" with {svg_custom_class: "icon-inline icon-lg svg-icon-text"} %}
    </button>
  </div>
</div>

Incluimos este tpl en el snipplet cart-panel.tpl y en el template cart.tpl. No es posible cambiar su nombre o su ubicación debido a que es usado desde el backend.


cart-totals.tpl

Este snipplet incluye:

  • El subtotal del carrito, que no incluye el costo de envío ni promociones
  • El calculador de envíos
  • Los locales físicos  (no aplica en Brasil)
  • El mensaje de promociones, por ejemplo 2x1
  • El total del carrito que incluye el costo de envío y promociones
  • Las cuotas en base al total, solo aplica en Brasil
  • El botón para finalizar la compra
  • El link para continuar comprando

También usamos la condición {% if cart_page %} ya que el snipplet es usado tanto para el carrito en su formato modal o popup, como en su formato “página”.

{# IMPORTANT Do not remove this hidden subtotal, it is used by JS to calculate cart total #}
<div class="subtotal-price hidden" data-priceraw="{{ cart.subtotal }}"></div>

{# Used to assign currency to total #}
<div id="store-curr" class="hidden">{{ cart.currency }}</div>
    
{# Cart panel subtotal #}
<h5 class="js-visible-on-cart-filled {% if not cart_page %}row{% else %}text-right{% endif %} mb-1 {% if cart_page %}text-center-xs{% endif %}" {% if cart.items_count == 0 %}style="display:none;"{% endif %}>
  <span {% if not cart_page %}class="col"{% endif %}>
    {{ "Subtotal" | translate }}
    {% if settings.shipping_calculator_cart_page %}
      <small>{{ " (sin envío)" | translate }}</small>
    {% endif %}
    :
  </span>
  <strong class="js-ajax-cart-total js-cart-subtotal {% if not cart_page %}col{% endif %} text-right" data-priceraw="{{ cart.subtotal }}">{{ cart.subtotal | money }}</strong>
</h5>

{# Cart panel promos #}
<div class="js-total-promotions">
  <span class="js-promo-title" style="display:none;">{{ "Promo" | translate }}</span>
  <span class="js-promo-in" style="display:none;">{{ "en" | translate }}</span>
  <span class="js-promo-all" style="display:none;">{{ "todos los productos" | translate }}</span>
  <span class="js-promo-buying" style="display:none;"> {{ "comprando" | translate }}</span>
  <span class="js-promo-units-or-more" style="display:none;"> {{ "o más" | translate }}</span>
  {% for promotion in cart.promotional_discount.promotions_applied %}
    {% if(promotion.scope_value_id) %}
      {% set id = promotion.scope_value_id %}
    {% else %}
      {% set id = 'all' %}
    {% endif %}
      <span class="js-total-promotions-detail-row row" id="{{ id }}">
        <span class="col">
          {% if promotion.discount_script_type == "NAtX%off" %}
            {{ promotion.selected_threshold.discount_decimal_percentage * 100 }}% OFF
          {% else %}
            {{ "Promo" | translate }} {{ promotion.discount_script_type }} 
          {% endif %}

          {{ "en" | translate }} {% if id == 'all' %}{{ "todos los productos" | translate }}{% else %}{{ promotion.scope_value_name }}{% endif %}

          {% if promotion.discount_script_type == "NAtX%off" %}
            <span>{{ "Comprando {1} o más" | translate(promotion.selected_threshold.quantity) }}</span>
          {% endif %}
          :
        </span>
        <span class="col text-right">-{{ promotion.total_discount_amount_short }}</span>
      </span>
  {% endfor %}
</div>

{% 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 %}

{# Cart panel total #}


<div class="js-cart-total-container js-visible-on-cart-filled mb-3" {% if cart.items_count == 0 %}style="display:none;"{% endif %}>
  <h2 class="{% if not cart_page %}row{% else %}text-right{% endif %} text-primary mb-0">
    <span {% if not cart_page %}class="col"{% endif %}>{{ "Total" | translate }}:</span>
    <span class="js-cart-total {% if cart.shipping_data.selected %}js-cart-saved-shipping{% endif %} {% if not cart_page %}col{% endif %} text-right">{{ cart.total | money }}</span>
  </h2>

  {# IMPORTANT Do not remove this hidden total, it is used by JS to calculate cart total #}
  <div class='total-price hidden'>
    {{ "Total" | translate }}: {{ cart.total | money }}
  </div>
  {% include "snipplets/payments/installments.tpl" with {'product': false} %}
</div>

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

  {# No stock alert #}

  <div id="error-ajax-stock" class='alert alert-warning' role='alert' style="display:none;">
     {{ "¡Uy! No tenemos más stock de este producto para agregar este producto al carrito. Si querés podés" | translate }}<a href="{{ store.products_url }}" class="btn-link">{{ "ver otros acá" | translate }}</a>
  </div>
  <div>
    {% if cart_page %}
    <div class="row justify-content-end">
      <div class="col col-md-3">
    {% endif %}

    {# Cart panel CTA #}
    
    {% set cart_total = (settings.cart_minimum_value * 100) %}

    <div class="js-ajax-cart-submit row mb-3" {{ cart.total < cart_total ? 'style="display:none"' }} id="ajax-cart-submit-div">
      <input class="btn btn-primary btn-block" type="submit" name="go_to_checkout" value="{{ 'Iniciar Compra' | translate }}"/>
    </div>

    {# Cart panel continue buying link #}

    {% if settings.continue_buying %}
      <div class="row mb-2">
        <div class="text-center w-100">
          <a href="#" class="js-modal-close btn btn-link">{{ 'Seguir comprando' | translate }}</a>
        </div>
      </div>
    {% endif %}

    {# Cart minium alert #}

    <div class="js-ajax-cart-minimum alert alert-warning mt-4" {{ cart.total >= cart_total ? 'style="display:none"' }} id="ajax-cart-minumum-div">
      {{ "El monto mínimo de compra (subtotal) es de" | translate }} {{ cart_total | money }}
    </div>
    <input type="hidden" id="ajax-cart-minimum-value" value="{{ cart_total }}"/>
    {% if cart_page %}
    </div>
    </div>
    {% endif %}
  </div>
</div>

Incluimos este tpl en el snipplet cart-panel.tpl y el template cart.tpl 


Home

Todos los archivos dentro de la carpeta home hacen referencia a las funcionalidades de la página inicial de la tienda. Estas son:

  • Banners (con imágen, texto y un botón)
  • Productos destacados
  • Feed de Instagram
  • Módulos con imágen y texto
  • Slider de imágenes
  • Video
  • Mensaje de bienvenida


home-banners.tpl

Como dice su nombre, son banners dentro de la página inicial (hasta 4)  y, como los módulos de imágen y texto, muestran una imagen, un título, un párrafo y un botón (con un link).

<section class="section-banners-home">
    <div class="container{% if settings.banners_full %}-fluid p-0{% endif %}">
        <div class="row {% if settings.banners_full %}no-gutters{% endif %} align-items-center">
            {% set num_banners = 0 %}
            {% for banner in ['banner_01', 'banner_02', 'banner_03'] %}
                {% set banner_show = attribute(settings,"#{banner}_show") %}
                {% set banner_title = attribute(settings,"#{banner}_title") %}
                {% set banner_button_text = attribute(settings,"#{banner}_button") %}
                {% set has_banner =  banner_show and (banner_title or banner_description or "#{banner}.jpg" | has_custom_image) %}
                {% if has_banner %}
                    {% set num_banners = num_banners + 1 %}
                {% endif %}
            {% endfor %}

            {% for banner in ['banner_01', 'banner_02', 'banner_03'] %}
                {% set banner_show = attribute(settings,"#{banner}_show") %}
                {% set banner_title = attribute(settings,"#{banner}_title") %}
                {% set banner_description = attribute(settings,"#{banner}_description") %}
                {% set banner_button_text = attribute(settings,"#{banner}_button") %}
                {% set banner_url = attribute(settings,"#{banner}_url") %}
                {% set has_banner =  banner_show and (banner_title or banner_description or "#{banner}.jpg" | has_custom_image) %}
                {% set has_banner_text =  banner_title or banner_description or banner_button_text %}
                {% if has_banner %}
                    <div class="col-md">
                        <div class="textbanner">
                            {% if banner_url %}
                                <a class="textbanner-link" href="{{ banner_url }}"{% if banner_title %} alt="{{ banner_title }}" title="{{ banner_title }}"{% endif %}>
                            {% endif %}
                            {% if store.thumbnails_enabled %}
                                <div class="textbanner-image{% if has_banner_text and textoverimage %} overlay{% endif %} lazyautosizes lazyload blur-up"{% if "#{banner}.jpg" | has_custom_image %} data-bgset='{{ "#{banner}.jpg" | static_url | settings_image_url('large') }} 480w, {{ "#{banner}.jpg" | static_url | settings_image_url('huge') }} 640w' data-sizes="auto" style="background-image: url({{ "#{banner}.jpg" | static_url | settings_image_url('tiny') }});"{% endif %}>
                            {% else %}
                                <div class="textbanner-image{% if has_banner_text and textoverimage %} overlay{% endif %} lazyload blur-up"{% if "#{banner}.jpg" | has_custom_image %} data-bg='{{ "#{banner}.jpg" | static_url }}' style="background-image: url({{ "#{banner}.jpg" | static_url | settings_image_url('tiny') }});" {% endif %}>
                            {% endif %}
                            </div>
                            <div class="textbanner-text{% if textoverimage %} over-image{% endif %}">
                                {% if banner_title %}
                                    <div class="h1 textbanner-title">{{ banner_title }}</div>
                                {% endif %}
                                {% if banner_description %}
                                    <div class="textbanner-paragraph">{{ banner_description }}</div>
                                {% endif %}
                                {% if banner_url and banner_button_text %}
                                    <div class="btn btn-line btn-small">{{ banner_button_text }}</div>
                                {% endif %}
                            </div>
                            {% if banner_url %}
                                </a>
                            {% endif %}
                        </div>
                    </div>
                {% endif %}
            {% endfor %}
        </div>
    </div>
</section>

Incluimos este tpl en el template home.tpl 

home-featured-products.tpl 

En este tpl tenemos a al slider que muestra los productos relacionados en la página del detalle de un producto.

{# /*============================================================================
  #Home featured grid
==============================================================================*/

#Properties

#Featured Slider

#}

{% if sections.primary.products %}
    <section class="section-featured-home">
        <div class="container">
            <div class="row">
                {% if settings.featured_products_title %}
                    <div class="col-12 text-center">
                        <h3>{{ settings.featured_products_title }}</h3>
                    </div>
                {% endif %}
                <div class="col-12">
                    <div class="js-swiper-featured swiper-container">
                        <div class="swiper-wrapper">
                            {% for product in sections.primary.products %}
                                {% include 'snipplets/grid/item.tpl' with {'slide_item': true} %}
                            {% endfor %}
                        </div>
                        <div class="js-swiper-featured-pagination swiper-pagination"></div>
                        <div class="js-swiper-featured-prev swiper-button-prev d-none d-md-block">{% include "snipplets/svg/chevron-left.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
                        <div class="js-swiper-featured-next swiper-button-next d-none d-md-block">{% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-2x svg-icon-text"} %}</div>
                    </div>
                </div>
            </div>
        </div>
    </section>
{% endif %}

Incluimos este tpl en el template home.tpl 

home-instafeed.tpl

Acá incluimos todo lo que tiene que ver con notificaciones dentro del Storefront, las cuales por ahora son dos: el mensaje cuando un producto es agregado al carrito, y el mensaje cuando el usuario finalizó su compra y puede hacer un seguimiento.

{% if settings.video_embed %}
    <section class="section-video-home">
        <div class="container{% if settings.video_full %}-fluid p-0{% endif %}">
            <div class="row no-gutters">
                <div class="col">
                    <div class="js-video-home embed-responsive embed-responsive-16by9">
                        <div class="js-play-button video-player">
                            <div class="video-player-icon">
                                {% include "snipplets/svg/play-circle.tpl" with {svg_custom_class: "icon-inline icon-2x svg-icon-invert"} %}
                            </div>
                        </div>
                        <div class="js-video-image">
                            <img data-src="" class="lazyload js-lazy-loading img-fluid video-image">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
{% endif %}

Incluimos este tpl en el template home.tpl 

home-modules.tpl

Este tpl lo usamos para mostrar hasta 2 módulos que permiten mostrar una imágen (alineada a la izquierda o derecha en desktop), un título, un párrafo y un botón (con un link).

<section class="section-home-modules">
    <div class="container{% if settings.modules_full %}-fluid p-0{% endif %}">
        {% set num_modules = 0 %}
        {% for module in ['module_01', 'module_02'] %}
            {% set module_show = attribute(settings,"#{module}_show") %}
            {% set module_title = attribute(settings,"#{module}_title") %}
            {% set module_button_text = attribute(settings,"#{module}_button") %}
            {% set has_module =  module_show and (module_title or module_description or "#{module}.jpg" | has_custom_image) %}
            {% if has_module %}
                {% set num_modules = num_modules + 1 %}
            {% endif %}
        {% endfor %}

        {% for module in ['module_01', 'module_02'] %}
            {% set module_show = attribute(settings,"#{module}_show") %}
            {% set module_align = attribute(settings,"#{module}_align") %}
            {% set module_title = attribute(settings,"#{module}_title") %}
            {% set module_description = attribute(settings,"#{module}_description") %}
            {% set module_button_text = attribute(settings,"#{module}_button") %}
            {% set module_url = attribute(settings,"#{module}_url") %}
            {% set has_module =  module_show and (module_title or module_description or "#{module}.jpg" | has_custom_image) %}
            {% set has_module_text =  module_title or module_description or module_button_text %}
            {% if has_module %}
            <div class="row {% if settings.modules_full %}no-gutters{% endif %} align-items-center">               
                
                {% if banner_url %}
                    <a class="module-with-text-link" href="{{ module_url }}"{% if module_title %} alt="{{ module_title }}" title="{{ module_title }}"{% endif %}>
                {% endif %}
                    <div class="col-md {% if module_align == 'right' %}order-md-2{% endif %}">
                        <div class="textbanner">
                        {% if store.thumbnails_enabled %}
                            <div class="textbanner-image{% if has_banner_text and textoverimage %} overlay{% endif %} lazyautosizes lazyload blur-up"{% if "#{module}.jpg" | has_custom_image %} data-bgset='{{ "#{module}.jpg" | static_url | settings_image_url('large') }} 480w, {{ "#{module}.jpg" | static_url | settings_image_url('huge') }} 640w' data-sizes="auto" style="background-image: url({{ "#{module}.jpg" | static_url | settings_image_url('tiny') }});"{% endif %}>
                        {% else %}
                            <div class="textbanner-image{% if has_banner_text and textoverimage %} overlay{% endif %} lazyload blur-up"{% if "#{module}.jpg" | has_custom_image %} data-bg='{{ "#{module}.jpg" | static_url }}' style="background-image: url({{ "#{module}.jpg" | static_url | settings_image_url('tiny') }});" {% endif %}>
                        {% endif %}
                            </div>
                        </div>
                    </div>
                    <div class="col-md">
                        <div class="textbanner-text{% if textoverimage %} over-image{% endif %}">
                            {% if module_title %}
                                <div class="h1 textbanner-title">{{ module_title }}</div>
                            {% endif %}
                            {% if module_description %}
                                <div class="textbanner-paragraph">{{ module_description }}</div>
                            {% endif %}
                            {% if module_url and module_button_text %}
                                <div class="btn btn-primary btn-small">{{ module_button_text }}</div>
                            {% endif %}
                        </div>
                    </div>  
                {% if module_url %}
                    </a>
                {% endif %}


            </div>
            {% endif %}
        {% endfor %}
    </div>
</section>

Incluimos este tpl en el template home.tpl 

home-slider.tpl

Usamos este snipplet para el slider principal del Storefront, mostrado en la página de inicio.

<section class="js-home-slider-container section-slider {% if not settings.slider or settings.slider is empty %} hidden {% endif %}">
    <div class="js-home-slider nube-slider-home swiper-container" style="visibility:hidden; height:0;">
        <div class="swiper-wrapper">
            {% for slide in settings.slider %}
                <div class="swiper-slide slide-container">
                    {% if slide.link %}
                        <a href="{{ slide.link }}">
                    {% endif %}        
                        <div data-background="{{ slide.image | static_url | settings_image_url('1080p') }}" class="slider-slide swiper-lazy">
                        </div>
                        {% if not params.preview %}
                        <div style="background-image: url({{ slide.image | static_url | settings_image_url('tiny') }});" class="js-slider-preloader slider-slide preloader-bg-img"></div>
                        {% endif %}
                    {% if slide.link %}
                        </a>
                    {% endif %}
                </div>
            {% endfor %}
        </div>
        <div class="js-swiper-home-pagination swiper-pagination swiper-pagination-white"></div>
        <div class="js-swiper-home-prev swiper-button-prev d-none d-md-block">{% include "snipplets/svg/chevron-left.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-lg svg-icon-invert"} %}</div>
        <div class="js-swiper-home-next swiper-button-next d-none d-md-block">{% include "snipplets/svg/chevron-right.tpl" with {svg_custom_class: "icon-inline icon-w-8 icon-lg svg-icon-invert"} %}</div>
    </div>
    {% snipplet 'placeholders/home-slider-placeholder.tpl' %}
</section>

Incluimos este tpl en el template home.tpl 

home-video.tpl

Como su nombre dice, es un snipplet para la funcionalidad del video que se muestra en la página de inicio, la cual está lista para aceptar URLs de Youtube y Vimeo.

{% if settings.video_embed %}
    <section class="section-video-home">
        <div class="container{% if settings.video_full %}-fluid p-0{% endif %}">
            <div class="row no-gutters">
                <div class="col">
                    <div class="js-video-home embed-responsive embed-responsive-16by9">
                        <div class="js-play-button video-player">
                            <div class="video-player-icon">
                                {% include "snipplets/svg/play-circle.tpl" with {svg_custom_class: "icon-inline icon-2x svg-icon-invert"} %}
                            </div>
                        </div>
                        <div class="js-video-image">
                            <img data-src="" class="lazyload js-lazy-loading img-fluid video-image">
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
{% endif %}

Incluimos este tpl en el template home.tpl 

home-welcome-message.tpl

A través del home-welcome-message.tpl mostramos un mensaje de bienvenida compuesto por un título y un párrafo en la página inicial del Storefront.

{% if settings.welcome_message %}
    <section class="section-welcome-home">
        <div class="container">
            <div class="row">
                <div class="col-md-8 offset-md-2">
                    <h2 class="welcome-title">{{ settings.welcome_message }}</h2>
                    {% if settings.welcome_text %}
                        <p class="welcome-text">{{ settings.welcome_text }}</p>
                    {% endif %}
                </div>
            </div>
        </div>
    </section>
{% endif %}

Incluimos este tpl en el template home.tpl 

modal.tpl

Este snipplet representa a todos los popups o modales del theme, en este caso lo usamos para 5 partes:

  • Medios de pago
  • Navegación
  • Carrito de compras
  • Filtros
  • Búsqueda

Es un componente con parámetros que permiten agregar clases, Ids, definir cómo va a ser la animación del modal y desde que parte de la pantalla aparece, entre otras cosas. Para ver más detalles dentro del propio archivo están explicadas todas las propiedades.

{# /*============================================================================
  #Modal
==============================================================================*/
#Properties
    // ID
    // Position - Top, Right, Bottom, Left
    // Transition - Slide and Fade
    // Width - Full and Box
    // modal_form_action - For modals that has a form
#Head
    // Block - modal_head
#Body
    // Block - modal_body
#Footer
    // Block - modal_footer
#}

{% set modal_overlay = modal_overlay | default(true) %}

<div id="{{ modal_id }}" class="js-modal modal modal-{{ modal_class }} modal-{{modal_position}} transition-{{modal_transition}} modal-{{modal_width}} transition-soft" style="display: none;">
    {% if modal_form_action %}
    <form action="{{ modal_form_action }}" method="post" class="{{ modal_form_class }}">
    {% endif %}
    <div class="js-modal-close modal-header">
        <span class="modal-close">
            {% include "snipplets/svg/times.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
        </span>
        {% block modal_head %}{% endblock %}
    </div>
    <div class="modal-body">
        {% block modal_body %}{% endblock %}
    </div>
    {% if modal_footer %}
        <div class="modal-footer d-md-block">
            {% block modal_foot %}{% endblock %}
        </div>
    {% endif %}
    {% if modal_form_action %}
    </form>
    {% endif %}
</div>

Incluimos este tpl en los snipplets header.tpl, payments.tpl y category.tpl 

notification.tpl

Acá incluimos todo lo que tiene que ver con notificaciones dentro del Storefront, las cuales por ahora son dos: el mensaje cuando un producto es agregado al carrito, y el mensaje cuando el usuario finalizó su compra y un link a la página de seguimiento.

{# Order notification #}

{% if order_notification and status_page_url %}
    <div data-url="{{ status_page_url }}" class="js-notification notification notification-secondary" style="display:none;">
        <div class="container">
            <div class="row">
                <div class="col">
                    <span>{{ "Seguí acá" | translate | a_tag(status_page_url) }}</span> <span class="btn btn-link">{{ "tu última compra" | translate }}</span>
                    <a class="js-notification-close ml-2" href="#">
                        {% include "snipplets/svg/times.tpl" with {svg_custom_class: "icon-inline svg-icon-primary"} %}
                    </a>
                </div>
            </div>
        </div>
    </div>
{% endif %}

{# Add to cart notification #}

{% if add_to_cart %}
    <div class="js-alert-added-to-cart notification-floating notification-hidden" style="display: none;">
        <div class="js-toggle-cart notification notification-primary"> 
            {% include "snipplets/svg/shopping-bag.tpl" with {svg_custom_class: "icon-inline svg-icon-primary mr-1"} %}
            <span>{{ '¡Excelente! Ya agregamos tu producto al carrito.' | translate }}</span>
        </div>
    </div>
{% endif %}

Incluimos este tpl en el snipplet header.tpl

labels.tpl

Los labels son los carteles de oferta, promociones, sin stock y envío gratis que se muestran tanto en el item en la lista de productos como en el detalle del producto.

En este tpl usamos el condicional {% if product_detail %} para determinar si usamos o no JavaScript en detalle del producto cuando se cambian las variantes, por ejemplo cuando una de estas no tiene stock o tiene un precio diferente que impacta en el porcentaje de descuento.

{% 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 or product.promotional_offer %}
  <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 or product.promotional_offer %}
        <div class="{% if not product.promotional_offer and product %}js-offer-label{% endif %} label label-primary" {% if (not product.compare_at_price and not product.promotional_offer) or not product.display_price %}style="display:none;"{% endif %}>
          {% if product.promotional_offer.script.is_percentage_off %}
            {{ product.promotional_offer.parameters.percent * 100 }}% OFF
          {% elseif product.promotional_offer.script.is_discount_for_quantity %}
            <div>{{ product.promotional_offer.selected_threshold.discount_decimal_percentage * 100 }}% OFF</div>
            <div class="label-small p-right-quarter p-left-quarter">{{ "Comprando {1} o más" | translate(product.promotional_offer.selected_threshold.quantity) }}</div>
          {% elseif product.promotional_offer %}
            {% if store.country == 'BR' %}
              {{ "Leve {1} Pague {2}" | translate(product.promotional_offer.script.quantity_to_take, product.promotional_offer.script.quantity_to_pay) }}
            {% else %}
              {{ "Promo" | translate }} {{ product.promotional_offer.script.type }} 
            {% endif %}
          {% else %}
            <span {% if product_detail %}class="js-offer-percentage"{% endif %}>{{ price_discount_percentage |round }}</span>% OFF
          {% endif %}
        </div>
      {% endif %}
      {% if product.free_shipping %}
        <div class="label label-secondary">{{ "Envío gratis" | translate }}</div>
      {% endif %}
    {% endif %}
  </div>
{% endif %}

Incluimos este tpl en el snipplet product-image.tpl y item.tpl 

logos-icons.tpl

Son las banderas que muestran medios de pago y envío

{% if payments %}
    {% for payment in settings.payments %}
        <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ payment | payment_new_logo }}" class="icon-logo lazyload" alt="{{ payment }}">
    {% endfor %}
{% elseif shipping %}
    {% for shipping in settings.shipping %}
        <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ shipping | shipping_logo }}" class="icon-logo lazyload" alt="{{ shipping }}">
    {% endfor %}
{% endif %}

Incluimos este tpl en el snipplet footer.tpl

Social

Social-links.tpl

Contiene todos los links e iconos de redes sociales que se muestran en el footer. Deben ser configurados en el Administrador nube desde la sección Mi Cuenta/Redes Sociales.

Incluye:

  • Facebook
  • Google+
  • Twitter
  • Instagram
  • Pinterest
{% for sn in ['facebook', 'twitter', 'google_plus', 'pinterest', 'instagram'] %}
    {% set sn_url = attribute(store,sn) %}
    {% if sn_url %}
        <a class="social-icon" href="{{ sn_url }}" target="_blank" {% if sn == 'google_plus' %}rel="publisher"{% endif %}>
            {% if sn == "google_plus" %}
                {% include "snipplets/svg/google-plus.tpl" with {svg_custom_class: "icon-inline"} %}
            {% elseif sn == "facebook" %}
                {% include "snipplets/svg/facebook-f.tpl" with {svg_custom_class: "icon-inline"} %}
            {% elseif sn == "instagram" %}
                {% include "snipplets/svg/instagram.tpl" with {svg_custom_class: "icon-inline"} %}
            {% elseif sn == "pinterest" %}
                {% include "snipplets/svg/pinterest.tpl" with {svg_custom_class: "icon-inline"} %}
            {% else %}
                {% include "snipplets/svg/twitter.tpl" with {svg_custom_class: "icon-inline"} %}
            {% endif %}
        </a>
    {% endif %}
{% endfor %}

Incluimos este tpl en el snipplet footer.tpl 

Social-share.tpl

Son los links para compartir un producto en las siguientes redes sociales:

  • Facebook
  • WhatsApp
  • Twitter
  • Pinterest

{# Mobile Sharing #}
<div class="social-share text-center">
    <h5 class="my-3">{{ "Compartir" | translate }}</h5>

    {# Whatsapp button #}
    <a class="social-share-button" data-network="whatsapp" target="_blank"
     href="whatsapp://send?text={{ product.social_url }}">
         {% include "snipplets/svg/whatsapp.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
    </a>

    {# Facebook button #}
    <a class="social-share-button" data-network="facebook" target="_blank"
     href="https://www.facebook.com/sharer/sharer.php?u={{ product.social_url }}"
     title="Share on Facebook">
         {% include "snipplets/svg/facebook-f.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
    </a>

    {# Twitter button #}
    <a class="social-share-button" data-network="twitter" target="_blank"
     href="https://twitter.com/share?url={{ product.social_url }}"
     title="Share on Twitter">
         {% include "snipplets/svg/twitter.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
    </a>
    
    {# Pinterest button #}
     <a class="js-pinterest-share social-share-button" href="#" target="_blank" data-network="pinterest">
        {% include "snipplets/svg/pinterest.tpl" with {svg_custom_class: "icon-inline svg-icon-text"} %}
     </a>
     <div class="pinterest-hidden social-share-button" style="display: none;" data-network="pinterest">
        {{product.social_url | pin_it('https:' ~ product.featured_image | product_image_url('large'))}}
    </div>
</div>

Incluimos este tpl en el snipplet product-form.tpl 

Placeholders

Los placeholders son iconos vectorizados que se muestran con una animación de opacidad hasta que la imagen o el slider de imagenes al cual reemplazan, esté listo para verse. Una vez que el slider o la imagen se carga, el placeholder se oculta.

 El JavaScript que oculta y muestra los placeholders está en el archivo store.js.tpl.

home-slider-placeholder.tpl

Se muestra hasta que el slider principal de la página de inicio está cargado.

{# Mobile home slider placeholder: to be hidden after content loaded #}

{% if settings.slider and settings.slider is not empty %}
    <div class="js-home-slider-placeholder placeholder-full-height placeholder-container d-md-none overflow-hidden">
        <div class="container home-placeholder-icons">
            <div class="row">
                <div class="col-10 offset-1 mb-3 placeholder-line-medium placeholder-color">
                </div>
                <div class="col-8 offset-2 mb-3 placeholder-line-medium placeholder-color">
                </div>
                <div class="col-6 offset-3 mb-3 placeholder-line-medium placeholder-color">
                </div>
            </div>
        </div>
        <div class="placeholder-shine">
        </div>
    </div>
    <div class="js-slider-desktop-placeholder slider-desktop-placeholder">
    </div>
{% endif %}

Incluimos este tpl en el snipplet home-slider.tpl

product-detail-image-placeholder.tpl

Se muestra hasta que el slider del detalle de producto está cargado.

{# Mobile product detail placeholder: to be hidden after content loaded #}

{# Define sizes of mobile img placeholder based on the tallest element #}

{% set max_product_height = product.featured_image.dimensions['height'] %}
{% set max_product_width = product.featured_image.dimensions['width'] %}

{% if product.images_count > 1 %}
    {% for image in product.images %}
        {% set max_product_height = max(image.dimensions['height'], max_product_height) %}
        {% if image.dimensions['height'] == max_product_height %}
            {% set max_product_width = max(image.dimensions['width'], max_product_width) %}
        {% endif %}
    {% endfor %}
{% endif %}

{% set has_image_sizes = max_product_width > 0 %}

<div class="js-product-slider-placeholder d-md-none product-placeholder-container placeholder-container {% if product.images_count == 1 %}hidden-when-content-ready{% endif %}">
    <div class="p-relative overflow-none" {% if has_image_sizes %}style="padding-bottom: {{ max_product_height / max_product_width * 100}}%;"{% endif %}>
        <div class="product-placeholder img-absolute">
        </div>
    </div>
    <div class="placeholder-icon">
        {% include "snipplets/svg/shopping-bag.tpl" with {svg_custom_class: "icon-inline icon-w-14 icon-8x svg-icon-text"} %}
    </div>
    <div class="placeholder-shine">
    </div>
</div>

Incluimos este tpl en el snipplet product-image.tpl 

page-header.tpl

Representa todos los títulos de todas las páginas del theme. Dentro de si incluye el snipplet de breadcrumbs.

{# /*============================================================================
  #Page header
==============================================================================*/

#Properties

#Title

#Breadcrumbs 

#}

<section class="page-header">
    {% if template != 'product' %}
    <div class="container">
        <div class="row">
    {% endif %}
            <div class="{% if template != 'product' %}col text-center{% endif %} {% if template == 'product' %}text-center text-md-left{% endif %}">
                {% include 'snipplets/breadcrumbs.tpl' %}
                <h1>{% block page_header_text %}{% endblock %}</h1>
            </div>
    {% if template != 'product' %}
        </div>
    </div>
    {% endif %}
</section>

Incluimos este tpl en los templates 404.tpl, address.tpl, addresses.tpl, info.tpl, login.tpl, newpass.tlp, order.tpl, orders.tpl, register.tpl, reset.tpl, cart.tpl, category.tpl, contact.tpl, page.tpl y search.tpl. También en el snipplet product-form.tpl 

breadcrumbs.tpl

Son los breadcrumbs de una página incluidos dentro del snipplet product-header.tpl pero listos para ser usados por separado.

{# /*============================================================================
  #Page breadcrmubs
==============================================================================*/
#Properties
#Breadcrumb
    //breadcrumbs_custom_class for custom CSS classes
#}

{% if breadcrumbs %}
    <div class="breadcrumbs {{ breadcrumbs_custom_class }}" itemprop="breadcrumb" itemscope itemtype="http://www.schema.org/WebPage" itemid="body">
        <a class="crumb" href="{{ store.url }}" title="{{ store.name }}">{{ "Inicio" | translate }}</a>
        <span class="divider">></span>
        {% if template == 'page' %}
            <span class="crumb active">{{ page.name }}</span>
        {% elseif template == 'cart' %}
            <span class="crumb active">{{ "Carrito de compras" | translate }}</span>
        {% elseif template == 'search' %}
            <span class="crumb active">{{ "Resultados de búsqueda" | translate }}</span>
        {% elseif template == 'account.order' %}
             <span class="crumb active">{{ 'Orden {1}' | translate(order.number) }}</span>
        {% else %}
            {% for crumb in breadcrumbs %}
                {% if crumb.last %}
                    <span class="crumb active">{{ crumb.name }}</span>
                {% else %}
                    <a class="crumb" href="{{ crumb.url }}" title="{{ crumb.name }}">{{ crumb.name }}</a>
                    <span class="divider">></span>
                {% endif %}
            {% endfor %}
        {% endif %}
    </div>
{% endif %}

 Incluimos este tpl en el snipplet page-header.tpl 

whatsapp-chat.tpl

Como su nombre indica, este snipplet lo usamos para mostrar un botón de WhatsApp que permite al usuario chatear con el administrador de la tienda. Lo que hace es abrir el WhatsApp web si el usuario está navegando desde una computadora y la app si es desde el celular.

Para que este botón se muestre es necesario activar la funcionalidad desde el Administrador nube en la sección Configuraciones/WhatsApp

{% if store.whatsapp %}    
    <a href="{{ store.whatsapp }}" target="_blank" class="btn-whatsapp">
        {% include "snipplets/svg/whatsapp.tpl" with {svg_custom_class: "icon-inline icon-2x"} %}
    </a>
{% endif %}

Incluimos este tpl en el layout.tpl 

contact-links.tpl

Estos son los links de contacto, configurados desde el Administrador nube en la sección Personalizar/Información de contacto.

Se muestran tanto en el footer como en la página de contacto, exhibiendo información sobre:

  • Teléfono o WhatsApp
  • Email
  • Dirección del local
  • URL a un blog 

{# /*============================================================================
  #Contact links
==============================================================================*/#}

<ul class="contact-info text-center{% if columns %} row{% endif %}">
{% if store.whatsapp %}
    <li class="contact-item{% if columns %} col-6 col-md{% endif %}">
        {% include "snipplets/svg/whatsapp.tpl" with {svg_custom_class: "icon-inline icon-lg icon-w mx-2 svg-icon-text"} %}
        <a href="{{ store.whatsapp }}" class="contact-link">{{ store.whatsapp |trim('https://wa.me/') }}</a>
    </li>
{% elseif store.phone %}
    <li class="contact-item{% if columns %} col-6 col-md{% endif %}">
        {% include "snipplets/svg/phone.tpl" with {svg_custom_class: "icon-inline icon-lg icon-w mx-2 svg-icon-text"} %}
        <a href="tel:{{ store.phone }}" class="contact-link">{{ store.phone }}</a>
    </li>
{% endif %}
{% if store.email %}
    <li class="contact-item{% if columns %} col-6 col-md{% endif %}">
        {% include "snipplets/svg/envelope.tpl" with {svg_custom_class: "icon-inline icon-lg icon-w mx-2 svg-icon-text"} %}
        <a href="mailto:{{ store.email }}" class="contact-link">{{ store.email }}</a>
    </li>
{% endif %}
{% if store.address %}
    <li class="contact-item{% if columns %} col-6 col-md{% endif %}">
        {% include "snipplets/svg/map-marker-alt.tpl" with {svg_custom_class: "icon-inline icon-lg icon-w mx-2 svg-icon-text"} %}
        {{ store.address }}
    </li>
{% endif %}
{% if store.blog %}
    <li class="contact-item{% if columns %} col-6 col-md{% endif %}">
        {% include "snipplets/svg/comments.tpl" with {svg_custom_class: "icon-inline icon-lg icon-w mx-2 svg-icon-text"} %}
        <a target="_blank" href="{{ store.blog }}" class="contact-link">{{ "Visita nuestro Blog!" | translate }}</a>
    </li>
{% endif %}
</ul>

Incluimos este tpl en el snipplet footer.tpl y el tamplate contact.tpl

logo-icons.tpl

Incluye los logos de medios de pago y medios de envío que se muestran dentro del footer.

{% if payments %}
    {% for payment in settings.payments %}
        <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ payment | payment_new_logo }}" class="icon-logo lazyload">
    {% endfor %}
{% elseif shipping %}
    {% for shipping in settings.shipping %}
        <img src="{{ 'images/empty-placeholder.png' | static_url }}" data-src="{{ shipping | shipping_logo }}" class="icon-logo lazyload">
    {% endfor %}
{% endif %}

Incluimos este tpl en el snipplet footer.tpl 

facebook-login.tpl

Incluye el botón para logearse o crear una cuenta usando Facebook.

{% if store_fb_app_id %}

    <a class="btn btn-primary btn-facebook d-block mb-4" onclick="loginFacebook();" >
        {% include "snipplets/svg/facebook.tpl" with {svg_custom_class: "icon-inline icon-2x mr-1 svg-fb-icon align-middle"} %}
        <span class="align-middle">{{ 'Facebook login' | translate }}</span>
    </a>
    {% if result.facebook and result.invalid %}
        <div class="alert alert-danger">{{ 'Hubo un problema con el login de Facebook.' | translate }}</div>
    {% endif %}

{% endif %}

Incluimos este tpl en los templates login.tpl y register.tpl 

card.tpl

Es un componente que consiste en una tarjeta, con head, body y footer; similar a los “panels” de Bootstrap.

{# /*============================================================================
  #Card
==============================================================================*/
#Head
    // Block - card_head
#Body
    // Block - card_body
#Footer
    // Block - card_footer
#}


<div class="card">
    <div class="card-header">
        {% block card_head %}{% endblock %}
    </div>
    <div class="card-body">
        {% block card_body %}{% endblock %}
    </div>
    {% if card_footer %}
        <div class="card-footer">
            {% block card_foot %}{% endblock %}
        </div>
    {% endif %}
</div>

Incluimos este tpl en el template orders.tpl 

newsletter.tpl

Es el formulario de newsletter que usamos en el footer del theme. 

Incluye un solo campo de email así como la posibilidad de agregar un título y un texto personalizado.

{% set newsletter_contact_error = contact.type == 'newsletter' and not contact.success %}

<div class="row justify-content-md-center">
    <div class="col-md-8 text-center">
        <div class="js-newsletter newsletter section-footer">
            {% if settings.news_title %}
                <h3>{{ settings.news_title }}</h3>
            {% endif %}
            {% if settings.news_text %}
                <p>{{ settings.news_text }}</p>
            {% endif %}
        
            {% if contact and contact.type == 'newsletter' %}
                {% if contact.success %}
                    <div class="alert alert-success">{{ "¡Gracias por suscribirte! A partir de ahora vas a recibir nuestras novedades en tu email" | translate }}</div>
                {% else %}
                    <div class="alert alert-danger">{{ "Necesitamos tu email para enviarte nuestras novedades." | translate }}</div>
                {% endif %}
            {% endif %}

            <form method="post" action="/winnie-pooh" onsubmit="$(this).attr('action', '');">
                <div class="input-append">
                  
                    {% embed "snipplets/forms/form-input.tpl" with{input_for: 'email', type_email: true, input_name: 'email', input_id: 'email', input_placeholder: 'E-mail' } %}
                        {% block input_label_text %}{{ 'E-mail' | translate }}{% endblock input_label_text %}
                    {% endembed %}

                <div class="winnie-pooh" style="display: none;">
                    <label for="winnie-pooh-newsletter">{{ "No completar este campo" | translate }}</label>
                    <input id="winnie-pooh-newsletter" type="text" name="winnie-pooh"/>
                </div>
                <input type="hidden" name="name" value="{{ "Sin nombre" | translate }}" />
                <input type="hidden" name="message" value="{{ "Pedido de inscripción a newsletter" | translate }}" />
                <input type="hidden" name="type" value="newsletter" />
                <input type="submit" name="contact" class="btn newsletter-btn" value='{{ "Enviar" | translate }}'>    
                </div>
            </form>
        </div>
    </div>
</div>

Incluimos este tpl en el snipplet footer.tpl 


Banners services

Los tpls dentro de esta carpeta mostramos el código para los banners que muestran información de:

  • Pagos
  • Envíos
  • Seguridad
  • Cambios y devoluciones
  • Promociones
  • Pago en efectivo
  • WhatsApp

banner-services.tpl

Es el archivo que incluye el for para cada item dentro de estos banners.

{% macro for_each_banner_include(template) %}
    {% set num_banners_services = 0 %}
    {% set available_banners = []%}
    {% for banner in ['banner_services_01', 'banner_services_02', 'banner_services_03'] %}
        {% set banner_services_icon = attribute(settings,"#{banner}_icon") %}
        {% set banner_services_title = attribute(settings,"#{banner}_title") %}
        {% set banner_services_description = attribute(settings,"#{banner}_description") %}
        {% set banner_services_url = attribute(settings,"#{banner}_url") %}
        {% set has_banner_services =  banner_services_title or banner_services_description %}
        {% if has_banner_services %}
            {% set num_banners_services = num_banners_services + 1 %}
            {% set available_banners = available_banners | merge([banner]) %}
        {% endif %}
    {% endfor %}
    {% for banner in available_banners %}
        {% set banner_services_title = attribute(settings,"#{banner}_title") %}
        {% set banner_services_icon = attribute(settings,"#{banner}_icon") %}
        {% set banner_services_description = attribute(settings,"#{banner}_description") %}
        {% set banner_services_url = attribute(settings,"#{banner}_url") %}
        {% include template %}
    {% endfor %}
{% endmacro %}
{% import _self as banner_services %}
{% if settings.banner_services %}
    <section class="section-informative-banners">
        <div class="container">
            <div class="row">
                <div class="js-informative-banners swiper-container">
                    <div class="swiper-wrapper">
                        {{ banner_services.for_each_banner_include('snipplets/banner-services/banner-services-item.tpl') }}
                    </div>
                    <div class="js-informative-banners-pagination service-pagination swiper-pagination swiper-pagination-black"></div>
                </div>
            </div>
        </div>
    </section>
{% endif %}

Incluimos este tpl en el template home.tpl 


banner-services-item.tpl

Este tpl es para cada item dentro del grupo de banners informativos.

<div class="service-item-container col-md swiper-slide p-0 px-md-3">
    <div class="service-item row justify-content-md-center text-md-left">
        
        <div class="col-md-auto">
            {% if banner_services_icon == 'shipping' %}
                {% include "snipplets/svg/truck.tpl" with {svg_custom_class: "icon-inline icon-w-20 icon-2x service-icon"} %}
            {% elseif banner_services_icon == 'card' %}
                {% include "snipplets/svg/credit-card-blank.tpl" with {svg_custom_class: "icon-inline icon-w-18 icon-2x service-icon"} %}
            {% elseif banner_services_icon == 'security' %}
                {% include "snipplets/svg/lock.tpl" with {svg_custom_class: "icon-inline icon-w-14 icon-2x service-icon"} %}
            {% elseif banner_services_icon == 'returns' %}
                {% include "snipplets/svg/sync-alt.tpl" with {svg_custom_class: "icon-inline icon-w-16 icon-2x service-icon"} %}
            {% elseif banner_services_icon == 'whatsapp' %}
                {% include "snipplets/svg/whatsapp.tpl" with {svg_custom_class: "icon-inline icon-w-16 icon-2x service-icon service-icon-big"} %}
            {% elseif banner_services_icon == 'promotions' %}
                {% include "snipplets/svg/tag.tpl" with {svg_custom_class: "icon-inline icon-w-16 icon-2x service-icon"} %}
            {% elseif banner_services_icon == 'cash' %}
                {% include "snipplets/svg/dollar-sign.tpl" with {svg_custom_class: "icon-inline icon-w-9 icon-2x service-icon"} %}
            {% endif %}
        </div>
        <div class="col">
            {% if banner_services_url %}
                <a href="{{ banner_services_url }}">
            {% endif %}
            <h3 class="service-title">{{ banner_services_title }}</h3>
            <p>{{ banner_services_description }}</p>
            {% if banner_services_url %}
                </a>
            {% endif %}
        </div>
    </div>
</div>

Incluimos este tpl en el snipplet banner-services.tpl