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
| Constante | Tipo | Descrição |
|---|---|---|
MESES | string[] | Nomes dos meses em pt-BR, índice 0-based |
PDF_COLORS | object | Paleta de cores RGB para o relatório PDF |
STORAGE | object | Chaves do localStorage: categorias, orcamentos, lancamentos |
Referências DOM
| Variável | ID 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.
| Nome | Percentual | Cor |
|---|---|---|
| Custos fixos | 30% | #f59e0b |
| Conforto | 5% | #22c55e |
| Metas | 11% | #ef4444 |
| Prazeres | 24% | #3b82f6 |
| Liberdade financeira | 25% | #a855f7 |
| Conhecimento | 5% | #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ção | Cor |
|---|---|
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": [...]
}
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.