diff --git a/lib/utils.ts b/lib/utils.ts index fb28b30..e504f46 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -22,3 +22,50 @@ export const formatCurrency = (number: number) => { return brlCurrencyFormatter.format(numberResult) } + +export const isValidCPF = (cpfStr: string) => { + if (!cpfStr || typeof cpfStr !== 'string') return false + + cpfStr = cpfStr.replace(/[^\d]+/g, '') + if (cpfStr.length !== 11 || !!cpfStr.match(/(\d)\1{10}/)) return false + + const cpfNumArr = cpfStr.split('').map(el => +el) + const remainder = (count) => ( + cpfNumArr.slice(0, count-12).reduce( + (sum, el, index) => (sum + el * (count-index)), 0 ) * 10) % 11 % 10 + + return remainder(10) === cpfNumArr[9] && remainder(11) === cpfNumArr[10] +} + +export const isValidCNPJ = (cnpjStr: string) => { + if (!cnpjStr || typeof cnpjStr !== 'string') return false + + cnpjStr = cnpjStr.replace(/[^\d]+/g, '') + if (cnpjStr.length !== 14 || !!cnpjStr.match(/(\d)\1{13}/)) return false + + const cnpjNumArr = cnpjStr.split('').map(el => +el) + + const remainder = (count) => { + return cnpjNumArr.slice(0, count).reduce( + (sum, el, index) => { + return sum + el * (count - index - (count - index - 7 > 1 ? 7 : -1)) + }, 0) * 10 % 11 % 10 + } + return (remainder(12) === cnpjNumArr[12]) && remainder(13) === cnpjNumArr[13]; +} + +export const isValidEmail = (emailStr: string) => { + return String(emailStr) + .toLowerCase() + .match( + /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + ); +} + +export const isValidChaveAleatoria = (chaveAleatoriaStr: string) => { + return String(chaveAleatoriaStr) + .toLowerCase() + .match( + /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i + ); +} diff --git a/pages/index.tsx b/pages/index.tsx index c26b795..4c7f6b3 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -26,6 +26,7 @@ import {io} from "@/lib/qrcode-kotlin" import {PatternFormat} from "react-number-format"; import {CurrencyInput} from "@/components/ui/currency-input"; import QRCode = io.github.g0dkar.qrcode.QRCode; +import {isValidCPF, isValidCNPJ, isValidEmail, isValidChaveAleatoria} from "@/lib/utils"; const CampoPix = ({show, campo, className = ""}) => { const campoValue = campo?.valueStr || campo?.value @@ -126,7 +127,7 @@ const Index = () => { } else if (tipo === "4") { return 10 } else if (tipo === "5") { - return 70 + return 36 } return 0 @@ -193,6 +194,19 @@ const Index = () => { }) } + const isValidChave = () => { + if (tipo === "0" && chave().length === chaveMaxSize() && !isValidCPF(chave())) { + return false + } else if (tipo === "1" && chave().length === chaveMaxSize() && !isValidCNPJ(chave())) { + return false + } else if (tipo === "2" && chave().length > 3 && !isValidEmail(chave())) { + return false + } else if (tipo === "5" && chave().length === chaveMaxSize() && !isValidChaveAleatoria(chave())) { + return false + } + return true + } + return QRCode do Pix @@ -283,14 +297,22 @@ const Index = () => { {tipo === "5" ? setChaveAleatorio(evt.target.value)} - placeholder="Chave Pix - Chave Aleatória" tabIndex={2} maxLength={70} + placeholder="Chave Pix - Chave Aleatória" tabIndex={2} maxLength={36} disabled={gerandoQrCode}/> : <>}

Tamanho: {chave().length - (tipo === "3" || tipo === "4" ? 3 : 0)}/{chaveMaxSize()} + className="pr-3 font-medium leading-none text-slate-700 dark:text-slate-300"> + Tamanho: {chave().length - (tipo === "3" || tipo === "4" ? 3 : 0)}/{chaveMaxSize()} + + {!isValidChave() ? + + A chave digitada é inválida. + + : + <> } Chave Pix que irá receber a transferência.

@@ -362,7 +384,7 @@ const Index = () => {