← App Documentação
📄 Documentação Técnica

Faculdade
Pedro & Caio

Sistema de controle de presença e divisão de gastos de faculdade. Registre os dias que foi, configure o valor por pessoa e acompanhe quem deve quanto — com histórico, créditos de gasolina e resumo anual.

HTML + CSS + JS Puro Sem frameworks localStorage Offline GitHub Pages Mobile-friendly
🧭

Visão Geral

O sistema nasceu da necessidade de dividir os custos de transporte até a faculdade entre duas pessoas: Pedro e Caio. A ideia central é simples: você define um valor por pessoa por dia, marca os dias que foi, e o sistema calcula tudo automaticamente.

Abas
3 painéis
Calendário, Pagamentos, Anual
Armazenamento
localStorage
100% offline, sem servidor
Tecnologia
HTML / CSS / JS
Sem frameworks ou dependências
Compatibilidade
PC e Mobile
Responsivo, design macOS Dark
💡
Caio é auto-pago: o sistema registra automaticamente o pagamento de Caio sempre que um dia é marcado. Pedro precisa informar o pagamento manualmente.
📁

Estrutura de Arquivos

O projeto é composto por 7 arquivos que devem estar todos na mesma pasta. Cada arquivo tem uma responsabilidade bem definida.

faculdade/
  ├── index.html — estrutura HTML, sem lógica
  ├── style.css — todo o CSS (macOS dark mode)
  ├── storage.js — localStorage, cálculos financeiros
  ├── calendar.js — calendário e strip de meses
  ├── payments.js — painel de pagamentos
  ├── annual.js — resumo anual
  └── app.js — inicialização, tabs, config

Os scripts são carregados no index.html em ordem: storage.js primeiro (pois define funções usadas pelos demais), depois os painéis, e por último app.js que inicializa tudo.

Arquivo Responsabilidade Funções principais
storage.js Persistência e cálculos calcMonthOwed, calcMonthPaid, syncCaioAutoPay
calendar.js Calendário interativo renderCalendar, toggleDay, renderMonthStrip
payments.js Pagamentos Pedro/Caio/Gas registerPayment, registerGas, renderPayments
annual.js Resumo consolidado por ano renderAnnual
app.js Bootstrap e navegação initTabs, initConfig, resyncAllCaio, renderAll
🚀

Deploy no GitHub Pages

Por ser um projeto estático (sem backend), o GitHub Pages funciona perfeitamente. Siga os passos:

⚠️
localStorage é por dispositivo: os dados salvos no celular não aparecem no PC e vice-versa. Cada navegador tem seu próprio armazenamento isolado.

📅

Calendário

O painel principal. Aqui você marca os dias que foi à faculdade e configura o valor cobrado por pessoa por dia.

Como usar

Cards de resumo

Dias presentes
Quantidade
Dias marcados no mês atual
Total do mês
R$ X,XX
Dias × valor/dia × 2 pessoas

Strip de meses

A barra horizontal mostra os 5 meses anteriores ao mês atual e 2 futuros. Cada chip exibe o total do mês (em reais). Clicar em um chip navega para aquele mês no calendário.

💳

Pagamentos

Controle de quem pagou quanto por mês. Ao entrar nesta aba, o mês exibido é sincronizado automaticamente com o mês visível no Calendário.

Pedro — pagamento manual

Pedro precisa informar manualmente o quanto pagou. Digite o valor no campo e clique em Pagar. O sistema nunca permite registrar mais do que o pendente.

Caio — auto-pago

Caio é marcado como auto-pago: sempre que um dia é marcado no calendário, o sistema registra automaticamente o pagamento de Caio no valor correspondente. Não é necessária nenhuma ação manual para Caio, a menos que você queira fazer um ajuste.

Por que auto-pago? O sistema assume que Caio sempre quita sua parte em dia. Apenas Pedro precisa ter seus pagamentos monitorados ativamente.

Colunas por pessoa

ColunaSignificado
DeveValor total que a pessoa deve no mês (dias × valor/dia)
PagoSoma dos pagamentos manuais + créditos de gasolina recebidos
Pendentemax(0, Deve − Pago) — nunca negativo

Badges de status

BadgeCondição
🟢 Pago ✓ / Auto-pago ✓Pendente ≤ R$ 0,01
🟡 ParcialHá pagamentos, mas ainda há pendência
🔴 PendenteNenhum pagamento registrado
⚪ Sem débitoNenhum dia marcado no mês

Histórico

Cada pagamento registrado aparece como uma linha no histórico com valor e data. Clique no para remover uma entrada (o valor é estornado do total pago). Entradas de auto-pagamento do Caio não podem ser removidas manualmente.

Ajuda com Gasolina

Quando um terceiro (familiar, colega, etc.) contribui com dinheiro para ajudar nos custos, use este campo. O valor é dividido igualmente entre Pedro e Caio.

Regra de divisão

Fórmula: crédito por pessoa = valor informado ÷ 2

Exemplo: alguém contribuiu R$ 100,00
→ Pedro recebe crédito de R$ 50,00
→ Caio recebe crédito de R$ 50,00

Comportamento do crédito

O crédito de gasolina é sempre somado ao "Pago", independentemente de a pessoa já ter quitado o mês. Se Pedro já havia pago R$200,00 (valor total do mês) e chega um crédito de R$50,00, o campo "Pago" passará a mostrar R$250,00 — e "Pendente" permanece R$0,00.

⚠️
Importante: créditos de gasolina são independentes dos pagamentos registrados. Eles nunca alteram o valor salvo nos registros de pagamento (rec.paid). São somados apenas na hora de exibir os valores na tela.

Como aparece no histórico

Cada crédito de gasolina aparece como uma linha verde no bloco de cada pessoa (identificado como "⛽ Crédito gasolina"), e também no bloco de gasolina com o valor total e data. Clique em para remover um crédito.

📊

Resumo Anual

Visão consolidada por ano calendário (Janeiro a Dezembro). Só exibe anos que possuem pelo menos um dado registrado.

ColunaDescrição
TotalSoma de todos os meses do ano: Σ (dias_mês × vpd × 2)
PagoSoma de tudo que foi pago (manual + gas), limitado ao total devido por mês
Pendentemax(0, Total − Pago)
ℹ️
O resumo anual não separa Pedro de Caio — mostra apenas o consolidado total. Para ver quem deve o quê, use a aba Pagamentos.

💾

Armazenamento (localStorage)

Todos os dados são persistidos no localStorage do navegador, sem servidor, sem banco de dados. São três chaves independentes:

Chave localStorageConteúdo
fac_presence_v3Dias marcados como presente
fac_payments_v4Pagamentos e créditos de gasolina
fac_settings_v3Configurações (valor por dia)

Estrutura dos dados de presença

// fac_presence_v3
{
  "2026-02-10": true,
  "2026-02-11": true,
  "2026-02-12": true,
  // chave: "YYYY-MM-DD", valor: true (dias sem presença não existem)
}

Estrutura dos dados de pagamento

// fac_payments_v4
{
  "2026-02": {
    pedro: {
      paid: 150.00,          // soma de pagamentos manuais
      history: [
        { amount: 150.00, date: "27/02/2026", note: "Pagamento manual" }
      ]
    },
    caio: {
      paid: 200.00,          // auto-pay + manuais
      history: [
        { amount: 200.00, date: "Auto", note: "Auto-pagamento" }
      ]
    },
    gas: [
      {
        amount: 100.00,
        date: "27/02/2026",
        pedro_credit: 50.00,
        caio_credit: 50.00
      }
    ]
  }
}

Estrutura das configurações

// fac_settings_v3
{
  valuePerDay: "25.00"   // valor por pessoa por dia, como string
}
🧮

Lógica Financeira

Todas as funções de cálculo ficam em storage.js. Aqui está o fluxo de como os valores são calculados:

Invariante principal

🔒
rec.paid = apenas pagamentos realmente registrados (manuais + auto-pay do Caio)
Gas entries = créditos independentes, nunca modificam rec.paid
Display "Pago" = rec.paid + Σ gas_credits

calcMonthOwed(y, m)

Calcula quanto cada pessoa deve no mês, baseado nos dias marcados e no valor configurado.

calcMonthOwed(y, m) → {
  total:    dias × vpd × 2,   // total do mês (ambos)
  pedro:    dias × vpd,       // cota de Pedro
  caio:     dias × vpd,       // cota de Caio
  days:     dias,             // dias marcados
  workDays: dias_uteis        // dias úteis totais do mês
}

calcMonthPaid(payments, y, m)

Retorna quanto cada pessoa efetivamente pagou (registros + créditos de gasolina). Nunca é limitado ao valor devido — pode exceder em caso de crédito excedente.

calcMonthPaid(payments, y, m) → {
  pedro: rec.pedro.paid + Σ(gas[].pedro_credit),
  caio:  rec.caio.paid  + Σ(gas[].caio_credit)
}

syncCaioAutoPay(y, m)

Sincroniza o auto-pagamento de Caio. Chamado apenas quando a presença muda ou o valor/dia muda. Nunca chamado quando gasolina é registrada.

syncCaioAutoPay(y, m):
  manualPaid = Σ(caio.history filtrado sem Auto-pagamento)
  autoPay    = max(0, owed.caio - manualPaid)
  caio.paid  = autoPay + manualPaid
  // gas NÃO entra neste cálculo
Regra crítica: registerGas() nunca chama syncCaioAutoPay(). Se chamasse, o auto-pay de Caio seria reduzido ao receber crédito de gasolina, apagando o valor já pago — o bug que foi corrigido.
📋

Referência dos Arquivos

storage.js — Funções exportadas

FunçãoParâmetrosRetorno
loadPresence()Objeto com dias marcados
savePresence(d)objetovoid
loadPayments()Objeto com pagamentos por mês
savePayments(d)objetovoid
loadSettings()Objeto com configurações
saveSettings(d)objetovoid
getValuePerDay()number (vpd atual)
calcMonthOwed(y, m)year, month (0-11){total, pedro, caio, days, workDays}
calcMonthPaid(payments, y, m)objeto, year, month{pedro, caio}
syncCaioAutoPay(y, m)year, month (0-11)void (salva direto)
brl(val)numberstring "R$ X,XX"
brlShort(val)numberstring curta (ex: "R$ 1,5k")
todayStr()string "DD/MM/YYYY"
dayKey(y,m,d)year, month(0-11), daystring "YYYY-MM-DD"
monthKey(y,m)year, month(0-11)string "YYYY-MM"

app.js — Funções globais

FunçãoDescrição
showToast(msg)Exibe notificação flutuante por 2,2 segundos
renderAll()Re-renderiza todos os painéis
resyncAllCaio()Sincroniza auto-pay do Caio para todos os meses com presença

Variáveis de estado globais

VariávelArquivoUso
NOWcalendar.jsData atual (new Date() na inicialização)
calYear / calMonthcalendar.jsMês visível no calendário
payYear / payMonthpayments.jsMês visível no painel de pagamentos

🔢

Fórmulas

CampoFórmula
Total do diavpd × 2
Cota de cada pessoa/diavpd × 1
Total do mêsdias_marcados × vpd × 2
Devido por pessoa/mêsdias_marcados × vpd
Pago efetivo (display)rec.paid + Σ gas_credits
Pendentemax(0, devido − pago_efetivo)
Crédito de gasolina/pessoavalor_ajuda ÷ 2
Ausências no mêsdias_úteis_mês − dias_marcados
Total anualΣ (total_mês) para Jan–Dez do ano
Pago anualΣ min(pago_efetivo_mês, devido_mês)
📌

Regras de Negócio

1
Fins de semana são ignorados. Sábados e domingos não podem ser marcados no calendário e não contam para o total de dias úteis.
2
Valor = por pessoa, por dia. O campo de configuração representa a cota de cada um. O total real cobrado por dia é sempre vpd × 2.
3
Caio é sempre auto-pago. O sistema registra o pagamento de Caio automaticamente ao marcar cada dia. Pedro precisa pagar manualmente.
4
Pagamentos manuais não podem exceder o pendente. Se Pedro deve R$200 e já pagou R$150 (restam R$50), um pagamento de R$100 será limitado automaticamente a R$50.
5
Créditos de gasolina não têm limite. Se a pessoa já quitou o mês e ainda assim chega um crédito, ele acumula no campo "Pago" sem ser bloqueado.
6
Gasolina nunca altera rec.paid. Os créditos de gasolina ficam separados em rec.gas[] e são somados apenas na exibição, nunca modificando os valores de pagamento armazenados.
7
Dados ficam para sempre. Não há expiração automática de dados. Todos os meses e anos ficam armazenados até que o localStorage seja limpo manualmente.
8
Alterar o valor/dia re-sincroniza tudo. Ao mudar o valor por dia, o sistema recalcula o auto-pay do Caio para todos os meses que têm presença registrada.