Produtos personalizados

Neste artigo, adicionaremos campos para oferecer produtos mais personalizados. Por exemplo, para casos em que a loja vende camisetas com um número e um nome.

Essas informações serão então levadas para o checkout e, finalmente, serão refletidas no detalhe do pedido do Administrador nuvem.

HTML

1.  Criamos a pasta forms dentro da pasta snipplets. Aqui, precisamos adicionar um novo arquivo com o nome form-input.tpl que usaremos para cada input nos detalhes do produto.

{# /*============================================================================
  #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
    // input_aria_label for aria-label attribute
#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 %}
            {% if input_aria_label %}aria-label="{{ input_aria_label }}"{% 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>

2. No snipplet do formulário do produto, product-form.tpl, dentro da pasta snipplets/product; ou dependendo do design pode ser diretamente no modelo product.tpl, adicione um input para a propriedade que você precisa. O importante é que esteja no form com o ID "product_form".

Este input deve ter um atributo "name" com o valor "properties [x]", substituindo o "X" pelo nome da propriedade que você precisa.

Por exemplo, para um número e um nome, precisamos de algo como:

{% embed "snipplets/forms/form-input.tpl" with{type_text: true, input_name: 'properties[Número]', input_label_text: 'Nombre' | translate } %}
{% endembed %}


{% embed "snipplets/forms/form-input.tpl" with{type_text: true, input_name: 'properties[Nombre]', input_label_text: 'Nombre' | translate } %}
{% endembed %}

Este embed mostra um HTML similar ao seguinte:

<div class="form-group">
    <label>{{ 'Número' | translate }}</label>
    <input type="text" name="properties[Número]" class="form-control">
</div>
<div class="form-group">
    <label>{{ 'Nombre' | translate }}</label>
    <input type="text" name="properties[Nombre]" class="form-control">
</div>

Se quisermos que o input seja informação oculta e que ela seja visível apenas na ordem da pessoa que gerencia a loja, basta adicionar o hifen no início do nome, por exemplo:

{% embed "snipplets/forms/form-input.tpl" with{type_text: true, input_name: 'properties[_Nombre]', select_label: false %}
{% endembed %}

Imprimindo algo como:

<div class="form-group">
    <input type="text" name="properties[_Nombre]" class="form-control">
</div>

Se, por algum motivo, precisarmos mostrar o input apenas em alguns produtos, será melhor adicionar essos inputs a partir da descrição do produto no Administrador nuvem, habilitando o formato HTML.

Mas devemos considerar que este campo não usa o Twig, então temos que usar o HTML “clássico”, por exemplo:

<div class="form-group">
    <label>{{ 'Nombre' | translate }}</label>
    <input type="text" name="properties[Nombre]" class="form-control">
</div>

Nós só temos que lembrar de colocar o código {{ product.description }} dentro do formulário do produto, uma vez que geralmente está fora dele.

A funcionalidade permite qualquer tipo de entrada (texto, número, etc), deve ser dentro do formulário do produto para que as informações sejam enviadas para o checkout e, depois, para o pedido gerado.

2. Para mostrar essas propriedades no carrinho, devemos adicionar o seguinte código no snipplet cart-item-ajax.tpl ou no template cart.tpl (dependendo do seu design):

{% for key, value in item.attributes if key[:1] != '_' %}
   <div><strong>{{key}}</strong>: {{value}}</div>
{% endfor %}

CSS

Requisito:

Ter adicionado helper classes em seu layout. Você pode seguir este pequeno tutorial para fazer isso (é só copiar e colar algumas classes, não leva mais que 1 minuto).

1. Adicionamos o seguinte SASS de cores em style-colors.scss.tpl (ou na stylesheet do seu layout que possui as cores e fontes da loja). Lembre-se de que as variáveis de cores e fontes podem variar em relação ao seu layout:

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


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


{# /* // Forms */ #}


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


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


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

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

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

{# /* // Forms */ #}


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


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


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

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

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

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


%element-margin {
  margin-bottom: 35px;
}


{# /* // Mixins */ #}


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


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


{# /* // Forms */ #}


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


{# /* Disabled controls */ #}


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

Pronto, agora você pode oferecer produtos personalizados em seu design!