From 89765d4373b820a3e7c8e4fa40479dd2673558b0 Mon Sep 17 00:00:00 2001 From: Felipe Coutinho Date: Tue, 9 Dec 2025 17:26:08 +0000 Subject: [PATCH] chore(plan): remover arquivo PLAN.md --- PLAN.md | 806 -------------------------------------------------------- 1 file changed, 806 deletions(-) delete mode 100644 PLAN.md diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index fe3c56e..0000000 --- a/PLAN.md +++ /dev/null @@ -1,806 +0,0 @@ ---- - -📊 Análise e Sugestões para OpenSheets - -🎯 Resumo Executivo - -O OpenSheets é uma aplicação financeira bem estruturada com 184 componentes, 15 widgets de dashboard, e um design system coeso baseado em cores terracota. A análise identificou pontos fortes significativos e -oportunidades estratégicas para melhorias. - ---- - -✅ Pontos Fortes Identificados - -Arquitetura - -- ✨ Server-first com Next.js 15 App Router -- 🚀 Fetching paralelo otimizado (18+ requests simultâneos) -- 🔒 Modo privacidade bem implementado -- 🎨 Design system consistente (OKLCH color space) - -Componentes - -- 📦 40+ componentes shadcn/ui bem organizados -- ♻️ Alta reutilização de componentes -- 🎭 Sistema de skeletons completo -- 🌙 Suporte total a tema dark/light - ---- - -🚀 Sugestões de Novas Features - -1. Análise Preditiva e Forecasting 🔮 - -Prioridade: Alta | Complexidade: Média - -// Nova página: app/(dashboard)/previsoes/ - -Features: - -- Previsão de gastos mensais baseada em histórico -- Alerta de contas a vencer na próxima semana -- Projeção de saldo futuro considerando despesas recorrentes -- Machine learning simples para detectar padrões de gasto - -Componentes sugeridos: - -- ForecastChart - Gráfico de linha com projeções -- UpcomingBillsWidget - Widget de contas a vencer -- SavingsGoalTracker - Acompanhamento de metas de economia - ---- - -2. Metas Financeiras (Goals) 🎯 - -Prioridade: Alta | Complexidade: Média - -// Nova tabela no schema: -export const metas = pgTable("metas", { -id: uuid("id").primaryKey().defaultRandom(), -userId: uuid("user_id").notNull().references(() => user.id), -nome: text("nome").notNull(), -valorAlvo: numeric("valor_alvo", { precision: 12, scale: 2 }).notNull(), -valorAtual: numeric("valor_atual", { precision: 12, scale: 2 }).default("0"), -prazo: timestamp("prazo"), -categoriaId: uuid("categoria_id").references(() => categorias.id), -tipo: text("tipo").notNull(), // 'economia', 'quitacao_divida', 'compra' -}); - -Features: - -- Criar metas de economia (ex: "Viagem para Europa - R$ 10.000") -- Vincular transações às metas -- Dashboard de progresso visual -- Sugestões automáticas de quanto economizar mensalmente - ---- - -3. Relatórios Exportáveis 📄 - -Prioridade: Média | Complexidade: Baixa - -Formatos: - -- PDF com gráficos (usando jsPDF + html2canvas) -- Excel/CSV detalhado (usando xlsx) -- JSON para backup completo - -Tipos de relatório: - -- Extrato mensal consolidado -- Análise de gastos por categoria -- Comparativo período a período -- Resumo anual (imposto de renda) - -Código sugerido: -// lib/reports/generate-pdf-report.ts -import { jsPDF } from 'jspdf'; - -export async function generateMonthlyReport(userId: string, period: string) { -const data = await fetchMonthlyData(userId, period); -const doc = new jsPDF(); - - // Adicionar logo, gráficos, tabelas - doc.save(`relatorio-${period}.pdf`); - -} - ---- - -4. Modo Comparativo de Períodos 📊 - -Prioridade: Média | Complexidade: Baixa - -UI sugerida: - - -Features: - -- Comparar dois meses lado a lado -- Ver variação percentual por categoria -- Identificar onde economizou/gastou mais -- Gráficos de delta de gastos - ---- - -5. Tags/Etiquetas para Transações 🏷️ - -Prioridade: Baixa | Complexidade: Baixa - -export const tags = pgTable("tags", { -id: uuid("id").primaryKey(), -userId: uuid("user_id").notNull(), -nome: text("nome").notNull(), -cor: text("cor").notNull(), // hex color -}); - -export const lancamento_tags = pgTable("lancamento_tags", { -lancamentoId: uuid("lancamento_id").references(() => lancamentos.id), -tagId: uuid("tag_id").references(() => tags.id), -}); - -Use cases: - -- Tag "Trabalho" para despesas dedutíveis -- Tag "Emergência" para gastos não planejados -- Tag "Investimento" para rastrear aplicações -- Filtrar dashboard por tags - ---- - -6. Anexos e Comprovantes 📎 - -Prioridade: Média | Complexidade: Alta - -Implementação: - -- Upload de imagens/PDFs de notas fiscais -- Armazenamento em storage (S3-compatible ou local) -- OCR para extrair dados automaticamente (Tesseract.js) -- Galeria de comprovantes por transação - -export const anexos = pgTable("anexos", { -id: uuid("id").primaryKey(), -lancamentoId: uuid("lancamento_id").references(() => lancamentos.id), -arquivo: text("arquivo_url").notNull(), -tipo: text("tipo").notNull(), // 'imagem', 'pdf' -tamanho: integer("tamanho_bytes"), -}); - ---- - -7. Investimentos Tracking 💹 - -Prioridade: Baixa | Complexidade: Alta - -Escopo: - -- Registrar compra/venda de ações, FIIs, criptomoedas -- Importação de extratos de corretoras -- Gráfico de evolução patrimonial -- Cálculo de rentabilidade - -Nova seção no sidebar: -{ -title: "Investimentos", -icon: RiLineChartLine, -href: "/investimentos", -} - ---- - -8. Gamificação e Conquistas 🏆 - -Prioridade: Baixa | Complexidade: Média - -Conquistas sugeridas: - -- "Primeiro Mês no Azul" - Receitas > Despesas -- "Economista" - Gastou menos que orçamento 3 meses seguidos -- "Organizado" - Todas transações categorizadas -- "Disciplinado" - 30 dias sem gastos em categoria específica - -Implementação: -export const conquistas = pgTable("conquistas", { -id: uuid("id").primaryKey(), -codigo: text("codigo").notNull(), // 'primeiro_mes_azul' -nome: text("nome").notNull(), -descricao: text("descricao"), -icone: text("icone"), -}); - -export const usuario_conquistas = pgTable("usuario_conquistas", { -userId: uuid("user_id").references(() => user.id), -conquistaId: uuid("conquista_id").references(() => conquistas.id), -desbloqueadaEm: timestamp("desbloqueada_em").defaultNow(), -}); - ---- - -9. Notificações e Lembretes 🔔 - -Prioridade: Alta | Complexidade: Média - -Tipos de notificação: - -- Lembrete de fatura vencendo em 3 dias -- Orçamento atingindo 80% do limite -- Despesa incomum detectada (> 2x média da categoria) -- Cobrança recorrente não registrada este mês - -Implementação: - -- Cron job diário verificando condições -- Sistema de notificações in-app -- Opcional: Email notifications (Resend/Nodemailer) -- Web Push Notifications (service worker) - ---- - -10. Importação Automática de Extratos 🔄 - -Prioridade: Alta | Complexidade: Alta - -Métodos: - -1. Upload de OFX/CSV - Parser para formatos bancários -2. API Open Banking - Integração com Pluggy/Belvo -3. Email parsing - Ler extratos enviados por email -4. OCR de PDFs - Extrair dados de PDFs bancários - -Fluxo sugerido: -// app/(dashboard)/importacao/page.tsx - -1. Selecionar conta bancária de destino -2. Upload de arquivo ou conectar via API -3. Pré-visualização das transações -4. Matching automático com categorias (ML) -5. Revisão e confirmação -6. Importação em lote - ---- - -🎨 Melhorias de UI/UX - -1. Redesign do Diálogo de Transação 💳 - -Problema: Diálogo com muitos campos condicionais pode confundir usuários - -Solução: -// Wizard multi-step com progresso visual - - -{/_ Nome, valor, data _/} - - -{/_ Método, conta, condição _/} - - -{/_ Categoria, pagador, notas _/} - - - -Indicador de progresso: - -
- 1}>1 - 2}>2 - 3 -
- ---- - -2. Tabela Responsiva com Card View 📱 - -Problema: Tabelas complexas em mobile têm scroll horizontal - -Solução: -// components/lancamentos/table/lancamentos-responsive-view.tsx -export function LancamentosResponsiveView() { -const isMobile = useIsMobile(); - - if (isMobile) { - return ; - } - - return ; - -} - -// Card view para mobile -function LancamentoCard({ lancamento }) { -return ( - -
-
-

{lancamento.nome}

-

-{lancamento.categoria} -

-
- -
-
-{lancamento.condicao} -{lancamento.formaPagamento} -
-
-); -} - ---- - -3. Dashboard Personalizável 🔧 - -Problema: Todos veem os mesmos 15 widgets - -Solução: -// lib/dashboard/widgets/user-widget-preferences.ts -export const widgetPreferences = pgTable("widget_preferences", { -userId: uuid("user_id").references(() => user.id), -widgetId: text("widget_id").notNull(), -ordem: integer("ordem").notNull(), -visivel: boolean("visivel").default(true), -tamanho: text("tamanho"), // 'small', 'medium', 'large' -}); - -// Drag-and-drop com dnd-kit -import { DndContext, closestCenter } from '@dnd-kit/core'; - - - - {widgets.map(widget => ( - - ))} - - - -Features: - -- Reordenar widgets via drag-and-drop -- Ocultar/mostrar widgets -- Redimensionar widgets (grid responsivo) -- Salvar preferências no banco - ---- - -4. Busca Global (Command Palette) ⌘K - -Problema: Navegar entre muitas páginas é lento - -Solução: -// components/command-palette.tsx -import { RiSearchLine } from '@remixicon/react'; - -export function CommandPalette() { -const [open, setOpen] = useState(false); - - useEffect(() => { - const down = (e: KeyboardEvent) => { - if (e.key === 'k' && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - setOpen(true); - } - }; - document.addEventListener('keydown', down); - return () => document.removeEventListener('keydown', down); - }, []); - - return ( - - - - - - - Nova Transação - - - - {recentTransactions.map(t => ( - {t.nome} - ))} - - - router.push('/dashboard')}> - Dashboard - - - - - ); - -} - -Ações rápidas: - -- Nova transação (Ctrl+K → "nova") -- Ver conta específica -- Buscar transação por nome/valor -- Navegar para qualquer página -- Executar ações (marcar como pago, editar, excluir) - ---- - -5. Onboarding Interativo 🎓 - -Problema: Novos usuários podem se sentir perdidos - -Solução: -// components/onboarding/onboarding-tour.tsx -import { Joyride } from 'react-joyride'; - -const steps = [ -{ -target: '.sidebar-nav', -content: 'Aqui você navega entre as diferentes seções', -}, -{ -target: '[data-tour="new-transaction"]', -content: 'Clique aqui para adicionar sua primeira transação', -}, -{ -target: '.month-picker', -content: 'Use isto para navegar entre meses', -}, -]; - -export function OnboardingTour() { -const { tourCompleted } = useUserPreferences(); - - return ( - - ); - -} - -Checklist inicial: - -- Criar primeira conta bancária -- Adicionar um cartão de crédito -- Registrar primeira transação -- Definir orçamento mensal -- Explorar dashboard - ---- - -6. Modo Compacto / Densidade Ajustável 📏 - -Problema: Algumas páginas têm muito espaço em branco - -Solução: -// Adicionar ao contexto de preferências -export const densitySettings = { -comfortable: { gap: 6, padding: 6, fontSize: 'text-base' }, -normal: { gap: 4, padding: 4, fontSize: 'text-sm' }, -compact: { gap: 2, padding: 2, fontSize: 'text-xs' }, -}; - -// Aplicar dinamicamente - -
- -Controle: -// Em ajustes/page.tsx - - ---- - -7. Indicadores Visuais de Status 🚦 - -Problema: Difícil ver rapidamente status de contas/faturas - -Solução: -// components/status-indicator.tsx -export function StatusIndicator({ status }: { status: string }) { -const config = { -'em-dia': { color: 'green', icon: RiCheckLine, label: 'Em dia' }, -'vencendo': { color: 'yellow', icon: RiTimeLine, label: 'Vencendo' }, -'atrasado': { color: 'red', icon: RiAlertLine, label: 'Atrasado' }, -}; - - const { color, icon: Icon, label } = config[status]; - - return ( - - - {label} - - ); - -} - -Aplicar em: - -- Cards de faturas (verde = paga, amarelo = próxima, vermelho = vencida) -- Boletos (status de pagamento) -- Orçamentos (verde = dentro, amarelo = 80%, vermelho = estourou) - ---- - -8. Gráficos Interativos com Drill-Down 📊 - -Problema: Gráficos mostram dados mas não permitem explorar - -Solução: -// components/dashboard/interactive-category-chart.tsx - - { -// Ao clicar em fatia, abrir modal com transações daquela categoria -showCategoryDetails(data.categoryId); -}} -/> - - -// Modal de drill-down -function CategoryDetailsModal({ categoryId, period }) { -const transactions = useCategoryTransactions(categoryId, period); - - return ( - - - Detalhes - {categoryName} - - - - - - ); - -} - ---- - -9. Tema de Cores Personalizável 🎨 - -Problema: Apenas uma cor primária (terracota) - -Solução: -// lib/theme/color-themes.ts -export const colorThemes = { -terracotta: { primary: 'oklch(69.18% 0.18855 38.353)' }, -ocean: { primary: 'oklch(69.18% 0.18855 220)' }, -forest: { primary: 'oklch(69.18% 0.18855 140)' }, -sunset: { primary: 'oklch(69.18% 0.18855 25)' }, -lavender: { primary: 'oklch(69.18% 0.18855 280)' }, -}; - -// Em ajustes/page.tsx -export function ThemeColorPicker() { -const { colorTheme, setColorTheme } = useTheme(); - - return ( -
- {Object.entries(colorThemes).map(([name, colors]) => ( -
- ); - -} - ---- - -10. Breadcrumbs e Page Headers Consistentes 🗺️ - -Problema: Inconsistência em headers entre páginas - -Solução: -// components/page-header.tsx -interface PageHeaderProps { -title: string; -description?: string; -breadcrumbs?: { label: string; href?: string }[]; -actions?: React.ReactNode; -} - -export function PageHeader({ -title, -description, -breadcrumbs, -actions -}: PageHeaderProps) { -return ( -
-{breadcrumbs && ( - -{breadcrumbs.map((crumb, i) => ( - -{crumb.href ? ( - -{crumb.label} - -) : ( -{crumb.label} -)} - -))} - -)} -
-
-

{title}

-{description && ( -

{description}

-)} -
-{actions &&
{actions}
} -
-
-); -} - -// Uso: -Nova Transação -} -/> - ---- - -🔧 Melhorias Técnicas - -1. Error Boundary Global - -// app/error.tsx -'use client'; - -export default function Error({ -error, -reset, -}: { -error: Error & { digest?: string }; -reset: () => void; -}) { -return ( -
-

Algo deu errado!

- -
-); -} - -2. Analytics e Telemetria - -// lib/analytics.ts -export function trackEvent(event: string, properties?: Record) { -// Posthog, Mixpanel, ou custom -console.log('[Analytics]', event, properties); -} - -// Uso: -trackEvent('transaction_created', { type: 'despesa', amount: 100 }); - -3. Rate Limiting para Actions - -// lib/rate-limit.ts -import { Ratelimit } from '@upstash/ratelimit'; - -const ratelimit = new Ratelimit({ -redis: Redis.fromEnv(), -limiter: Ratelimit.slidingWindow(10, '10 s'), -}); - -export async function checkRateLimit(userId: string) { -const { success } = await ratelimit.limit(userId); -if (!success) throw new Error('Rate limit exceeded'); -} - ---- - -📊 Priorização Sugerida - -🔥 Fase 1 - Quick Wins (1-2 semanas) - -1. ✅ Breadcrumbs e Page Headers consistentes -2. ✅ Command Palette (⌘K) -3. ✅ Indicadores visuais de status -4. ✅ Modo card para tabelas em mobile -5. ✅ Relatórios PDF básicos - -🚀 Fase 2 - Value Boost (1 mês) - -1. 🎯 Metas Financeiras -2. 🔮 Análise Preditiva -3. 🔔 Sistema de Notificações -4. 📊 Gráficos interativos com drill-down -5. 🎓 Onboarding interativo - -💎 Fase 3 - Diferenciais (2-3 meses) - -1. 🔄 Importação automática de extratos (OFX/CSV) -2. 📎 Anexos e comprovantes com OCR -3. 🎨 Temas personalizáveis -4. 🏆 Gamificação e conquistas -5. 💹 Tracking de investimentos - ---- - -🎯 Métricas de Sucesso - -Para medir o impacto das melhorias: - -1. Engajamento: - - - - Tempo médio na aplicação - - Frequência de uso (DAU/MAU) - - Transações criadas por usuário/mês - -2. Usabilidade: - - - - Taxa de conclusão de onboarding - - Tempo para criar primeira transação - - Taxa de erro em formulários - -3. Performance: - - - - LCP (Largest Contentful Paint) < 2.5s - - FID (First Input Delay) < 100ms - - CLS (Cumulative Layout Shift) < 0.1 - -4. Adoção de Features: - - - - % de usuários usando metas - - % de usuários que personalizam dashboard - - Taxa de uso do command palette - ---- - -📝 Conclusão - -O OpenSheets já possui uma base sólida com excelente arquitetura e design. As sugestões focam em: - -1. Melhorar a experiência mobile (responsividade avançada) -2. Adicionar inteligência (previsões, notificações, insights) -3. Aumentar a eficiência (command palette, importação automática) -4. Personalização (temas, dashboard, densidade) -5. Gamificação (metas, conquistas) para engajamento - -Próximos Passos Recomendados: - -1. Validar com usuários quais features têm maior demanda -2. Implementar quick wins da Fase 1 -3. A/B testing de novos designs -4. Iteração baseada em feedback