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:
49
apps/web/src/lib/utils/constants.ts
Normal file
49
apps/web/src/lib/utils/constants.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// Constantes para selects e opções do formulário
|
||||
|
||||
export const SEXO_OPTIONS = [
|
||||
{ value: "masculino", label: "Masculino" },
|
||||
{ value: "feminino", label: "Feminino" },
|
||||
{ value: "outro", label: "Outro" },
|
||||
];
|
||||
|
||||
export const ESTADO_CIVIL_OPTIONS = [
|
||||
{ value: "solteiro", label: "Solteiro(a)" },
|
||||
{ value: "casado", label: "Casado(a)" },
|
||||
{ value: "divorciado", label: "Divorciado(a)" },
|
||||
{ value: "viuvo", label: "Viúvo(a)" },
|
||||
{ value: "uniao_estavel", label: "União Estável" },
|
||||
];
|
||||
|
||||
export const GRAU_INSTRUCAO_OPTIONS = [
|
||||
{ value: "fundamental", label: "Ensino Fundamental" },
|
||||
{ value: "medio", label: "Ensino Médio" },
|
||||
{ value: "superior", label: "Ensino Superior" },
|
||||
{ value: "pos_graduacao", label: "Pós-Graduação" },
|
||||
{ value: "mestrado", label: "Mestrado" },
|
||||
{ value: "doutorado", label: "Doutorado" },
|
||||
];
|
||||
|
||||
export const GRUPO_SANGUINEO_OPTIONS = [
|
||||
{ value: "A", label: "A" },
|
||||
{ value: "B", label: "B" },
|
||||
{ value: "AB", label: "AB" },
|
||||
{ value: "O", label: "O" },
|
||||
];
|
||||
|
||||
export const FATOR_RH_OPTIONS = [
|
||||
{ value: "positivo", label: "Positivo (+)" },
|
||||
{ value: "negativo", label: "Negativo (-)" },
|
||||
];
|
||||
|
||||
export const APOSENTADO_OPTIONS = [
|
||||
{ value: "nao", label: "Não" },
|
||||
{ value: "funape_ipsep", label: "FUNAPE/IPSEP" },
|
||||
{ value: "inss", label: "INSS" },
|
||||
];
|
||||
|
||||
export const UFS_BRASIL = [
|
||||
"AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA",
|
||||
"MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN",
|
||||
"RS", "RO", "RR", "SC", "SP", "SE", "TO"
|
||||
];
|
||||
|
||||
581
apps/web/src/lib/utils/declaracoesGenerator.ts
Normal file
581
apps/web/src/lib/utils/declaracoesGenerator.ts
Normal file
@@ -0,0 +1,581 @@
|
||||
import jsPDF from 'jspdf';
|
||||
import type { Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import logoGovPE from '$lib/assets/logo_governo_PE.png';
|
||||
|
||||
type Funcionario = Doc<'funcionarios'>;
|
||||
|
||||
// Helper para adicionar logo no canto superior esquerdo
|
||||
async function addLogo(doc: jsPDF): Promise<number> {
|
||||
try {
|
||||
// Criar uma promise para carregar a imagem
|
||||
const logoImg = await new Promise<HTMLImageElement>((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.crossOrigin = 'anonymous'; // Para evitar problemas de CORS
|
||||
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = (err) => reject(err);
|
||||
|
||||
// Timeout de 3 segundos
|
||||
setTimeout(() => reject(new Error('Timeout loading logo')), 3000);
|
||||
|
||||
// Importante: definir src depois de definir os handlers
|
||||
img.src = logoGovPE;
|
||||
});
|
||||
|
||||
// Logo proporcional: largura 25mm, altura ajustada automaticamente
|
||||
const logoWidth = 25;
|
||||
const aspectRatio = logoImg.height / logoImg.width;
|
||||
const logoHeight = logoWidth * aspectRatio;
|
||||
|
||||
// Adicionar a imagem ao PDF
|
||||
doc.addImage(logoImg, 'PNG', 15, 10, logoWidth, logoHeight);
|
||||
|
||||
// Retorna a posição Y onde o conteúdo pode começar (logo + margem)
|
||||
return 10 + logoHeight + 5;
|
||||
} catch (err) {
|
||||
console.error('Erro ao carregar logo:', err);
|
||||
return 20; // Posição padrão se a logo falhar
|
||||
}
|
||||
}
|
||||
|
||||
// Helper para adicionar texto formatado
|
||||
function addText(doc: jsPDF, text: string, x: number, y: number, options?: { bold?: boolean; size?: number; align?: 'left' | 'center' | 'right' }) {
|
||||
if (options?.bold) {
|
||||
doc.setFont('helvetica', 'bold');
|
||||
} else {
|
||||
doc.setFont('helvetica', 'normal');
|
||||
}
|
||||
|
||||
if (options?.size) {
|
||||
doc.setFontSize(options.size);
|
||||
}
|
||||
|
||||
const align = options?.align || 'left';
|
||||
doc.text(text, x, y, { align });
|
||||
}
|
||||
|
||||
// Helper para adicionar campo com valor
|
||||
function addField(doc: jsPDF, label: string, value: string, x: number, y: number, width?: number) {
|
||||
doc.setFontSize(10);
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text(label, x, y);
|
||||
|
||||
doc.setFont('helvetica', 'normal');
|
||||
const labelWidth = doc.getTextWidth(label) + 2;
|
||||
|
||||
if (width) {
|
||||
// Desenhar linha para preenchimento
|
||||
doc.line(x + labelWidth, y + 1, x + width, y + 1);
|
||||
if (value) {
|
||||
doc.text(value, x + labelWidth + 2, y);
|
||||
}
|
||||
} else {
|
||||
doc.text(value || '_____________________', x + labelWidth + 2, y);
|
||||
}
|
||||
|
||||
return y + 7;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Declaração de Acumulação de Cargo, Emprego, Função Pública ou Proventos
|
||||
*/
|
||||
export async function gerarDeclaracaoAcumulacaoCargo(funcionario: Funcionario): Promise<Blob> {
|
||||
const doc = new jsPDF();
|
||||
|
||||
// Adicionar logo e obter posição inicial do conteúdo
|
||||
let y = await addLogo(doc);
|
||||
|
||||
// Cabeçalho (ao lado da logo)
|
||||
addText(doc, 'GOVERNO DO ESTADO DE PERNAMBUCO', 105, Math.max(y - 10, 20), { bold: true, size: 14, align: 'center' });
|
||||
addText(doc, 'SECRETARIA DE ESPORTES', 105, Math.max(y - 2, 28), { bold: true, size: 12, align: 'center' });
|
||||
|
||||
y = Math.max(y, 40);
|
||||
y += 5;
|
||||
|
||||
addText(doc, 'DECLARAÇÃO DE ACUMULAÇÃO DE CARGO, EMPREGO,', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 6;
|
||||
addText(doc, 'FUNÇÃO PÚBLICA OU PROVENTOS', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 15;
|
||||
|
||||
// Corpo
|
||||
doc.setFontSize(11);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
const text1 = `Eu, ${funcionario.nome}, portador(a) do CPF nº ${funcionario.cpf}, `;
|
||||
const text2 = `inscrito(a) no RG nº ${funcionario.rg}, residente e domiciliado(a) à ${funcionario.endereco}, `;
|
||||
const text3 = `${funcionario.cidade}/${funcionario.uf}, DECLARO, para os devidos fins, que:`;
|
||||
|
||||
doc.text(text1, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text2, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text3, 20, y, { maxWidth: 170 });
|
||||
y += 15;
|
||||
|
||||
// Opções
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('( ) NÃO EXERÇO', 25, y);
|
||||
y += 7;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('Outro cargo, emprego ou função pública, bem como não percebo proventos de', 30, y, { maxWidth: 160 });
|
||||
y += 5;
|
||||
doc.text('aposentadoria de regime próprio de previdência social ou do regime geral de', 30, y, { maxWidth: 160 });
|
||||
y += 5;
|
||||
doc.text('previdência social.', 30, y);
|
||||
y += 12;
|
||||
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('( ) EXERÇO', 25, y);
|
||||
y += 7;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('Outro cargo, emprego ou função pública, conforme discriminado abaixo:', 30, y, { maxWidth: 160 });
|
||||
y += 10;
|
||||
|
||||
// Campos para preenchimento de outro cargo
|
||||
y = addField(doc, 'Órgão/Entidade:', funcionario.orgaoOrigem || '', 30, y, 160);
|
||||
y = addField(doc, 'Cargo/Função:', '', 30, y, 160);
|
||||
y = addField(doc, 'Carga Horária:', '', 30, y, 80);
|
||||
y = addField(doc, 'Remuneração:', '', 30, y, 80);
|
||||
y += 5;
|
||||
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('( ) PERCEBO', 25, y);
|
||||
y += 7;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('Proventos de aposentadoria:', 30, y);
|
||||
y += 10;
|
||||
|
||||
y = addField(doc, 'Regime:', funcionario.aposentado === 'funape_ipsep' ? 'FUNAPE/IPSEP' : funcionario.aposentado === 'inss' ? 'INSS' : '', 30, y, 160);
|
||||
y = addField(doc, 'Valor:', '', 30, y, 80);
|
||||
y += 15;
|
||||
|
||||
// Declaração de veracidade
|
||||
doc.text('Declaro, ainda, que estou ciente de que a acumulação ilegal de cargos,', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('empregos ou funções públicas constitui infração administrativa, sujeitando-me', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('às sanções legais cabíveis.', 20, y);
|
||||
y += 20;
|
||||
|
||||
// Data e local
|
||||
const hoje = new Date().toLocaleDateString('pt-BR');
|
||||
doc.text(`Recife, ${hoje}`, 20, y);
|
||||
y += 25;
|
||||
|
||||
// Assinatura
|
||||
doc.line(70, y, 140, y);
|
||||
y += 5;
|
||||
addText(doc, funcionario.nome, 105, y, { align: 'center' });
|
||||
y += 5;
|
||||
addText(doc, `CPF: ${funcionario.cpf}`, 105, y, { size: 9, align: 'center' });
|
||||
|
||||
// Rodapé
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100);
|
||||
doc.text('SGSE - Sistema de Gerenciamento da Secretaria de Esportes', 105, 285, { align: 'center' });
|
||||
|
||||
return doc.output('blob');
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. Declaração de Dependentes para Fins de Imposto de Renda
|
||||
*/
|
||||
export async function gerarDeclaracaoDependentesIR(funcionario: Funcionario): Promise<Blob> {
|
||||
const doc = new jsPDF();
|
||||
|
||||
// Adicionar logo e obter posição inicial do conteúdo
|
||||
let y = await addLogo(doc);
|
||||
|
||||
// Cabeçalho (ao lado da logo)
|
||||
addText(doc, 'GOVERNO DO ESTADO DE PERNAMBUCO', 105, Math.max(y - 10, 20), { bold: true, size: 14, align: 'center' });
|
||||
addText(doc, 'SECRETARIA DE ESPORTES', 105, Math.max(y - 2, 28), { bold: true, size: 12, align: 'center' });
|
||||
|
||||
y = Math.max(y, 40);
|
||||
y += 5;
|
||||
|
||||
addText(doc, 'DECLARAÇÃO DE DEPENDENTES', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 6;
|
||||
addText(doc, 'PARA FINS DE IMPOSTO DE RENDA', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 15;
|
||||
|
||||
// Corpo
|
||||
doc.setFontSize(11);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
const text1 = `Eu, ${funcionario.nome}, portador(a) do CPF nº ${funcionario.cpf}, `;
|
||||
const text2 = `inscrito(a) no RG nº ${funcionario.rg}, matrícula nº ${funcionario.matricula}, `;
|
||||
const text3 = `DECLARO, para fins de dedução no Imposto de Renda na Fonte, que possuo os seguintes dependentes:`;
|
||||
|
||||
doc.text(text1, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text2, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text3, 20, y, { maxWidth: 170 });
|
||||
y += 15;
|
||||
|
||||
// Tabela de dependentes
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.setFontSize(10);
|
||||
doc.text('NOME', 20, y);
|
||||
doc.text('CPF', 80, y);
|
||||
doc.text('PARENTESCO', 130, y);
|
||||
doc.text('NASC.', 175, y);
|
||||
y += 2;
|
||||
doc.line(20, y, 195, y);
|
||||
y += 8;
|
||||
|
||||
// Linhas para preenchimento (5 linhas)
|
||||
doc.setFont('helvetica', 'normal');
|
||||
for (let i = 0; i < 5; i++) {
|
||||
doc.line(20, y, 75, y);
|
||||
doc.line(80, y, 125, y);
|
||||
doc.line(130, y, 170, y);
|
||||
doc.line(175, y, 195, y);
|
||||
y += 12;
|
||||
}
|
||||
|
||||
y += 10;
|
||||
|
||||
// Declaração de veracidade
|
||||
doc.setFontSize(11);
|
||||
doc.text('Declaro estar ciente de que a inclusão de dependente sem direito constitui', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('falsidade ideológica, sujeitando-me às penalidades previstas em lei, inclusive', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('ao recolhimento do imposto devido acrescido de multa e juros.', 20, y, { maxWidth: 170 });
|
||||
y += 20;
|
||||
|
||||
// Data e local
|
||||
const hoje = new Date().toLocaleDateString('pt-BR');
|
||||
doc.text(`Recife, ${hoje}`, 20, y);
|
||||
y += 25;
|
||||
|
||||
// Assinatura
|
||||
doc.line(70, y, 140, y);
|
||||
y += 5;
|
||||
addText(doc, funcionario.nome, 105, y, { align: 'center' });
|
||||
y += 5;
|
||||
addText(doc, `CPF: ${funcionario.cpf} | Matrícula: ${funcionario.matricula}`, 105, y, { size: 9, align: 'center' });
|
||||
|
||||
// Rodapé
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100);
|
||||
doc.text('SGSE - Sistema de Gerenciamento da Secretaria de Esportes', 105, 285, { align: 'center' });
|
||||
|
||||
return doc.output('blob');
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. Declaração de Idoneidade
|
||||
*/
|
||||
export async function gerarDeclaracaoIdoneidade(funcionario: Funcionario): Promise<Blob> {
|
||||
const doc = new jsPDF();
|
||||
|
||||
// Adicionar logo e obter posição inicial do conteúdo
|
||||
let y = await addLogo(doc);
|
||||
|
||||
// Cabeçalho (ao lado da logo)
|
||||
addText(doc, 'GOVERNO DO ESTADO DE PERNAMBUCO', 105, Math.max(y - 10, 20), { bold: true, size: 14, align: 'center' });
|
||||
addText(doc, 'SECRETARIA DE ESPORTES', 105, Math.max(y - 2, 28), { bold: true, size: 12, align: 'center' });
|
||||
|
||||
y = Math.max(y, 40);
|
||||
y += 5;
|
||||
|
||||
addText(doc, 'DECLARAÇÃO DE IDONEIDADE MORAL', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 15;
|
||||
|
||||
// Corpo
|
||||
doc.setFontSize(11);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
const text1 = `Eu, ${funcionario.nome}, portador(a) do CPF nº ${funcionario.cpf}, `;
|
||||
const text2 = `inscrito(a) no RG nº ${funcionario.rg}, residente e domiciliado(a) à ${funcionario.endereco}, `;
|
||||
const text3 = `${funcionario.cidade}/${funcionario.uf}, DECLARO, sob as penas da lei, que:`;
|
||||
|
||||
doc.text(text1, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text2, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text3, 20, y, { maxWidth: 170 });
|
||||
y += 15;
|
||||
|
||||
// Itens da declaração
|
||||
const itens = [
|
||||
'Gozo de boa saúde física e mental para o exercício das atribuições do cargo/função;',
|
||||
'Não fui condenado(a) por crime contra a Administração Pública;',
|
||||
'Não fui condenado(a) por ato de improbidade administrativa;',
|
||||
'Não sofri, no exercício de função pública, penalidade incompatível com a investidura em cargo público;',
|
||||
'Não estou em situação de incompatibilidade ou impedimento para o exercício de cargo ou função pública;',
|
||||
'Tenho idoneidade moral e reputação ilibada;',
|
||||
'Não respondo a processo administrativo disciplinar em qualquer esfera da Administração Pública;',
|
||||
'Não fui demitido(a) ou exonerado(a) de cargo ou função pública por justa causa.'
|
||||
];
|
||||
|
||||
itens.forEach((item, index) => {
|
||||
doc.text(`${index + 1}. ${item}`, 20, y, { maxWidth: 170 });
|
||||
y += 12;
|
||||
});
|
||||
|
||||
y += 10;
|
||||
|
||||
// Declaração de veracidade
|
||||
doc.text('Declaro, ainda, que todas as informações aqui prestadas são verdadeiras,', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('estando ciente de que a falsidade desta declaração configura crime previsto no', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('Código Penal Brasileiro, passível de apuração na forma da lei.', 20, y);
|
||||
y += 20;
|
||||
|
||||
// Data e local
|
||||
const hoje = new Date().toLocaleDateString('pt-BR');
|
||||
doc.text(`Recife, ${hoje}`, 20, y);
|
||||
y += 25;
|
||||
|
||||
// Assinatura
|
||||
doc.line(70, y, 140, y);
|
||||
y += 5;
|
||||
addText(doc, funcionario.nome, 105, y, { align: 'center' });
|
||||
y += 5;
|
||||
addText(doc, `CPF: ${funcionario.cpf}`, 105, y, { size: 9, align: 'center' });
|
||||
|
||||
// Rodapé
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100);
|
||||
doc.text('SGSE - Sistema de Gerenciamento da Secretaria de Esportes', 105, 285, { align: 'center' });
|
||||
|
||||
return doc.output('blob');
|
||||
}
|
||||
|
||||
/**
|
||||
* 4. Termo de Declaração de Nepotismo
|
||||
*/
|
||||
export async function gerarTermoNepotismo(funcionario: Funcionario): Promise<Blob> {
|
||||
const doc = new jsPDF();
|
||||
|
||||
// Adicionar logo e obter posição inicial do conteúdo
|
||||
let y = await addLogo(doc);
|
||||
|
||||
// Cabeçalho (ao lado da logo)
|
||||
addText(doc, 'GOVERNO DO ESTADO DE PERNAMBUCO', 105, Math.max(y - 10, 20), { bold: true, size: 14, align: 'center' });
|
||||
addText(doc, 'SECRETARIA DE ESPORTES', 105, Math.max(y - 2, 28), { bold: true, size: 12, align: 'center' });
|
||||
|
||||
y = Math.max(y, 40);
|
||||
y += 5;
|
||||
|
||||
addText(doc, 'TERMO DE DECLARAÇÃO DE NEPOTISMO', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 15;
|
||||
|
||||
// Corpo
|
||||
doc.setFontSize(11);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
const text1 = `Eu, ${funcionario.nome}, portador(a) do CPF nº ${funcionario.cpf}, `;
|
||||
const text2 = `inscrito(a) no RG nº ${funcionario.rg}, matrícula nº ${funcionario.matricula}, `;
|
||||
const text3 = `nomeado(a) para o cargo/função de ${funcionario.descricaoCargo || '_________________'}, `;
|
||||
const text4 = `DECLARO, para os fins do disposto na Súmula Vinculante nº 13 do STF e demais `;
|
||||
const text5 = `normas de combate ao nepotismo, que:`;
|
||||
|
||||
doc.text(text1, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text2, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text3, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text4, 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text(text5, 20, y, { maxWidth: 170 });
|
||||
y += 15;
|
||||
|
||||
// Opções
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('( ) NÃO POSSUO', 25, y);
|
||||
y += 7;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('Cônjuge, companheiro(a) ou parente em linha reta, colateral ou por afinidade, até', 30, y, { maxWidth: 160 });
|
||||
y += 5;
|
||||
doc.text('o terceiro grau, exercendo cargo em comissão ou função de confiança nesta', 30, y, { maxWidth: 160 });
|
||||
y += 5;
|
||||
doc.text('Secretaria ou em órgão a ela vinculado.', 30, y);
|
||||
y += 12;
|
||||
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('( ) POSSUO', 25, y);
|
||||
y += 7;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
doc.text('O(s) seguinte(s) parente(s) com vínculo nesta Secretaria:', 30, y);
|
||||
y += 10;
|
||||
|
||||
// Campos para parentes
|
||||
for (let i = 0; i < 3; i++) {
|
||||
y = addField(doc, 'Nome:', '', 30, y, 160);
|
||||
y = addField(doc, 'CPF:', '', 30, y, 80);
|
||||
y = addField(doc, 'Grau de Parentesco:', '', 110, y - 7, 80);
|
||||
y = addField(doc, 'Cargo/Função:', '', 30, y, 160);
|
||||
y = addField(doc, 'Órgão:', '', 30, y, 160);
|
||||
y += 8;
|
||||
}
|
||||
|
||||
y += 5;
|
||||
|
||||
// Declaração de veracidade
|
||||
doc.text('Declaro estar ciente de que a nomeação, designação ou contratação em', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('desconformidade com as vedações ao nepotismo importará em nulidade do ato,', 20, y, { maxWidth: 170 });
|
||||
y += 5;
|
||||
doc.text('sem prejuízo das sanções administrativas, civis e penais cabíveis.', 20, y);
|
||||
y += 20;
|
||||
|
||||
// Data e local
|
||||
const hoje = new Date().toLocaleDateString('pt-BR');
|
||||
doc.text(`Recife, ${hoje}`, 20, y);
|
||||
y += 25;
|
||||
|
||||
// Assinatura
|
||||
doc.line(70, y, 140, y);
|
||||
y += 5;
|
||||
addText(doc, funcionario.nome, 105, y, { align: 'center' });
|
||||
y += 5;
|
||||
addText(doc, `CPF: ${funcionario.cpf} | Matrícula: ${funcionario.matricula}`, 105, y, { size: 9, align: 'center' });
|
||||
|
||||
// Rodapé
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100);
|
||||
doc.text('SGSE - Sistema de Gerenciamento da Secretaria de Esportes', 105, 285, { align: 'center' });
|
||||
|
||||
return doc.output('blob');
|
||||
}
|
||||
|
||||
/**
|
||||
* 5. Termo de Opção - Remuneração
|
||||
*/
|
||||
export async function gerarTermoOpcaoRemuneracao(funcionario: Funcionario): Promise<Blob> {
|
||||
const doc = new jsPDF();
|
||||
|
||||
// Adicionar logo e obter posição inicial do conteúdo
|
||||
let y = await addLogo(doc);
|
||||
|
||||
// Cabeçalho (ao lado da logo)
|
||||
addText(doc, 'GOVERNO DO ESTADO DE PERNAMBUCO', 105, Math.max(y - 10, 20), { bold: true, size: 14, align: 'center' });
|
||||
addText(doc, 'SECRETARIA DE ESPORTES', 105, Math.max(y - 2, 28), { bold: true, size: 12, align: 'center' });
|
||||
|
||||
y = Math.max(y, 40);
|
||||
y += 5;
|
||||
|
||||
addText(doc, 'TERMO DE OPÇÃO DE REMUNERAÇÃO', 105, y, { bold: true, size: 12, align: 'center' });
|
||||
y += 15;
|
||||
|
||||
// Corpo
|
||||
doc.setFontSize(11);
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
const text1 = `Eu, ${funcionario.nome}, portador(a) do CPF nº ${funcionario.cpf}, `;
|
||||
const text2 = `inscrito(a) no RG nº ${funcionario.rg}, matrícula nº ${funcionario.matricula}, `;
|
||||
const text3 = `nomeado(a) para o cargo/função de ${funcionario.descricaoCargo || '_________________'}, `;
|
||||
const text4 = `nos termos do Ato/Portaria nº ${funcionario.nomeacaoPortaria || '_____'} de ${funcionario.nomeacaoData || '___/___/___'}, `;
|
||||
const text5 = `DECLARO, para os devidos fins, que:`;
|
||||
|
||||
doc.text(text1, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text2, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text3, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text4, 20, y, { maxWidth: 170 });
|
||||
y += 7;
|
||||
doc.text(text5, 20, y);
|
||||
y += 15;
|
||||
|
||||
// Seção 1 - Vínculo Anterior
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('1. QUANTO AO VÍNCULO ANTERIOR:', 20, y);
|
||||
y += 10;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
doc.text('( ) NÃO POSSUO outro vínculo com a Administração Pública', 25, y);
|
||||
y += 10;
|
||||
|
||||
doc.text('( ) POSSUO vínculo efetivo com:', 25, y);
|
||||
y += 8;
|
||||
|
||||
y = addField(doc, 'Órgão/Entidade:', funcionario.orgaoOrigem || '', 30, y, 160);
|
||||
y = addField(doc, 'Cargo:', '', 30, y, 160);
|
||||
y = addField(doc, 'Matrícula:', '', 30, y, 80);
|
||||
y += 10;
|
||||
|
||||
// Seção 2 - Opção de Remuneração
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('2. QUANTO À REMUNERAÇÃO, OPTO POR RECEBER:', 20, y);
|
||||
y += 10;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
doc.text('( ) A remuneração do cargo em comissão/função gratificada ora assumido', 25, y);
|
||||
y += 10;
|
||||
|
||||
doc.text('( ) A remuneração do cargo efetivo + a gratificação/símbolo', 25, y);
|
||||
y += 10;
|
||||
|
||||
doc.text('( ) A remuneração do cargo efetivo (sem percepção de gratificação)', 25, y);
|
||||
y += 15;
|
||||
|
||||
// Seção 3 - Dados Bancários
|
||||
doc.setFont('helvetica', 'bold');
|
||||
doc.text('3. DADOS BANCÁRIOS PARA PAGAMENTO:', 20, y);
|
||||
y += 10;
|
||||
doc.setFont('helvetica', 'normal');
|
||||
|
||||
y = addField(doc, 'Banco:', 'Bradesco', 20, y, 80);
|
||||
y = addField(doc, 'Agência:', funcionario.contaBradescoAgencia || '', 110, y - 7, 80);
|
||||
y = addField(doc, 'Conta Corrente:', funcionario.contaBradescoNumero || '', 20, y, 80);
|
||||
y = addField(doc, 'Dígito:', funcionario.contaBradescoDV || '', 110, y - 7, 40);
|
||||
y += 15;
|
||||
|
||||
// Declaração de ciência
|
||||
doc.text('Declaro estar ciente de que:', 20, y);
|
||||
y += 8;
|
||||
|
||||
const ciencias = [
|
||||
'A remuneração será paga conforme a opção acima, respeitada a legislação vigente;',
|
||||
'Qualquer alteração na opção deverá ser comunicada formalmente à Secretaria;',
|
||||
'A não apresentação deste termo poderá implicar em atraso no pagamento;',
|
||||
'As informações aqui prestadas são verdadeiras e atualizadas.'
|
||||
];
|
||||
|
||||
ciencias.forEach((item, index) => {
|
||||
doc.text(`${index + 1}. ${item}`, 25, y, { maxWidth: 165 });
|
||||
y += 10;
|
||||
});
|
||||
|
||||
y += 5;
|
||||
|
||||
// Data e local
|
||||
const hoje = new Date().toLocaleDateString('pt-BR');
|
||||
doc.text(`Recife, ${hoje}`, 20, y);
|
||||
y += 25;
|
||||
|
||||
// Assinatura
|
||||
doc.line(70, y, 140, y);
|
||||
y += 5;
|
||||
addText(doc, funcionario.nome, 105, y, { align: 'center' });
|
||||
y += 5;
|
||||
addText(doc, `CPF: ${funcionario.cpf} | Matrícula: ${funcionario.matricula}`, 105, y, { size: 9, align: 'center' });
|
||||
|
||||
// Rodapé
|
||||
doc.setFontSize(8);
|
||||
doc.setTextColor(100);
|
||||
doc.text('SGSE - Sistema de Gerenciamento da Secretaria de Esportes', 105, 285, { align: 'center' });
|
||||
|
||||
return doc.output('blob');
|
||||
}
|
||||
|
||||
// Função helper para download
|
||||
export function downloadBlob(blob: Blob, filename: string) {
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
187
apps/web/src/lib/utils/documentos.ts
Normal file
187
apps/web/src/lib/utils/documentos.ts
Normal file
@@ -0,0 +1,187 @@
|
||||
// Definições dos documentos com URLs de referência
|
||||
|
||||
export interface DocumentoDefinicao {
|
||||
campo: string;
|
||||
nome: string;
|
||||
helpUrl?: string;
|
||||
categoria: string;
|
||||
}
|
||||
|
||||
export const documentos: DocumentoDefinicao[] = [
|
||||
// Antecedentes Criminais
|
||||
{
|
||||
campo: "certidaoAntecedentesPF",
|
||||
nome: "Certidão de Antecedentes Criminais - Polícia Federal",
|
||||
helpUrl: "https://servicos.pf.gov.br/epol-sinic-publico/",
|
||||
categoria: "Antecedentes Criminais",
|
||||
},
|
||||
{
|
||||
campo: "certidaoAntecedentesJFPE",
|
||||
nome: "Certidão de Antecedentes Criminais - Justiça Federal de Pernambuco",
|
||||
helpUrl: "https://certidoes.trf5.jus.br/certidoes2022/paginas/certidaocriminal.faces",
|
||||
categoria: "Antecedentes Criminais",
|
||||
},
|
||||
{
|
||||
campo: "certidaoAntecedentesSDS",
|
||||
nome: "Certidão de Antecedentes Criminais - SDS-PE",
|
||||
helpUrl: "http://www.servicos.sds.pe.gov.br/antecedentes/public/pages/certidaoAntecedentesCriminais/certidaoAntecedentesCriminaisEmitir.jsf",
|
||||
categoria: "Antecedentes Criminais",
|
||||
},
|
||||
{
|
||||
campo: "certidaoAntecedentesTJPE",
|
||||
nome: "Certidão de Antecedentes Criminais - TJPE",
|
||||
helpUrl: "https://certidoesunificadas.app.tjpe.jus.br/certidao-criminal-pf",
|
||||
categoria: "Antecedentes Criminais",
|
||||
},
|
||||
{
|
||||
campo: "certidaoImprobidade",
|
||||
nome: "Certidão Improbidade Administrativa",
|
||||
helpUrl: "https://www.cnj.jus.br/improbidade_adm/consultar_requerido.php",
|
||||
categoria: "Antecedentes Criminais",
|
||||
},
|
||||
|
||||
// Documentos Pessoais
|
||||
{
|
||||
campo: "rgFrente",
|
||||
nome: "Carteira de Identidade SDS/PE ou (SSP-PE) - Frente",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
{
|
||||
campo: "rgVerso",
|
||||
nome: "Carteira de Identidade SDS/PE ou (SSP-PE) - Verso",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
{
|
||||
campo: "cpfFrente",
|
||||
nome: "CPF/CIC - Frente",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
{
|
||||
campo: "cpfVerso",
|
||||
nome: "CPF/CIC - Verso",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
{
|
||||
campo: "situacaoCadastralCPF",
|
||||
nome: "Situação Cadastral CPF",
|
||||
helpUrl: "https://servicos.receita.fazenda.gov.br/servicos/cpf/consultasituacao/consultapublica.asp",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
{
|
||||
campo: "certidaoRegistroCivil",
|
||||
nome: "Certidão de Registro Civil (Nascimento, Casamento ou União Estável)",
|
||||
categoria: "Documentos Pessoais",
|
||||
},
|
||||
|
||||
// Documentos Eleitorais
|
||||
{
|
||||
campo: "tituloEleitorFrente",
|
||||
nome: "Título de Eleitor - Frente",
|
||||
categoria: "Documentos Eleitorais",
|
||||
},
|
||||
{
|
||||
campo: "tituloEleitorVerso",
|
||||
nome: "Título de Eleitor - Verso",
|
||||
categoria: "Documentos Eleitorais",
|
||||
},
|
||||
{
|
||||
campo: "comprovanteVotacao",
|
||||
nome: "Comprovante de Votação Última Eleição ou Certidão de Quitação Eleitoral",
|
||||
helpUrl: "https://www.tse.jus.br",
|
||||
categoria: "Documentos Eleitorais",
|
||||
},
|
||||
|
||||
// Documentos Profissionais
|
||||
{
|
||||
campo: "carteiraProfissionalFrente",
|
||||
nome: "Carteira Profissional - Frente (página da foto)",
|
||||
categoria: "Documentos Profissionais",
|
||||
},
|
||||
{
|
||||
campo: "carteiraProfissionalVerso",
|
||||
nome: "Carteira Profissional - Verso (página da foto)",
|
||||
categoria: "Documentos Profissionais",
|
||||
},
|
||||
{
|
||||
campo: "comprovantePIS",
|
||||
nome: "Comprovante de PIS/PASEP",
|
||||
categoria: "Documentos Profissionais",
|
||||
},
|
||||
{
|
||||
campo: "reservistaDoc",
|
||||
nome: "Reservista (obrigatória para homem até 45 anos)",
|
||||
categoria: "Documentos Profissionais",
|
||||
},
|
||||
|
||||
// Certidões e Comprovantes
|
||||
{
|
||||
campo: "certidaoNascimentoDependentes",
|
||||
nome: "Certidão de Nascimento do(s) Dependente(s) para Imposto de Renda",
|
||||
categoria: "Certidões e Comprovantes",
|
||||
},
|
||||
{
|
||||
campo: "cpfDependentes",
|
||||
nome: "CPF do(s) Dependente(s) para Imposto de Renda",
|
||||
categoria: "Certidões e Comprovantes",
|
||||
},
|
||||
{
|
||||
campo: "comprovanteEscolaridade",
|
||||
nome: "Documento de Comprovação do Nível de Escolaridade",
|
||||
categoria: "Certidões e Comprovantes",
|
||||
},
|
||||
{
|
||||
campo: "comprovanteResidencia",
|
||||
nome: "Comprovante de Residência",
|
||||
categoria: "Certidões e Comprovantes",
|
||||
},
|
||||
{
|
||||
campo: "comprovanteContaBradesco",
|
||||
nome: "Comprovante de Conta-Corrente no Banco BRADESCO",
|
||||
categoria: "Certidões e Comprovantes",
|
||||
},
|
||||
|
||||
// Declarações
|
||||
{
|
||||
campo: "declaracaoAcumulacaoCargo",
|
||||
nome: "Declaração de Acumulação de Cargo, Emprego, Função Pública ou Proventos",
|
||||
categoria: "Declarações",
|
||||
},
|
||||
{
|
||||
campo: "declaracaoDependentesIR",
|
||||
nome: "Declaração de Dependentes para Fins de Imposto de Renda",
|
||||
categoria: "Declarações",
|
||||
},
|
||||
{
|
||||
campo: "declaracaoIdoneidade",
|
||||
nome: "Declaração de Idoneidade",
|
||||
categoria: "Declarações",
|
||||
},
|
||||
{
|
||||
campo: "termoNepotismo",
|
||||
nome: "Termo de Declaração de Nepotismo",
|
||||
categoria: "Declarações",
|
||||
},
|
||||
{
|
||||
campo: "termoOpcaoRemuneracao",
|
||||
nome: "Termo de Opção - Remuneração",
|
||||
categoria: "Declarações",
|
||||
},
|
||||
];
|
||||
|
||||
export const categoriasDocumentos = [
|
||||
"Antecedentes Criminais",
|
||||
"Documentos Pessoais",
|
||||
"Documentos Eleitorais",
|
||||
"Documentos Profissionais",
|
||||
"Certidões e Comprovantes",
|
||||
"Declarações",
|
||||
];
|
||||
|
||||
export function getDocumentosByCategoria(categoria: string): DocumentoDefinicao[] {
|
||||
return documentos.filter(doc => doc.categoria === categoria);
|
||||
}
|
||||
|
||||
export function getDocumentoDefinicao(campo: string): DocumentoDefinicao | undefined {
|
||||
return documentos.find(doc => doc.campo === campo);
|
||||
}
|
||||
|
||||
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();
|
||||
};
|
||||
|
||||
52
apps/web/src/lib/utils/modelosDeclaracoes.ts
Normal file
52
apps/web/src/lib/utils/modelosDeclaracoes.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
// Definições dos modelos de declaração
|
||||
|
||||
export interface ModeloDeclaracao {
|
||||
id: string;
|
||||
nome: string;
|
||||
descricao: string;
|
||||
arquivo: string;
|
||||
podePreencherAutomaticamente: boolean;
|
||||
}
|
||||
|
||||
export const modelosDeclaracoes: ModeloDeclaracao[] = [
|
||||
{
|
||||
id: "acumulacao_cargo",
|
||||
nome: "Declaração de Acumulação de Cargo",
|
||||
descricao: "Declaração sobre acumulação de cargo, emprego, função pública ou proventos",
|
||||
arquivo: "/modelos/declaracoes/Declaração de Acumulação de Cargo, Emprego, Função Pública ou Proventos.pdf",
|
||||
podePreencherAutomaticamente: true,
|
||||
},
|
||||
{
|
||||
id: "dependentes_ir",
|
||||
nome: "Declaração de Dependentes",
|
||||
descricao: "Declaração de dependentes para fins de Imposto de Renda",
|
||||
arquivo: "/modelos/declaracoes/Declaração de Dependentes para Fins de Imposto de Renda.pdf",
|
||||
podePreencherAutomaticamente: true,
|
||||
},
|
||||
{
|
||||
id: "idoneidade",
|
||||
nome: "Declaração de Idoneidade",
|
||||
descricao: "Declaração de idoneidade moral e conduta ilibada",
|
||||
arquivo: "/modelos/declaracoes/Declaração de Idoneidade.pdf",
|
||||
podePreencherAutomaticamente: true,
|
||||
},
|
||||
{
|
||||
id: "nepotismo",
|
||||
nome: "Termo de Declaração de Nepotismo",
|
||||
descricao: "Declaração sobre inexistência de situação de nepotismo",
|
||||
arquivo: "/modelos/declaracoes/Termo de Declaração de Nepotismo.pdf",
|
||||
podePreencherAutomaticamente: true,
|
||||
},
|
||||
{
|
||||
id: "opcao_remuneracao",
|
||||
nome: "Termo de Opção - Remuneração",
|
||||
descricao: "Termo de opção de remuneração",
|
||||
arquivo: "/modelos/declaracoes/Termo de Opção - Remuneração.pdf",
|
||||
podePreencherAutomaticamente: true,
|
||||
},
|
||||
];
|
||||
|
||||
export function getModeloById(id: string): ModeloDeclaracao | undefined {
|
||||
return modelosDeclaracoes.find(modelo => modelo.id === id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user