Initial SeConectai briefing system
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { z } from "zod";
|
||||
import { onlyDigits } from "@/lib/crypto";
|
||||
|
||||
function hasSameDigits(value: string) {
|
||||
return /^(\d)\1+$/.test(value);
|
||||
}
|
||||
|
||||
export function isValidCpf(value: string) {
|
||||
const cpf = onlyDigits(value);
|
||||
|
||||
if (cpf.length !== 11 || hasSameDigits(cpf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const calcDigit = (base: string, factor: number) => {
|
||||
let total = 0;
|
||||
|
||||
for (const digit of base) {
|
||||
total += Number(digit) * factor;
|
||||
factor -= 1;
|
||||
}
|
||||
|
||||
const rest = (total * 10) % 11;
|
||||
return rest === 10 ? 0 : rest;
|
||||
};
|
||||
|
||||
const firstDigit = calcDigit(cpf.slice(0, 9), 10);
|
||||
const secondDigit = calcDigit(cpf.slice(0, 10), 11);
|
||||
|
||||
return firstDigit === Number(cpf[9]) && secondDigit === Number(cpf[10]);
|
||||
}
|
||||
|
||||
export function isValidCnpj(value: string) {
|
||||
const cnpj = onlyDigits(value);
|
||||
|
||||
if (cnpj.length !== 14 || hasSameDigits(cnpj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const calcDigit = (base: string, weights: number[]) => {
|
||||
const total = base
|
||||
.split("")
|
||||
.reduce((sum, digit, index) => sum + Number(digit) * weights[index], 0);
|
||||
const rest = total % 11;
|
||||
return rest < 2 ? 0 : 11 - rest;
|
||||
};
|
||||
|
||||
const firstDigit = calcDigit(cnpj.slice(0, 12), [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
|
||||
const secondDigit = calcDigit(cnpj.slice(0, 13), [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
|
||||
|
||||
return firstDigit === Number(cnpj[12]) && secondDigit === Number(cnpj[13]);
|
||||
}
|
||||
|
||||
export function normalizeWhatsapp(value: string) {
|
||||
const digits = onlyDigits(value);
|
||||
const withoutCountry = digits.startsWith("55") && digits.length === 13 ? digits.slice(2) : digits;
|
||||
|
||||
if (withoutCountry.length !== 11) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return `+55${withoutCountry}`;
|
||||
}
|
||||
|
||||
export const cadastroSchema = z
|
||||
.object({
|
||||
nomeCompleto: z.string().trim().min(3, "Informe seu nome completo."),
|
||||
cpf: z.string().refine(isValidCpf, "Informe um CPF valido."),
|
||||
whatsapp: z.string().refine((value) => normalizeWhatsapp(value) !== null, "Informe um WhatsApp com DDD."),
|
||||
email: z.string().trim().email("Informe um e-mail valido.").toLowerCase(),
|
||||
senha: z.string().min(8, "A senha precisa ter pelo menos 8 caracteres."),
|
||||
confirmarSenha: z.string(),
|
||||
tipo: z.enum(["PF", "PJ"]),
|
||||
razaoSocial: z.string().trim().optional(),
|
||||
cnpj: z.string().optional(),
|
||||
cep: z.string().optional(),
|
||||
logradouro: z.string().optional(),
|
||||
numero: z.string().optional(),
|
||||
complemento: z.string().optional(),
|
||||
bairro: z.string().optional(),
|
||||
cidade: z.string().optional(),
|
||||
uf: z.string().optional(),
|
||||
lgpdAceite: z.literal("on", {
|
||||
errorMap: () => ({ message: "Aceite a Politica de Privacidade para continuar." })
|
||||
})
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
if (data.senha !== data.confirmarSenha) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["confirmarSenha"],
|
||||
message: "As senhas nao conferem."
|
||||
});
|
||||
}
|
||||
|
||||
if (data.tipo === "PJ") {
|
||||
if (!data.razaoSocial) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["razaoSocial"],
|
||||
message: "Informe a razao social."
|
||||
});
|
||||
}
|
||||
|
||||
if (!data.cnpj || !isValidCnpj(data.cnpj)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["cnpj"],
|
||||
message: "Informe um CNPJ valido."
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export type CadastroInput = z.infer<typeof cadastroSchema>;
|
||||
Reference in New Issue
Block a user