// All UI components for the dashboard // Loaded as global components. const { useState, useMemo, useEffect, useRef } = React; // ---------- TOP NAV (header único: etapas + progresso + fechamento) ---------- function TopNav({ active, setActive, onRelatorio, appState, onOpenFechamento }) { const etapas = [ { id: "familia", label: "Família", icon: "👨‍👩‍👧‍👦" }, { id: "orcamento", label: "Orçamento", icon: "💳" }, { id: "patrimonio", label: "Patrimônio", icon: "📊" }, { id: "reserva", label: "Reserva", icon: "💸" }, { id: "imoveis", label: "Imóveis", icon: "🏘️" }, { id: "automoveis", label: "Automóveis", icon: "🚗" }, { id: "protecao", label: "Proteção", icon: "🛡️" }, { id: "irpf", label: "IRPF", icon: "🧾" }, { id: "aposentadoria", label: "Aposentadoria", icon: "🌴" }, ]; const extras = []; const done = etapas.map(e => window.etapaAutoDone ? window.etapaAutoDone(e.id, appState) : false); const concluidas = done.filter(Boolean).length; const pct = Math.round((concluidas / etapas.length) * 100); const fech = window.calcFechamento ? window.calcFechamento(appState.fechamento) : null; const Tab = ({ t, num, isDone }) => ( ); return (
⚜️
LRfin
{concluidas}/{etapas.length} etapas preenchidas {fech && ( )}
); } // ---------- RIGHT PANEL (guia de saúde financeira por etapa) ---------- function guiaEtapa(view, plano, appState) { const money = v => window.fmtBRLString(Math.max(0, v)).replace(",00", ""); const g = plano.gastos; const inc = plano.income; const aporte10 = inc * 0.10; const seguros = (appState?.seguros || []).length; switch (view) { case "familia": return { icon: "👨‍👩‍👧‍👦", titulo: "Família e objetivos", texto: "Estrutura familiar e objetivos definem o tamanho dos 3 baldes de 10% (caridade, capital ativo e passivo). Comece por aqui." }; case "orcamento": return inc <= 0 ? { icon: "💳", titulo: "Orçamento", texto: "Lance a receita do mês para ativar a regra 70·10·10·10: 70% é o teto de gastos, 30% viram caridade e capital." } : g.over ? { icon: "🚨", titulo: "Gastos acima dos 70%", texto: `Corte ${money(g.redutivelPendente)} nos ✂️ redutíveis ainda não validados para voltar ao teto de ${money(g.target)}. Depois valide tudo e feche o mês.` } : { icon: "✅", titulo: "Dentro dos 70%", texto: `Folga de ${money(g.target - g.used)} no teto. Valide os lançamentos e feche o balanço do mês para consolidar.` }; case "patrimonio": return { icon: "📊", titulo: "Patrimônio", texto: inc > 0 ? `Os 10% de Capital Passivo (${money(aporte10)}/mês) são o motor deste patrimônio. Constância vale mais que valor.` : "O patrimônio cresce com os 10% de Capital Passivo aportados todo mês." }; case "protecao": return seguros > 0 ? { icon: "🛡️", titulo: "Proteção", texto: "Prêmios de seguro entram como classe Proteção dentro dos 70% de gastos — fixos e não redutíveis. Revise coberturas 1x ao ano." } : { icon: "🛡️", titulo: "Sem proteção cadastrada", texto: "Antes de acelerar os 10% de investimento, proteja a renda: seguros cabem nos 70% como gasto fixo essencial." }; case "reserva": return { icon: "💸", titulo: "Reserva de emergência", texto: inc > 0 ? `Direcione os 10% de Capital Passivo (${money(aporte10)}/mês) para a reserva até completar o alvo — só depois migre para investimentos de longo prazo.` : "A reserva vem antes dos investimentos: é o primeiro destino dos 10% de Capital Passivo." }; case "aposentadoria": return { icon: "🌴", titulo: "Independência", texto: inc > 0 ? `Mantidos os 10% (${money(aporte10)}/mês) aportados sem falha, a projeção de capital se sustenta. O teto de 70% é o que garante o aporte.` : "A aposentadoria é financiada pelos 10% de Capital Passivo — que só existem se os gastos respeitarem os 70%." }; case "imoveis": case "automoveis": return { icon: "🏘️", titulo: "Bens de uso", texto: "Custos de imóveis e veículos (financiamento, IPVA, manutenção) são gastos fixos — precisam caber dentro dos 70%." }; case "irpf": return { icon: "🧾", titulo: "IRPF", texto: "Previdência dedutível e doações incentivadas fazem os baldes de 10% renderem também no imposto." }; default: return inc > 0 && g.over ? { icon: "🧭", titulo: "Próximo passo", texto: `Seus gastos passaram do teto de 70% em ${money(g.overBy)}. Vá ao Orçamento e corte nos redutíveis.` } : { icon: "🧭", titulo: "Regra 70·10·10·10", texto: "Viva com 70% da receita; doe 10%; invista 10% em você (capital ativo) e 10% em ativos (capital passivo)." }; } } function RightPanel({ user, plano, monthLabel, onGoTo, monthKey, planoCheck, onSavePlanoCheck, view, appState }) { const { income, buckets, gastos } = plano; const onTrack = income > 0 && !gastos.over; const guia = guiaEtapa(view, plano, appState); const money = v => window.fmtBRLString(Math.max(0, v)).replace(",00", ""); const checks = (planoCheck && planoCheck[monthKey]) || {}; const [editing, setEditing] = useState(null); // bucket key aberto para edição const [note, setNote] = useState(""); function openEditor(key) { const cur = checks[key] || {}; setNote(cur.nota || ""); setEditing(e => (e === key ? null : key)); } function saveNote(key) { onSavePlanoCheck(monthKey, key, { nota: note }); setEditing(null); } return (