1561 lines
54 KiB
JavaScript
1561 lines
54 KiB
JavaScript
// Configurações - CATÁLOGO LABERI KIDS
|
|
const CONFIG = {
|
|
SUPABASE_URL: 'https://ydhzylfnpqlxnzfcclla.supabase.co',
|
|
SUPABASE_ANON_KEY: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkaHp5bGZucHFseG56ZmNjbGxhIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjA1NDA1NjIsImV4cCI6MjA3NjExNjU2Mn0.gIHxyAYngqkJ8z2Gt5ESYmG605vhY_LGTQB7Cjp4ZTA',
|
|
WHATSAPP_NUMBER: '5543999762754',
|
|
VENDEDORA_NOME: 'Maiara'
|
|
};
|
|
|
|
// Estado global
|
|
let produtos = [];
|
|
let carrinho = [];
|
|
let filtros = { tamanho: '', genero: '', destaque: '' };
|
|
let supabaseClient = null;
|
|
let currentUser = null;
|
|
let catalogoConfig = {
|
|
catalogoAtivo: false,
|
|
exibirPrecos: true,
|
|
exibirEstoque: false,
|
|
exibirNovidades: true,
|
|
exibirPromocoes: true
|
|
};
|
|
|
|
const atualizarViewportCSSVar = (() => {
|
|
let rafId = null;
|
|
|
|
const setVar = () => {
|
|
rafId = null;
|
|
const viewport = window.visualViewport;
|
|
const height = viewport && viewport.height ? viewport.height : window.innerHeight;
|
|
if (!height) {
|
|
return;
|
|
}
|
|
document.documentElement.style.setProperty('--visual-vh', `${height}px`);
|
|
};
|
|
|
|
const schedule = () => {
|
|
if (rafId !== null) {
|
|
return;
|
|
}
|
|
rafId = window.requestAnimationFrame(setVar);
|
|
};
|
|
|
|
return {
|
|
update: schedule,
|
|
immediate: () => {
|
|
if (rafId !== null) {
|
|
cancelAnimationFrame(rafId);
|
|
rafId = null;
|
|
}
|
|
setVar();
|
|
}
|
|
};
|
|
})();
|
|
|
|
atualizarViewportCSSVar.immediate();
|
|
window.addEventListener('resize', atualizarViewportCSSVar.update);
|
|
window.addEventListener('orientationchange', atualizarViewportCSSVar.update);
|
|
|
|
if (window.visualViewport) {
|
|
window.visualViewport.addEventListener('resize', atualizarViewportCSSVar.update);
|
|
window.visualViewport.addEventListener('scroll', atualizarViewportCSSVar.update);
|
|
}
|
|
|
|
// Inicialização
|
|
document.addEventListener('DOMContentLoaded', async function() {
|
|
atualizarViewportCSSVar.immediate();
|
|
inicializarSupabase();
|
|
inicializarEventListeners();
|
|
inicializarImageViewer();
|
|
carregarCarrinho();
|
|
atualizarContadorCarrinho();
|
|
await carregarConfiguracoesCatalogo();
|
|
await carregarProdutos();
|
|
await verificarAutenticacao();
|
|
});
|
|
|
|
// Carregar carrinho do localStorage
|
|
function carregarCarrinho() {
|
|
const carrinhoSalvo = localStorage.getItem('liberi_carrinho');
|
|
if (carrinhoSalvo) {
|
|
try {
|
|
carrinho = JSON.parse(carrinhoSalvo);
|
|
} catch (error) {
|
|
console.error('Erro ao carregar carrinho:', error);
|
|
carrinho = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
function criarDataLocal(date) {
|
|
if (!date) return new Date();
|
|
if (date instanceof Date) {
|
|
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
|
}
|
|
|
|
if (typeof date === 'string') {
|
|
const partes = date.split('-');
|
|
if (partes.length === 3) {
|
|
const [ano, mes, dia] = partes.map((parte) => parseInt(parte, 10));
|
|
if (!Number.isNaN(ano) && !Number.isNaN(mes) && !Number.isNaN(dia)) {
|
|
return new Date(ano, mes - 1, dia);
|
|
}
|
|
}
|
|
}
|
|
|
|
const data = new Date(date);
|
|
if (Number.isNaN(data.getTime())) {
|
|
return new Date();
|
|
}
|
|
return new Date(data.getFullYear(), data.getMonth(), data.getDate());
|
|
}
|
|
|
|
function formatarDataInput(date) {
|
|
if (!date) return '';
|
|
const data = criarDataLocal(date);
|
|
const ano = data.getFullYear();
|
|
const mes = String(data.getMonth() + 1).padStart(2, '0');
|
|
const dia = String(data.getDate()).padStart(2, '0');
|
|
return `${ano}-${mes}-${dia}`;
|
|
}
|
|
|
|
function obterHojeISO() {
|
|
return formatarDataInput(new Date());
|
|
}
|
|
|
|
function adicionarDias(dataBase, dias) {
|
|
const data = criarDataLocal(dataBase || new Date());
|
|
data.setDate(data.getDate() + dias);
|
|
return formatarDataInput(data);
|
|
}
|
|
|
|
function formatarMoedaBR(valor) {
|
|
const numero = Number(valor) || 0;
|
|
return numero.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
|
|
}
|
|
|
|
function formatarDataHumanaBR(date) {
|
|
const data = criarDataLocal(date);
|
|
const dia = String(data.getDate()).padStart(2, '0');
|
|
const mes = String(data.getMonth() + 1).padStart(2, '0');
|
|
const ano = data.getFullYear();
|
|
return `${dia}/${mes}/${ano}`;
|
|
}
|
|
|
|
function gerarIdVendaCatalogo() {
|
|
const agora = new Date();
|
|
const ano = agora.getFullYear();
|
|
const mes = String(agora.getMonth() + 1).padStart(2, '0');
|
|
const dia = String(agora.getDate()).padStart(2, '0');
|
|
const hora = String(agora.getHours()).padStart(2, '0');
|
|
const minuto = String(agora.getMinutes()).padStart(2, '0');
|
|
const segundo = String(agora.getSeconds()).padStart(2, '0');
|
|
return `VDWEB${ano}${mes}${dia}${hora}${minuto}${segundo}`;
|
|
}
|
|
|
|
// Funções relacionadas a pagamentos foram removidas — o pedido apenas envia mensagem à vendedora.
|
|
|
|
// Inicializar Supabase
|
|
function inicializarSupabase() {
|
|
if (!CONFIG.SUPABASE_URL || !CONFIG.SUPABASE_ANON_KEY) {
|
|
console.error('Configurações do Supabase não encontradas');
|
|
return;
|
|
}
|
|
|
|
if (!window.supabase) {
|
|
console.error('Biblioteca do Supabase não encontrada');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
supabaseClient = window.supabase.createClient(CONFIG.SUPABASE_URL, CONFIG.SUPABASE_ANON_KEY);
|
|
console.log('Supabase inicializado com sucesso');
|
|
} catch (error) {
|
|
console.error('Erro ao inicializar Supabase:', error);
|
|
}
|
|
}
|
|
|
|
// Carregar configurações do catálogo
|
|
async function carregarConfiguracoesCatalogo() {
|
|
try {
|
|
if (!supabaseClient) return;
|
|
|
|
const { data, error } = await supabaseClient
|
|
.from('configuracoes')
|
|
.select('valor')
|
|
.eq('chave', 'catalogo_config')
|
|
.single();
|
|
|
|
if (!error && data && data.valor) {
|
|
catalogoConfig = {
|
|
...catalogoConfig,
|
|
...data.valor
|
|
};
|
|
console.log('Configurações do catálogo carregadas:', catalogoConfig);
|
|
|
|
// Aplicar configurações visuais
|
|
if (!catalogoConfig.exibirPrecos) {
|
|
document.body.classList.add('hide-prices');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Erro ao carregar configurações do catálogo:', error);
|
|
}
|
|
}
|
|
|
|
// Event Listeners
|
|
function inicializarEventListeners() {
|
|
const filterPanel = document.getElementById('filterPanel');
|
|
if (filterPanel) {
|
|
filterPanel.addEventListener('click', handleFilterChipClick);
|
|
}
|
|
}
|
|
|
|
function inicializarImageViewer() {
|
|
const viewer = document.getElementById('produtoImageViewer');
|
|
const viewerImg = document.getElementById('produtoImageViewerImg');
|
|
|
|
if (!viewer) {
|
|
return;
|
|
}
|
|
|
|
viewer.addEventListener('click', event => {
|
|
if (event.target === viewer) {
|
|
fecharImagemExpandida();
|
|
}
|
|
});
|
|
|
|
if (viewerImg) {
|
|
viewerImg.addEventListener('click', event => {
|
|
event.stopPropagation();
|
|
});
|
|
}
|
|
|
|
// Navegação por teclado
|
|
document.addEventListener('keydown', event => {
|
|
if (!viewer.classList.contains('active')) return;
|
|
|
|
if (event.key === 'Escape') {
|
|
fecharImagemExpandida();
|
|
} else if (event.key === 'ArrowLeft') {
|
|
navegarImagemViewer(-1);
|
|
} else if (event.key === 'ArrowRight') {
|
|
navegarImagemViewer(1);
|
|
}
|
|
});
|
|
}
|
|
|
|
function atualizarEstadoFiltro() {
|
|
const filterBtn = document.querySelector('.filter-btn');
|
|
if (!filterBtn) return;
|
|
const algumFiltroAtivo = Boolean(filtros.tamanho || filtros.genero || filtros.destaque);
|
|
filterBtn.classList.toggle('has-filter', algumFiltroAtivo);
|
|
}
|
|
|
|
function escapeHtmlAttr(value = '') {
|
|
return value
|
|
.toString()
|
|
.replace(/&/g, '&')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>');
|
|
}
|
|
|
|
// Carregar produtos
|
|
async function carregarProdutos() {
|
|
const loading = document.getElementById('loading');
|
|
const grid = document.getElementById('produtosGrid');
|
|
const noProducts = document.getElementById('noProducts');
|
|
|
|
try {
|
|
mostrarLoading(true);
|
|
|
|
if (supabaseClient) {
|
|
const { data, error } = await supabaseClient
|
|
.from('produtos')
|
|
.select(`
|
|
*,
|
|
produto_variacoes (
|
|
id, tamanho, cor, quantidade, fotos
|
|
)
|
|
`)
|
|
.eq('ativo', true)
|
|
.eq('visivel_catalogo', true)
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) throw error;
|
|
|
|
// Carregar fotos adicionais do bucket 'catalogo' para cada produto
|
|
const produtosComFotos = await Promise.all((data || []).map(async (produto) => {
|
|
try {
|
|
const { data: fotosAdicionais } = await supabaseClient
|
|
.storage
|
|
.from('catalogo')
|
|
.list(`produto_${produto.id}`, {
|
|
limit: 10,
|
|
sortBy: { column: 'name', order: 'asc' }
|
|
});
|
|
|
|
if (fotosAdicionais && fotosAdicionais.length > 0) {
|
|
produto.fotosAdicionais = fotosAdicionais.map(foto => {
|
|
const { data: urlData } = supabaseClient
|
|
.storage
|
|
.from('catalogo')
|
|
.getPublicUrl(`produto_${produto.id}/${foto.name}`);
|
|
return urlData.publicUrl;
|
|
});
|
|
} else {
|
|
produto.fotosAdicionais = [];
|
|
}
|
|
} catch (err) {
|
|
console.log('Sem fotos adicionais para produto', produto.id);
|
|
produto.fotosAdicionais = [];
|
|
}
|
|
return produto;
|
|
}));
|
|
|
|
produtos = mapearProdutos(produtosComFotos);
|
|
}
|
|
|
|
if (!produtos.length) {
|
|
noProducts.style.display = 'block';
|
|
grid.innerHTML = '';
|
|
} else {
|
|
noProducts.style.display = 'none';
|
|
popularFiltros();
|
|
renderizarProdutos();
|
|
}
|
|
} catch (error) {
|
|
console.error('Erro ao carregar produtos:', error);
|
|
mostrarPopup('Erro ao carregar produtos: ' + error.message, 'error');
|
|
} finally {
|
|
mostrarLoading(false);
|
|
}
|
|
}
|
|
|
|
// Mapear produtos do Supabase
|
|
function mapearProdutos(produtosData) {
|
|
return (produtosData || []).map(produto => {
|
|
const variacoes = (produto.produto_variacoes || []).map(variacao => ({
|
|
...variacao,
|
|
quantidade: Number(variacao.quantidade || 0),
|
|
tamanhoNormalizado: (variacao.tamanho || '').toString().toLowerCase()
|
|
}));
|
|
|
|
const generoLabel = (produto.genero || '').trim();
|
|
|
|
// Construir galeria de fotos: foto principal + fotos das variações + fotos adicionais
|
|
const fotosDasVariacoes = variacoes.flatMap(v => v.fotos || []).filter(Boolean);
|
|
const fotosAdicionais = produto.fotosAdicionais || [];
|
|
const todasFotos = [
|
|
produto.foto_principal,
|
|
...fotosDasVariacoes,
|
|
...fotosAdicionais
|
|
].filter(Boolean);
|
|
|
|
// Remover duplicatas
|
|
const galeriaFotos = [...new Set(todasFotos)];
|
|
|
|
return {
|
|
id: produto.id?.toString() ?? '',
|
|
id_produto: produto.id_produto || '',
|
|
codigo: produto.id_produto || '',
|
|
nome: produto.nome,
|
|
marca: produto.marca,
|
|
genero: generoLabel,
|
|
generoFiltro: generoLabel.toLowerCase(),
|
|
estacao: produto.estacao,
|
|
descricao: produto.descricao,
|
|
preco_venda: Number(produto.valor_revenda ?? produto.valor_compra ?? 0),
|
|
preco_promocional: produto.preco_promocional ? Number(produto.preco_promocional) : null,
|
|
em_promocao: produto.em_promocao || false,
|
|
novidade: produto.novidade || false,
|
|
variacoes,
|
|
imagemPrincipal: galeriaFotos[0] || null,
|
|
galeriaFotos: galeriaFotos,
|
|
ativo: produto.ativo,
|
|
visivelCatalogo: produto.visivel_catalogo
|
|
};
|
|
});
|
|
}
|
|
|
|
// Renderizar produtos
|
|
function renderizarProdutos() {
|
|
const container = document.getElementById('produtosGrid');
|
|
if (!container) return;
|
|
|
|
const produtosFiltrados = obterProdutosFiltrados();
|
|
const noProducts = document.getElementById('noProducts');
|
|
|
|
if (!produtosFiltrados.length) {
|
|
container.innerHTML = '';
|
|
if (noProducts) noProducts.style.display = 'block';
|
|
return;
|
|
}
|
|
|
|
if (noProducts) noProducts.style.display = 'none';
|
|
|
|
container.innerHTML = produtosFiltrados.map(produto => {
|
|
const variacoesDisponiveis = produto.variacoes || [];
|
|
const tamanhosDisponiveis = [...new Set(variacoesDisponiveis.map(v => v.tamanho).filter(Boolean))]
|
|
.sort((a, b) => a.toString().localeCompare(b.toString(), 'pt-BR', { numeric: true, sensitivity: 'base' }));
|
|
const temEstoque = variacoesDisponiveis.some(v => v.quantidade > 0);
|
|
|
|
// Preços
|
|
const precoNormal = produto.preco_venda;
|
|
const precoPromo = produto.preco_promocional;
|
|
const emPromocao = produto.em_promocao && precoPromo && precoPromo > 0;
|
|
const precoExibir = emPromocao ? precoPromo : precoNormal;
|
|
const precoFormatado = `R$ ${precoExibir.toFixed(2).replace('.', ',')}`;
|
|
const precoNormalFormatado = `R$ ${precoNormal.toFixed(2).replace('.', ',')}`;
|
|
|
|
const tamanhosVisiveis = tamanhosDisponiveis.slice(0, 4);
|
|
const possuiMaisTamanhos = tamanhosDisponiveis.length > tamanhosVisiveis.length;
|
|
|
|
// Badges
|
|
const exibirNovidades = catalogoConfig.exibirNovidades !== false;
|
|
const exibirPromocoes = catalogoConfig.exibirPromocoes !== false;
|
|
const mostrarBadgeNovidade = produto.novidade && exibirNovidades;
|
|
const mostrarBadgePromocao = emPromocao && exibirPromocoes;
|
|
|
|
return `
|
|
<div class="produto-card ${!temEstoque ? 'sem-estoque' : ''}" onclick="abrirProdutoModal('${produto.id}')" data-produto-id="${produto.id}">
|
|
${produto.imagemPrincipal ?
|
|
`<img class="produto-card-image" src="${produto.imagemPrincipal}" alt="${produto.nome}" loading="lazy" onerror="this.style.display='none';">` :
|
|
`<div class="produto-card-no-image"><i class="fas fa-image"></i></div>`
|
|
}
|
|
|
|
${(mostrarBadgePromocao || mostrarBadgeNovidade || !temEstoque) ? `
|
|
<div class="produto-badges">
|
|
${!temEstoque ? '<span class="badge-esgotado">ESGOTADO</span>' : ''}
|
|
${mostrarBadgePromocao ? '<span class="badge-promocao">🏷️ PROMOÇÃO</span>' : ''}
|
|
${mostrarBadgeNovidade ? '<span class="badge-novidade">✨ NOVO</span>' : ''}
|
|
</div>
|
|
` : ''}
|
|
|
|
<div class="produto-info-minimal">
|
|
<div class="produto-nome-minimal">${produto.nome}</div>
|
|
<div class="produto-preco-row">
|
|
<div class="produto-precos">
|
|
${emPromocao ? `<span class="produto-preco-original">${precoNormalFormatado}</span>` : ''}
|
|
<span class="produto-preco-minimal ${emPromocao ? 'preco-promocional' : ''}">${precoFormatado}</span>
|
|
</div>
|
|
<div class="produto-tamanhos-inline">
|
|
${tamanhosDisponiveis.length
|
|
? tamanhosVisiveis.map(tamanho => `<span class="tamanho-chip">${tamanho}</span>`).join('')
|
|
: '<span class="tamanho-chip">Único</span>'}
|
|
${possuiMaisTamanhos ? '<span class="tamanho-chip">+</span>' : ''}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
}
|
|
|
|
function obterProdutosFiltrados() {
|
|
const generoFiltro = filtros.genero;
|
|
const tamanhoFiltro = filtros.tamanho;
|
|
const destaqueFiltro = filtros.destaque;
|
|
|
|
return produtos.filter(produto => {
|
|
const generoConfere = !generoFiltro || produto.generoFiltro === generoFiltro;
|
|
const tamanhoConfere = !tamanhoFiltro || produto.variacoes.some(variacao => {
|
|
return (variacao.tamanhoNormalizado || (variacao.tamanho || '').toString().toLowerCase()) === tamanhoFiltro;
|
|
});
|
|
|
|
let destaqueConfere = true;
|
|
if (destaqueFiltro === 'promocao') {
|
|
destaqueConfere = produto.em_promocao && produto.preco_promocional > 0;
|
|
} else if (destaqueFiltro === 'novo') {
|
|
destaqueConfere = produto.novidade;
|
|
}
|
|
|
|
return generoConfere && tamanhoConfere && destaqueConfere;
|
|
});
|
|
}
|
|
|
|
// Função de extração de cor desativada (não utilizada no layout atual)
|
|
// function extrairCorDominante(img) { ... }
|
|
|
|
// Verificar autenticação com localStorage
|
|
async function verificarAutenticacao() {
|
|
try {
|
|
// Verificar se há dados salvos no localStorage
|
|
const savedUser = localStorage.getItem('liberi_user');
|
|
|
|
if (savedUser) {
|
|
const userData = JSON.parse(savedUser);
|
|
|
|
// Verificar se o cliente ainda existe no banco
|
|
const { data: cliente, error } = await supabaseClient
|
|
.from('clientes')
|
|
.select('*')
|
|
.eq('id', userData.cliente.id)
|
|
.single();
|
|
|
|
if (!error && cliente) {
|
|
currentUser = { cliente };
|
|
atualizarInterfaceUsuario(true);
|
|
console.log('✅ Login restaurado:', cliente.nome_completo);
|
|
return true;
|
|
} else {
|
|
// Cliente não existe mais, limpar localStorage
|
|
localStorage.removeItem('liberi_user');
|
|
}
|
|
}
|
|
|
|
// Não há login salvo ou cliente não existe
|
|
currentUser = null;
|
|
atualizarInterfaceUsuario(false);
|
|
return false;
|
|
} catch (error) {
|
|
console.error('Erro ao verificar autenticação:', error);
|
|
localStorage.removeItem('liberi_user');
|
|
currentUser = null;
|
|
atualizarInterfaceUsuario(false);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Atualizar interface do usuário
|
|
function atualizarInterfaceUsuario(isLoggedIn) {
|
|
const userNotLogged = document.getElementById('userNotLogged');
|
|
const userLogged = document.getElementById('userLogged');
|
|
const userName = document.getElementById('userName');
|
|
|
|
if (isLoggedIn && currentUser?.cliente) {
|
|
userNotLogged.style.display = 'none';
|
|
userLogged.style.display = 'flex';
|
|
userName.textContent = currentUser.cliente.nome_completo.split(' ')[0];
|
|
} else {
|
|
userNotLogged.style.display = 'block';
|
|
userLogged.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Função de login
|
|
async function handleLogin(event) {
|
|
event.preventDefault();
|
|
|
|
const phone = document.getElementById('loginPhone').value.trim();
|
|
const password = document.getElementById('loginPassword').value.trim();
|
|
const loginBtn = document.getElementById('loginBtn');
|
|
|
|
if (!phone || !password) {
|
|
mostrarPopup('Por favor, digite seu WhatsApp e senha', 'error');
|
|
return;
|
|
}
|
|
|
|
const cleanPhone = phone.replace(/\D/g, '');
|
|
|
|
loginBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Entrando...';
|
|
loginBtn.disabled = true;
|
|
|
|
try {
|
|
// Buscar cliente na tabela
|
|
const { data: cliente, error: clienteError } = await supabaseClient
|
|
.from('clientes')
|
|
.select('*')
|
|
.eq('whatsapp', cleanPhone)
|
|
.single();
|
|
|
|
if (clienteError || !cliente) {
|
|
throw new Error('Cliente não encontrado. Verifique seu número ou cadastre-se.');
|
|
}
|
|
|
|
// Verificar senha diretamente (sem Supabase Auth)
|
|
if (cliente.senha_hash !== password) {
|
|
throw new Error('Senha incorreta. Tente novamente.');
|
|
}
|
|
|
|
// Login bem-sucedido
|
|
currentUser = { cliente };
|
|
|
|
// Salvar no localStorage para manter login
|
|
localStorage.setItem('liberi_user', JSON.stringify(currentUser));
|
|
|
|
// Mostrar popup de confirmação
|
|
mostrarConfirmacao(
|
|
'Login realizado!',
|
|
`Bem-vindo(a) de volta, ${cliente.nome_completo.split(' ')[0]}!`,
|
|
() => {
|
|
closeLoginModal();
|
|
atualizarInterfaceUsuario(true);
|
|
}
|
|
);
|
|
|
|
} catch (error) {
|
|
console.error('Erro no login:', error);
|
|
mostrarPopup(error.message, 'error');
|
|
} finally {
|
|
loginBtn.innerHTML = '<i class="fas fa-sign-in-alt"></i> Entrar';
|
|
loginBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
// Função de cadastro
|
|
async function handleRegister(event) {
|
|
event.preventDefault();
|
|
|
|
const formData = {
|
|
nome_completo: document.getElementById('registerName').value.trim(),
|
|
email: document.getElementById('registerEmail').value.trim() || null,
|
|
whatsapp: document.getElementById('registerWhatsapp').value.replace(/\D/g, ''),
|
|
endereco: document.getElementById('registerAddress').value.trim(),
|
|
senha: document.getElementById('registerPassword').value.trim()
|
|
};
|
|
|
|
const registerBtn = document.getElementById('registerBtn');
|
|
|
|
if (!formData.nome_completo || !formData.whatsapp || !formData.endereco || !formData.senha) {
|
|
mostrarPopup('Preencha todos os campos obrigatórios', 'error');
|
|
return;
|
|
}
|
|
|
|
if (formData.senha.length < 6) {
|
|
mostrarPopup('A senha deve ter pelo menos 6 caracteres', 'error');
|
|
return;
|
|
}
|
|
|
|
registerBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Criando conta...';
|
|
registerBtn.disabled = true;
|
|
|
|
try {
|
|
const { data: existingClient, error: checkError } = await supabaseClient
|
|
.from('clientes')
|
|
.select('id')
|
|
.eq('whatsapp', formData.whatsapp)
|
|
.single();
|
|
|
|
if (existingClient) {
|
|
throw new Error('Este WhatsApp já está cadastrado. Faça login.');
|
|
}
|
|
|
|
// Inserir cliente com senha diretamente na tabela
|
|
const { data: cliente, error: clienteError } = await supabaseClient
|
|
.from('clientes')
|
|
.insert([{
|
|
nome_completo: formData.nome_completo,
|
|
email: formData.email,
|
|
whatsapp: formData.whatsapp,
|
|
endereco: formData.endereco,
|
|
senha_hash: formData.senha
|
|
}])
|
|
.select()
|
|
.single();
|
|
|
|
if (clienteError) throw clienteError;
|
|
|
|
// Login automático após cadastro
|
|
currentUser = { cliente };
|
|
|
|
// Salvar no localStorage para manter login
|
|
localStorage.setItem('liberi_user', JSON.stringify(currentUser));
|
|
|
|
// Mostrar popup de confirmação
|
|
mostrarConfirmacao(
|
|
'Conta criada com sucesso!',
|
|
`Bem-vindo(a), ${formData.nome_completo.split(' ')[0]}! Sua conta foi criada e você já está logado(a).`,
|
|
() => {
|
|
closeRegisterModal();
|
|
atualizarInterfaceUsuario(true);
|
|
}
|
|
);
|
|
|
|
} catch (error) {
|
|
console.error('Erro no cadastro:', error);
|
|
mostrarPopup(error.message, 'error');
|
|
} finally {
|
|
registerBtn.innerHTML = '<i class="fas fa-user-plus"></i> Criar Conta';
|
|
registerBtn.disabled = false;
|
|
}
|
|
}
|
|
|
|
// Funções dos modais de autenticação com animação
|
|
function ativarAuthModal(modal) {
|
|
if (!modal) return;
|
|
|
|
modal.classList.add('pre-active');
|
|
requestAnimationFrame(() => {
|
|
modal.classList.remove('pre-active');
|
|
modal.classList.add('active');
|
|
});
|
|
}
|
|
|
|
function desativarAuthModal(modal) {
|
|
if (!modal) return;
|
|
|
|
if (!modal.classList.contains('active')) {
|
|
modal.classList.remove('pre-active');
|
|
return;
|
|
}
|
|
|
|
const finalizar = (event) => {
|
|
if (event.target !== modal) {
|
|
return;
|
|
}
|
|
modal.removeEventListener('transitionend', finalizar);
|
|
modal.classList.remove('pre-active');
|
|
};
|
|
|
|
modal.addEventListener('transitionend', finalizar);
|
|
modal.classList.remove('active');
|
|
}
|
|
|
|
function showRegisterModal() {
|
|
const loginModal = document.getElementById('loginModal');
|
|
const registerModal = document.getElementById('registerModal');
|
|
|
|
if (loginModal) {
|
|
desativarAuthModal(loginModal);
|
|
}
|
|
if (registerModal) {
|
|
ativarAuthModal(registerModal);
|
|
}
|
|
}
|
|
|
|
function closeRegisterModal() {
|
|
desativarAuthModal(document.getElementById('registerModal'));
|
|
}
|
|
|
|
function closeLoginModal() {
|
|
desativarAuthModal(document.getElementById('loginModal'));
|
|
}
|
|
|
|
// Funções auxiliares
|
|
function mostrarLoading(show) {
|
|
const loading = document.getElementById('loading');
|
|
const grid = document.getElementById('produtosGrid');
|
|
|
|
if (loading) loading.style.display = show ? 'block' : 'none';
|
|
if (grid) grid.style.display = show ? 'none' : 'grid';
|
|
}
|
|
|
|
function atualizarContadorCarrinho() {
|
|
const cartCount = document.querySelector('.cart-count');
|
|
if (cartCount) {
|
|
const totalItens = carrinho.reduce((sum, item) => sum + item.quantidade, 0);
|
|
cartCount.textContent = totalItens;
|
|
}
|
|
}
|
|
|
|
function popularFiltros() {
|
|
const tamanhoContainer = document.getElementById('tamanhoFilterChips');
|
|
const generoContainer = document.getElementById('generoFilterChips');
|
|
if (!tamanhoContainer || !generoContainer) return;
|
|
|
|
const tamanhos = new Set();
|
|
const generos = new Set();
|
|
|
|
produtos.forEach(produto => {
|
|
(produto.variacoes || []).forEach(variacao => {
|
|
if (variacao.tamanho) {
|
|
tamanhos.add(variacao.tamanho.toString());
|
|
}
|
|
});
|
|
if (produto.genero) {
|
|
generos.add(produto.genero);
|
|
}
|
|
});
|
|
|
|
const ordenar = (a, b) => a.toString().localeCompare(b.toString(), 'pt-BR', { numeric: true, sensitivity: 'base' });
|
|
const tamanhosOrdenados = Array.from(tamanhos).sort(ordenar);
|
|
const generosOrdenados = Array.from(generos).sort(ordenar);
|
|
|
|
const construirChips = (valores, tipo) => {
|
|
const ativo = filtros[tipo] || '';
|
|
const itens = [''].concat(valores);
|
|
return itens.map(valor => {
|
|
const normalizado = valor ? valor.toString().toLowerCase() : '';
|
|
const label = valor || 'Todos';
|
|
const ativoChip = normalizado === ativo;
|
|
return `<button class="filter-chip ${ativoChip ? 'active' : ''}" data-filter="${tipo}" data-value="${escapeHtmlAttr(valor || '')}">
|
|
${label}
|
|
</button>`;
|
|
}).join('');
|
|
};
|
|
|
|
tamanhoContainer.innerHTML = construirChips(tamanhosOrdenados, 'tamanho');
|
|
generoContainer.innerHTML = construirChips(generosOrdenados, 'genero');
|
|
|
|
// Atualizar filtros de destaque (Promoção e Novo)
|
|
const destaquesContainer = document.getElementById('destaquesFilterChips');
|
|
if (destaquesContainer) {
|
|
const destaqueAtivo = filtros.destaque || '';
|
|
destaquesContainer.querySelectorAll('.filter-chip').forEach(chip => {
|
|
const valorChip = (chip.dataset.value || '').toLowerCase();
|
|
if (valorChip === destaqueAtivo) {
|
|
chip.classList.add('active');
|
|
} else {
|
|
chip.classList.remove('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
atualizarEstadoFiltro();
|
|
}
|
|
|
|
function handleFilterChipClick(event) {
|
|
const chip = event.target.closest('.filter-chip');
|
|
if (!chip) return;
|
|
|
|
const tipo = chip.dataset.filter;
|
|
if (!tipo) return;
|
|
|
|
const valorOriginal = (chip.dataset.value || '').toString();
|
|
const valorNormalizado = valorOriginal.toLowerCase();
|
|
|
|
if (filtros[tipo] === valorNormalizado) {
|
|
filtros[tipo] = '';
|
|
} else {
|
|
filtros[tipo] = valorNormalizado;
|
|
}
|
|
|
|
popularFiltros();
|
|
renderizarProdutos();
|
|
}
|
|
|
|
// Estado do modal
|
|
let produtoSelecionado = null;
|
|
let variacaoSelecionada = null;
|
|
|
|
function abrirProdutoModal(produtoId) {
|
|
const produto = produtos.find(p => p.id === produtoId);
|
|
if (!produto) return;
|
|
|
|
produtoSelecionado = produto;
|
|
variacaoSelecionada = null;
|
|
|
|
const modal = document.getElementById('produtoModal');
|
|
const modalImage = document.getElementById('produtoModalImage');
|
|
const modalNome = document.getElementById('produtoModalNome');
|
|
const modalMarca = document.getElementById('produtoModalMarca');
|
|
const modalPreco = document.getElementById('produtoModalPreco');
|
|
const modalDescricao = document.getElementById('produtoModalDescricao');
|
|
const modalVariacoesGrid = document.getElementById('produtoModalVariacoesGrid');
|
|
const modalBotao = document.getElementById('produtoModalBotao');
|
|
|
|
// Preencher informações básicas
|
|
modalNome.textContent = produto.nome;
|
|
modalMarca.textContent = produto.marca;
|
|
|
|
// Preço (considerar promoção)
|
|
const precoNormal = produto.preco_venda;
|
|
const precoPromo = produto.preco_promocional;
|
|
const emPromocao = produto.em_promocao && precoPromo && precoPromo > 0;
|
|
const precoExibir = emPromocao ? precoPromo : precoNormal;
|
|
const precoFormatado = `R$ ${precoExibir.toFixed(2).replace('.', ',')}`;
|
|
|
|
if (emPromocao) {
|
|
const precoNormalFormatado = `R$ ${precoNormal.toFixed(2).replace('.', ',')}`;
|
|
modalPreco.innerHTML = `
|
|
<span class="modal-preco-original">${precoNormalFormatado}</span>
|
|
<span class="modal-preco-promocional">${precoFormatado}</span>
|
|
`;
|
|
} else {
|
|
modalPreco.textContent = precoFormatado;
|
|
}
|
|
|
|
modalDescricao.textContent = produto.descricao || 'Produto de qualidade superior para o conforto e estilo do seu filho.';
|
|
|
|
// Preencher imagem e galeria
|
|
const galeriaFotos = produto.galeriaFotos || [];
|
|
const imagemPrincipal = galeriaFotos[0] || '';
|
|
|
|
if (imagemPrincipal) {
|
|
const imagemEscapada = escapeHtmlAttr(imagemPrincipal);
|
|
const nomeEscapado = escapeHtmlAttr(produto.nome || '');
|
|
modalImage.dataset.imageUrl = imagemPrincipal;
|
|
modalImage.innerHTML = `
|
|
<button type="button" class="produto-modal-image-trigger" aria-label="Ampliar imagem do produto">
|
|
<img src="${imagemEscapada}" alt="${nomeEscapado}" id="modalImagemPrincipal">
|
|
<span class="produto-modal-image-zoom-hint">
|
|
<i class="fas fa-expand"></i>
|
|
Ver maior
|
|
</span>
|
|
</button>
|
|
${galeriaFotos.length > 1 ? `
|
|
<div class="produto-modal-galeria">
|
|
${galeriaFotos.map((foto, index) => `
|
|
<img src="${escapeHtmlAttr(foto)}"
|
|
alt="${nomeEscapado} - Foto ${index + 1}"
|
|
class="galeria-miniatura ${index === 0 ? 'active' : ''}"
|
|
onclick="trocarImagemModal('${escapeHtmlAttr(foto).replace(/'/g, "\\'")}', this)">
|
|
`).join('')}
|
|
</div>
|
|
` : ''}
|
|
`;
|
|
const trigger = modalImage.querySelector('.produto-modal-image-trigger');
|
|
if (trigger) {
|
|
trigger.addEventListener('click', expandirImagemProduto);
|
|
}
|
|
} else {
|
|
modalImage.dataset.imageUrl = '';
|
|
modalImage.innerHTML = `<div class="placeholder-img"><i class="fas fa-image"></i></div>`;
|
|
}
|
|
|
|
// Preencher variações
|
|
const variacoesComEstoque = produto.variacoes.filter(v => v.quantidade > 0);
|
|
if (variacoesComEstoque.length > 0) {
|
|
modalVariacoesGrid.innerHTML = variacoesComEstoque.map(variacao => `
|
|
<div class="variacao-item ${variacao.quantidade === 0 ? 'sem-estoque' : ''}"
|
|
onclick="selecionarVariacao('${variacao.id}')"
|
|
data-variacao-id="${variacao.id}">
|
|
<div class="variacao-tamanho">${variacao.tamanho}</div>
|
|
<div class="variacao-cor">${variacao.cor}</div>
|
|
<div class="variacao-estoque">${variacao.quantidade > 0 ? `${variacao.quantidade} disponível${variacao.quantidade > 1 ? 'is' : ''}` : 'Esgotado'}</div>
|
|
</div>
|
|
`).join('');
|
|
|
|
modalBotao.disabled = true;
|
|
modalBotao.style.opacity = '0.5';
|
|
} else {
|
|
modalVariacoesGrid.innerHTML = '<p style="text-align: center; color: #dc3545;">Produto esgotado</p>';
|
|
modalBotao.disabled = true;
|
|
modalBotao.style.opacity = '0.5';
|
|
}
|
|
|
|
// Exibir modal
|
|
if (!modal.classList.contains('active')) {
|
|
modal.classList.add('pre-active');
|
|
requestAnimationFrame(() => {
|
|
modal.classList.remove('pre-active');
|
|
modal.classList.add('active');
|
|
});
|
|
}
|
|
}
|
|
|
|
function trocarImagemModal(novaUrl, elemento) {
|
|
const imagemPrincipal = document.getElementById('modalImagemPrincipal');
|
|
const modalImage = document.getElementById('produtoModalImage');
|
|
|
|
if (imagemPrincipal) {
|
|
imagemPrincipal.src = novaUrl;
|
|
modalImage.dataset.imageUrl = novaUrl;
|
|
}
|
|
|
|
// Atualizar classe active nas miniaturas
|
|
const miniaturas = document.querySelectorAll('.galeria-miniatura');
|
|
miniaturas.forEach(min => min.classList.remove('active'));
|
|
if (elemento) {
|
|
elemento.classList.add('active');
|
|
}
|
|
}
|
|
|
|
function fecharProdutoModal(event) {
|
|
if (event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
const modal = document.getElementById('produtoModal');
|
|
|
|
if (modal) {
|
|
modal.classList.remove('active');
|
|
|
|
const remover = () => {
|
|
modal.removeEventListener('transitionend', remover);
|
|
if (!modal.classList.contains('active')) {
|
|
modal.style.display = 'none';
|
|
void modal.offsetWidth;
|
|
modal.style.display = '';
|
|
}
|
|
};
|
|
|
|
modal.addEventListener('transitionend', remover);
|
|
}
|
|
|
|
fecharImagemExpandida();
|
|
produtoSelecionado = null;
|
|
variacaoSelecionada = null;
|
|
}
|
|
|
|
function selecionarVariacao(variacaoId) {
|
|
if (!produtoSelecionado) return;
|
|
|
|
const variacao = produtoSelecionado.variacoes.find(v => v.id.toString() === variacaoId.toString());
|
|
if (!variacao || variacao.quantidade === 0) return;
|
|
|
|
// Remover seleção anterior
|
|
document.querySelectorAll('.variacao-item').forEach(item => {
|
|
item.classList.remove('selected');
|
|
});
|
|
|
|
// Adicionar seleção atual
|
|
const item = document.querySelector(`[data-variacao-id="${variacaoId}"]`);
|
|
if (item) {
|
|
item.classList.add('selected');
|
|
variacaoSelecionada = variacao;
|
|
|
|
const modalImage = document.getElementById('produtoModalImage');
|
|
if (modalImage) {
|
|
const fallbackImagem = produtoSelecionado.imagemPrincipal || (produtoSelecionado.variacoes || []).find(v => Array.isArray(v.fotos) && v.fotos.length)?.fotos?.[0] || '';
|
|
const novaImagem = (variacao.fotos && variacao.fotos.length > 0)
|
|
? variacao.fotos[0]
|
|
: fallbackImagem;
|
|
|
|
if (novaImagem) {
|
|
let trigger = modalImage.querySelector('.produto-modal-image-trigger');
|
|
if (!trigger) {
|
|
const imagemEscapada = escapeHtmlAttr(novaImagem);
|
|
const nomeEscapado = escapeHtmlAttr(produtoSelecionado.nome || '');
|
|
modalImage.innerHTML = `
|
|
<button type="button" class="produto-modal-image-trigger" aria-label="Ampliar imagem do produto">
|
|
<img src="${imagemEscapada}" alt="${nomeEscapado}">
|
|
<span class="produto-modal-image-zoom-hint">
|
|
<i class="fas fa-expand"></i>
|
|
Ver maior
|
|
</span>
|
|
</button>
|
|
`;
|
|
trigger = modalImage.querySelector('.produto-modal-image-trigger');
|
|
if (trigger) {
|
|
trigger.addEventListener('click', expandirImagemProduto);
|
|
}
|
|
}
|
|
|
|
const imgElement = modalImage.querySelector('img');
|
|
if (imgElement) {
|
|
modalImage.dataset.imageUrl = novaImagem;
|
|
imgElement.src = novaImagem;
|
|
const descricaoImagem = `${produtoSelecionado.nome || ''} - ${variacao.tamanho || ''} ${variacao.cor || ''}`.trim();
|
|
if (descricaoImagem) {
|
|
imgElement.alt = descricaoImagem;
|
|
}
|
|
}
|
|
} else {
|
|
modalImage.dataset.imageUrl = '';
|
|
}
|
|
}
|
|
|
|
// Habilitar botão
|
|
const modalBotao = document.getElementById('produtoModalBotao');
|
|
modalBotao.disabled = false;
|
|
modalBotao.style.opacity = '1';
|
|
}
|
|
}
|
|
|
|
let currentImageIndex = 0;
|
|
let viewerImages = [];
|
|
|
|
function expandirImagemProduto(event) {
|
|
if (event) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
|
|
const viewer = document.getElementById('produtoImageViewer');
|
|
const viewerImg = document.getElementById('produtoImageViewerImg');
|
|
const modalImage = document.getElementById('produtoModalImage');
|
|
|
|
if (!viewer || !viewerImg || !modalImage) {
|
|
return;
|
|
}
|
|
|
|
const imageUrl = modalImage.dataset.imageUrl;
|
|
if (!imageUrl) {
|
|
return;
|
|
}
|
|
|
|
// Obter galeria de fotos do produto
|
|
if (produtoSelecionado && produtoSelecionado.galeriaFotos) {
|
|
viewerImages = produtoSelecionado.galeriaFotos;
|
|
currentImageIndex = viewerImages.indexOf(imageUrl);
|
|
if (currentImageIndex === -1) currentImageIndex = 0;
|
|
} else {
|
|
viewerImages = [imageUrl];
|
|
currentImageIndex = 0;
|
|
}
|
|
|
|
viewerImg.src = imageUrl;
|
|
viewer.classList.add('active');
|
|
|
|
// Mostrar/ocultar controles de navegação
|
|
const prevBtn = viewer.querySelector('.viewer-prev');
|
|
const nextBtn = viewer.querySelector('.viewer-next');
|
|
const counter = viewer.querySelector('.viewer-counter');
|
|
|
|
if (viewerImages.length > 1) {
|
|
if (prevBtn) prevBtn.style.display = 'flex';
|
|
if (nextBtn) nextBtn.style.display = 'flex';
|
|
if (counter) {
|
|
counter.style.display = 'block';
|
|
counter.textContent = `${currentImageIndex + 1} / ${viewerImages.length}`;
|
|
}
|
|
} else {
|
|
if (prevBtn) prevBtn.style.display = 'none';
|
|
if (nextBtn) nextBtn.style.display = 'none';
|
|
if (counter) counter.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function navegarImagemViewer(direction) {
|
|
if (viewerImages.length <= 1) return;
|
|
|
|
currentImageIndex += direction;
|
|
|
|
// Loop circular
|
|
if (currentImageIndex < 0) {
|
|
currentImageIndex = viewerImages.length - 1;
|
|
} else if (currentImageIndex >= viewerImages.length) {
|
|
currentImageIndex = 0;
|
|
}
|
|
|
|
const viewerImg = document.getElementById('produtoImageViewerImg');
|
|
const counter = document.querySelector('.viewer-counter');
|
|
|
|
if (viewerImg) {
|
|
viewerImg.src = viewerImages[currentImageIndex];
|
|
}
|
|
|
|
if (counter) {
|
|
counter.textContent = `${currentImageIndex + 1} / ${viewerImages.length}`;
|
|
}
|
|
}
|
|
|
|
function fecharImagemExpandida() {
|
|
const viewer = document.getElementById('produtoImageViewer');
|
|
const viewerImg = document.getElementById('produtoImageViewerImg');
|
|
|
|
if (!viewer || !viewerImg) {
|
|
return;
|
|
}
|
|
|
|
viewer.classList.remove('active');
|
|
viewerImg.src = '';
|
|
viewerImages = [];
|
|
currentImageIndex = 0;
|
|
}
|
|
|
|
function adicionarAoCarrinhoModal() {
|
|
if (!produtoSelecionado || !variacaoSelecionada) {
|
|
mostrarPopup('Selecione um tamanho e cor antes de adicionar ao carrinho', 'error');
|
|
return;
|
|
}
|
|
|
|
// Verificar se já existe no carrinho
|
|
const itemExistente = carrinho.find(item =>
|
|
item.produtoId === produtoSelecionado.id &&
|
|
item.variacaoId === variacaoSelecionada.id
|
|
);
|
|
|
|
if (itemExistente) {
|
|
// Verificar se há estoque disponível
|
|
if (itemExistente.quantidade < variacaoSelecionada.quantidade) {
|
|
itemExistente.quantidade++;
|
|
} else {
|
|
mostrarPopup('Quantidade máxima em estoque já adicionada', 'error');
|
|
return;
|
|
}
|
|
} else {
|
|
// Adicionar novo item
|
|
carrinho.push({
|
|
produtoId: produtoSelecionado.id,
|
|
variacaoId: variacaoSelecionada.id,
|
|
codigo: produtoSelecionado.codigo || produtoSelecionado.id_produto || '',
|
|
nome: `${produtoSelecionado.marca} ${produtoSelecionado.nome}`,
|
|
tamanho: variacaoSelecionada.tamanho,
|
|
cor: variacaoSelecionada.cor,
|
|
preco: produtoSelecionado.preco_venda,
|
|
quantidade: 1,
|
|
imagem: produtoSelecionado.imagemPrincipal
|
|
});
|
|
}
|
|
|
|
// Salvar carrinho no localStorage
|
|
localStorage.setItem('liberi_carrinho', JSON.stringify(carrinho));
|
|
|
|
// Atualizar interface
|
|
atualizarContadorCarrinho();
|
|
renderizarCarrinho();
|
|
|
|
// Fechar modal e mostrar confirmação
|
|
fecharProdutoModal();
|
|
mostrarPopup('Produto adicionado ao carrinho!', 'success');
|
|
}
|
|
|
|
function toggleFilterPanel() {
|
|
const panel = document.getElementById('filterPanel');
|
|
const filterBtn = document.querySelector('.filter-btn');
|
|
if (panel) {
|
|
const isOpen = panel.classList.toggle('open');
|
|
if (filterBtn) {
|
|
filterBtn.classList.toggle('active', isOpen);
|
|
}
|
|
if (isOpen) {
|
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
}
|
|
}
|
|
}
|
|
|
|
function toggleCart() {
|
|
const cartModal = document.getElementById('cartModal');
|
|
|
|
if (cartModal) {
|
|
const isOpen = cartModal.classList.contains('active');
|
|
|
|
if (isOpen) {
|
|
desativarAuthModal(cartModal);
|
|
} else {
|
|
renderizarCarrinho();
|
|
ativarAuthModal(cartModal);
|
|
}
|
|
}
|
|
}
|
|
|
|
function renderizarCarrinho() {
|
|
const cartContent = document.getElementById('cartContent');
|
|
const cartFooter = document.getElementById('cartFooter');
|
|
const cartTotal = document.getElementById('cartTotal');
|
|
|
|
if (carrinho.length === 0) {
|
|
cartContent.innerHTML = `
|
|
<div class="empty-cart" style="text-align: center; padding: 2rem;">
|
|
<i class="fas fa-shopping-cart" style="font-size: 3rem; color: #cbd5e0; margin-bottom: 1rem;"></i>
|
|
<p style="font-size: 1.1rem; color: #4a5568; margin-bottom: 0.5rem;">Seu carrinho está vazio</p>
|
|
<span style="color: #9ca3af;">Adicione produtos para começar!</span>
|
|
</div>
|
|
`;
|
|
cartFooter.style.display = 'none';
|
|
if (cartTotal) {
|
|
cartTotal.textContent = '0,00';
|
|
}
|
|
return;
|
|
}
|
|
|
|
let total = 0;
|
|
|
|
cartContent.innerHTML = carrinho.map((item, index) => {
|
|
const subtotal = item.preco * item.quantidade;
|
|
total += subtotal;
|
|
|
|
return `
|
|
<div class="cart-item">
|
|
<div class="cart-item-image">
|
|
${item.imagem ?
|
|
`<img src="${item.imagem}" alt="${item.nome}">` :
|
|
`<i class="fas fa-image"></i>`
|
|
}
|
|
</div>
|
|
<div class="cart-item-info">
|
|
<h4>${item.nome}</h4>
|
|
<p>${item.tamanho} - ${item.cor}</p>
|
|
<div class="cart-item-price">R$ ${item.preco.toFixed(2).replace('.', ',')}</div>
|
|
</div>
|
|
<div class="cart-item-actions">
|
|
<div class="quantity-control">
|
|
<button onclick="alterarQuantidade(${index}, -1)">-</button>
|
|
<span>${item.quantidade}</span>
|
|
<button onclick="alterarQuantidade(${index}, 1)">+</button>
|
|
</div>
|
|
<button class="remove-item" onclick="removerDoCarrinho(${index})">
|
|
<i class="fas fa-trash"></i>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}).join('');
|
|
|
|
if (cartTotal) {
|
|
cartTotal.textContent = total.toFixed(2).replace('.', ',');
|
|
}
|
|
cartFooter.style.display = 'flex';
|
|
}
|
|
|
|
function alterarQuantidade(index, delta) {
|
|
if (index < 0 || index >= carrinho.length) return;
|
|
|
|
const item = carrinho[index];
|
|
const produto = produtos.find(p => p.id === item.produtoId);
|
|
const variacao = produto?.variacoes.find(v => v.id === item.variacaoId);
|
|
|
|
const novaQuantidade = item.quantidade + delta;
|
|
|
|
if (novaQuantidade <= 0) {
|
|
removerDoCarrinho(index);
|
|
return;
|
|
}
|
|
|
|
if (variacao && novaQuantidade > variacao.quantidade) {
|
|
mostrarPopup('Quantidade máxima em estoque atingida', 'error');
|
|
return;
|
|
}
|
|
|
|
item.quantidade = novaQuantidade;
|
|
localStorage.setItem('liberi_carrinho', JSON.stringify(carrinho));
|
|
|
|
atualizarContadorCarrinho();
|
|
renderizarCarrinho();
|
|
}
|
|
|
|
function removerDoCarrinho(index) {
|
|
if (index < 0 || index >= carrinho.length) return;
|
|
|
|
carrinho.splice(index, 1);
|
|
localStorage.setItem('liberi_carrinho', JSON.stringify(carrinho));
|
|
|
|
atualizarContadorCarrinho();
|
|
renderizarCarrinho();
|
|
|
|
if (carrinho.length === 0) {
|
|
toggleCart();
|
|
}
|
|
}
|
|
|
|
async function finalizarPedido() {
|
|
if (!currentUser) {
|
|
toggleCart();
|
|
mostrarPopup('Faça login para finalizar seu pedido', 'error');
|
|
setTimeout(() => showLoginModal(), 500);
|
|
return;
|
|
}
|
|
|
|
if (carrinho.length === 0) {
|
|
mostrarPopup('Adicione produtos ao carrinho antes de finalizar', 'error');
|
|
return;
|
|
}
|
|
|
|
const checkoutBtn = document.querySelector('.checkout-btn');
|
|
const btnOriginalHTML = checkoutBtn ? checkoutBtn.innerHTML : null;
|
|
if (checkoutBtn) {
|
|
checkoutBtn.disabled = true;
|
|
checkoutBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Enviando...';
|
|
}
|
|
|
|
const cliente = currentUser.cliente;
|
|
const totalPedido = carrinho.reduce((sum, item) => sum + (item.preco * item.quantidade), 0);
|
|
|
|
let mensagem = `*Novo Pedido - Liberi Kids*\n\n`;
|
|
mensagem += `*Cliente:* ${cliente.nome_completo}\n`;
|
|
mensagem += `*WhatsApp:* ${cliente.whatsapp}\n`;
|
|
if (cliente.endereco) {
|
|
mensagem += `*Endereço:* ${cliente.endereco}\n`;
|
|
}
|
|
|
|
mensagem += `\n*Itens do Pedido:*\n`;
|
|
|
|
carrinho.forEach((item, index) => {
|
|
const subtotal = item.preco * item.quantidade;
|
|
const codigoItem = item.codigo || item.produtoId || 'N/A';
|
|
mensagem += `\n${index + 1}. ${item.nome}\n`;
|
|
mensagem += ` ID: ${codigoItem}\n`;
|
|
mensagem += ` Tamanho: ${item.tamanho} | Cor: ${item.cor}\n`;
|
|
mensagem += ` Qtd: ${item.quantidade} x ${formatarMoedaBR(item.preco)} = ${formatarMoedaBR(subtotal)}\n`;
|
|
});
|
|
|
|
mensagem += `\n*Total:* ${formatarMoedaBR(totalPedido)}\n`;
|
|
mensagem += `\nPor favor, confirme o pagamento com a vendedora. Obrigado!`;
|
|
|
|
const pedidoPayload = {
|
|
cliente: {
|
|
nome: cliente.nome_completo,
|
|
whatsapp: cliente.whatsapp,
|
|
endereco: cliente.endereco || null
|
|
},
|
|
itens: carrinho.map((item) => ({
|
|
nome: item.nome,
|
|
codigo: item.codigo || item.produtoId || null,
|
|
tamanho: item.tamanho,
|
|
cor: item.cor,
|
|
quantidade: item.quantidade,
|
|
preco: Number(item.preco) || 0,
|
|
subtotal: Number((item.preco * item.quantidade).toFixed(2))
|
|
})),
|
|
total: totalPedido,
|
|
mensagem
|
|
};
|
|
|
|
try {
|
|
const response = await fetch('/api/catalogo/pedidos', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(pedidoPayload)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const erroServidor = await response.json().catch(() => ({}));
|
|
throw new Error(erroServidor.error || 'Não foi possível registrar o pedido no sistema.');
|
|
}
|
|
} catch (error) {
|
|
console.error('Erro ao salvar pedido do catálogo:', error);
|
|
mostrarPopup('Pedido enviado para a vendedora, mas não foi possível registrar na plataforma. ' + (error.message || ''), 'error');
|
|
}
|
|
|
|
const mensagemCodificada = encodeURIComponent(mensagem);
|
|
const whatsappUrl = `https://wa.me/${CONFIG.WHATSAPP_NUMBER}?text=${mensagemCodificada}`;
|
|
window.open(whatsappUrl, '_blank');
|
|
|
|
mostrarConfirmacao(
|
|
'Pedido enviado!',
|
|
'A vendedora receberá os detalhes do pedido e entrará em contato com você pelo WhatsApp.',
|
|
() => {
|
|
carrinho = [];
|
|
localStorage.setItem('liberi_carrinho', JSON.stringify(carrinho));
|
|
atualizarContadorCarrinho();
|
|
renderizarCarrinho();
|
|
toggleCart();
|
|
}
|
|
);
|
|
|
|
if (checkoutBtn) {
|
|
checkoutBtn.disabled = false;
|
|
checkoutBtn.innerHTML = btnOriginalHTML || '<i class="fab fa-whatsapp"></i> Finalizar Pedido';
|
|
}
|
|
}
|
|
|
|
function abrirWhatsApp() {
|
|
const whatsappUrl = `https://wa.me/${CONFIG.WHATSAPP_NUMBER}?text=Olá! Gostaria de saber mais sobre os produtos da Laberi Kids.`;
|
|
window.open(whatsappUrl, '_blank');
|
|
}
|
|
|
|
// ========================================
|
|
// SISTEMA DE POPUPS E NOTIFICAÇÕES
|
|
// ========================================
|
|
|
|
// Função para mostrar popup de erro/sucesso
|
|
function mostrarPopup(mensagem, tipo = 'info', callback = null) {
|
|
// Remover popup existente se houver
|
|
const existingPopup = document.querySelector('.custom-popup');
|
|
if (existingPopup) {
|
|
existingPopup.remove();
|
|
}
|
|
|
|
// Criar popup
|
|
const popup = document.createElement('div');
|
|
popup.className = `custom-popup ${tipo}`;
|
|
|
|
const icon = tipo === 'error' ? 'fas fa-exclamation-circle' :
|
|
tipo === 'success' ? 'fas fa-check-circle' :
|
|
'fas fa-info-circle';
|
|
|
|
popup.innerHTML = `
|
|
<div class="custom-popup-content">
|
|
<div class="popup-icon">
|
|
<i class="${icon}"></i>
|
|
</div>
|
|
<div class="popup-message">${mensagem}</div>
|
|
<button class="popup-btn" onclick="fecharPopup(this)">OK</button>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(popup);
|
|
|
|
// Animar entrada
|
|
setTimeout(() => popup.classList.add('show'), 10);
|
|
|
|
// Callback se fornecido
|
|
if (callback) {
|
|
popup.setAttribute('data-callback', 'true');
|
|
popup.callback = callback;
|
|
}
|
|
}
|
|
|
|
// Função para fechar popup
|
|
function fecharPopup(btn) {
|
|
const popup = btn.closest('.custom-popup');
|
|
if (popup) {
|
|
popup.classList.remove('show');
|
|
setTimeout(() => {
|
|
if (popup.callback) {
|
|
popup.callback();
|
|
}
|
|
popup.remove();
|
|
}, 300);
|
|
}
|
|
}
|
|
|
|
// Função para mostrar confirmação
|
|
function mostrarConfirmacao(titulo, mensagem, callback = null) {
|
|
mostrarPopup(`<strong>${titulo}</strong><br>${mensagem}`, 'success', callback);
|
|
}
|
|
|
|
// Melhorar função de login para verificar se já está logado
|
|
function showLoginModal() {
|
|
// Se já estiver logado, mostrar status
|
|
if (currentUser) {
|
|
const nomeUsuario = currentUser.cliente.nome_completo.split(' ')[0];
|
|
mostrarPopupConfirmacao(
|
|
'Você já está logado!',
|
|
`Olá, ${nomeUsuario}! 👋<br><br>Deseja sair da sua conta?`,
|
|
() => logout()
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Se não estiver logado, mostrar modal de login
|
|
const loginModal = document.getElementById('loginModal');
|
|
const registerModal = document.getElementById('registerModal');
|
|
|
|
if (registerModal) {
|
|
desativarAuthModal(registerModal);
|
|
}
|
|
if (loginModal) {
|
|
ativarAuthModal(loginModal);
|
|
}
|
|
}
|
|
|
|
// Função para popup de confirmação com Sim/Não
|
|
function mostrarPopupConfirmacao(titulo, mensagem, callbackSim = null, callbackNao = null) {
|
|
// Remover popup existente se houver
|
|
const existingPopup = document.querySelector('.custom-popup');
|
|
if (existingPopup) {
|
|
existingPopup.remove();
|
|
}
|
|
|
|
// Criar popup de confirmação
|
|
const popup = document.createElement('div');
|
|
popup.className = 'custom-popup confirmation';
|
|
|
|
popup.innerHTML = `
|
|
<div class="custom-popup-content">
|
|
<div class="popup-icon">
|
|
<i class="fas fa-question-circle"></i>
|
|
</div>
|
|
<div class="popup-title">${titulo}</div>
|
|
<div class="popup-message">${mensagem}</div>
|
|
<div class="popup-buttons">
|
|
<button class="popup-btn secondary" onclick="fecharPopupConfirmacao(this, false)">Não</button>
|
|
<button class="popup-btn primary" onclick="fecharPopupConfirmacao(this, true)">Sim</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.appendChild(popup);
|
|
|
|
// Animar entrada
|
|
setTimeout(() => popup.classList.add('show'), 10);
|
|
|
|
// Callbacks
|
|
popup.callbackSim = callbackSim;
|
|
popup.callbackNao = callbackNao;
|
|
}
|
|
|
|
// Função para fechar popup de confirmação
|
|
function fecharPopupConfirmacao(btn, resposta) {
|
|
const popup = btn.closest('.custom-popup');
|
|
if (popup) {
|
|
popup.classList.remove('show');
|
|
setTimeout(() => {
|
|
if (resposta && popup.callbackSim) {
|
|
popup.callbackSim();
|
|
} else if (!resposta && popup.callbackNao) {
|
|
popup.callbackNao();
|
|
}
|
|
popup.remove();
|
|
}, 300);
|
|
}
|
|
}
|
|
|
|
// Função de logout melhorada (substituindo a anterior)
|
|
function logout() {
|
|
// Limpar dados locais e localStorage
|
|
currentUser = null;
|
|
carrinho = [];
|
|
localStorage.removeItem('liberi_user');
|
|
|
|
atualizarInterfaceUsuario(false);
|
|
atualizarContadorCarrinho();
|
|
mostrarPopup('Você saiu da sua conta com sucesso!', 'success');
|
|
}
|