Skip to main content

Elementos importantes

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

O Header geralmente traz uma lista de links utilizados no menu do seu site. Veremos então como buscar esses itens automaticamente ou 'linkar' eles de forma manual.

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 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. 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 categorias de forma automática no seu projeto, basta entrar em nosso ambiente de CMS, no menu lateral de Layout e acessar 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:

Menu de categorias no CMS

Clique no botão editar para visualisar os critérios que podem ser atribuídos para fazer a chamada das categorias.

Temos no "popup" lateral três campos: atributo, condição e valor. Utilizando esses campos em que você poderá "filtrar" as categorias da sua loja. Veja no exemplo abaixo os campos:

Critérios para selecionar categorias

Vale a pena lembrar que após aplicar os "filtros" 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 podemos utilizar o código abaixo:

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

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

Cartão de produto

Outro elemento fundamental da loja é o cartão de produto. Falaremos a seguir sobre como chamar os valores do produto dentro do cartão.

Esse elemento é alimentado pelas vitrines e também pela listagem de resultados das páginas category.html e search.html.

Nesses dois exemplos temos a chamada do elemento cartão de produto que foi importado como {% include 'cartao de produto' %}, geralmente localizado no layout base em 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 de listagem de produtos, para que não haja uma quebra de padrão em outras chamadas, até porque, o que define o reconhecimento do produto é o atributo que está sendo usado dentro do elemento cartão de produto, ou seja, o 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.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 também nosso querido carrinho de compras! Existem muitas funcionalidades que podem ser utilizadas no carrinho, falaremos delas separadamente a seguir.

Você vai notar que no projeto base que oferecemos, o carrinho se encontra em Elementos > cart. Nessa pasta temos o arquivo container.html como a base do carrinho, e dentro dele temos as principais funcionalidades.

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:

Você poderá usar o código abaixo para aplicar uma 'barra de frete grátis' no seu carrinho:

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

Lembrando que é necessária a estilização css para o funcionamento do código.

Carrinho vazio:

O código abaixo pode ser utilizado para exibição de uma mensagem caso não exista nenhum item no carrinho:

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

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

Listagem dos produtos:

O código abaixo é utilizado para listar os itens adicionados ao carrinho:

<!-- 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.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:

O código abaixo pode ser usada para que o cliente consiga calcular o valor do frete dentro do carrinho:

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

Este código pode ser utilizado para buscar um cupom de desconto dentro do carrinho:

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

Código para exibir o resumo da compra e os valores totais do carrinho (subtotal, descontos, total):

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

Código para o botão que leva ao checkout:

<button {{ _checkout() }} class="cart__totals--button">
Finalizar minha compra
</button>