// Wave 3a — RH (5 telas): Funcionários, Horários, Ponto, Folha CLT, Ajustes Salariais
// Shared employee data
const EMPLOYEES = [
{ id: 1, nome: 'Ana Paula Mendes', cargo: 'Gerente Geral', depto: 'Administrativo', admissao: '12/03/2019', salario: 7800, status: 'ativo', cpf: '128.472.930-18', pis: '120.48291.82-4', tipo: 'CLT', centro: 'Matriz', email: 'ana.mendes@padaria.com.br', tel: '(31) 98472-1829' },
{ id: 2, nome: 'Bruno Tavares Silva', cargo: 'Vendedor Sênior', depto: 'Comercial', admissao: '05/06/2020', salario: 3800, status: 'ativo', cpf: '091.283.472-91', pis: '201.84729.10-3', tipo: 'CLT', centro: 'Matriz', email: 'bruno.tavares@padaria.com.br', tel: '(31) 99128-4720' },
{ id: 3, nome: 'Carolina Ferreira', cargo: 'Confeiteira Chefe', depto: 'Produção', admissao: '22/01/2021', salario: 4200, status: 'ativo', cpf: '204.918.374-02', pis: '304.92018.43-7', tipo: 'CLT', centro: 'Matriz', email: 'carol.ferreira@padaria.com.br', tel: '(31) 98210-3849' },
{ id: 4, nome: 'Diego Almeida', cargo: 'Atendente', depto: 'Vendas', admissao: '14/08/2022', salario: 1980, status: 'ativo', cpf: '371.029.482-56', pis: '208.10928.74-1', tipo: 'CLT', centro: 'Filial Savassi', email: 'diego.almeida@padaria.com.br', tel: '(31) 97482-0192' },
{ id: 5, nome: 'Eduarda Lopes', cargo: 'Auxiliar de Produção', depto: 'Produção', admissao: '03/11/2023', salario: 1680, status: 'ativo', cpf: '482.019.273-04', pis: '102.93847.20-8', tipo: 'CLT', centro: 'Matriz', email: 'eduarda.lopes@padaria.com.br', tel: '(31) 98901-2837' },
{ id: 6, nome: 'Felipe Rocha Santos', cargo: 'Padeiro', depto: 'Produção', admissao: '18/04/2022', salario: 2800, status: 'ativo', cpf: '590.382.471-82', pis: '401.28937.41-2', tipo: 'CLT', centro: 'Matriz', email: 'felipe.rocha@padaria.com.br', tel: '(31) 99302-8471' },
{ id: 7, nome: 'Gabriela Costa', cargo: 'Caixa', depto: 'Vendas', admissao: '27/02/2024', salario: 1820, status: 'férias', cpf: '619.482.039-15', pis: '502.10283.94-5', tipo: 'CLT', centro: 'Filial Savassi', email: 'gabi.costa@padaria.com.br', tel: '(31) 98120-4782' },
{ id: 8, nome: 'Henrique Batista', cargo: 'Auxiliar Administrativo', depto: 'Administrativo', admissao: '09/07/2023', salario: 2400, status: 'ativo', cpf: '728.193.047-28', pis: '603.92017.48-1', tipo: 'CLT', centro: 'Matriz', email: 'henrique.batista@padaria.com.br', tel: '(31) 97201-9384' },
{ id: 9, nome: 'Isabela Nunes', cargo: 'Vendedora', depto: 'Comercial', admissao: '15/09/2024', salario: 2200, status: 'ativo', cpf: '837.294.018-46', pis: '704.10293.82-4', tipo: 'CLT', centro: 'Matriz', email: 'isabela.nunes@padaria.com.br', tel: '(31) 99182-0473' },
{ id: 10, nome: 'João Vitor Dias', cargo: 'Motorista Entregador', depto: 'Logística', admissao: '01/10/2022', salario: 2600, status: 'ativo', cpf: '948.102.394-73', pis: '805.29384.71-0', tipo: 'CLT', centro: 'Matriz', email: 'joao.dias@padaria.com.br', tel: '(31) 98472-1038' },
{ id: 11, nome: 'Karina Oliveira', cargo: 'Confeiteira', depto: 'Produção', admissao: '12/05/2023', salario: 2900, status: 'licença', cpf: '057.291.483-62', pis: '906.38471.29-3', tipo: 'CLT', centro: 'Matriz', email: 'karina.oliveira@padaria.com.br', tel: '(31) 97109-2847' },
{ id: 12, nome: 'Lucas Pereira', cargo: 'Padeiro', depto: 'Produção', admissao: '23/06/2021', salario: 2800, status: 'ativo', cpf: '168.309.472-59', pis: '107.29384.71-5', tipo: 'CLT', centro: 'Matriz', email: 'lucas.pereira@padaria.com.br', tel: '(31) 98203-9471' },
{ id: 13, nome: 'Mariana Souza', cargo: 'Supervisora de Loja', depto: 'Vendas', admissao: '07/01/2020', salario: 4600, status: 'ativo', cpf: '279.418.302-71', pis: '208.38471.29-8', tipo: 'CLT', centro: 'Filial Savassi', email: 'mariana.souza@padaria.com.br', tel: '(31) 99472-1083' },
{ id: 14, nome: 'Nathalia Ramos', cargo: 'Atendente', depto: 'Vendas', admissao: '19/03/2025', salario: 1820, status: 'experiência', cpf: '390.284.017-48', pis: '309.47128.30-2', tipo: 'CLT', centro: 'Filial Savassi', email: 'nath.ramos@padaria.com.br', tel: '(31) 98120-4739' },
{ id: 15, nome: 'Otávio Lima', cargo: 'Auxiliar de Cozinha', depto: 'Produção', admissao: '24/11/2023', salario: 1740, status: 'ativo', cpf: '401.293.847-18', pis: '410.29384.71-7', tipo: 'CLT', centro: 'Matriz', email: 'otavio.lima@padaria.com.br', tel: '(31) 97283-0419' },
{ id: 16, nome: 'Patrícia Gomes', cargo: 'Assistente de RH', depto: 'Administrativo', admissao: '08/04/2024', salario: 3100, status: 'ativo', cpf: '512.038.472-09', pis: '511.38492.71-4', tipo: 'CLT', centro: 'Matriz', email: 'patricia.gomes@padaria.com.br', tel: '(31) 98910-2374' },
{ id: 17, nome: 'Rafael Cardoso', cargo: 'Diretor Comercial', depto: 'Diretoria', admissao: '01/02/2018', salario: 9200, status: 'ativo', cpf: '623.149.028-36', pis: '612.29384.71-9', tipo: 'PJ', centro: 'Matriz', email: 'rafael.cardoso@padaria.com.br', tel: '(31) 99102-8473' },
];
const statusChipRH = (s) => ({
ativo: { bg: 'rgba(34,197,94,.14)', c: '#86efac', l: 'Ativo' },
'férias': { bg: 'rgba(245,158,11,.14)', c: '#fcd34d', l: 'Em férias' },
'licença': { bg: 'rgba(59,130,246,.14)', c: '#93c5fd', l: 'Licença' },
'experiência': { bg: 'rgba(139,92,246,.14)', c: '#c4b5fd', l: 'Experiência' },
desligado: { bg: 'rgba(239,68,68,.14)', c: '#fca5a5', l: 'Desligado' },
})[s];
const deptColors = {
'Administrativo': '#3b82f6', 'Comercial': '#8b5cf6', 'Produção': '#f59e0b',
'Vendas': '#22c55e', 'Logística': '#06b6d4', 'Diretoria': '#ec4899',
};
const rhSelectStyle = { padding: '7px 12px', borderRadius: 8, fontSize: 12.5, background: 'var(--bg-2)', border: '1px solid var(--line-2)', color: 'var(--text-1)' };
// =============================================================
// 1. Funcionários
// =============================================================
const PageFuncionarios = ({ onNavigate }) => {
const [search, setSearch] = React.useState('');
const [filterDept, setFilterDept] = React.useState('todos');
const [selected, setSelected] = React.useState(null);
const filtered = EMPLOYEES.filter(e =>
(filterDept === 'todos' || e.depto === filterDept) &&
(!search || e.nome.toLowerCase().includes(search.toLowerCase()) || e.cargo.toLowerCase().includes(search.toLowerCase()))
);
const totalSalarios = EMPLOYEES.filter(e => e.status !== 'desligado').reduce((t, e) => t + e.salario, 0);
const depts = [...new Set(EMPLOYEES.map(e => e.depto))];
return (
>}
>
e.status === 'ativo').length} sub={`${EMPLOYEES.length} totais · 2 novos mês`}/>
| Funcionário |
Cargo |
Departamento |
Admissão |
Salário |
Status |
Tipo |
Ações |
{filtered.map(e => {
const st = statusChipRH(e.status);
return (
setSelected(e)} style={{ cursor: 'pointer' }}>
|
|
{e.cargo} |
{e.depto}
|
{e.admissao} |
{BRL(e.salario)} |
{st.l} |
{e.tipo} |
|
);
})}
{selected && setSelected(null)}/>}
);
};
const FuncionarioDrawer = ({ emp, onClose }) => {
const [tab, setTab] = React.useState('pessoal');
const tabs = [
{ id: 'pessoal', l: 'Pessoal', i: 'users' },
{ id: 'contrato', l: 'Contrato', i: 'doc' },
{ id: 'dependentes', l: 'Dependentes', i: 'users' },
{ id: 'banco', l: 'Banco & PIS', i: 'wallet' },
{ id: 'docs', l: 'Documentos', i: 'file' },
];
return (
<>
{emp.nome}
{emp.cargo} · {emp.depto}
ID · {String(emp.id).padStart(4, '0')} · Admissão {emp.admissao}
{tabs.map(t => (
))}
{tab === 'pessoal' &&
}
{tab === 'contrato' && <>
>}
{tab === 'dependentes' &&
{[
{ nome: 'Pedro Henrique Mendes', rel: 'Filho', nasc: '22/08/2012 (13 anos)', ir: true, sf: true },
{ nome: 'Sofia Mendes', rel: 'Filha', nasc: '04/05/2016 (8 anos)', ir: true, sf: true },
].map((d, i) => (
{d.nome}
{d.rel} · {d.nasc}
{d.ir && Dep. IRRF}
{d.sf && Salário-família}
))}
}
{tab === 'banco' &&
}
{tab === 'docs' &&
{[
{ n: 'Contrato de trabalho assinado.pdf', sz: '412 KB', d: emp.admissao },
{ n: 'Cópia RG e CPF.pdf', sz: '284 KB', d: emp.admissao },
{ n: 'Comprovante de residência.pdf', sz: '128 KB', d: '15/03/2024' },
{ n: 'Carta de apresentação.docx', sz: '24 KB', d: emp.admissao },
{ n: 'ASO admissional.pdf', sz: '182 KB', d: emp.admissao },
{ n: 'Foto 3x4.jpg', sz: '89 KB', d: emp.admissao },
].map((f, i) => (
))}
}
>
);
};
const DataGrid = ({ rows }) => (
{rows.map(([k, v, variant], i) => (
{k}
{v}
))}
);
// =============================================================
// 2. Horários
// =============================================================
const PageHorarios = ({ onNavigate }) => {
const dias = ['Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado', 'Domingo'];
const funcs = EMPLOYEES.slice(0, 10);
// Turnos: 0 = folga, 'm' = manhã 6-14, 't' = tarde 14-22, 'n' = noite 22-06, 'c' = comercial 8-17
const scale = {
1: ['c', 'c', 'c', 'c', 'c', 0, 0],
2: ['c', 'c', 'c', 'c', 'c', 'c', 0],
3: ['m', 'm', 'm', 'm', 'm', 'm', 0],
4: ['t', 't', 't', 't', 't', 't', 0],
5: ['m', 'm', 'm', 0, 'm', 'm', 'm'],
6: ['m', 'm', 'm', 'm', 'm', 0, 0],
9: [0, 't', 't', 't', 't', 't', 't'],
10: ['c', 'c', 'c', 'c', 'c', 0, 0],
12: ['m', 'm', 'm', 'm', 'm', 'm', 0],
13: ['c', 'c', 'c', 'c', 'c', 'c', 0],
};
const turnoMeta = {
m: { l: 'Manhã', h: '06:00 – 14:00', bg: 'rgba(245,158,11,.16)', c: '#fcd34d', border: 'rgba(245,158,11,.3)' },
t: { l: 'Tarde', h: '14:00 – 22:00', bg: 'rgba(139,92,246,.16)', c: '#c4b5fd', border: 'rgba(139,92,246,.3)' },
n: { l: 'Noite', h: '22:00 – 06:00', bg: 'rgba(59,130,246,.16)', c: '#93c5fd', border: 'rgba(59,130,246,.3)' },
c: { l: 'Comercial', h: '08:00 – 17:00', bg: 'rgba(34,197,94,.14)', c: '#86efac', border: 'rgba(34,197,94,.3)' },
};
return (
>}
>
Escala semanal
{Object.entries(turnoMeta).map(([k, m]) => (
{m.l} {m.h}
))}
{/* Header */}
Funcionário
{dias.map((d, i) => (
= 5 ? 'var(--accent-text)' : 'var(--text-3)', fontWeight: 600, textAlign: 'center' }}>
{d}
{14 + i}
))}
{/* Rows */}
{funcs.map((emp, ri) => {
const row = scale[emp.id] || ['c','c','c','c','c',0,0];
const totalH = row.reduce((t, s) => t + (s === 0 ? 0 : 8), 0);
return (
{emp.nome.split(' ').slice(0, 2).join(' ')}
{totalH}h semana
{row.map((s, ci) => {
if (s === 0) return (
—
);
const m = turnoMeta[s];
return (
);
})}
);
})}
);
};
// =============================================================
// 3. Ponto Eletrônico
// =============================================================
const PagePonto = ({ onNavigate }) => {
const [view, setView] = React.useState('hoje');
const batidas = [
{ tipo: 'entrada', hora: '07:58', loc: 'Matriz · Av. Cristiano Machado', status: 'ok', foto: true },
{ tipo: 'almoco-saida', hora: '12:02', loc: 'Matriz · Av. Cristiano Machado', status: 'ok', foto: true },
{ tipo: 'almoco-volta', hora: '13:04', loc: 'Matriz · Av. Cristiano Machado', status: 'ok', foto: true },
{ tipo: 'saida', hora: '17:12', loc: 'Matriz · Av. Cristiano Machado', status: 'extra', foto: true },
];
const espelho = Array.from({ length: 14 }, (_, i) => {
const dia = i + 1;
const isWknd = (dia % 7 === 5 || dia % 7 === 6);
if (isWknd && dia !== 12) return { dia, dow: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'][new Date(2026, 3, dia).getDay()], entrada: '—', almoco: '—', saida: '—', total: '—', extra: '—', tipo: 'folga' };
const variant = [dia === 3, dia === 7, dia === 10, dia === 12][Math.min(3, dia % 4)];
if (dia === 3) return { dia, dow: 'Sex', entrada: '08:12', almoco: '12:00/13:00', saida: '17:04', total: '07:52', extra: '—', tipo: 'atraso' };
if (dia === 7) return { dia, dow: 'Ter', entrada: '—', almoco: '—', saida: '—', total: '—', extra: '—', tipo: 'falta' };
if (dia === 10) return { dia, dow: 'Sex', entrada: '07:55', almoco: '12:01/13:03', saida: '18:24', total: '09:25', extra: '+01:25', tipo: 'extra' };
return { dia, dow: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'][new Date(2026, 3, dia).getDay()], entrada: '07:58', almoco: '12:00/13:00', saida: '17:02', total: '08:04', extra: '—', tipo: 'ok' };
});
const typeStyle = {
ok: { c: 'var(--text-1)', bg: 'transparent' },
atraso: { c: '#fcd34d', bg: 'rgba(245,158,11,.06)' },
falta: { c: '#fca5a5', bg: 'rgba(239,68,68,.08)' },
extra: { c: '#86efac', bg: 'rgba(34,197,94,.06)' },
folga: { c: 'var(--text-4)', bg: 'var(--bg-base)' },
};
return (
>}
>
{/* Live batidas - card */}
Batidas de hoje · 17/abr/2026
Ao vivo
{/* Mini map with pin */}
📍 Matriz · 12m de precisão
{batidas.map((b, i) => {
const labels = { entrada: 'Entrada', 'almoco-saida': 'Saída p/ almoço', 'almoco-volta': 'Retorno', saida: 'Saída' };
const icons = { entrada: 'arrowDown', 'almoco-saida': 'arrowUp', 'almoco-volta': 'arrowDown', saida: 'arrowUp' };
return (
{b.hora}
{b.foto &&
Foto OK}
);
})}
{/* Espelho table */}
Espelho de ponto · abril/2026
Dias 1–14
| Dia |
Entrada |
Almoço |
Saída |
Total |
Extras |
{espelho.map(e => {
const ts = typeStyle[e.tipo];
return (
|
{String(e.dia).padStart(2, '0')}
{e.dow}
|
{e.entrada} |
{e.almoco} |
{e.saida} |
{e.total} |
{e.extra} |
);
})}
| TOTAL ABRIL |
80:45 |
+01:25 |
);
};
// =============================================================
// 4. Folha CLT
// =============================================================
const PageFolha = ({ onNavigate }) => {
const [step, setStep] = React.useState(3);
const steps = [
{ id: 1, l: 'Período', i: 'calendar' },
{ id: 2, l: 'Funcionários', i: 'users' },
{ id: 3, l: 'Eventos', i: 'edit' },
{ id: 4, l: 'Conferência', i: 'check' },
{ id: 5, l: 'Fechamento', i: 'lock' },
];
// Payroll calc: INSS progressive, IRRF simplified
const calcINSS = (b) => {
if (b <= 1412) return b * 0.075;
if (b <= 2666.68) return 1412 * 0.075 + (b - 1412) * 0.09;
if (b <= 4000.03) return 1412 * 0.075 + (2666.68 - 1412) * 0.09 + (b - 2666.68) * 0.12;
if (b <= 7786.02) return 1412 * 0.075 + (2666.68 - 1412) * 0.09 + (4000.03 - 2666.68) * 0.12 + (b - 4000.03) * 0.14;
return 908.86;
};
const calcIRRF = (b, inss, dep = 0) => {
const base = b - inss - dep * 189.59;
if (base <= 2259.20) return 0;
if (base <= 2826.65) return base * 0.075 - 169.44;
if (base <= 3751.05) return base * 0.15 - 381.44;
if (base <= 4664.68) return base * 0.225 - 662.77;
return base * 0.275 - 896.00;
};
const rows = EMPLOYEES.slice(0, 10).map(e => {
const horasExtras = [0, 0, 0, 85, 0, 160, 0, 0, 120, 0][e.id % 10] || 0;
const comissao = e.depto === 'Comercial' ? e.salario * 0.12 : 0;
const proventos = e.salario + horasExtras + comissao;
const inss = calcINSS(proventos);
const irrf = Math.max(0, calcIRRF(proventos, inss, e.id === 1 ? 2 : 0));
const fgts = proventos * 0.08;
const vt = 220;
const liquido = proventos - inss - irrf - vt;
return { ...e, horasExtras, comissao, proventos, inss, irrf, fgts, vt, liquido };
});
const totais = rows.reduce((t, r) => ({
proventos: t.proventos + r.proventos,
inss: t.inss + r.inss,
irrf: t.irrf + r.irrf,
fgts: t.fgts + r.fgts,
liquido: t.liquido + r.liquido,
}), { proventos: 0, inss: 0, irrf: 0, fgts: 0, liquido: 0 });
return (
>}
>
{/* Wizard stepper */}
{steps.map((s, i) => {
const active = step === s.id;
const done = step > s.id;
return (
{i < steps.length - 1 && }
);
})}
Folha detalhada · abril/2026
Pagamento: 05/05/2026
| Funcionário |
Salário |
H. Extras |
Comissão |
PROVENTOS |
INSS |
IRRF |
VT |
DESC. |
FGTS |
LÍQUIDO |
{rows.map(r => (
{r.nome.split(' ').slice(0, 2).join(' ')}
{r.cargo}
|
{BRL(r.salario)} |
0 ? 'var(--text-1)' : 'var(--text-4)' }}>{r.horasExtras > 0 ? BRL(r.horasExtras) : '—'} |
0 ? 'var(--text-1)' : 'var(--text-4)' }}>{r.comissao > 0 ? BRL(r.comissao) : '—'} |
{BRL(r.proventos)} |
-{BRL(r.inss)} |
0 ? '#fca5a5' : 'var(--text-4)' }}>{r.irrf > 0 ? '-' + BRL(r.irrf) : '—'} |
-{BRL(r.vt)} |
-{BRL(r.inss + r.irrf + r.vt)} |
{BRL(r.fgts)} |
{BRL(r.liquido)} |
))}
| TOTAIS |
|
{BRL(totais.proventos)} |
-{BRL(totais.inss)} |
-{BRL(totais.irrf)} |
|
|
{BRL(totais.fgts)} |
{BRL(totais.liquido)} |
);
};
// =============================================================
// 5. Ajustes Salariais
// =============================================================
const PageAjustes = ({ onNavigate }) => {
const [selected, setSelected] = React.useState(EMPLOYEES[1]); // Bruno Tavares
const hist = {
1: [
{ data: '12/03/2019', tipo: 'admissao', de: 0, para: 3500, motivo: 'Admissão', por: 'Rafael Cardoso' },
{ data: '01/03/2020', tipo: 'dissidio', de: 3500, para: 3640, motivo: 'Dissídio coletivo 4%', por: 'Sistema' },
{ data: '15/07/2021', tipo: 'promocao', de: 3640, para: 5200, motivo: 'Promoção → Coordenadora', por: 'Rafael Cardoso' },
{ data: '01/03/2022', tipo: 'dissidio', de: 5200, para: 5512, motivo: 'Dissídio coletivo 6%', por: 'Sistema' },
{ data: '20/01/2023', tipo: 'merito', de: 5512, para: 6200, motivo: 'Mérito · avaliação excelente', por: 'Patrícia Gomes' },
{ data: '01/03/2023', tipo: 'dissidio', de: 6200, para: 6572, motivo: 'Dissídio coletivo 6%', por: 'Sistema' },
{ data: '08/08/2023', tipo: 'promocao', de: 6572, para: 7400, motivo: 'Promoção → Gerente Geral', por: 'Rafael Cardoso' },
{ data: '01/03/2024', tipo: 'dissidio', de: 7400, para: 7696, motivo: 'Dissídio coletivo 4%', por: 'Sistema' },
{ data: '01/01/2026', tipo: 'merito', de: 7696, para: 7800, motivo: 'Ajuste de mercado', por: 'Patrícia Gomes' },
],
2: [
{ data: '05/06/2020', tipo: 'admissao', de: 0, para: 2200, motivo: 'Admissão', por: 'Rafael Cardoso' },
{ data: '01/03/2021', tipo: 'dissidio', de: 2200, para: 2310, motivo: 'Dissídio coletivo 5%', por: 'Sistema' },
{ data: '15/11/2021', tipo: 'merito', de: 2310, para: 2600, motivo: 'Mérito anual', por: 'Rafael Cardoso' },
{ data: '01/03/2022', tipo: 'dissidio', de: 2600, para: 2756, motivo: 'Dissídio coletivo 6%', por: 'Sistema' },
{ data: '22/06/2023', tipo: 'promocao', de: 2756, para: 3400, motivo: 'Promoção → Vendedor Sênior', por: 'Rafael Cardoso' },
{ data: '01/03/2024', tipo: 'dissidio', de: 3400, para: 3536, motivo: 'Dissídio coletivo 4%', por: 'Sistema' },
{ data: '12/10/2025', tipo: 'merito', de: 3536, para: 3800, motivo: 'Mérito · superou metas Q3', por: 'Patrícia Gomes' },
],
};
const changes = hist[selected.id] || [];
const tipoStyle = {
admissao: { l: 'Admissão', bg: 'rgba(59,130,246,.14)', c: '#93c5fd', i: 'user' },
merito: { l: 'Mérito', bg: 'rgba(139,92,246,.14)', c: '#c4b5fd', i: 'award' },
promocao: { l: 'Promoção', bg: 'rgba(34,197,94,.14)', c: '#86efac', i: 'trending-up' },
dissidio: { l: 'Dissídio', bg: 'rgba(245,158,11,.14)', c: '#fcd34d', i: 'sync' },
};
return (
>}
>
{/* Employee list */}
{EMPLOYEES.slice(0, 10).map(e => (
))}
{/* Detail + chart */}
{selected.nome}
{selected.cargo} · admitido em {selected.admissao}
Salário atual
{BRL(selected.salario)}
{changes.length > 1 && (
+{(((selected.salario - changes[0].para) / changes[0].para) * 100).toFixed(0)}% desde admissão
)}
{/* Evolution chart */}
{/* Timeline */}
Histórico de alterações
{changes.length} registros
{[...changes].reverse().map((c, i) => {
const ts = tipoStyle[c.tipo];
const pct = c.de === 0 ? 100 : ((c.para - c.de) / c.de) * 100;
return (
{ts.l}
{c.data}
{c.motivo}
Por {c.por}
{c.de > 0 &&
{BRL(c.de)}
}
{BRL(c.para)}
{c.de > 0 &&
+{pct.toFixed(1)}%
}
);
})}
);
};
Object.assign(window, { EMPLOYEES, statusChipRH, deptColors, rhSelectStyle, PageFuncionarios, PageHorarios, PagePonto, PageFolha, PageAjustes });