SaldoMais
Carregando…
Documento 02 de 07

Módulos JavaScript

Os 8 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

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): void
// Exibe toast de notificação por 2500ms.

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: 1, _exportado_em, categorias, orcamentos, lancamentos }
// 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": 1,
  "_exportado_em": "2026-04-18T12:00:00.000Z",
  "categorias": [...],
  "orcamentos": [...],
  "lancamentos": [...]
}
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.

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, logoBtnSidebar

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
//   #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.

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