SaldoMais
Carregando…
Documento 02 de 07

Módulos JavaScript

Os 11 módulos JS do projeto — responsabilidades, funções públicas, contratos de entrada/saída e comportamentos relevantes para quem precisa modificar ou estender o código.

core.js

Fundação do projeto. Define constantes globais, referências DOM, acesso ao storage e utilitários usados por todos os demais módulos. Deve ser carregado primeiro.

Constantes

ConstanteTipoDescrição
MESESstring[]Nomes dos meses em pt-BR, índice 0-based
PDF_COLORSobjectPaleta de cores RGB para o relatório PDF
STORAGEobjectChaves do localStorage: categorias, orcamentos, lancamentos, receitas

Referências DOM

VariávelID no DOM
orcamentoInput#orcamentoInput
valorInput#valorInput
desc#desc
categoriaSelect#categoriaSelect
listaLancamentos#listaLancamentos
listaCategorias#listaCategorias
categoriasStatus#categoriasStatus
grafico#grafico (canvas do Chart.js)

Funções de storage

get(key: string): any[]
// Lê e parseia JSON do localStorage. Retorna [] se ausente ou inválido.

set(key: string, val: any): void
// Serializa e persiste no localStorage.

Funções utilitárias

formatarMoeda(valor: number): string
// Formata como BRL usando Intl.NumberFormat pt-BR.
// Ex: 1500.5 → "R$ 1.500,50"

desformatarMoeda(texto: string): number
// Converte string formatada de volta para number.
// Ex: "R$ 1.500,50" → 1500.5

notificar(msg: string, type?: 'success'|'error'|'warn'|'info'): void
// Exibe toast de notificação por 3200ms. Se type omitido, infere pelo conteúdo da mensagem.

confirmar(msg: string): Promise<boolean>
// Abre modal de confirmação. Resolve com true (confirmou) ou false (cancelou).

editarCategoriaNome(nomeAtual: string): Promise<string | null>
// Abre modal com input pré-preenchido. Resolve com o novo nome ou null se cancelado.

mostrarLoading(): void
// Exibe o overlay de loading. Auto-oculta após 1500ms.

ocultarLoading(): void
// Remove o overlay de loading imediatamente.

withLoadingDelay(fn: Function, delay?: number): void
// Exibe loading e executa fn após delay (padrão: 100ms).

atualizarDataMes(): void
// Preenche #mesAtualText com "Mês de Ano" (ex: "Abril de 2026").

Funções de setup

setupModals(): void
// Registra os listeners de clique nos botões dos modais.
// Deve ser chamado uma única vez em init().

navegar(): void
// Registra onclick em todos os [data-screen] para troca de tela ativa.

lancamentos.js

Gerencia orçamentos mensais e transações (lançamentos). Depende de core.js.

Funções auxiliares

mesAtual(): string
// Retorna a referência do mês corrente no formato "YYYY-MM".
// Ex: "2026-04"

orcamentoAtual(): object | undefined
// Busca o orçamento cujo mes_referencia === mesAtual().
// Retorna undefined se não existir orçamento para o mês.

Handlers de ação

salvarOrcamentoHandler(): void
// Lê orcamentoInput, valida (> 0), cria ou atualiza o orçamento do mês.
// Persiste e chama renderComplete().

adicionarLancamento(): void
// Lê desc, valorInput e categoriaSelect.
// Validações: orçamento definido, descrição preenchida, valor > 0,
// total da categoria não excede o limite (valor_total * percentual / 100).
// Persiste e chama renderComplete().

deletarLancamento(id: number): Promise<void>
// Abre modal de confirmação. Se confirmado, remove o lançamento por id e chama renderComplete().

resetarMes(): Promise<void>
// Abre modal de confirmação. Remove todos os lançamentos do orçamento atual
// e zera o valor_total do orçamento. Chama renderComplete().

Funções de render

renderSelect(): void
// Reconstrói as <option> do #categoriaSelect com as categorias do storage.

renderOrcamentoInput(): void
// Preenche #orcamentoInput com o valor formatado do orçamento atual.
// Limpa o input se não houver orçamento.

renderLancamentos(): void
// Reconstrói #listaLancamentos com os lançamentos do mês atual.
// Exibe empty state se não houver orçamento ou lançamentos.
// Cada item tem data-action="deletar-lancamento" e data-id para event delegation.

categorias.js

CRUD de categorias, gerenciamento de percentuais e seed inicial. Depende de core.js.

Setup

criarCategorias(): void
// Idempotente — só executa se o storage de categorias estiver vazio.
// Insere 6 categorias padrão com percentuais e cores pré-definidos.
NomePercentualCor
Custos fixos30%#f59e0b
Conforto5%#22c55e
Metas11%#ef4444
Prazeres24%#3b82f6
Liberdade financeira25%#a855f7
Conhecimento5%#f97316

Funções de gerenciamento

adicionarNovaCategoria(): void
// Lê #novaCategoriaNome e #novaCategoriaCor.
// Validações: nome não vazio, nome único (case-insensitive).
// Cria com percentual 0. Persiste e chama renderComplete().

abrirEditorCategoria(catId: number): Promise<void>
// Abre modal de edição com o nome atual.
// Validações: nome diferente do atual, nome único.
// Persiste e chama renderComplete().

deletarCategoriaConfirm(catId: number): Promise<void>
// Modal de confirmação antes de chamar deletarCategoria().

deletarCategoria(catId: number): void
// Remove a categoria e todos os lançamentos vinculados.
// Chama renderComplete(). Use deletarCategoriaConfirm para fluxo com UX.

Sliders de percentual

atualizarPercentual(catId: number, valor: string, container: Element): void
// Sincroniza todos os [data-cat-id=catId] (slider + input + preview)
// com o novo valor (clamped 0-100).
// Atualiza o totalizador com a soma atual.

salvarPercentuaisEm(container: Element): void
// Lê todos os .percentual-slider dentro do container.
// Valida que a soma seja exatamente 100%.
// Persiste os novos percentuais e chama renderAll() + renderCategoriasLista().

Funções de render

renderCategorias(): void
// Reconstrói #listaCategorias com o editor de sliders de percentual.
// Renderizado na tela "configuracoes".

renderCategoriasLista(): void
// Reconstrói #categoriasListaEditor com editor de sliders
// + lista de categorias com botões Editar e Remover.
// Renderizado na tela "categorias".

dashboard.js

Renderiza o dashboard: cards de resumo financeiro, gráfico de distribuição e barras de status por categoria. Depende de core.js, lancamentos.js e categorias.js.

renderDashboard(): void
// Ponto de entrada único do dashboard.
// Se não houver orçamento definido, exibe empty state.
// Caso contrário, chama renderResumoGeral(), barras de status e renderGrafico().

renderResumoGeral(cats, lanc, o): void
// Constrói os cards em #resumoGeral:
//   - Total Disponível (valor_total do orçamento)
//   - Total Gasto (soma dos lançamentos) com barra de progresso
//   - Disponível (valor_total - totalGasto) — verde se positivo, vermelho se negativo
//   - Card de alerta (opcional) se alguma categoria exceder o limite

renderGrafico(cats, lanc, o): void
// Instancia ou recria o doughnut via Chart.js em window.graficoChart.
// Destrói a instância anterior (window.graficoChart.destroy()).
// Se totalGasto === 0: distribui igualmente entre todas as categorias.
// Legenda customizada em #grafico-legenda (nativa do Chart.js desabilitada).

Lógica de cor das barras de status

CondiçãoCor
percentualGasto > 100%#ef4444 (vermelho)
percentualGasto > 80%#fb923c (laranja)
else#22c55e (verde)

calculadoras.js

8 calculadoras financeiras. Cada uma tem uma função matemática pura (sem acesso ao DOM) e uma função de UI (lê inputs, valida, chama a pura e renderiza o resultado).

Função auxiliar de parsing

parseBRCalc(str: string): number
// Converte string no formato brasileiro para float.
// "1.000,50" → 1000.5 | "1000.50" → 1000.5 | "1000,5" → 1000.5

Assinaturas das funções puras

calcJurosCompostos(capital, aporte, taxaAnual, periodo)
calcCDBCDI(valor, taxaCDI, percentual, prazo)
calcAporteMeta(meta, prazo, taxaMensal)
calcDividendYield(patrimonio, yieldAnual)
calcFinanciamentoPrice(pv, taxaMensal, n)
calcRotativoCartao(divida, taxaMensal, pagamento)
calcAVistaVsParcelado(avista, parcelaValor, nParcelas, taxaMensal)
calcQuitarDivida(saldo, taxaDivida, parcelas, desconto, disponivel, taxaInvest)

Padrão das funções de UI

// Cada calcularXxx() segue o padrão:
function calcularMinhaCalc() {
  // 1. Lê inputs com parseBRCalc() ou parseInt()
  // 2. Valida campos — chama notificar() e retorna em caso de erro
  // 3. Chama a função matemática pura
  // 4. Injeta HTML de resultado no DOM
  // 5. Chama mostrarResultado(id) para animar a exibição
  if (window.lucide) lucide.createIcons();
}

mostrarResultado(id: string): void
// Exibe o elemento com animação fadeSlideIn.
// Injeta header com botão "Fechar" se ainda não existir.

backup.js

Exportação e importação do estado completo da aplicação. Depende de core.js.

exportarBackup(): void
// Serializa { _versao: 2, _exportado_em, categorias, orcamentos, lancamentos, receitas }
// Cria um Blob JSON e dispara download via <a> temporário.
// Nome: SaldoMais-backup-YYYY-MM-DD.json

importarBackup(e: Event): void
// Lê o arquivo via FileReader.
// Valida presença das chaves categorias, orcamentos, lancamentos.
// Sobrescreve o storage completamente e chama renderComplete().
// Reseta e.target.value para permitir reimportar o mesmo arquivo.

Formato do arquivo

{
  "_versao": 2,
  "_exportado_em": "2026-04-18T12:00:00.000Z",
  "categorias": [...],
  "orcamentos": [...],
  "lancamentos": [...],
  "receitas": [...]
}
Atenção: A validação de importação verifica apenas a existência das três chaves — não valida a estrutura interna dos objetos.

pdf.js

Geração do relatório mensal em PDF via jsPDF. Depende de core.js e lancamentos.js.

Helper de drawing

pdfHelpers(doc: jsPDF): object
// Retorna utilitários para estilizar o documento:
//   bg(rgb[])         — cor de preenchimento
//   pen(rgb[], w)     — cor e espessura de linha
//   color(rgb[])      — cor de texto
//   bold(size)        — fonte helvetica bold + tamanho
//   normal(size)      — fonte helvetica normal + tamanho
//   rrect(x,y,w,h,r) — retângulo com bordas arredondadas
//   hexToRgb(hex)     — "#rrggbb" → [r, g, b]

Funções de seção

pdfCabecalho(doc, { W, M, o }): Promise<void>
// Async — tenta buscar o logo via fetch (falha silenciosamente em file://).
// Desenha fundo, linha amber, logo, nome do app, tagline, mês/ano.

pdfCardsResumo(doc, { W, M, CW, o, totalGasto, totalRestante, pct, y }): number
// 3 cards (orçamento, gasto, disponível) e barra de progresso.

pdfSectionTitle(doc, { W, M, label, y }): number
// Título de seção com linha divisória.

pdfTabelaCategorias(doc, { M, CW, cats, lancs, o, y }): number
// Tabela com zebra striping: categoria, % alocado, gasto, disponível.

pdfTabelaLancamentos(doc, { W, H, M, CW, cats, lancs, totalGasto, y }): number
// Adiciona nova página automaticamente quando y > H - 26.

pdfRodape(doc, { W, H, M }): void
// Itera todas as páginas e adiciona rodapé com data/hora de exportação.

Orquestrador

exportarPDF(): Promise<void>
// Valida: orçamento definido, jsPDF carregado.
// Configura documento A4 portrait (210×297mm), fundo escuro.
// Chama seções: cabecalho → cards → categorias → lançamentos → rodapé.
// Salva como SaldoMais-YYYY-MM.pdf.

gastos-fixos.js

Gerencia despesas recorrentes mensais que são aplicadas automaticamente no primeiro dia de cada mês. Depende de core.js e lancamentos.js.

Estende o objeto STORAGE de core.js adicionando a chave gastosFixos → "saldomain_gastos_fixos".

adicionarGastoFixo(): void
// Lê #gastoFixoNome, #gastoFixoValor, #gastoFixoCategoria.
// Validações: orçamento definido, nome não vazio, valor > 0, categoria selecionada.
// Persiste e chama renderGastosFixos().

deletarGastoFixo(id: number): Promise<void>
// Modal de confirmação antes de remover. Chama renderGastosFixos().

aplicarGastosFixos(): void
// Verificada no init(). Aplica cada gasto fixo como lançamento no mês atual
// somente se ainda não foi aplicado (identifica via id_gasto_fixo no lançamento).
// Notifica o usuário se algum gasto foi aplicado.

renderGastosFixos(): void
// Reconstrói #listaGastosFixos. Exibe total de gastos fixos no rodapé da lista.

receitas.js

Gerencia as entradas financeiras do mês e sincroniza o orçamento automaticamente com a soma das receitas. Depende de core.js e lancamentos.js.

totalReceitasMes(): number
// Soma os valores de todas as receitas do mês atual.

receitasDoMes(): Receita[]
// Retorna as receitas filtradas pelo mês atual (mes_referencia === mesAtual()).

sincronizarOrcamentoComReceitas(): void
// Se houver receitas no mês, atualiza o valor_total do orçamento atual
// com a soma total das receitas. Cria o orçamento se não existir.
// Chamada no init() e a cada add/delete de receita.

adicionarReceita(): void
// Lê #receitaDesc, #receitaValor, #receitaTipo, #receitaData.
// Persiste e chama sincronizarOrcamentoComReceitas() + renderComplete().

deletarReceita(id: number): Promise<void>
// Modal de confirmação antes de remover. Ressincroniza orçamento e re-renderiza.

renderReceitas(): void
// Reconstrói #listaReceitas com badges de tipo coloridos e total do mês.

Tipos de receita

TipoLabelCor
salarioSalárioverde
freelanceFreelanceazul
rendimentoRendimentoâmbar
outroOutroroxo

carteira.js

Módulo de carteira de investimentos. Auto-inicializa via initCarteira(). Independente do fluxo de renderComplete() — gerencia seu próprio ciclo de render.

Constantes

ConstanteDescrição
CATALOGO30 ativos fixos agrupados em 5 classes: Renda Fixa, Renda Variável, Fundos, Previdência, Criptomoedas
CLASSE_CORESMapeamento classe → cor hex para os gráficos
TAXA_ANUAL_CLASSETaxa anual estimada por classe (RF 12%, RV 10%, Fundos 9%, Prev 8%, Cripto 20%)
CARTEIRA_STORAGEChaves: saldomain_carteiras, saldomain_carteira_ativa, saldomain_historico_aportes

Funções principais

// ─ Gestão de carteiras ─
carteiraNovaHandler(): Promise<void>
// Abre modal carteiraInputModal para nome. Cria nova carteira e a torna ativa.

carteiraRenomearHandler(): Promise<void>
// Abre modal com nome atual pré-preenchido. Atualiza o nome na carteira ativa.

carteiraDeletarHandler(): Promise<void>
// Modal de confirmação. Remove carteira ativa e ativa a anterior (se existir).

carteiraSalvarHandler(): void
// Persiste os percentuais checados no storage da carteira ativa.
// Só habilita o botão quando a soma === 100%.

// ─ Abas ─
carteiraCalcularAporte(): void
// Lê o valor de aporte. Distribui em centeiros inteiros por cada ativo (sem float).
// Alerta se algum ativo ficou abaixo do mínimo permitido por tipo.
// Salva no histórico (máx 50 entradas) e exibe gráfico de barras horizontais.

carteiraSimular(): void
// Projeta evolução patrimonial com aporteMensal × prazoAnos (máx 50 anos).
// Taxa anual ponderada pela alocação da carteira. Gráfico de área (Chart.js).

carteiraExportarCSV(): void
// Exporta o resultado do último cálculo de aporte como CSV UTF-8 com BOM.

// ─ Visualização ─
carteiraRenderDonut(): void
// Gráfico doughnut Chart.js com distribuição por classe de ativo.

carteiraRenderSunburst(): void
// Gráfico sunburst ECharts ("Distribuição Hierárquica") — classe → ativos.
// Sem labels; informações exibidas apenas no tooltip.

Perfil do investidor

Calculado a partir do percentual de Renda Fixa sobre o total alocado:

PerfilCondiçãoCorÍcone
ConservadorRF ≥ 70%verdeshield
ModeradoRF 40–69%âmbaractivity
ArrojadoRF < 40%vermelhozap

app.js

Orquestração geral: conecta todos os módulos, registra eventos e inicializa a aplicação. Deve ser carregado por último.

renderAll(): void
// Chama: renderSelect, renderLancamentos, renderOrcamentoInput,
//        renderCategorias, renderCategoriasLista.
// Envolto em try/catch — erros logam no console mas não travam o app.

renderComplete(): void
// renderAll() + renderDashboard().

setupButtons(): void
// Registra listeners para:
//   salvarOrcamento, limparMes, addLancamento,
//   btnExportPdf, btnExportBackup, inputImportBackup,
//   btnAdicionarCategoria, btnAdicionarGastoFixo,
//   btnAdicionarReceita, btnAdicionarCarteira

setupCurrencyMask(el: HTMLElement): void
// Formata em tempo real como BRL.
// Permite apenas dígitos, máximo de 11 dígitos.

setupEventDelegation(): void
// Event delegation em:
//   #listaLancamentos      → deletar-lancamento, editar-lancamento
//   #listaGastosFixos      → deletar-gasto-fixo
//   #listaReceitas         → deletar-receita
//   #categoriasListaEditor → salvar-percentuais, editar-categoria,
//                            deletar-categoria, percentual-slider/input
//   #listaCategorias       → salvar-percentuais, percentual-slider/input

setupMobileMenu(): void
// Hamburger abre sidebar.open com overlay.
// Overlay e cada .nav-btn fecham o menu em mobile.

setupSidebarToggle(): void
// Gerencia colapso da sidebar no desktop (Alt+B).
// Persiste estado em saldomain_sidebar_collapsed.

init(): void
// Sequência de bootstrap completa. Chamado ao final do arquivo.