// Barra de etapas (ordem de preenchimento) + pendência mensal de prestação de contas const { useState: useStateSb, useMemo: useMemoSb } = React; const ETAPAS = [ { id: "familia", label: "Família e Objetivos" }, { id: "orcamento", label: "Orçamento" }, { id: "patrimonio", label: "Patrimônio Líquido" }, { id: "reserva", label: "Reserva de Emergência" }, { id: "imovel", label: "Imóvel" }, { id: "automovel", label: "Automóvel" }, { id: "protecao", label: "Proteção" }, { id: "aposentadoria", label: "Aposentadoria" }, { id: "irpf", label: "IRPF" }, ]; function etapaAutoDone(id, s) { const p = s.patrimonio || {}; switch (id) { case "familia": { const d = s.objetivosPessoais || {}; return Object.values(d).some(v => v && v.selecionado && v.motivo) || (s.objetivos || []).length > 0; } case "orcamento": return (s.transactions || []).length > 0; case "patrimonio": return ["imoveis", "veiculos", "saldos", "participacoes", "outros"].some(k => (p[k] || []).length > 0); case "protecao": return (s.seguros || []).length > 0; case "reserva": return !!(s.reserva && s.reserva.mesesAlvo); case "aposentadoria": return !!(s.aposentadoria && s.aposentadoria.idadeAlvo); case "irpf": { if (s.etapas && s.etapas.irpf) return true; // Página derivada: considera preenchida quando os insumos existem (bens ou rendimentos) const temBens = ["imoveis", "veiculos", "saldos", "participacoes", "outros"].some(k => (p[k] || []).length > 0); const temRend = Object.values(s.aggregates || {}).some(a => Object.values(a.receitas || {}).some(arr => arr.some(v => v > 0))) || (s.transactions || []).some(t => t.type === "Receita"); return temBens && temRend; } default: return false; } } // ----- utilidades de fechamento mensal ----- const MES_NOMES = ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"]; function chaveMes(y, m) { return `${y}-${String(m + 1).padStart(2, "0")}`; } function mesFechado(hoje) { const m = hoje.getMonth() - 1; return m < 0 ? { y: hoje.getFullYear() - 1, m: 11 } : { y: hoje.getFullYear(), m }; } function calcFechamento(fechamento, hoje = new Date()) { const dia = Number((fechamento && fechamento.dia) || 5); const ref = mesFechado(hoje); const key = chaveMes(ref.y, ref.m); const entrega = ((fechamento && fechamento.entregas) || {})[key]; const venc = new Date(hoje.getFullYear(), hoje.getMonth(), Math.min(dia, 28)); const diffDias = Math.ceil((venc - new Date(hoje.getFullYear(), hoje.getMonth(), hoje.getDate())) / 86400000); return { dia, refKey: key, refLabel: `${MES_NOMES[ref.m]}/${ref.y}`, entregue: !!(entrega && entrega.feito), entrega, venc, vencLabel: `${String(venc.getDate()).padStart(2, "0")}/${String(venc.getMonth() + 1).padStart(2, "0")}`, diffDias, atrasado: diffDias < 0, }; } // ----- BARRA DE ETAPAS: fundida no TopNav (components-shell.jsx) ----- // ----- MODAL DE PRESTAÇÃO DE CONTAS ----- // ----- MODAL DE PRESTAÇÃO DE CONTAS ----- function FechamentoModal({ fechamento, onClose, onSave, onRelatorio }) { const fech = calcFechamento(fechamento); const atual = fech.entrega || {}; const [dia, setDia] = useStateSb(fech.dia); const [nota, setNota] = useStateSb(atual.nota || ""); const [pontos, setPontos] = useStateSb(atual.pontos || ""); const [ajustes, setAjustes] = useStateSb(atual.ajustes || ""); const entregas = (fechamento && fechamento.entregas) || {}; const hist = Object.keys(entregas).sort().reverse().slice(0, 6); function salvarRecorrencia(d) { setDia(d); onSave({ dia: Number(d) }, null); } function gerarRelatorio() { if (nota.trim()) { onSave({ dia: Number(dia) }, { key: fech.refKey, dados: { feito: true, nota, pontos, ajustes, dataEntrega: new Date().toISOString().slice(0, 10) }, }); } onClose(); if (onRelatorio) onRelatorio(fech.refKey); } function entregar() { onSave({ dia: Number(dia) }, { key: fech.refKey, dados: { feito: true, nota, pontos, ajustes, dataEntrega: new Date().toISOString().slice(0, 10) }, }); onClose(); } return ( }>
Data de fechamento (recorrência mensal)
Todo mês, até o dia escolhido, você presta contas do mês anterior.
Mês de referência: {fech.refLabel} {fech.entregue ? `Entregue em ${atual.dataEntrega ? atual.dataEntrega.split("-").reverse().join("/") : "—"}` : fech.atrasado ? `Venceu em ${fech.vencLabel} — ${Math.abs(fech.diffDias)} dia(s) de atraso` : `Vence em ${fech.vencLabel} — faltam ${fech.diffDias} dia(s)`}