// Patrimônio Líquido, Imóveis e Automóveis const { useState: useStateP, useMemo: useMemoP } = React; // ---------- Pequenos gráficos ---------- function HBar({ items, total }) { const max = Math.max(...items.map(i => i.valor), 1); return (
{items.map(i => (
{i.icon} {i.label}
{window.fmtCompact(i.valor)} {total > 0 ? Math.round((i.valor / total) * 100) : 0}%
))}
); } function PieLegend({ items, colors }) { const total = items.reduce((s, i) => s + i.valor, 0); let acc = 0; const grads = items.map((i, idx) => { const from = (acc / total) * 360; acc += i.valor; const to = (acc / total) * 360; return `${colors[idx % colors.length]} ${from}deg ${to}deg`; }); return (
0 ? `conic-gradient(${grads.join(",")})` : "#e5e7eb" }}>
{items.map((i, idx) => (
{i.classe} {window.fmtBRLString(i.valor)}
))} {items.length === 0 &&
Nenhum saldo cadastrado.
}
); } const PIE_COLORS = ["#311131", "#0663AA", "#7fb8e0", "#EA404D", "#EA404D", "#bcdcf3", "#0E92D2"]; // ---------- Campos de formulário (module scope: não remonta a cada tecla) ---------- function Field({ label, k, type = "text", _f, _s, ...rest }) { const money = type === "money"; return (
_s(k, e.target.value)} {...rest}/>
); } function TitField({ _f, _s }) { return (
); } // ---------- Modal genérico de ativo ---------- function AssetModal({ kind, edit, onClose, onSave }) { const defaults = { imovel: { nome: "", tipo: "Apartamento", endereco: "", valor: "", titularidade: "Comum", restricao: false, segurado: false, aluguel: "" }, veiculo: { nome: "", marca: "", ano: "", valor: "", titularidade: "Comum", restricao: false, segurado: false }, saldo: { nome: "", classe: "Conta corrente", instituicao: "", valor: "", moeda: "BRL", titularidade: "Comum", reserva: false }, participacao: { nome: "", cnpj: "", pct: "", valorPatrimonial: "", capitalSocial: "", titularidade: "Cliente" }, outro: { nome: "", valor: "", titularidade: "Comum" }, seguro: { tipo: "Vida", nome: "", seguradora: "", capital: "", premioMensal: "", vigencia: "", segurado: "Cliente" }, objetivo:{ nome: "", icone: "🎯", alvo: "", acumulado: "", prazo: "" }, }; const [form, setForm] = useStateP({ ...defaults[kind], ...(edit || {}) }); const set = (k, v) => setForm(f => ({ ...f, [k]: v })); const titles = { imovel: "Imóvel", veiculo: "Automóvel", saldo: "Saldo / Investimento", participacao: "Participação societária", outro: "Outro bem", seguro: "Seguro", objetivo: "Objetivo" }; function submit(e) { e.preventDefault(); const num = k => { const n = window.parseValor(form[k]); return isNaN(n) ? 0 : n; }; const out = { ...form, id: edit?.id || window.uid() }; for (const k of ["valor", "aluguel", "pct", "valorPatrimonial", "capitalSocial", "capital", "premioMensal", "alvo", "acumulado", "ano"]) { if (k in out) out[k] = num(k); } onSave(out); onClose(); } return (
{kind === "imovel" && (<>
)} {kind === "veiculo" && (<>
)} {kind === "saldo" && (<>
{form.moeda === "USD" && (

Convertido no compilado pelo dólar do dia (US$ 1 = {window.fmtBRLString(window.FX.usd)}{window.FX.data ? " · " + window.FX.data.split("-").reverse().join("/") : ""}): ≈ {window.fmtBRLString((window.parseValor(form.valor) || 0) * window.FX.usd)}

)}
)} {kind === "participacao" && (<>
)} {kind === "outro" && (<>
)} {kind === "seguro" && (<>
)} {kind === "objetivo" && (<>
)}
); } // ---------- Tabela de ativos genérica ---------- function AssetTable({ cols, rows, onEdit, onDelete, empty }) { return ( {cols.map(c => )} {rows.map(r => ( {r.cells.map((c, i) => )} ))} {rows.length === 0 && }
{c}
{c}
{empty}
); } function TitBadge({ t }) { return {t}; } // ---------- PATRIMÔNIO LÍQUIDO ---------- function PatrimonioPage({ state, onAsset, onEditAsset, onDeleteAsset, onGoTo }) { const p = state.patrimonio; const tot = window.patrimonioTotais(p, state.dividas); const saldosClasse = window.saldosPorClasse(p.saldos); const catItems = [ { label: "Imóveis", icon: "🏠", valor: tot.imoveis, color: "#311131" }, { label: "Veículos", icon: "🚗", valor: tot.veiculos, color: "#0663AA" }, { label: "Participações societárias", icon: "🏢", valor: tot.participacoes, color: "#7fb8e0" }, { label: "Saldos e Investimentos", icon: "💰", valor: tot.financeiro, color: "#EA404D" }, { label: "Outros bens", icon: "📦", valor: tot.outros, color: "#EA404D" }, ].filter(i => i.valor > 0); const counts = [ { label: "Imóveis", n: p.imoveis.length, v: tot.imoveis, go: "imoveis" }, { label: "Veículos", n: p.veiculos.length, v: tot.veiculos, go: "automoveis" }, { label: "Participações", n: p.participacoes.length, v: tot.participacoes, kind: "participacao" }, { label: "Outros bens", n: p.outros.length, v: tot.outros, kind: "outro" }, ]; return (

🏛️ Patrimônio Líquido

Bens, investimentos e dívidas do casal.
Patrimônio total
Comum {window.fmtCompact(tot.porTitularidade.Comum)} · Cliente {window.fmtCompact(tot.porTitularidade.Cliente)} · Cônjuge {window.fmtCompact(tot.porTitularidade["Cônjuge"])}
Dívidas
gerencie em Orçamento → Dívidas
Patrimônio líquido
Não financeiro{window.fmtCompact(tot.naoFinanceiro)}
Financeiro{window.fmtCompact(tot.financeiro)}
Livre de inventário{window.fmtCompact(tot.previdencia)}

Composição por categoria

{catItems.length > 0 ? :
Cadastre bens para ver a composição.
}

Saldos e Investimentos · {window.fmtCompact(tot.financeiro)}

Inventário de bens

{counts.map(c => ( ))}

Saldos e Investimentos

{tot.offshore > 0 && Offshore {window.fmtCompact(tot.offshore)} · US$ 1 = {window.fmtBRLString(window.FX.usd)}{window.FX.data ? " (" + window.FX.data.split("-").reverse().join("/") + ")" : ""}}
({ id: s.id, raw: { ...s, __kind: "saldo" }, cells: [ {s.nome}{s.reserva ? " 🚨" : ""}, s.classe, s.instituicao || "—", , {window.fmtBRLString(window.valorBRL(s))}{s.moeda === "USD" ? · US$ {Number(s.valor||0).toLocaleString("pt-BR")} : null}, ]}))} onEdit={onEditAsset} onDelete={id => onDeleteAsset("saldos", id)} empty="Nenhum saldo cadastrado."/>

Participações societárias

({ id: s.id, raw: { ...s, __kind: "participacao" }, cells: [ s.nome, s.cnpj || "—", (s.pct || 0) + "%", window.fmtBRLString(s.capitalSocial), {window.fmtBRLString(s.valorPatrimonial)}, ]}))} onEdit={onEditAsset} onDelete={id => onDeleteAsset("participacoes", id)} empty="Nenhuma participação cadastrada."/>

Outros bens

({ id: s.id, raw: { ...s, __kind: "outro" }, cells: [ s.nome, , {window.fmtBRLString(s.valor)}, ]}))} onEdit={onEditAsset} onDelete={id => onDeleteAsset("outros", id)} empty="Nenhum outro bem."/>
); } // ---------- IMÓVEIS ---------- function ImoveisPage({ state, onAsset, onEditAsset, onDeleteAsset }) { const imoveis = state.patrimonio.imoveis; const total = imoveis.reduce((s, i) => s + Number(i.valor || 0), 0); const alugueis = imoveis.reduce((s, i) => s + Number(i.aluguel || 0), 0); const segurados = imoveis.filter(i => i.segurado).length; const restritos = imoveis.filter(i => i.restricao).length; return (

🏠 Imóveis

Patrimônio imobiliário e renda de aluguéis.
Valor total
Renda de aluguéis / mês
Imóveis
Segurados{segurados}/{imoveis.length}
Com restrição{restritos}
({ id: i.id, raw: { ...i, __kind: "imovel" }, cells: [ {i.nome}{i.restricao ? " ⚠️" : ""}, i.tipo, i.endereco || "—", , i.aluguel > 0 ? window.fmtBRLString(i.aluguel) : "—", i.segurado ? Segurado : Sem seguro, {window.fmtBRLString(i.valor)}, ]}))} onEdit={onEditAsset} onDelete={id => onDeleteAsset("imoveis", id)} empty="Nenhum imóvel cadastrado."/>
); } // ---------- AUTOMÓVEIS ---------- function AutomoveisPage({ state, onAsset, onEditAsset, onDeleteAsset }) { const veiculos = state.patrimonio.veiculos; const total = veiculos.reduce((s, i) => s + Number(i.valor || 0), 0); const segurados = veiculos.filter(i => i.segurado).length; const segurosAuto = state.seguros.filter(s => s.tipo === "Automóvel"); const premioMensal = segurosAuto.reduce((s, x) => s + Number(x.premioMensal || 0), 0); return (

🚗 Automóveis

Frota da família, seguros e restrições.
Valor total
Prêmio de seguros / mês
Veículos
Segurados{segurados}/{veiculos.length}
Com restrição{veiculos.filter(i => i.restricao).length}
({ id: i.id, raw: { ...i, __kind: "veiculo" }, cells: [ {i.nome}{i.restricao ? " ⚠️" : ""}, i.marca || "—", i.ano || "—", , i.segurado ? Segurado : Sem seguro, {window.fmtBRLString(i.valor)}, ]}))} onEdit={onEditAsset} onDelete={id => onDeleteAsset("veiculos", id)} empty="Nenhum veículo cadastrado."/>
); } Object.assign(window, { PatrimonioPage, ImoveisPage, AutomoveisPage, AssetModal, AssetTable, TitBadge, HBar, PieLegend, PIE_COLORS });