// Objetivos, Reserva de Emergência, Aposentadoria e IRPF const { useState: useStatePl, useMemo: useMemoPl } = React; // ---------- OBJETIVOS ---------- function ObjetivosPage({ state, onAsset, onEditAsset, onDeleteAsset }) { const objetivos = state.objetivos; const totalAlvo = objetivos.reduce((s, o) => s + Number(o.alvo || 0), 0); const totalAcum = objetivos.reduce((s, o) => s + Number(o.acumulado || 0), 0); return (

🎯 Objetivos

Metas financeiras da família com progresso e prazo.
Soma dos alvos
Já acumulado
Falta
Objetivos{objetivos.length}
Concluídos{objetivos.filter(o => o.acumulado >= o.alvo && o.alvo > 0).length}
{objetivos.map(o => { const pct = o.alvo > 0 ? Math.min(o.acumulado / o.alvo, 1) : 0; const done = pct >= 1; const meses = o.prazo ? Math.max(0, Math.round((new Date(o.prazo) - new Date()) / (30.44 * 864e5))) : null; const aporteNec = meses > 0 ? Math.max(0, (o.alvo - o.acumulado) / meses) : null; return (
{o.icone || "🎯"}

{o.nome}

{window.fmtBRLString(o.acumulado)} de {window.fmtBRLString(o.alvo)}
{Math.round(pct * 100)}% {o.prazo && até {o.prazo.split("-").reverse().join("/")}} {aporteNec != null && !done && ≈ {window.fmtCompact(aporteNec)}/mês} {done && ✅ concluído}
); })} {objetivos.length === 0 &&
Nenhum objetivo. Adicione o primeiro!
}
); } // ---------- RESERVA DE EMERGÊNCIA ---------- function ReservaPage({ state, onUpdateReserva, onAsset, onEditAsset }) { const base = state.reserva.base || "todos"; const custo = window.custoFixoDetalhe(state.transactions, 3, base); const custoMensal = custo.media; const mesRotulo = k => window.MESES[Number(k.slice(5, 7)) - 1] + "/" + k.slice(2, 4); const mesesAlvo = state.reserva.mesesAlvo || 6; const alvo = custoMensal * mesesAlvo; const saldosReserva = state.patrimonio.saldos.filter(s => s.reserva); const saldoAuto = saldosReserva.reduce((s, x) => s + Number(x.valor || 0), 0); const saldo = state.reserva.saldoManual != null ? state.reserva.saldoManual : saldoAuto; const pct = alvo > 0 ? Math.min(saldo / alvo, 1) : 0; const mesesCobertos = custoMensal > 0 ? saldo / custoMensal : 0; return (

🚨 Reserva de Emergência

Colchão de segurança em ativos líquidos, dimensionado pelo seu custo fixo.
Reserva atual
Alvo ({mesesAlvo} meses)
Custo fixo mensal (média)
Meses cobertos{mesesCobertos.toFixed(1)}
Progresso{Math.round(pct * 100)}%

Progresso da reserva

{[...Array(mesesAlvo)].map((_, i) => ( ))}
{mesesCobertos.toFixed(1)} de {mesesAlvo} meses de custo fixo {pct < 1 ? Faltam {window.fmtBRLString(Math.max(0, alvo - saldo))} : ✅ Reserva completa}

Custo fixo mensal

Média {base === "todos" ? "de todos os gastos lançados" : "dos lançamentos não redutíveis"} {custo.meses.length > 0 ? `· ${custo.meses.map(m => mesRotulo(m.key)).join(", ")}` : ""}
{custo.meses.length === 0 ? (
Nenhum gasto lançado ainda. Classifique os lançamentos no Checklist para dimensionar a reserva.
) : ( {custo.porClasse.map(c => ( ))}
ClasseMédia mensal
{c.icon} {c.label}{window.fmtBRLString(c.valor)}
Total{window.fmtBRLString(custoMensal)}
)}

Ativos que compõem a reserva

({ id: s.id, raw: { ...s, __kind: "saldo" }, cells: [ s.nome, s.classe, s.instituicao || "—", {window.fmtBRLString(s.valor)}, ]}))} onEdit={onEditAsset} onDelete={() => {}} empty='Nenhum ativo marcado como reserva. Edite um saldo e marque "Faz parte da reserva de emergência".'/>
); } // ---------- APOSENTADORIA ---------- function AposentadoriaPage({ state, onUpdateAposentadoria }) { const cfg = state.aposentadoria; const tot = window.patrimonioTotais(state.patrimonio, state.dividas); const calc = window.calcAposentadoria(cfg, tot.financeiro); const previdencias = state.patrimonio.saldos.filter(s => s.classe === "Previdência"); const set = (k, v) => onUpdateAposentadoria({ ...cfg, [k]: Number(v) || 0 }); return (

🌴 Aposentadoria

Independência financeira: capital necessário para viver de renda.
Capital necessário
renda de {window.fmtBRLString(cfg.rendaMensalDesejada)}/mês a {cfg.taxaRealAA}% a.a. real
Patrimônio financeiro hoje
{Math.round(calc.pct * 100)}% do alvo
Projeção aos {cfg.idadeAlvo} anos
com aportes de {window.fmtBRLString(cfg.aporteMensal)}/mês
Anos até lá{calc.anos}
Aporte necessário{window.fmtCompact(calc.aporteNecessario)}/mês

Premissas

set("idadeAtual", e.target.value)}/>
set("idadeAlvo", e.target.value)}/>
set("rendaMensalDesejada", e.target.value)}/>
set("taxaRealAA", e.target.value)}/>
set("aporteMensal", e.target.value)}/>

Progresso rumo ao alvo

{window.fmtCompact(tot.financeiro)} de {window.fmtCompact(calc.alvo)} {Math.round(calc.pct * 100)}%
Projeção com aportes atuais{window.fmtCompact(calc.projecao)}
{calc.projecao >= calc.alvo ? "Excedente projetado" : "Déficit projetado"}= calc.alvo ? "" : "neg"}>{window.fmtCompact(Math.abs(calc.projecao - calc.alvo))}
Aporte p/ fechar a conta{window.fmtBRLString(calc.aporteNecessario)}/mês

Previdências (livres de inventário)

({ id: s.id, raw: { ...s, __kind: "saldo" }, cells: [ s.nome, s.instituicao || "—", , {window.fmtBRLString(s.valor)}, ]}))} onEdit={() => {}} onDelete={() => {}} empty='Nenhuma previdência. Cadastre um saldo com classe "Previdência" no Patrimônio Líquido.'/>
); } // ---------- IRPF ---------- function IrpfPage({ state, year, onToggleEtapa }) { const revisado = !!(state.etapas && state.etapas.irpf); const p = state.patrimonio; const tot = window.patrimonioTotais(p, state.dividas); const agg = state.aggregates[year] || state.aggregates[Object.keys(state.aggregates).sort().pop()]; const rendimentos = agg ? Object.entries(agg.receitas).map(([fonte, arr]) => ({ fonte, total: arr.reduce((s, v) => s + Number(v || 0), 0) })).filter(r => r.total > 0) : []; const totalRend = rendimentos.reduce((s, r) => s + r.total, 0); const bens = [ ...p.imoveis.map(i => ({ grupo: "01 — Bens imóveis", desc: i.nome, valor: i.valor })), ...p.veiculos.map(i => ({ grupo: "02 — Bens móveis", desc: i.nome, valor: i.valor })), ...p.participacoes.map(i => ({ grupo: "03 — Participações societárias", desc: i.nome, valor: i.valorPatrimonial })), ...p.saldos.map(i => ({ grupo: i.classe === "Conta corrente" ? "06 — Depósitos à vista" : "07 — Fundos e aplicações", desc: i.nome, valor: i.valor })), ...p.outros.map(i => ({ grupo: "99 — Outros bens", desc: i.nome, valor: i.valor })), ]; const previdenciaPGBL = p.saldos.filter(s => s.classe === "Previdência").reduce((s, x) => s + Number(x.valor || 0), 0); const limitePGBL = totalRend * 0.12; return (

🧾 IRPF

Prévia da declaração gerada automaticamente dos seus dados: rendimentos, bens e direitos, dívidas e ônus. Ano-base {year}.
Rendimentos no ano
Bens e direitos
Dívidas e ônus reais
Itens de bens{bens.length}
Limite dedução PGBL (12%){window.fmtCompact(limitePGBL)}

Rendimentos por fonte — {year}

{rendimentos.map(r => ( ))} {rendimentos.length === 0 && } {rendimentos.length > 0 && }
FonteTotal no ano
{r.fonte}{window.fmtBRLString(r.total)}
Sem rendimentos lançados em {year}.
Total{window.fmtBRLString(totalRend)}

Dicas para a declaração

  • PGBL: você tem {window.fmtBRLString(previdenciaPGBL)} em previdência. Aportes em PGBL são dedutíveis até 12% da renda tributável ({window.fmtBRLString(limitePGBL)} em {year}).
  • Bens comuns: no regime de {state.familia.cliente.regimeBens.toLowerCase()}, bens comuns podem ser declarados integralmente por um dos cônjuges.
  • Dívidas > R$ 5.000: devem ser informadas na ficha "Dívidas e Ônus Reais".
  • Aluguéis recebidos: {p.imoveis.some(i => i.aluguel > 0) ? "você tem imóveis alugados — recolha o carnê-leão mensalmente." : "nenhum imóvel alugado cadastrado."}

Bens e direitos (rascunho da ficha)

{bens.map((b, i) => ( ))} {bens.length === 0 && } {bens.length > 0 && }
GrupoDiscriminaçãoSituação atual
{b.grupo}{b.desc}{window.fmtBRLString(b.valor)}
Cadastre bens no Patrimônio Líquido.
Total{window.fmtBRLString(tot.total)}

Dívidas e ônus reais

{state.dividas.map(d => ( ))} {state.dividas.length === 0 && }
DescriçãoCredorSaldo devedor
{d.descricao}{d.credor || "—"}{window.fmtBRLString(d.saldoDevedor)}
Nenhuma dívida.
); } Object.assign(window, { ObjetivosPage, ReservaPage, AposentadoriaPage, IrpfPage });