Skip to main content

Elementos importantes

Vamos falar agora sobre dois elementos muito importantes para o seu projeto, vou disponibilizar alguns códigos abaixo para que possam ser reaproveitados, facilitando a integração de algumas funcionalidades.

O Header geralmente traz uma lista de links para o menu do seu site. Vamos ver então algumas formas de buscar esses itens do menu automáticamente do back-end, além também de 'linkar' de forma manual. Além também, de ter a famosa barra de busca que também iremos mostrar abaixo.

No seu projeto inicial, você verá que o header está localizado em Elementos > header > index.html.

  • Itens do menu:

    Vamos demonstrar abaixo um código responsável pela busca dos itens do menu.

{% set categorias = _cms('categories', 'menu de categorias') %}

<ul class="list" data-grid="nowrap">
{% for categoria in categorias.content %}
<li class="item" data-grid="center-center">
<a {{ _href(categoria, 1) }} class="link">
{{ categoria.name }}
</a>

{% if categoria.subcategories | length > 0 %}
<div class="subitems">
{% for subcategoria in categoria.subcategories %}
<a {{ _href(subcategoria, 1) }} class="subitem">
{{ subcategoria.name }}
</a>
{% endfor %}
</div>
{% endif %}

<span class="accordion-subcategory ismobile">
{% include 'icons/arrow-left' %}
</span>
</li>
{% endfor %}
</ul>

Iniciamos então com a criação do atributo categories, que recebe do método _cms() os valores das categorias buscadas.

O método _cms() também é o responsável por enviar os dados para o nosso painel de CMS, nele são passados dois parâmetros, o tipo do conteúdo que nesse caso é categories e o nome de identificação que seria menu de categorias, mas pode ser chamado por qualquer nome. O CMS traz um ambiente mais amigável para a gestão de conteúdos do seu projeto, saiba mais sobre o CMS clicando aqui.

Para alimentar e buscar as cartegorias de forma automática do seu projeto, basta entrar em nosso ambiente de CMS, no menu lateral acessar a aba de CMS > minha_pagina, acesse então a página/elemento onde você fez a chamada do método _cms() como mencionado acima.

Ao acessar a página na 'aba' Conteúdo, você verá que o nome dado para o seu conteúdo do menu será menu de categorias (caso tenha seguido o exemplo acima), veja o exemplo abaixo:

An image

clique no botão editar, para visualisar os critérios que vamos atribuir para fazer a chamada das categorias.

Temos então três campos, atributo, condição e valor. Teremos alguns campos em que você poderá filtrar para buscar as categorias da sua loja. Veja no exemplo abaixo os campos selecionados (talvez não atenda exatamente o seu e-commerce).

An image

Vale a pena lembrar que, após aplicar os campos que deseja filtrar para buscar as categorias, é necessário clicar em Salvar.

Dessa forma, o campo que criamos {% set categorias = _cms('categories', 'menu de categorias') %} (categorias), receberá o array de categorias buscadas no CMS.


  • Linkar manualmente as categorias do menu:

    Apresentamos anteriormente como trazer as categorias de forma automática, além do exemplo de código que mostra como redirecionar para a categoria desejada.

    Para linkar de forma manual, temos o seguinte código abaixo:

      <a {{ _href('/categoria') }}>Categoria</a>

    O método _href() é o responsável pelo redirecionamento, ele basicamente representa o atributo onclick que dispara o método _navigate(), dessa forma: onclick="_navigate()".

Cartão de produto

Temos então o nosso principal elemento da loja, vamos falar sobre a chamada dos valores do produto no cartão de produto.

O cartão de produto é alimentado pelas vitrines de campanha e também de listagem de resultados das telas de categoria.html e pesquisa.html. Basicamente, aqui temos dois exemplos: Vitrine de produtos na Home e Listagem de produtos.

Nesses dois exemplos temos a chamada do elemento cartão de produto que foi importado como {% include 'template/product card' %}. Para exibir as informações do produto, o campo product que está sendo usado por padrão em ambos na chamada do {% for product in products %}, é reconhecido automaticamente no elemento cartão de produto, é de extrema importância que o atributo product se repita em todas as chamadas para a listagem de produtos, para não haver uma quebra de padrão em outras chamadas, até porque, o que vai definir o reconhecimento do produto, é o atributo que está sendo usado dentro do elemento cartão de produto ou seja, nesse caso está sendo chamado pelo atributo product. Vamos ao código:

<article class="product-card">
<!-- Imagem do produto -->
<a {{ _href(product) }} class="image">
{% include 'template/tag-products-card' %}

<img
src="{{ product.media[0].cached }}"
alt="{{ product.name }}"
onerror="this.src = 'https://storage.test.increazy.com/base_pwa/images/no-image.webp'"
/>
</a>

<div data-grid class="info">
<span
onclick="toggleWishlist(event)"
data-favorites="{{ product.id }}"
data-favorites-data="{{ _object(_only(product, 'id', 'name', 'prices')) }}"
class="favorite"
>
<span class="heart-line">
{% include 'icons/heart-line' %}
</span>

<span class="heart-fill">
{% include 'icons/heart-fill' %}
</span>
</span>

<h3 class="name">{{ product.name | raw }}</h3>
<p class="price">{{ _price('min', product, true, customerGroup) }}</p>

{% set maiorParcela = _price('installments', product, true, customerGroup) | last %}
<small class="installment">
Até {{ maiorParcela.qty }}x de {{ _price('format', maiorParcela.price) }} sem juros
</small>
</div>
</article>

Carrinho

Temos então nosso querido carrinho de compras, existem muitas funcionalidades que podemos dar ao carrinho, então, para simplificar as explicações, vamos fazer por parte.

Você vai notar que no projeto base que oferecemos, o carrinho se encontra dentro de Elementos, e dentro de cart teremos o arquivo container.html como a base do carrinho, e dentro dela temos as principais funcionalidades, que falaremos sobre cada uma delas abaixo:

O Principal atributo do carrinho é o cart, que é um objeto padrão da PWA que dá acesso à todos os atributos e informações do carrinho, que por sua vez, pode ser usado livremente no projeto.

  • Aplicando calculo para frete grátis.
{% set valorParaFreteGratis = 300 %}

<div>
<span
class="{{ (valorParaFreteGratis - cart.subtotal) <= 0 ? 'free' : '' }}"
style="width: {{ (cart.subtotal * 100) / valorParaFreteGratis }}%"
>
</span>

<div>
{% include 'icons/truck' %}

{% if (valorParaFreteGratis - cart.subtotal) > 0 %}
<p>
Faltam apenas {{ _price('format', valorParaFreteGratis - cart.subtotal) }}<br>
<span>para você garantir frete grátis</span>
</p>
{% else %}
<p class="win">
Você ganhou frete grátis!
</p>
{% endif %}
</div>
</div>

  • Carrinho vazio:
{% if (cart.items | length) <= 0 %}
<div>
<h3>Carrinho vazio</h3>

<button>
Ver novidades
</button>
</div>
{% endif %}

  • Listagem dos produtos:
<!-- itens do carrinho listados -->
<ul class="cart__shop-list" id="cart-items">
{% for key, product in cart.items %}

{% set productInfo = _object(_only(product, 'id', 'sku', 'item_id')) %}

<li class="cart__shop-list--item">
<article class="cart__shop-list--layout">
<figure>
<img
loading="lazy"
onerror="this.src='https://storage.test.increazy.com/drivetest/no-image.webp'"
src="{{ product.image }}"
alt="{{ product.name }}"
/>
</figure>

<div class="cart__shop-list--text">
<div class="cart__shop-list--name">
<h3>{{ product.name }}</h3>
<img
onclick="removeItem({{ productInfo }})"
src="{{ _file('/icons/trash-can.svg') }}"
alt="Remover"
title="Remover"
/>
</div>

{% if product.options.attributes_info %}
<ul class="cart__options">
{% for option in product.options.attributes_info %}
<li>
<strong>{{ option.label }}:</strong> {{ option.value }}
</li>
{% endfor %}
</ul>
{% endif %}

{% if product.options.options %}
<ul class="cart__options">
{% for option in product.options.options %}
<li>
<strong>{{ option.label }}:</strong> {{ option.value }}
</li>
{% endfor %}
</ul>
{% endif %}

<div class="cart__shop-list--price">
<small>{{ _price('format', product.price - product.discount) }}</small>
<span>Total: {{ _price('format', (product.price - product.discount) * product.quantity) }}</span>
</div>

<div class="cart__shop-list--btn">
<span onclick="changeQuantityByProduct({{ productInfo }}, {{ product.increment * -1 }})">-</span>
<input
onchange="updateItem({{ productInfo }}, event.target.value)"
min="0"
value="{{ product.quantity }}"
type="number"
name="quantity"
required
data-product-quantity="{{ product.sku }}"
/>
<span onclick="changeQuantityByProduct({{ productInfo }}, {{ product.increment }})">+</span>
</div>
</div>
</article>
</li>
{% endfor %}'
</ul>

<script type="text/javascript">
function changeQuantityByProduct(product, increment) {
const input = document.querySelector(`input[data-product-quantity="${product.sku}"]`);

if (input) {
input.value = (+input.value) + increment;
updateItem(product, input.value);
}
}

async function updateItem(product, quantity) {
const cart = await _ecommerce('cart/changeItem', {
body: {
product,
quantity
},
})

await refreshCart({ cart });
toast('Produto atualizado', 'green');
}

async function removeItem(product) {
const cart = await _ecommerce('cart/removeItem', {
body: { product },
})

await refreshCart({ cart });
toast('Produto removido', 'green');
}
</script>

  • Consultar frete:
<form onsubmit="searchShipping(event)">
<label for="shipping">Calcule o frete:</label>

<span>
<input value="{{ postal }}" required id="shipping" name="shipping" placeholder="Digite seu CEP">

<button type="submit">
Calcular
</button>
</span>

<a href="https://buscacepinter.correios.com.br" target="_blank">Não sei meu CEP</a>
</form>

{% if fretes | length > 0 %}
{% for frete in fretes %}
<span class="freight__result">
<small>
<strong>{{ frete.title }}</strong>:
{{ frete.price > 0 ? _price('format', frete.price) : 'Grátis' }}
</small>
</span>
{% endfor %}
{% elseif fretes %}
<span class="freight__result">Sem resultado encontrado.</span>
{% endif %}

<script>
async function searchShipping(event) {
event.stopPropagation();
event.preventDefault();

const cepNotCleaned = document.querySelector('#shipping');
const cepCleaned = cepNotCleaned.value.replace(/[^a-zA-Z0-9 ]/g, '');

const fretes = await _ecommerce('freight/byCart', {
body: { postal: cepCleaned }
});

await refreshCart({
fretes,
postal: cepCleaned
});
}
</script>

  • Consultar cupom:
<form onsubmit="toggleCoupon(event)" id="coupon-form" style="display: {{ cart.coupon  ? 'flex' : 'none' }}">
<label for="coupon">Cupom de deconto:</label>

<span>
<input value="{{ cart.coupon }}" required class="cart__shipping--input" id="coupon" name="coupon"
placeholder="Digite seu cupom">

{% if cart.coupon == null %}
<input type="hidden" id="coupon_action" value="add">
<button type="submit" class="cart__shipping--button main-button">
Aplicar
</button>
{% endif %}

{% if cart.coupon %}
<input type="hidden" id="coupon_action" value="del">
<button type="submit" class="cart__shipping--button main-button">
Remover
</button>
{% endif %}
</span>
</form>

<a onclick="showCouponForm(event)" style="display: {{ cart.coupon ? 'none' : 'inline' }}" class="cart__shipping--coupon" >
Tem cupom de desconto?
</a>

<script>
function showCouponForm(event) {
event.target.style.display = 'none';
const el = document.getElementById('coupon-form');
el.style.display = 'flex';
}

async function toggleCoupon(event) {
event.stopPropagation();
event.preventDefault();

const action = document.getElementById('coupon_action').value;
const method = action == 'add' ? 'addCoupon' : 'removeCoupon';

const cart = await _ecommerce(`cart/${method}`, { body: { coupon: '_dom:#coupon$value' } })
await refreshCart({ cart });

const message = action == 'add' ? 'Cupom adicionado' : 'Cupom removido';
toast(message, 'green');
}
</script>

  • Resumo das compras e totais:
{% if (cart.items | length) > 0 %}

<ul class="cart__totals">
<li class="cart__totals--item">
<p>Subtotal</p>
<p>{{ _price('format', cart.subtotal) }}</p>
</li>

<li class="cart__totals--item">
<p>Entrega</p>
<a onclick="document.getElementById('shipping').focus()">
Consultar seu frete
</a>
</li>

{% if cart.discount > 0 %}
<li class="cart__totals--item">
<p>Desconto</p>
<p>{{ _price('format', cart.discount) }}</p>
</li>
{% endif %}

<li class="cart__totals--item grand-total">
<h3>Total</h3>

<div class="cart__totals--grand-total">
<h3>{{ _price('format', cart.total) }}</h3>
<p>Parcele em até</p>

{% set maiorParcela = _price('installments', cart.total) | last %}

<span>
{{ maiorParcela.qty }}x de {{ _price('format', maiorParcela.price) }}
</span>
</div>
</li>
</ul>
{% endif %}

  • Botão de finalizar compra:
<button {{ _checkout() }} class="cart__totals--button">
Finalizar minha compra
</button>