// Validação de CPF function validarCPF(cpf) { cpf = cpf.replace(/[^\d]/g, ''); if (cpf.length !== 11) return false; // Verifica se todos os dígitos são iguais if (/^(\d)\1{10}$/.test(cpf)) return false; // Validação do primeiro dígito verificador let soma = 0; for (let i = 0; i < 9; i++) { soma += parseInt(cpf.charAt(i)) * (10 - i); } let resto = 11 - (soma % 11); let dv1 = resto > 9 ? 0 : resto; if (dv1 !== parseInt(cpf.charAt(9))) return false; // Validação do segundo dígito verificador soma = 0; for (let i = 0; i < 10; i++) { soma += parseInt(cpf.charAt(i)) * (11 - i); } resto = 11 - (soma % 11); let dv2 = resto > 9 ? 0 : resto; if (dv2 !== parseInt(cpf.charAt(10))) return false; return true; } // Validação de email function validarEmail(email) { const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return re.test(email); } // Validação de telefone function validarTelefone(telefone) { telefone = telefone.replace(/[^\d]/g, ''); return telefone.length >= 10 && telefone.length <= 11; } // Inicialização dos formulários document.addEventListener('DOMContentLoaded', function() { // Validação personalizada para CPF const cpfInputs = document.querySelectorAll('input[name="cpf"]'); cpfInputs.forEach(input => { input.addEventListener('blur', function() { const cpf = this.value; if (!validarCPF(cpf)) { this.setCustomValidity('CPF inválido'); this.classList.add('is-invalid'); } else { this.setCustomValidity(''); this.classList.remove('is-invalid'); } }); }); // Validação personalizada para email const emailInputs = document.querySelectorAll('input[type="email"]'); emailInputs.forEach(input => { input.addEventListener('blur', function() { const email = this.value; if (!validarEmail(email)) { this.setCustomValidity('Email inválido'); this.classList.add('is-invalid'); } else { this.setCustomValidity(''); this.classList.remove('is-invalid'); } }); }); // Validação personalizada para telefone const phoneInputs = document.querySelectorAll('input[name="telefone"]'); phoneInputs.forEach(input => { input.addEventListener('blur', function() { const telefone = this.value; if (!validarTelefone(telefone)) { this.setCustomValidity('Telefone inválido'); this.classList.add('is-invalid'); } else { this.setCustomValidity(''); this.classList.remove('is-invalid'); } }); }); // Validação de campos monetários const moneyInputs = document.querySelectorAll('input[type="number"][step="0.01"]'); moneyInputs.forEach(input => { input.addEventListener('blur', function() { const value = parseFloat(this.value); if (isNaN(value) || value < 0) { this.setCustomValidity('Valor inválido'); this.classList.add('is-invalid'); } else { this.setCustomValidity(''); this.classList.remove('is-invalid'); this.value = value.toFixed(2); } }); }); // Validação de datas const dateInputs = document.querySelectorAll('input[type="date"], input.date-mask'); dateInputs.forEach(input => { input.addEventListener('change', function() { console.log('Validando data:', this.value); let dataValida = true; let mensagemErro = ''; // Se for um campo com máscara, validar o formato if (this.classList.contains('date-mask')) { if (!validarData(this.value)) { dataValida = false; mensagemErro = 'Por favor, insira uma data válida no formato DD/MM/AAAA'; } } else { // Para campos type="date", converter para Date const date = new Date(this.value); if (isNaN(date.getTime())) { dataValida = false; mensagemErro = 'Data inválida'; } } // Validar limites de data if (dataValida) { const hoje = new Date(); hoje.setHours(0, 0, 0, 0); let dataComparacao; if (this.classList.contains('date-mask')) { const [dia, mes, ano] = this.value.split('/').map(Number); dataComparacao = new Date(ano, mes - 1, dia); } else { dataComparacao = new Date(this.value); } // Verificar data mínima if (this.hasAttribute('min')) { const minDate = new Date(this.getAttribute('min')); if (dataComparacao < minDate) { dataValida = false; mensagemErro = `A data não pode ser anterior a ${minDate.toLocaleDateString()}`; } } // Verificar data máxima if (this.hasAttribute('max')) { const maxDate = new Date(this.getAttribute('max')); if (dataComparacao > maxDate) { dataValida = false; mensagemErro = `A data não pode ser posterior a ${maxDate.toLocaleDateString()}`; } } // Verificar se é data futura (quando não permitido) if (this.hasAttribute('data-no-future') && dataComparacao > hoje) { dataValida = false; mensagemErro = 'A data não pode ser futura'; } } // Atualizar validação do campo if (!dataValida) { console.warn('Data inválida:', this.value, mensagemErro); this.setCustomValidity(mensagemErro); this.classList.add('is-invalid'); // Atualizar mensagem de feedback const feedback = this.nextElementSibling; if (feedback && feedback.classList.contains('invalid-feedback')) { feedback.textContent = mensagemErro; } } else { console.log('Data válida:', this.value); this.setCustomValidity(''); this.classList.remove('is-invalid'); } }); // Limpar validação ao começar a digitar input.addEventListener('input', function() { this.setCustomValidity(''); this.classList.remove('is-invalid'); }); }); // Feedback visual para campos obrigatórios const requiredInputs = document.querySelectorAll('input[required], select[required], textarea[required]'); requiredInputs.forEach(input => { const label = input.previousElementSibling; if (label && label.tagName === 'LABEL') { label.innerHTML += ' *'; } }); });