Cálculo de frete na página de produto
Como adicionar o formulário de cálculo de frete na página de produto
A loja pode disponibilizar na página do produto um formulário de cálculo de frete. Esse formulário calcula o frete de acordo com o CEP do cliente e equivale ao cálculo de frete do checkout. Dessa forma, o cliente já visualiza prazo e custo de entrega antes de adicionar o produto no carrinho.
É possível que o template da sua loja já possua o formulário de frete na página do produto. Confira na página do produto se o formulário está disponível. Caso não possua e você deseja adicionar, você precisa incluir dois arquivos no projeto da loja. Para isso:
- Acesse o diretório liquids > partials > product do seu projeto e crie o arquivo
_shipping.liquid
com o código abaixo:
<div class="shipping" data-shipping-calculator>
<form action="">
<div class="form-group">
<div class="zip-header">
<label for="cep">
calcular frete e prazo
</label>
</div>
<div class="cep-wrapper">
<input name="cep" maxlength="9" placeholder="CEP" type="text" required class="cep"/>
<button type="submit" class="btn-submit" text-original="calcular" text-progress="calculando">calcular</button>
</div>
</div>
</form>
<div class="list-shipping" data-list-shipping></div>
</div>
- Acesse o diretório assets > javascripts > components > product > content do seu projeto e crie o arquivo
shipping.js
com o código abaixo:
import { formatMoney, urlencodeFormData } from '../components/utilities';
const Shipping = {
handleShipping: async function (form) {
// primeiramente, pegamos o sku e a quantidade de itens do produto em questão. essas informacões devem ser dinamicas com o formulário de compra, já que o sku e a quantidade interferem no peso do produto e com isso no valor do frete.
const sku = document.querySelector('[data-product-box] [name="sku"]').value;
const quantity = document.querySelector(
'[data-product-box] [name="quantity"]'
).value;
// depois pegamos o cep fornecido no input do formulário de calculo de frete. e damos um replace para caso o valor seja informado com -, ele seja removido.
const zip = form.querySelector('.input').value.replace('-', '');
const buttonSubmit = form.querySelector('.action');
// aqui verificamos se o cep contém menos ou mais 8 caractéres e enviamos uma mensagem de erro avisando que o formato do frete é inválido
if (zip.length != 8) {
form.classList.add('error');
form.querySelector('.msg-error').classList.add('-visible');
form.querySelector('.msg-error').innerHTML = 'Formato de CEP inválido';
} else {
// caso o frete seja válido, montamos as informacoes em FormData
const formData = new FormData();
formData.set('sku', sku);
formData.set('quantity', quantity);
formData.set('zip', zip);
// essa verificacão é feita para que se o usuário clique várias vezes no botão antes da requisicão terminar, não faca requisicões duplicadas
if (!form.classList.contains('-sending')) {
form.classList.remove('-error');
form.classList.add('-sending');
buttonSubmit.classList.add('-sending');
try {
// aqui fazermos a requisicão para o endpoint /frete_produto enviando sku, quantity e zip
const response = await fetch('/frete_produto', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: urlencodeFormData(formData),
});
const data = await response.json();
if (data.error) {
// aqui é definido o comportamento caso não seja encontrado condicões de frete disponíveis no momento
console.error('Ocorreu um erro ao consultar o frete');
console.error(data.error);
form.classList.add('error');
form.querySelector('.msg-error').classList.add('-visible');
form.querySelector('.msg-error').innerHTML =
'Ocorreu um erro ao calcular o frete, favor verifique seu cep.';
setTimeout(function () {
form.classList.remove('-error');
form.querySelector('.msg-error').classList.remove('-visible');
buttonSubmit.classList.remove('-sending');
}, 3500);
} else {
// aqui é denifido o comportamento caso seja encontrado forma de entrega disponível
const methods = JSON.parse(data.methods);
const address = data.address_details;
let result = `<h4 class="street">${address.street_name}, ${address.neighborhood} - ${address.city}/${address.state}</h4>`;
result += '<ul class="shipping-list">';
methods.forEach((method) => {
let price = method.price;
price = price == 0 ? 'Grátis' : formatMoney(price);
result += `
<li class="shipping-list-item">
<div class="method">
<p class="type">${method.name}</p>
<p class="price">${price}</p>
</div>
<span class="prazo">${method.description}</span>
</li>
`;
});
result += '</ul>';
document.querySelector('[data-list-shipping]').innerHTML = result;
}
} catch (error) {
//define comportamento caso a requisicão falhe.
console.error('Erro ao enviar dados para consulta de frete');
console.error(error);
form.classList.add('error');
form.querySelector('.msg-error').classList.add('-visible');
form.querySelector('.msg-error').innerHTML =
'Ocorreu um erro ao calcular o frete, favor verifique seu cep.';
buttonSubmit.classList.remove('-sending');
}
form.classList.remove('-sending');
buttonSubmit.classList.remove('-sending');
}
}
},
init: function () {
const _this = this;
const form = document.querySelector('[name="shipping-form"]');
const inputValue = form.querySelector('.input');
inputValue.addEventListener('input', (event) => {
// cria a máscara de frete para que o input fique mais intuitivo e previna erros do usuário
const x = event.target.value
.replace(/\D/g, '')
.match(/(\d{0,5})(\d{0,3})/);
event.target.value = !x[2] ? x[1] : x[1] + '-' + x[2];
});
form.addEventListener('submit', (event) => {
event.preventDefault();
_this.handleShipping(form);
});
},
};
export default Shipping;
O formulário de frete está disponível na página do produto.
Para testar o cálculo de frete do formulário certifique-se de que a loja já possui algum meio de entrega cadastrado.
Updated about 1 year ago