feat: adicionar versão na sidebar e atualizar documentação

- Exibir versão (v1.2.5) ao lado do logo na sidebar
- Adicionar link do repositório Companion na aba de configurações
- Atualizar README com documentação completa do OpenSheets Companion
- Atualizar versões das dependências e estrutura do banco de dados
- Adicionar logo do Creditas
- Remover fontes não utilizadas
- Atualizar logo_text.png

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-02-01 21:49:26 +00:00
parent 79a2899bf2
commit 3f77dcf5d3
12 changed files with 301 additions and 994 deletions

246
README.md
View File

@@ -12,6 +12,7 @@
[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org/)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-18-blue?style=flat-square&logo=postgresql)](https://www.postgresql.org/) [![PostgreSQL](https://img.shields.io/badge/PostgreSQL-18-blue?style=flat-square&logo=postgresql)](https://www.postgresql.org/)
[![Docker](https://img.shields.io/badge/Docker-Ready-blue?style=flat-square&logo=docker)](https://www.docker.com/) [![Docker](https://img.shields.io/badge/Docker-Ready-blue?style=flat-square&logo=docker)](https://www.docker.com/)
[![Android Companion](https://img.shields.io/badge/Companion-Android-3DDC84?style=flat-square&logo=android)](https://github.com/felipegcoutinho/opensheets-companion)
[![License](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-orange?style=flat-square&logo=creative-commons)](LICENSE) [![License](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-orange?style=flat-square&logo=creative-commons)](LICENSE)
[![Sponsor](https://img.shields.io/badge/Sponsor-❤️-ea4aaa?style=flat-square&logo=github-sponsors)](https://github.com/sponsors/felipegcoutinho) [![Sponsor](https://img.shields.io/badge/Sponsor-❤️-ea4aaa?style=flat-square&logo=github-sponsors)](https://github.com/sponsors/felipegcoutinho)
@@ -37,6 +38,7 @@
- [Configuração de Variáveis de Ambiente](#-configuração-de-variáveis-de-ambiente) - [Configuração de Variáveis de Ambiente](#-configuração-de-variáveis-de-ambiente)
- [Banco de Dados](#-banco-de-dados) - [Banco de Dados](#-banco-de-dados)
- [Arquitetura](#-arquitetura) - [Arquitetura](#-arquitetura)
- [Destaques e Funcionalidades Recentes](#-destaques-e-funcionalidades-recentes)
- [Contribuindo](#-contribuindo) - [Contribuindo](#-contribuindo)
- [Apoie o Projeto](#-apoie-o-projeto) - [Apoie o Projeto](#-apoie-o-projeto)
@@ -51,13 +53,14 @@ A ideia é simples: ter um lugar onde consigo ver todas as minhas contas, cartõ
### 📊 Estatísticas do Projeto ### 📊 Estatísticas do Projeto
- **~200 componentes React** organizados por feature - **~200 componentes React** organizados por feature
- **15+ tabelas de banco de dados** com relações complexas - **17+ tabelas de banco de dados** com relações complexas
- **20+ widgets** no dashboard principal - **20+ widgets** no dashboard principal
- **18+ queries paralelas** otimizadas para performance - **18+ queries paralelas** otimizadas para performance
- **736 linhas** de schema Drizzle ORM - **~820 linhas** de schema Drizzle ORM
- **Docker multi-stage** com imagem final de ~200MB - **Docker multi-stage** com imagem final de ~200MB
- **100% TypeScript** com strict mode - **100% TypeScript** com strict mode
- **Self-hosted** - seus dados, seu controle - **Self-hosted** - seus dados, seu controle
- **App Companion Android** - captura automática de notificações bancárias
> 💡 **Licença Não-Comercial:** Este projeto é gratuito para uso pessoal, mas não pode ser usado comercialmente. Veja mais detalhes na seção [Licença](#-licença). > 💡 **Licença Não-Comercial:** Este projeto é gratuito para uso pessoal, mas não pode ser usado comercialmente. Veja mais detalhes na seção [Licença](#-licença).
@@ -71,7 +74,14 @@ Este projeto é self-hosted. Você precisa rodar no seu próprio computador ou s
Você precisa registrar manualmente suas transações. Se você procura algo que sincroniza automaticamente com seu banco, este projeto não é pra você. Você precisa registrar manualmente suas transações. Se você procura algo que sincroniza automaticamente com seu banco, este projeto não é pra você.
**3. Requer disciplina** **3. 🤖 OpenSheets Companion (Android)**
Existe um app Android complementar que captura notificações de transações dos seus apps de banco (Nubank, Itaú, Bradesco, Inter, C6 e outros) e envia automaticamente para sua caixa de entrada no OpenSheets. As notificações ficam como "pré-lançamentos" para você revisar e aprovar.
- **Repositório:** [github.com/felipegcoutinho/opensheets-companion](https://github.com/felipegcoutinho/opensheets-companion)
- **Configuração:** Ajustes → OpenSheets Companion → Gere um token de API
**4. Requer disciplina**
O Opensheets funciona melhor para quem: O Opensheets funciona melhor para quem:
@@ -147,6 +157,21 @@ Se você não se importa em dedicar alguns minutos por dia (ou semana) para mant
- Navegação intuitiva por data - Navegação intuitiva por data
- Filtros e organização temporal - Filtros e organização temporal
📲 **OpenSheets Companion (Android)**
- App Android que captura notificações bancárias
- Suporte a Nubank, Itaú, Bradesco, Inter, C6 e outros
- Pré-lançamentos para revisão antes de aprovar
- Autenticação via tokens de API seguros
- Sincronização automática em segundo plano
📊 **Relatórios avançados**
- Tendências de categorias ao longo do tempo
- Análise de uso de cartões de crédito
- Top estabelecimentos mais frequentes
- Filtros por período personalizáveis
⚙️ **Preferências e personalização** ⚙️ **Preferências e personalização**
- Tema claro/escuro - Tema claro/escuro
@@ -175,12 +200,13 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
### 🔐 Autenticação ### 🔐 Autenticação
- Better Auth 1.4.10 integrado - Better Auth 1.4.18 integrado
- OAuth (Google) - OAuth (Google)
- Autenticação por email/senha - Autenticação por email/senha
- Session management com tokens - Session management com tokens
- Protected routes via middleware - Protected routes via middleware
- Verificação de email - Verificação de email
- Tokens de API para integrações externas
### 🗄️ Banco de Dados ### 🗄️ Banco de Dados
@@ -238,11 +264,21 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
- shadcn/ui components (Radix UI) - shadcn/ui components (Radix UI)
- Tailwind CSS v4 - Tailwind CSS v4
- Dark mode com next-themes - Dark mode com next-themes
- Animações fluidas com Motion - Drag-and-drop com dnd-kit
- Responsive design - Responsive design
- Modo privacidade (oculta valores) - Modo privacidade (oculta valores)
- Componentes acessíveis (ARIA) - Componentes acessíveis (ARIA)
### 📲 OpenSheets Companion
- App Android para captura de notificações bancárias
- Suporte a múltiplos bancos (Nubank, Itaú, Bradesco, Inter, C6, etc.)
- Caixa de entrada (pré-lançamentos) para revisão
- Tokens de API com hash SHA-256 (nunca armazenados em texto)
- Rate limiting (100 requests/min por usuário)
- API batch para envio de múltiplas notificações
- Endpoint de health check para validação
### 📝 Produtividade ### 📝 Produtividade
- Sistema de anotações e tarefas - Sistema de anotações e tarefas
@@ -263,11 +299,11 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
### 🧪 Desenvolvimento ### 🧪 Desenvolvimento
- Next.js 16.1 com App Router - Next.js 16.1.6 com App Router
- Turbopack (fast refresh) - Turbopack (fast refresh)
- TypeScript 5.9 (strict mode) - TypeScript 5.9.3 (strict mode)
- Biome (linting + formatting) - Biome 2.x (linting + formatting + import organization)
- React 19.2 (com Compiler) - React 19.2.4 (com Compiler)
- Server Actions - Server Actions
- Parallel data fetching - Parallel data fetching
- Streaming SSR - Streaming SSR
@@ -278,16 +314,16 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
### Frontend ### Frontend
- **Framework:** Next.js 16.1.1 (App Router) - **Framework:** Next.js 16.1.6 (App Router)
- **Linguagem:** TypeScript 5.9.3 - **Linguagem:** TypeScript 5.9.3
- **UI Library:** React 19.2.3 - **UI Library:** React 19.2.4
- **Styling:** Tailwind CSS 4.1.18 - **Styling:** Tailwind CSS 4.1.18
- **Components:** shadcn/ui (Radix UI) - **Components:** shadcn/ui (Radix UI)
- **Icons:** Remixicon 4.8.0 - **Icons:** Remixicon 4.9.0
- **Animations:** Motion 12.23.26 - **Drag & Drop:** dnd-kit
- **Tables:** TanStack React Table 8.21.3 - **Tables:** TanStack React Table 8.21.3
- **Charts:** Recharts 3.6.0 - **Charts:** Recharts 3.7.0
- **Forms:** React Hook Form + Zod 4.3.4 - **Validation:** Zod 4.3.6
- **Theme:** next-themes 0.4.6 - **Theme:** next-themes 0.4.6
### Backend ### Backend
@@ -295,18 +331,18 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
- **Runtime:** Node.js 22 - **Runtime:** Node.js 22
- **Database:** PostgreSQL 18 - **Database:** PostgreSQL 18
- **ORM:** Drizzle ORM 0.45.1 - **ORM:** Drizzle ORM 0.45.1
- **Database Driver:** pg 8.16.3 - **Database Driver:** pg 8.18.0
- **Auth:** Better Auth 1.4.10 - **Auth:** Better Auth 1.4.18
- **Email:** Resend 6.6.0 - **Email:** Resend 6.9.1
- **Validation:** Zod 4.3.4 - **Validation:** Zod 4.3.6
### AI Integration (Opcional) ### AI Integration (Opcional)
- **AI SDK:** Vercel AI SDK 6.0.6 - **AI SDK:** Vercel AI SDK 6.0.67
- **Anthropic:** Claude (via @ai-sdk/anthropic 3.0.2) - **Anthropic:** Claude (via @ai-sdk/anthropic 3.0.35)
- **OpenAI:** GPT (via @ai-sdk/openai 3.0.2) - **OpenAI:** GPT (via @ai-sdk/openai 3.0.25)
- **Google:** Gemini (via @ai-sdk/google 3.0.2) - **Google:** Gemini (via @ai-sdk/google 3.0.20)
- **OpenRouter:** via @openrouter/ai-sdk-provider 1.5.4 - **OpenRouter:** via @openrouter/ai-sdk-provider 2.1.1
### Utilities ### Utilities
@@ -322,7 +358,8 @@ O projeto é open source, seus dados ficam no seu controle (pode rodar localment
- **Containerization:** Docker + Docker Compose - **Containerization:** Docker + Docker Compose
- **Package Manager:** pnpm - **Package Manager:** pnpm
- **Build Tool:** Turbopack - **Build Tool:** Turbopack
- **Linting & Formatting:** Biome 2.x - **Linting & Formatting:** Biome 2.3.13
- **Database Tools:** Drizzle Kit 0.31.8
- **Analytics:** Vercel Analytics + Speed Insights - **Analytics:** Vercel Analytics + Speed Insights
--- ---
@@ -869,7 +906,10 @@ opensheets/
├── app/ # Next.js App Router ├── app/ # Next.js App Router
│ ├── api/ # API Routes │ ├── api/ # API Routes
│ │ ├── auth/[...all]/ # Better Auth endpoints │ │ ├── auth/[...all]/ # Better Auth endpoints
│ │ ── health/ # Health check endpoint │ │ ── health/ # Health check (Companion validation)
│ │ └── inbox/ # API para Companion App
│ │ ├── route.ts # POST - Enviar notificação única
│ │ └── batch/route.ts # POST - Enviar múltiplas notificações
│ ├── (auth)/ # Rotas públicas de autenticação │ ├── (auth)/ # Rotas públicas de autenticação
│ │ ├── login/ # Página de login │ │ ├── login/ # Página de login
│ │ └── signup/ # Página de cadastro │ │ └── signup/ # Página de cadastro
@@ -877,6 +917,7 @@ opensheets/
│ │ ├── dashboard/ # Dashboard principal │ │ ├── dashboard/ # Dashboard principal
│ │ │ └── analise-parcelas/ # Análise de parcelas │ │ │ └── analise-parcelas/ # Análise de parcelas
│ │ ├── lancamentos/ # Lançamentos/transações │ │ ├── lancamentos/ # Lançamentos/transações
│ │ ├── pre-lancamentos/ # Caixa de entrada (Companion)
│ │ ├── contas/ # Contas bancárias │ │ ├── contas/ # Contas bancárias
│ │ │ └── [contaId]/extrato # Extrato da conta │ │ │ └── [contaId]/extrato # Extrato da conta
│ │ ├── cartoes/ # Cartões de crédito │ │ ├── cartoes/ # Cartões de crédito
@@ -891,7 +932,9 @@ opensheets/
│ │ │ └── arquivadas/ # Anotações arquivadas │ │ │ └── arquivadas/ # Anotações arquivadas
│ │ ├── insights/ # Insights de IA │ │ ├── insights/ # Insights de IA
│ │ ├── relatorios/ # Relatórios │ │ ├── relatorios/ # Relatórios
│ │ │ ── categorias/ # Relatório de categorias │ │ │ ── tendencias/ # Tendências de categorias
│ │ │ └── uso-cartoes/ # Análise de cartões
│ │ ├── top-estabelecimentos/ # Top estabelecimentos
│ │ ├── calendario/ # Visão de calendário │ │ ├── calendario/ # Visão de calendário
│ │ ├── changelog/ # Histórico de mudanças │ │ ├── changelog/ # Histórico de mudanças
│ │ └── ajustes/ # Configurações │ │ └── ajustes/ # Configurações
@@ -923,8 +966,11 @@ opensheets/
│ ├── anotacoes/ # Componentes de anotações │ ├── anotacoes/ # Componentes de anotações
│ ├── insights/ # Componentes de insights IA │ ├── insights/ # Componentes de insights IA
│ ├── relatorios/ # Componentes de relatórios │ ├── relatorios/ # Componentes de relatórios
│ ├── pre-lancamentos/ # Componentes da caixa de entrada
│ ├── top-estabelecimentos/ # Top estabelecimentos
│ ├── calendario/ # Componentes de calendário │ ├── calendario/ # Componentes de calendário
│ ├── calculadora/ # Calculadora integrada │ ├── calculadora/ # Calculadora integrada
│ ├── ajustes/ # Configurações e Companion
│ ├── sidebar/ # Sidebar de navegação │ ├── sidebar/ # Sidebar de navegação
│ ├── skeletons/ # Estados de loading │ ├── skeletons/ # Estados de loading
│ └── month-picker/ # Seletor de mês/período │ └── month-picker/ # Seletor de mês/período
@@ -1003,7 +1049,8 @@ opensheets/
| Diretório | Descrição | Arquivos | | Diretório | Descrição | Arquivos |
| ------------------ | ------------------------------------------- | -------- | | ------------------ | ------------------------------------------- | -------- |
| `app/(dashboard)/` | Páginas protegidas da aplicação | ~50 | | `app/(dashboard)/` | Páginas protegidas da aplicação | ~60 |
| `app/api/` | Endpoints da API (auth, inbox, health) | ~5 |
| `components/` | Componentes React reutilizáveis | ~200 | | `components/` | Componentes React reutilizáveis | ~200 |
| `lib/` | Lógica de negócio, helpers e utilitários | ~80 | | `lib/` | Lógica de negócio, helpers e utilitários | ~80 |
| `db/` | Schema do banco de dados | 1 | | `db/` | Schema do banco de dados | 1 |
@@ -1013,106 +1060,124 @@ opensheets/
### Estrutura do Banco de Dados ### Estrutura do Banco de Dados
O OpenSheets possui um schema robusto com 15+ tabelas e relações complexas: O OpenSheets possui um schema robusto com 17+ tabelas e relações complexas:
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ TABELAS PRINCIPAIS │ │ TABELAS PRINCIPAIS │
├─────────────────────────────────────────────────────────────────┤ ├─────────────────────────────────────────────────────────────────┤
│ │ │ │
│ user user_preferences │ user preferenciasUsuario
│ ├── id ├── id │ │ ├── id ├── id │
│ ├── name ├── user_id → user.id │ │ ├── name ├── userId → user.id
│ ├── email ├── disable_magnetlines │ │ ├── email ├── disableMagnetlines │
│ └── ... ── ... │ └── ... ── dashboardWidgets (JSON)
│ └── ... │
│ │ │ │
│ contas cartoes │ │ contas cartoes │
│ ├── id ├── id │ │ ├── id ├── id │
│ ├── user_id → user.id ├── user_id → user.id │ │ ├── userId → user.id ├── userId → user.id
│ ├── nome ├── conta_id → contas.id │ │ ├── nome ├── contaId → contas.id
│ ├── tipo_conta ├── nome │ │ ├── tipoConta ├── nome │
│ ├── saldo_inicial ├── bandeira │ │ ├── saldoInicial ├── bandeira │
│ └── ... ├── dt_fechamento │ │ └── ... ├── dtFechamento
│ ├── dt_vencimento │ │ ├── dtVencimento
│ └── ... │ │ └── ... │
│ │ │ │
│ categorias pagadores │ │ categorias pagadores │
│ ├── id ├── id │ │ ├── id ├── id │
│ ├── user_id → user.id ├── user_id → user.id │ │ ├── userId → user.id ├── userId → user.id
│ ├── nome ├── nome │ │ ├── nome ├── nome │
│ ├── tipo ├── email │ │ ├── tipo ├── email │
│ ├── icone ├── share_code (único) │ │ ├── icone ├── shareCode (único)
│ └── ... ├── role │ └── ... ├── isAutoSend
│ └── ... │ │ └── ... │
│ │ │ │
pagador_shares compartilhamentosPagador
│ ├── id │ │ ├── id │
│ ├── pagador_id → pagadores.id │ │ ├── pagadorId → pagadores.id
│ ├── shared_with_user_id → user.id │ │ ├── sharedWithUserId → user.id
│ ├── created_by_user_id → user.id │ │ ├── createdByUserId → user.id
│ ├── permission (read/write) │ │ ├── permission (read/write) │
│ └── ... │ │ └── ... │
│ │ │ │
│ lancamentos (TABELA PRINCIPAL) │ │ lancamentos (TABELA PRINCIPAL) │
│ ├── id │ │ ├── id │
│ ├── user_id → user.id │ │ ├── userId → user.id
│ ├── conta_id → contas.id │ │ ├── contaId → contas.id
│ ├── cartao_id → cartoes.id │ │ ├── cartaoId → cartoes.id
│ ├── categoria_id → categorias.id │ │ ├── categoriaId → categorias.id
│ ├── pagador_id → pagadores.id │ │ ├── pagadorId → pagadores.id
│ ├── nome │ │ ├── nome │
│ ├── valor │ │ ├── valor │
│ ├── tipo_transacao (receita/despesa/transferencia) │ │ ├── tipoTransacao (receita/despesa/transferencia)
│ ├── forma_pagamento │ │ ├── formaPagamento
│ ├── condicao (aberto/realizado/cancelado) │ │ ├── condicao (aberto/realizado/cancelado) │
│ ├── data_compra │ │ ├── dataCompra
│ ├── periodo (YYYY-MM) │ │ ├── periodo (YYYY-MM) │
│ ├── qtde_parcela │ │ ├── qtdeParcela
│ ├── parcela_atual │ │ ├── parcelaAtual
│ ├── series_id (agrupa parcelas) │ │ ├── seriesId (agrupa parcelas)
│ ├── transfer_id (agrupa transferências) │ │ ├── transferId (agrupa transferências)
│ ├── antecipado (boolean) │ │ ├── antecipado (boolean) │
│ ├── antecipacao_id → installment_anticipations.id │ ├── antecipacaoId → antecipacoesParcelas.id
│ └── ... │ │ └── ... │
│ │ │ │
installment_anticipations antecipacoesParcelas
│ ├── id │ │ ├── id │
│ ├── user_id → user.id │ │ ├── userId → user.id
│ ├── series_id │ ├── seriesId
│ ├── lancamento_id → lancamentos.id │ │ ├── lancamentoId → lancamentos.id
│ ├── periodo_antecipacao │ │ ├── periodoAntecipacao
│ ├── parcelas_antecipadas (JSONB array) │ │ ├── parcelasAntecipadas (JSONB array)
│ ├── valor_total │ │ ├── valorTotal
│ ├── desconto │ │ ├── desconto │
│ └── ... │ │ └── ... │
│ │ │ │
│ faturas orcamentos │ │ faturas orcamentos │
│ ├── id ├── id │ │ ├── id ├── id │
│ ├── user_id → user.id ├── user_id → user.id │ │ ├── userId → user.id ├── userId → user.id
│ ├── cartao_id → cartoes ├── categoria_id → categorias.id │ │ ├── cartaoId → cartoes ├── categoriaId → categorias.id
│ ├── periodo ├── valor │ │ ├── periodo ├── valor │
│ ├── status_pagamento ├── periodo │ │ ├── statusPagamento ├── periodo │
│ └── ... └── ... │ │ └── ... └── ... │
│ │ │ │
│ anotacoes saved_insights │ │ anotacoes insightsSalvos
│ ├── id ├── id │ │ ├── id ├── id │
│ ├── user_id → user.id ├── user_id → user.id │ │ ├── userId → user.id ├── userId → user.id
│ ├── titulo ├── period │ │ ├── titulo ├── period │
│ ├── descricao ├── model_id │ ├── descricao ├── modelId
│ ├── tipo (nota/tarefa) ├── data (JSON) │ │ ├── tipo (nota/tarefa) ├── data (JSON) │
│ ├── tasks (JSON) ── created_at │ ├── tasks (JSON) ── createdAt
│ ├── arquivada └── updated_at │ ├── arquivada
│ └── ... │
│ │
│ ══════════════════ COMPANION APP ══════════════════ │
│ │
│ tokensApi preLancamentos │
│ ├── id ├── id │
│ ├── userId → user.id ├── userId → user.id │
│ ├── name ├── sourceApp │
│ ├── tokenHash (SHA-256) ├── sourceAppName │
│ ├── tokenPrefix ├── originalTitle │
│ ├── lastUsedAt ├── originalText │
│ ├── lastUsedIp ├── parsedName │
│ ├── expiresAt ├── parsedAmount │
│ ├── revokedAt ├── status (pending/processed) │
│ └── createdAt ├── lancamentoId → lancamentos.id │
│ └── ... │ │ └── ... │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────┘
ÍNDICES OTIMIZADOS: ÍNDICES OTIMIZADOS:
• user_id + period (queries do dashboard) • userId + periodo (queries do dashboard)
• user_id + purchase_date (ordenação por data) • userId + dataCompra (ordenação por data)
• series_id (agrupamento de parcelas) • seriesId (agrupamento de parcelas)
• cartao_id + period (faturas) • cartaoId + periodo (faturas)
• user_id + condition (filtros de condição) • userId + condicao (filtros de condição)
• share_code (compartilhamento) • shareCode (compartilhamento)
• tokenHash (autenticação API)
• userId + status (inbox filtering)
``` ```
### Fluxo de Autenticação ### Fluxo de Autenticação
@@ -1181,6 +1246,20 @@ O OpenSheets possui um schema robusto com 15+ tabelas e relações complexas:
O OpenSheets está em desenvolvimento ativo. Aqui estão algumas das funcionalidades mais interessantes já implementadas: O OpenSheets está em desenvolvimento ativo. Aqui estão algumas das funcionalidades mais interessantes já implementadas:
### 📲 OpenSheets Companion
Integração completa com app Android para captura automática de notificações bancárias:
- **Captura automática:** Nubank, Itaú, Bradesco, Inter, C6 e outros bancos
- **Caixa de entrada:** Notificações chegam como pré-lançamentos para revisão
- **Edição inline:** Ajuste valores e descrições antes de aprovar
- **Tokens seguros:** Autenticação via tokens com hash SHA-256
- **Rate limiting:** Proteção contra abuso (100 req/min)
- **API batch:** Envio de múltiplas notificações de uma vez
- **Health check:** Endpoint para validação de conectividade
O app Companion está disponível em: [github.com/felipegcoutinho/opensheets-companion](https://github.com/felipegcoutinho/opensheets-companion)
### 💸 Sistema Avançado de Parcelamentos ### 💸 Sistema Avançado de Parcelamentos
O controle de parcelamentos vai além do básico: O controle de parcelamentos vai além do básico:
@@ -1215,7 +1294,10 @@ Analytics poderosos para entender suas finanças:
- **Dashboard interativo:** 20+ widgets com diferentes visualizações - **Dashboard interativo:** 20+ widgets com diferentes visualizações
- **Relatórios de categorias:** Análise profunda por categoria com histórico - **Relatórios de categorias:** Análise profunda por categoria com histórico
- **Comparativos mensais:** Veja a evolução dos seus gastos ao longo do tempo - **Tendências:** Visualize a evolução de categorias ao longo de 3, 6 ou 12 meses
- **Uso de cartões:** Análise detalhada de gastos por cartão de crédito
- **Top estabelecimentos:** Veja onde você mais gasta
- **Comparativos mensais:** Evolução dos seus gastos ao longo do tempo
- **Exportações:** PDF e Excel para análise externa - **Exportações:** PDF e Excel para análise externa
- **Gráficos interativos:** Recharts com dados em tempo real - **Gráficos interativos:** Recharts com dados em tempo real
@@ -1258,6 +1340,7 @@ Feito por desenvolvedores, para desenvolvedores:
- **Migrations automáticas:** Schema sync simplificado - **Migrations automáticas:** Schema sync simplificado
- **Docker completo:** Ambiente reproduzível em qualquer lugar - **Docker completo:** Ambiente reproduzível em qualquer lugar
- **Scripts facilitados:** Comandos npm para tudo - **Scripts facilitados:** Comandos npm para tudo
- **Biome:** Linting e formatting unificados em uma ferramenta
--- ---
@@ -1356,6 +1439,7 @@ Para o texto legal completo, consulte o arquivo [LICENSE](LICENSE) ou visite [cr
- [Better Auth](https://better-auth.com/) - [Better Auth](https://better-auth.com/)
- [Drizzle ORM](https://orm.drizzle.team/) - [Drizzle ORM](https://orm.drizzle.team/)
- [shadcn/ui](https://ui.shadcn.com/) - [shadcn/ui](https://ui.shadcn.com/)
- [Biome](https://biomejs.dev/)
- [Vercel](https://vercel.com/) - [Vercel](https://vercel.com/)
--- ---

View File

@@ -1,8 +1,10 @@
"use client"; "use client";
import type { ReactNode } from "react";
import { import {
RiAndroidLine, RiAndroidLine,
RiDownload2Line, RiDownload2Line,
RiExternalLinkLine,
RiNotification3Line, RiNotification3Line,
RiQrCodeLine, RiQrCodeLine,
RiShieldCheckLine, RiShieldCheckLine,
@@ -25,11 +27,28 @@ interface CompanionTabProps {
tokens: ApiToken[]; tokens: ApiToken[];
} }
const steps = [ const steps: {
icon: typeof RiDownload2Line;
title: string;
description: ReactNode;
}[] = [
{ {
icon: RiDownload2Line, icon: RiDownload2Line,
title: "Instale o app", title: "Instale o app",
description: "Instale o APK.", description: (
<>
Baixe o APK no{" "}
<a
href="https://github.com/felipegcoutinho/opensheets-companion"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-0.5 text-primary hover:underline"
>
GitHub
<RiExternalLinkLine className="h-3 w-3" />
</a>
</>
),
}, },
{ {
icon: RiQrCodeLine, icon: RiQrCodeLine,

View File

@@ -1,12 +1,18 @@
import Image from "next/image"; import Image from "next/image";
import { cn } from "@/lib/utils/ui"; import { cn } from "@/lib/utils/ui";
import { version } from "@/package.json";
interface LogoProps { interface LogoProps {
variant?: "full" | "small"; variant?: "full" | "small";
className?: string; className?: string;
showVersion?: boolean;
} }
export function Logo({ variant = "full", className }: LogoProps) { export function Logo({
variant = "full",
className,
showVersion = false,
}: LogoProps) {
if (variant === "small") { if (variant === "small") {
return ( return (
<Image <Image
@@ -21,7 +27,7 @@ export function Logo({ variant = "full", className }: LogoProps) {
} }
return ( return (
<div className={cn("flex items-center py-4", className)}> <div className={cn("flex items-center gap-1.5 py-4", className)}>
<Image <Image
src="/logo_small.png" src="/logo_small.png"
alt="Opensheets" alt="Opensheets"
@@ -38,6 +44,11 @@ export function Logo({ variant = "full", className }: LogoProps) {
className="object-contain dark:invert" className="object-contain dark:invert"
priority priority
/> />
{showVersion && (
<span className="text-[10px] font-medium text-muted-foreground">
v{version}
</span>
)}
</div> </div>
); );
} }

View File

@@ -11,13 +11,13 @@ interface ReturnButtonProps {
const ReturnButton = React.memo(({ disabled, onClick }: ReturnButtonProps) => { const ReturnButton = React.memo(({ disabled, onClick }: ReturnButtonProps) => {
return ( return (
<Button <Button
className="w-28 h-6 rounded-sm" className="w-32 h-6 rounded-sm lowercase"
size="sm" size="sm"
disabled={disabled} disabled={disabled}
onClick={onClick} onClick={onClick}
aria-label="Retornar para o mês atual" aria-label="Retornar para o mês atual"
> >
Mês Atual Ir para Mês Atual
</Button> </Button>
); );
}); });

View File

@@ -53,7 +53,7 @@ export function AppSidebar({
<SidebarMenuItem> <SidebarMenuItem>
<SidebarMenuButton <SidebarMenuButton
asChild asChild
className="data-[slot=sidebar-menu-button]:px-1.5! hover:bg-transparent active:bg-transparent pt-4 justify-center hover:scale-105 transition-all duration-200" className="data-[slot=sidebar-menu-button]:px-1.5! hover:bg-transparent active:bg-transparent pt-8 py-6 justify-center hover:scale-120 scale-110 transition-all duration-200"
> >
<a href="/dashboard"> <a href="/dashboard">
<LogoContent /> <LogoContent />
@@ -77,5 +77,10 @@ function LogoContent() {
const { state } = useSidebar(); const { state } = useSidebar();
const isCollapsed = state === "collapsed"; const isCollapsed = state === "collapsed";
return <Logo variant={isCollapsed ? "small" : "full"} />; return (
<Logo
variant={isCollapsed ? "small" : "full"}
showVersion={!isCollapsed}
/>
);
} }

View File

@@ -13,7 +13,7 @@ import {
RiInboxLine, RiInboxLine,
RiNoCreditCardLine, RiNoCreditCardLine,
RiPriceTag3Line, RiPriceTag3Line,
RiSettingsLine, RiSettings2Line,
RiSparklingLine, RiSparklingLine,
RiTodoLine, RiTodoLine,
} from "@remixicon/react"; } from "@remixicon/react";
@@ -199,7 +199,7 @@ export function createSidebarNavData(
{ {
title: "Ajustes", title: "Ajustes",
url: "/ajustes", url: "/ajustes",
icon: RiSettingsLine, icon: RiSettings2Line,
}, },
], ],
}; };

View File

@@ -1,6 +1,6 @@
{ {
"name": "opensheets", "name": "opensheets",
"version": "1.0.0", "version": "1.2.5",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev --turbopack", "dev": "next dev --turbopack",
@@ -27,9 +27,9 @@
"docker:rebuild": "docker compose up --build --force-recreate" "docker:rebuild": "docker compose up --build --force-recreate"
}, },
"dependencies": { "dependencies": {
"@ai-sdk/anthropic": "^3.0.31", "@ai-sdk/anthropic": "^3.0.35",
"@ai-sdk/google": "^3.0.18", "@ai-sdk/google": "^3.0.20",
"@ai-sdk/openai": "^3.0.23", "@ai-sdk/openai": "^3.0.25",
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0", "@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2", "@dnd-kit/utilities": "^3.2.2",
@@ -59,7 +59,7 @@
"@tanstack/react-table": "8.21.3", "@tanstack/react-table": "8.21.3",
"@vercel/analytics": "^1.6.1", "@vercel/analytics": "^1.6.1",
"@vercel/speed-insights": "^1.3.1", "@vercel/speed-insights": "^1.3.1",
"ai": "^6.0.62", "ai": "^6.0.67",
"babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-compiler": "^1.0.0",
"better-auth": "1.4.18", "better-auth": "1.4.18",
"class-variance-authority": "0.7.1", "class-variance-authority": "0.7.1",
@@ -69,10 +69,9 @@
"drizzle-orm": "0.45.1", "drizzle-orm": "0.45.1",
"jspdf": "^4.0.0", "jspdf": "^4.0.0",
"jspdf-autotable": "^5.0.7", "jspdf-autotable": "^5.0.7",
"motion": "^12.29.2",
"next": "16.1.6", "next": "16.1.6",
"next-themes": "0.4.6", "next-themes": "0.4.6",
"pg": "8.17.2", "pg": "8.18.0",
"react": "19.2.4", "react": "19.2.4",
"react-day-picker": "^9.13.0", "react-day-picker": "^9.13.0",
"react-dom": "19.2.4", "react-dom": "19.2.4",
@@ -87,13 +86,10 @@
"devDependencies": { "devDependencies": {
"@biomejs/biome": "2.3.13", "@biomejs/biome": "2.3.13",
"@tailwindcss/postcss": "4.1.18", "@tailwindcss/postcss": "4.1.18",
"@types/d3-array": "^3.2.2",
"@types/node": "25.1.0", "@types/node": "25.1.0",
"@types/pg": "^8.16.0", "@types/pg": "^8.16.0",
"@types/react": "19.2.10", "@types/react": "19.2.10",
"@types/react-dom": "19.2.3", "@types/react-dom": "19.2.3",
"baseline-browser-mapping": "^2.9.19",
"depcheck": "^1.4.7",
"dotenv": "^17.2.3", "dotenv": "^17.2.3",
"drizzle-kit": "0.31.8", "drizzle-kit": "0.31.8",
"tailwindcss": "4.1.18", "tailwindcss": "4.1.18",

978
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 30 KiB

BIN
public/logos/creditas.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB