227 lines
No EOL
6.8 KiB
TypeScript
227 lines
No EOL
6.8 KiB
TypeScript
/**
|
|
* Biblioteca de máscaras compartilhada para formatação de dados
|
|
* Contém funções para formatação de CPF, CNPJ, telefone e outras máscaras comuns
|
|
*/
|
|
|
|
/**
|
|
* Formata um CPF com a máscara XXX.XXX.XXX-XX
|
|
* @param value - Valor a ser formatado
|
|
* @returns CPF formatado
|
|
*/
|
|
export const formatCPF = (value: string): string => {
|
|
const numbers = value.replace(/\D/g, '');
|
|
if (numbers.length <= 11) {
|
|
return numbers.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
|
|
}
|
|
return numbers.substring(0, 11).replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
|
|
};
|
|
|
|
/**
|
|
* Formata um CNPJ com a máscara XX.XXX.XXX/XXXX-XX
|
|
* @param value - Valor a ser formatado
|
|
* @returns CNPJ formatado
|
|
*/
|
|
export const formatCNPJ = (value: string): string => {
|
|
const numbers = value.replace(/\D/g, '');
|
|
if (numbers.length <= 14) {
|
|
return numbers.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, '$1.$2.$3/$4-$5');
|
|
}
|
|
return numbers.substring(0, 14).replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, '$1.$2.$3/$4-$5');
|
|
};
|
|
|
|
/**
|
|
* Formata um telefone com a máscara +55 (XX) XXXXX-XXXX ou +55 (XX) XXXX-XXXX
|
|
* @param value - Valor a ser formatado
|
|
* @returns Telefone formatado no padrão brasileiro
|
|
*/
|
|
export const formatPhone = (value: string): string => {
|
|
const numbers = value.replace(/\D/g, '');
|
|
|
|
// Se já tem código do país (55), remove para reformatar
|
|
let cleanNumbers = numbers;
|
|
if (numbers.startsWith('55') && numbers.length >= 12) {
|
|
cleanNumbers = numbers.substring(2);
|
|
}
|
|
|
|
// Formata conforme o tamanho
|
|
if (cleanNumbers.length === 10) {
|
|
// Telefone fixo: +55 (XX) XXXX-XXXX
|
|
return cleanNumbers.replace(/(\d{2})(\d{4})(\d{4})/, '+55 ($1) $2-$3');
|
|
} else if (cleanNumbers.length === 11) {
|
|
// Celular: +55 (XX) XXXXX-XXXX
|
|
return cleanNumbers.replace(/(\d{2})(\d{5})(\d{4})/, '+55 ($1) $2-$3');
|
|
} else if (cleanNumbers.length >= 8) {
|
|
// Tenta formatar com o que tem disponível
|
|
if (cleanNumbers.length <= 10) {
|
|
return cleanNumbers.replace(/(\d{2})(\d{4})(\d{0,4})/, '+55 ($1) $2-$3');
|
|
} else {
|
|
return cleanNumbers.replace(/(\d{2})(\d{5})(\d{0,4})/, '+55 ($1) $2-$3');
|
|
}
|
|
}
|
|
|
|
// Se não conseguir formatar, retorna com +55 na frente
|
|
return numbers.length > 0 ? `+55 ${numbers}` : numbers;
|
|
};
|
|
|
|
/**
|
|
* Formata um CEP com a máscara XXXXX-XXX
|
|
* @param value - Valor a ser formatado
|
|
* @returns CEP formatado
|
|
*/
|
|
export const formatCEP = (value: string): string => {
|
|
const numbers = value.replace(/\D/g, '');
|
|
if (numbers.length <= 8) {
|
|
return numbers.replace(/(\d{5})(\d{3})/, '$1-$2');
|
|
}
|
|
return numbers.substring(0, 8).replace(/(\d{5})(\d{3})/, '$1-$2');
|
|
};
|
|
|
|
/**
|
|
* Remove todos os caracteres não numéricos de uma string
|
|
* @param value - Valor a ser limpo
|
|
* @returns String apenas com números
|
|
*/
|
|
export const removeNonNumeric = (value: string): string => {
|
|
return value.replace(/\D/g, '');
|
|
};
|
|
|
|
/**
|
|
* Valida se um CPF é válido
|
|
* @param cpf - CPF a ser validado
|
|
* @returns true se válido, false caso contrário
|
|
*/
|
|
export const validateCPF = (cpf: string): boolean => {
|
|
const numbers = removeNonNumeric(cpf);
|
|
|
|
if (numbers.length !== 11) return false;
|
|
|
|
// Verifica se todos os dígitos são iguais
|
|
if (/^(\d)\1{10}$/.test(numbers)) return false;
|
|
|
|
// Validação do primeiro dígito verificador
|
|
let sum = 0;
|
|
for (let i = 0; i < 9; i++) {
|
|
sum += parseInt(numbers[i]) * (10 - i);
|
|
}
|
|
let remainder = sum % 11;
|
|
const digit1 = remainder < 2 ? 0 : 11 - remainder;
|
|
|
|
if (parseInt(numbers[9]) !== digit1) return false;
|
|
|
|
// Validação do segundo dígito verificador
|
|
sum = 0;
|
|
for (let i = 0; i < 10; i++) {
|
|
sum += parseInt(numbers[i]) * (11 - i);
|
|
}
|
|
remainder = sum % 11;
|
|
const digit2 = remainder < 2 ? 0 : 11 - remainder;
|
|
|
|
return parseInt(numbers[10]) === digit2;
|
|
};
|
|
|
|
/**
|
|
* Valida se um CNPJ é válido
|
|
* @param cnpj - CNPJ a ser validado
|
|
* @returns true se válido, false caso contrário
|
|
*/
|
|
export const validateCNPJ = (cnpj: string): boolean => {
|
|
const numbers = removeNonNumeric(cnpj);
|
|
|
|
if (numbers.length !== 14) return false;
|
|
|
|
// Verifica se todos os dígitos são iguais
|
|
if (/^(\d)\1{13}$/.test(numbers)) return false;
|
|
|
|
// Validação do primeiro dígito verificador
|
|
const weights1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
let sum = 0;
|
|
for (let i = 0; i < 12; i++) {
|
|
sum += parseInt(numbers[i]) * weights1[i];
|
|
}
|
|
let remainder = sum % 11;
|
|
const digit1 = remainder < 2 ? 0 : 11 - remainder;
|
|
|
|
if (parseInt(numbers[12]) !== digit1) return false;
|
|
|
|
// Validação do segundo dígito verificador
|
|
const weights2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
sum = 0;
|
|
for (let i = 0; i < 13; i++) {
|
|
sum += parseInt(numbers[i]) * weights2[i];
|
|
}
|
|
remainder = sum % 11;
|
|
const digit2 = remainder < 2 ? 0 : 11 - remainder;
|
|
|
|
return parseInt(numbers[13]) === digit2;
|
|
};
|
|
|
|
/**
|
|
* Valida se um telefone tem formato válido
|
|
* @param phone - Telefone a ser validado
|
|
* @returns true se válido, false caso contrário
|
|
*/
|
|
export const validatePhone = (phone: string): boolean => {
|
|
const numbers = removeNonNumeric(phone);
|
|
return numbers.length >= 10 && numbers.length <= 11;
|
|
};
|
|
|
|
/**
|
|
* Valida se um CEP tem formato válido
|
|
* @param cep - CEP a ser validado
|
|
* @returns true se válido, false caso contrário
|
|
*/
|
|
export const validateCEP = (cep: string): boolean => {
|
|
const numbers = removeNonNumeric(cep);
|
|
return numbers.length === 8;
|
|
};
|
|
|
|
/**
|
|
* Valida se um email tem formato válido
|
|
* @param email - Email a ser validado
|
|
* @returns true se válido, false caso contrário
|
|
*/
|
|
export const validateEmail = (email: string): boolean => {
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(email);
|
|
};
|
|
|
|
/**
|
|
* Capitaliza a primeira letra de cada palavra
|
|
* @param text - Texto a ser formatado
|
|
* @returns Texto com primeira letra de cada palavra maiúscula
|
|
*/
|
|
export const capitalizeWords = (text: string): string => {
|
|
return text.toLowerCase().replace(/\b\w/g, l => l.toUpperCase());
|
|
};
|
|
|
|
/**
|
|
* Formata um valor monetário para o padrão brasileiro
|
|
* @param value - Valor a ser formatado
|
|
* @returns Valor formatado como moeda brasileira
|
|
*/
|
|
export const formatCurrency = (value: number): string => {
|
|
return new Intl.NumberFormat('pt-BR', {
|
|
style: 'currency',
|
|
currency: 'BRL'
|
|
}).format(value);
|
|
};
|
|
|
|
/**
|
|
* Formata uma data para o padrão brasileiro
|
|
* @param date - Data a ser formatada
|
|
* @returns Data formatada como DD/MM/AAAA
|
|
*/
|
|
export const formatDate = (date: Date | string): string => {
|
|
const dateObj = typeof date === 'string' ? new Date(date) : date;
|
|
return dateObj.toLocaleDateString('pt-BR');
|
|
};
|
|
|
|
/**
|
|
* Formata uma data e hora para o padrão brasileiro
|
|
* @param date - Data a ser formatada
|
|
* @returns Data e hora formatada como DD/MM/AAAA HH:MM
|
|
*/
|
|
export const formatDateTime = (date: Date | string): string => {
|
|
const dateObj = typeof date === 'string' ? new Date(date) : date;
|
|
return dateObj.toLocaleString('pt-BR');
|
|
}; |