203 lines
7.4 KiB
JavaScript
203 lines
7.4 KiB
JavaScript
// 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 += ' <span class="text-danger">*</span>';
|
|
}
|
|
});
|
|
});
|