// 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`}/>
setSearch(e.target.value)} placeholder="Buscar por nome, cargo, CPF..." style={{ width: '100%', padding: '8px 12px 8px 32px', borderRadius: 8, fontSize: 12.5, background: 'var(--bg-2)', border: '1px solid var(--line-2)', color: 'var(--text-1)', }}/>
{filtered.map(e => { const st = statusChipRH(e.status); return ( setSelected(e)} style={{ cursor: 'pointer' }}> ); })}
Funcionário Cargo Departamento Admissão Salário Status Tipo Ações
{e.nome}
{e.cpf}
{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) => (
{f.n}
{f.sz} · {f.d}
))}
}
); }; 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 (
{m.l}
{m.h}
); })}
); })}
); }; // ============================================================= // 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 */}
{[...Array(10)].map((_, i) => )} {[...Array(25)].map((_, i) => )} -19.9167, -43.9345
📍 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 (
{labels[b.tipo]}
{b.loc}
{b.hora}
{b.foto && Foto OK}
); })}
{/* Espelho table */}
Espelho de ponto · abril/2026
Dias 1–14
{espelho.map(e => { const ts = typeStyle[e.tipo]; return ( ); })}
Dia Entrada Almoço Saída Total Extras
{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
{rows.map(r => ( ))}
Funcionário Salário H. Extras Comissão PROVENTOS INSS IRRF VT DESC. FGTS LÍQUIDO
{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 */}
Funcionários
{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 */}
{(() => { const vals = changes.slice(1).map(c => c.para); const max = Math.max(...vals) * 1.1, min = Math.min(...vals) * 0.9; const pts = vals.map((v, i) => [40 + i * ((720) / (vals.length - 1)), 150 - ((v - min) / (max - min)) * 130]); const path = pts.map((p, i) => (i === 0 ? `M${p[0]},${p[1]}` : `L${p[0]},${p[1]}`)).join(' '); return <> {pts.map((p, i) => { const ch = changes[i + 1]; const ts = tipoStyle[ch.tipo]; return {BRLShort(ch.para).replace('R$ ', '')} ; })} ; })()}
{/* 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 });