- SellerDashboard: migrado para Shell (header topo), removida sidebar lateral, cards KPI brancos com react-icons pretos (FaChartLine, FaBoxOpen, FaReceipt) - Shell: adicionados todos os links de nav para owner/seller no header (Estoque, Buscar Produtos, Pedidos, Carteira, Equipe, Config. Entrega) - Wallet: ícone FaMoneyCheck no botão Solicitar Saque, card saldo com #0F4C81, thead da tabela com #0F4C81, fix R$ NaN (formatCurrency null-safe) - Team: botões e thead com #0F4C81, emojis removidos dos roleLabels - ShippingSettings: wrapped com Shell (mantém header), emojis substituídos por react-icons pretos (FaTruck, FaLocationDot, FaStore, FaCircleInfo, FaFloppyDisk), botão Salvar com #0F4C81 - Orders: removido box cinza de fundo dos ícones nas abas e estado vazio - LocationPicker: fallback seguro para OpenStreetMap quando VITE_MAP_TILE_LAYER não está definido (corrige tela branca em /search) - Inventory/Cart: cores dos botões e thead atualizadas para #0F4C81
70 lines
1.9 KiB
TypeScript
70 lines
1.9 KiB
TypeScript
/**
|
|
* Validates a CNPJ (Cadastro Nacional da Pessoa Jurídica)
|
|
* Checks format and verifies check digits
|
|
*/
|
|
export function validateCNPJ(cnpj: string): boolean {
|
|
// Remove non-numeric characters
|
|
const cleaned = cnpj.replace(/\D/g, '')
|
|
|
|
// Must have exactly 14 digits
|
|
if (cleaned.length !== 14) {
|
|
return false
|
|
}
|
|
|
|
// All same digits are invalid
|
|
if (/^(\d)\1{13}$/.test(cleaned)) {
|
|
return false
|
|
}
|
|
|
|
// Validate first check digit
|
|
let sum = 0
|
|
let position = 5
|
|
for (let i = 0; i < 8; i++) {
|
|
sum += parseInt(cleaned[i]) * position
|
|
position -= 1
|
|
}
|
|
let remainder = sum % 11
|
|
const firstDigit = remainder < 2 ? 0 : 11 - remainder
|
|
|
|
if (parseInt(cleaned[8]) !== firstDigit) {
|
|
return false
|
|
}
|
|
|
|
// Validate second check digit
|
|
sum = 0
|
|
position = 9
|
|
for (let i = 0; i < 9; i++) {
|
|
sum += parseInt(cleaned[i]) * position
|
|
position -= 1
|
|
}
|
|
remainder = sum % 11
|
|
const secondDigit = remainder < 2 ? 0 : 11 - remainder
|
|
|
|
if (parseInt(cleaned[9]) !== secondDigit) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Formats a CNPJ string to the standard format: 00.000.000/0000-00
|
|
* Accepts both formatted and unformatted input
|
|
*/
|
|
export function formatCNPJ(value: string): string {
|
|
const cleaned = value.replace(/\D/g, '').slice(0, 14)
|
|
|
|
if (cleaned.length === 0) return ''
|
|
if (cleaned.length <= 2) return cleaned
|
|
if (cleaned.length <= 5) return `${cleaned.slice(0, 2)}.${cleaned.slice(2)}`
|
|
if (cleaned.length <= 8) return `${cleaned.slice(0, 2)}.${cleaned.slice(2, 5)}.${cleaned.slice(5)}`
|
|
if (cleaned.length <= 12) return `${cleaned.slice(0, 2)}.${cleaned.slice(2, 5)}.${cleaned.slice(5, 8)}/${cleaned.slice(8)}`
|
|
return `${cleaned.slice(0, 2)}.${cleaned.slice(2, 5)}.${cleaned.slice(5, 8)}/${cleaned.slice(8, 12)}-${cleaned.slice(12)}`
|
|
}
|
|
|
|
/**
|
|
* Removes CNPJ formatting, returning only digits
|
|
*/
|
|
export function removeCNPJFormatting(cnpj: string): string {
|
|
return cnpj.replace(/\D/g, '')
|
|
}
|