feat: integrate jsPDF and jsPDF-autotable for document generation; enhance employee management with print functionality and improved data handling in employee forms
This commit is contained in:
176
apps/web/src/lib/utils/masks.ts
Normal file
176
apps/web/src/lib/utils/masks.ts
Normal file
@@ -0,0 +1,176 @@
|
||||
// Helper functions for input masks and validations
|
||||
|
||||
/** Remove all non-digit characters from string */
|
||||
export const onlyDigits = (value: string): string => {
|
||||
return (value || "").replace(/\D/g, "");
|
||||
};
|
||||
|
||||
/** Format CPF: 000.000.000-00 */
|
||||
export const maskCPF = (value: string): string => {
|
||||
const digits = onlyDigits(value).slice(0, 11);
|
||||
return digits
|
||||
.replace(/(\d{3})(\d)/, "$1.$2")
|
||||
.replace(/(\d{3})(\d)/, "$1.$2")
|
||||
.replace(/(\d{3})(\d{1,2})$/, "$1-$2");
|
||||
};
|
||||
|
||||
/** Validate CPF format and checksum */
|
||||
export const validateCPF = (value: string): boolean => {
|
||||
const digits = onlyDigits(value);
|
||||
|
||||
if (digits.length !== 11 || /^([0-9])\1+$/.test(digits)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const calculateDigit = (base: string, factor: number): number => {
|
||||
let sum = 0;
|
||||
for (let i = 0; i < base.length; i++) {
|
||||
sum += parseInt(base[i]) * (factor - i);
|
||||
}
|
||||
const rest = (sum * 10) % 11;
|
||||
return rest === 10 ? 0 : rest;
|
||||
};
|
||||
|
||||
const digit1 = calculateDigit(digits.slice(0, 9), 10);
|
||||
const digit2 = calculateDigit(digits.slice(0, 10), 11);
|
||||
|
||||
return digits[9] === String(digit1) && digits[10] === String(digit2);
|
||||
};
|
||||
|
||||
/** Format CEP: 00000-000 */
|
||||
export const maskCEP = (value: string): string => {
|
||||
const digits = onlyDigits(value).slice(0, 8);
|
||||
return digits.replace(/(\d{5})(\d{1,3})$/, "$1-$2");
|
||||
};
|
||||
|
||||
/** Format phone: (00) 0000-0000 or (00) 00000-0000 */
|
||||
export const maskPhone = (value: string): string => {
|
||||
const digits = onlyDigits(value).slice(0, 11);
|
||||
|
||||
if (digits.length <= 10) {
|
||||
return digits
|
||||
.replace(/(\d{2})(\d)/, "($1) $2")
|
||||
.replace(/(\d{4})(\d{1,4})$/, "$1-$2");
|
||||
}
|
||||
|
||||
return digits
|
||||
.replace(/(\d{2})(\d)/, "($1) $2")
|
||||
.replace(/(\d{5})(\d{1,4})$/, "$1-$2");
|
||||
};
|
||||
|
||||
/** Format date: dd/mm/aaaa */
|
||||
export const maskDate = (value: string): string => {
|
||||
const digits = onlyDigits(value).slice(0, 8);
|
||||
return digits
|
||||
.replace(/(\d{2})(\d)/, "$1/$2")
|
||||
.replace(/(\d{2})(\d{1,4})$/, "$1/$2");
|
||||
};
|
||||
|
||||
/** Validate date in format dd/mm/aaaa */
|
||||
export const validateDate = (value: string): boolean => {
|
||||
const match = value.match(/^(\d{2})\/(\d{2})\/(\d{4})$/);
|
||||
if (!match) return false;
|
||||
|
||||
const day = Number(match[1]);
|
||||
const month = Number(match[2]) - 1;
|
||||
const year = Number(match[3]);
|
||||
|
||||
const date = new Date(year, month, day);
|
||||
|
||||
return (
|
||||
date.getFullYear() === year &&
|
||||
date.getMonth() === month &&
|
||||
date.getDate() === day
|
||||
);
|
||||
};
|
||||
|
||||
/** Format UF: uppercase, max 2 chars */
|
||||
export const maskUF = (value: string): string => {
|
||||
return (value || "").toUpperCase().replace(/[^A-Z]/g, "").slice(0, 2);
|
||||
};
|
||||
|
||||
/** Format RG by UF */
|
||||
const rgFormatByUF: Record<string, [number, number, number, number]> = {
|
||||
RJ: [2, 3, 2, 1],
|
||||
SP: [2, 3, 3, 1],
|
||||
MG: [2, 3, 3, 1],
|
||||
ES: [2, 3, 3, 1],
|
||||
PR: [2, 3, 3, 1],
|
||||
SC: [2, 3, 3, 1],
|
||||
RS: [2, 3, 3, 1],
|
||||
BA: [2, 3, 3, 1],
|
||||
PE: [2, 3, 3, 1],
|
||||
CE: [2, 3, 3, 1],
|
||||
PA: [2, 3, 3, 1],
|
||||
AM: [2, 3, 3, 1],
|
||||
AC: [2, 3, 3, 1],
|
||||
AP: [2, 3, 3, 1],
|
||||
AL: [2, 3, 3, 1],
|
||||
RN: [2, 3, 3, 1],
|
||||
PB: [2, 3, 3, 1],
|
||||
MA: [2, 3, 3, 1],
|
||||
PI: [2, 3, 3, 1],
|
||||
DF: [2, 3, 3, 1],
|
||||
GO: [2, 3, 3, 1],
|
||||
MT: [2, 3, 3, 1],
|
||||
MS: [2, 3, 3, 1],
|
||||
RO: [2, 3, 3, 1],
|
||||
RR: [2, 3, 3, 1],
|
||||
TO: [2, 3, 3, 1],
|
||||
};
|
||||
|
||||
export const maskRGByUF = (uf: string, value: string): string => {
|
||||
const raw = (value || "").toUpperCase().replace(/[^0-9X]/g, "");
|
||||
const [a, b, c, dv] = rgFormatByUF[uf?.toUpperCase()] ?? [2, 3, 3, 1];
|
||||
const baseMax = a + b + c;
|
||||
const baseDigits = raw.replace(/X/g, "").slice(0, baseMax);
|
||||
const verifier = raw.slice(baseDigits.length, baseDigits.length + dv).slice(0, 1);
|
||||
|
||||
const g1 = baseDigits.slice(0, a);
|
||||
const g2 = baseDigits.slice(a, a + b);
|
||||
const g3 = baseDigits.slice(a + b, a + b + c);
|
||||
|
||||
let formatted = g1;
|
||||
if (g2) formatted += `.${g2}`;
|
||||
if (g3) formatted += `.${g3}`;
|
||||
if (verifier) formatted += `-${verifier}`;
|
||||
|
||||
return formatted;
|
||||
};
|
||||
|
||||
export const padRGLeftByUF = (uf: string, value: string): string => {
|
||||
const raw = (value || "").toUpperCase().replace(/[^0-9X]/g, "");
|
||||
const [a, b, c, dv] = rgFormatByUF[uf?.toUpperCase()] ?? [2, 3, 3, 1];
|
||||
const baseMax = a + b + c;
|
||||
let base = raw.replace(/X/g, "");
|
||||
const verifier = raw.slice(base.length, base.length + dv).slice(0, 1);
|
||||
|
||||
if (base.length < baseMax) {
|
||||
base = base.padStart(baseMax, "0");
|
||||
}
|
||||
|
||||
return maskRGByUF(uf, base + (verifier || ""));
|
||||
};
|
||||
|
||||
/** Format account number */
|
||||
export const maskContaBancaria = (value: string): string => {
|
||||
const digits = onlyDigits(value);
|
||||
return digits;
|
||||
};
|
||||
|
||||
/** Format zone and section for voter title */
|
||||
export const maskZonaSecao = (value: string): string => {
|
||||
const digits = onlyDigits(value).slice(0, 4);
|
||||
return digits;
|
||||
};
|
||||
|
||||
/** Format general numeric field */
|
||||
export const maskNumeric = (value: string): string => {
|
||||
return onlyDigits(value);
|
||||
};
|
||||
|
||||
/** Remove extra spaces and trim */
|
||||
export const normalizeText = (value: string): string => {
|
||||
return (value || "").replace(/\s+/g, " ").trim();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user