From bff72d0504d78222a6349b076b44a793b26bc60d Mon Sep 17 00:00:00 2001 From: Felipe Coutinho Date: Mon, 2 Mar 2026 17:20:46 +0000 Subject: [PATCH] chore(cleanup): remove dead code and legacy top-estabelecimentos route --- CHANGELOG.md | 15 +++ .../top-estabelecimentos/layout.tsx | 23 ---- .../top-estabelecimentos/loading.tsx | 58 ---------- app/(dashboard)/top-estabelecimentos/page.tsx | 76 ------------- app/robots.ts | 1 - components/auth/auth-footer.tsx | 17 --- components/auth/login-form.tsx | 1 - components/auth/signup-form.tsx | 1 - components/categorias/category-card.tsx | 103 ------------------ .../dashboard/recent-transactions-widget.tsx | 67 ------------ components/lancamentos/index.ts | 21 ---- components/lancamentos/shared/index.ts | 4 - components/relatorios/index.ts | 13 --- lib/dashboard/fetch-dashboard-data.ts | 16 +-- lib/dashboard/recent-transactions.ts | 78 ------------- 15 files changed, 23 insertions(+), 471 deletions(-) delete mode 100644 app/(dashboard)/top-estabelecimentos/layout.tsx delete mode 100644 app/(dashboard)/top-estabelecimentos/loading.tsx delete mode 100644 app/(dashboard)/top-estabelecimentos/page.tsx delete mode 100644 components/auth/auth-footer.tsx delete mode 100644 components/categorias/category-card.tsx delete mode 100644 components/dashboard/recent-transactions-widget.tsx delete mode 100644 components/lancamentos/index.ts delete mode 100644 components/lancamentos/shared/index.ts delete mode 100644 components/relatorios/index.ts delete mode 100644 lib/dashboard/recent-transactions.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3aedcd7..a834dfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,10 +13,17 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR - Tabela `passkey` no banco de dados para persistência de credenciais WebAuthn vinculadas ao usuário - Nova aba **Passkeys** em `/ajustes` com gerenciamento de credenciais: listar, adicionar, renomear e remover passkeys - Ação de login com passkey na tela de autenticação (`/login`) +- Dashboard: botões rápidos na toolbar de widgets para `Nova receita`, `Nova despesa` e `Nova anotação` com abertura direta dos diálogos correspondentes +- Widget de **Anotações** no dashboard com listagem das anotações ativas, ações discretas de editar e ver detalhes, e atalho para `/anotacoes` ### Alterado - `PasskeysForm` refatorado para melhor experiência com React 19/Next 16: detecção de suporte do navegador, bloqueio de ações simultâneas e atualização da lista sem loader global após operações +- Widget de pagadores no dashboard agora exibe variação percentual em relação ao mês anterior (seta + cor semântica), seguindo o padrão visual dos widgets de categorias +- Dashboard: widgets `Condições de Pagamentos` + `Formas de Pagamento` unificados em um único widget com abas; `Top Estabelecimentos` + `Maiores Gastos do Mês` também unificados em widget com abas +- Relatórios: rota de Top Estabelecimentos consolidada em `/relatorios/estabelecimentos` +- Dashboard: widget `Lançamentos recentes` removido e substituído por `Progresso de metas` com lista de orçamentos do período (gasto, limite configurado e percentual de uso por categoria) +- Dashboard: `fetchDashboardData` deixou de carregar `notificationsSnapshot` (notificações continuam sendo carregadas no layout), reduzindo uma query no carregamento da página inicial ### Corrigido @@ -24,6 +31,14 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR - Listagem de passkeys em Ajustes agora trata `createdAt` ausente sem gerar data inválida na interface - Migração `0017_previous_warstar` tornou-se idempotente para colunas de `preferencias_usuario` com `IF NOT EXISTS`, evitando falha em bancos já migrados +### Removido + +- Código legado não utilizado no dashboard: widget e fetcher de `Lançamentos Recentes` +- Componente legado `CategoryCard` em categorias (substituído pelo layout atual em tabela) +- Componente `AuthFooter` não utilizado na autenticação +- Barrel files sem consumo em `components/relatorios`, `components/lancamentos` e `components/lancamentos/shared` +- Rota legada `/top-estabelecimentos` e arquivos auxiliares (`layout.tsx` e `loading.tsx`) removidos + ## [1.7.5] - 2026-02-28 ### Adicionado diff --git a/app/(dashboard)/top-estabelecimentos/layout.tsx b/app/(dashboard)/top-estabelecimentos/layout.tsx deleted file mode 100644 index c20ca10..0000000 --- a/app/(dashboard)/top-estabelecimentos/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { RiStore2Line } from "@remixicon/react"; -import PageDescription from "@/components/page-description"; - -export const metadata = { - title: "Top Estabelecimentos | OpenMonetis", -}; - -export default function RootLayout({ - children, -}: { - children: React.ReactNode; -}) { - return ( -
- } - title="Top Estabelecimentos" - subtitle="Análise dos locais onde você mais compra e gasta" - /> - {children} -
- ); -} diff --git a/app/(dashboard)/top-estabelecimentos/loading.tsx b/app/(dashboard)/top-estabelecimentos/loading.tsx deleted file mode 100644 index b0fb8e5..0000000 --- a/app/(dashboard)/top-estabelecimentos/loading.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Card, CardContent, CardHeader } from "@/components/ui/card"; -import { Skeleton } from "@/components/ui/skeleton"; - -export default function Loading() { - return ( -
-
-
- - -
- -
- -
- {[1, 2, 3, 4].map((i) => ( - - - - - - ))} -
- -
- - -
- -
-
- - - - - - {[1, 2, 3, 4, 5, 6, 7, 8].map((i) => ( - - ))} - - -
-
- - - - - - {[1, 2, 3, 4, 5].map((i) => ( - - ))} - - -
-
-
- ); -} diff --git a/app/(dashboard)/top-estabelecimentos/page.tsx b/app/(dashboard)/top-estabelecimentos/page.tsx deleted file mode 100644 index deb9c5c..0000000 --- a/app/(dashboard)/top-estabelecimentos/page.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { EstablishmentsList } from "@/components/top-estabelecimentos/establishments-list"; -import { HighlightsCards } from "@/components/top-estabelecimentos/highlights-cards"; -import { PeriodFilterButtons } from "@/components/top-estabelecimentos/period-filter"; -import { SummaryCards } from "@/components/top-estabelecimentos/summary-cards"; -import { TopCategories } from "@/components/top-estabelecimentos/top-categories"; -import { Card } from "@/components/ui/card"; -import { getUser } from "@/lib/auth/server"; -import { - fetchTopEstabelecimentosData, - type PeriodFilter, -} from "@/lib/top-estabelecimentos/fetch-data"; -import { parsePeriodParam } from "@/lib/utils/period"; - -type PageSearchParams = Promise>; - -type PageProps = { - searchParams?: PageSearchParams; -}; - -const getSingleParam = ( - params: Record | undefined, - key: string, -) => { - const value = params?.[key]; - if (!value) return null; - return Array.isArray(value) ? (value[0] ?? null) : value; -}; - -const validatePeriodFilter = (value: string | null): PeriodFilter => { - if (value === "3" || value === "6" || value === "12") { - return value; - } - return "6"; -}; - -export default async function TopEstabelecimentosPage({ - searchParams, -}: PageProps) { - const user = await getUser(); - const resolvedSearchParams = searchParams ? await searchParams : undefined; - const periodoParam = getSingleParam(resolvedSearchParams, "periodo"); - const mesesParam = getSingleParam(resolvedSearchParams, "meses"); - - const { period: currentPeriod } = parsePeriodParam(periodoParam); - const periodFilter = validatePeriodFilter(mesesParam); - - const data = await fetchTopEstabelecimentosData( - user.id, - currentPeriod, - periodFilter, - ); - - return ( -
- - - Selecione o intervalo de meses - - - - - - - - -
-
- -
-
- -
-
-
- ); -} diff --git a/app/robots.ts b/app/robots.ts index 8fcca48..446c333 100644 --- a/app/robots.ts +++ b/app/robots.ts @@ -24,7 +24,6 @@ export default function robots(): MetadataRoute.Robots { "/consultor", "/ajustes", "/relatorios", - "/top-estabelecimentos", "/pre-lancamentos", "/login", "/api/", diff --git a/components/auth/auth-footer.tsx b/components/auth/auth-footer.tsx deleted file mode 100644 index 09cb9d9..0000000 --- a/components/auth/auth-footer.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { FieldDescription } from "@/components/ui/field"; - -export function AuthFooter() { - return ( - - Ao continuar, você concorda com nossos{" "} - - Termos de Serviço - {" "} - e{" "} - - Política de Privacidade - - . - - ); -} diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx index a828dfd..4a2ff0f 100644 --- a/components/auth/login-form.tsx +++ b/components/auth/login-form.tsx @@ -255,7 +255,6 @@ export function LoginForm({ className, ...props }: DivProps) { - {/* */} Voltar para o site diff --git a/components/auth/signup-form.tsx b/components/auth/signup-form.tsx index aeb8f35..1efeb98 100644 --- a/components/auth/signup-form.tsx +++ b/components/auth/signup-form.tsx @@ -281,7 +281,6 @@ export function SignupForm({ className, ...props }: DivProps) { - {/* */} Voltar para o site diff --git a/components/categorias/category-card.tsx b/components/categorias/category-card.tsx deleted file mode 100644 index f129a5d..0000000 --- a/components/categorias/category-card.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; - -import { - RiDeleteBin5Line, - RiFileList2Line, - RiPencilLine, -} from "@remixicon/react"; -import Link from "next/link"; -import { Card, CardContent, CardFooter } from "@/components/ui/card"; -import { cn } from "@/lib/utils/ui"; -import { CategoryIconBadge } from "./category-icon-badge"; -import type { Category } from "./types"; - -interface CategoryCardProps { - category: Category; - colorIndex: number; - onEdit: (category: Category) => void; - onRemove: (category: Category) => void; -} - -export function CategoryCard({ - category, - colorIndex, - onEdit, - onRemove, -}: CategoryCardProps) { - const categoriasProtegidas = [ - "Transferência interna", - "Saldo inicial", - "Pagamentos", - ]; - const isProtegida = categoriasProtegidas.includes(category.name); - - const actions = [ - { - label: "editar", - icon: , - onClick: () => onEdit(category), - variant: "default" as const, - disabled: isProtegida, - }, - { - label: "detalhes", - icon: , - href: `/categorias/${category.id}`, - variant: "default" as const, - disabled: false, - }, - { - label: "remover", - icon: , - onClick: () => onRemove(category), - variant: "destructive" as const, - disabled: isProtegida, - }, - ].filter((action) => !action.disabled); - - return ( - - -
- -

{category.name}

-
-
- - - {actions.map(({ label, icon, onClick, href, variant }) => { - const className = cn( - "flex items-center gap-1 font-medium transition-opacity hover:opacity-80", - variant === "destructive" ? "text-destructive" : "text-primary", - ); - - if (href) { - return ( - - {icon} - {label} - - ); - } - - return ( - - ); - })} - -
- ); -} diff --git a/components/dashboard/recent-transactions-widget.tsx b/components/dashboard/recent-transactions-widget.tsx deleted file mode 100644 index 083e256..0000000 --- a/components/dashboard/recent-transactions-widget.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { RiExchangeLine } from "@remixicon/react"; -import { EstabelecimentoLogo } from "@/components/lancamentos/shared/estabelecimento-logo"; -import MoneyValues from "@/components/money-values"; -import type { RecentTransactionsData } from "@/lib/dashboard/recent-transactions"; -import { WidgetEmptyState } from "../widget-empty-state"; - -type RecentTransactionsWidgetProps = { - data: RecentTransactionsData; -}; - -const formatTransactionDate = (date: Date | string) => { - const d = date instanceof Date ? date : new Date(date); - const formatter = new Intl.DateTimeFormat("pt-BR", { - weekday: "short", - day: "2-digit", - month: "short", - timeZone: "UTC", - }); - - const formatted = formatter.format(d); - // Capitaliza a primeira letra do dia da semana - return formatted.charAt(0).toUpperCase() + formatted.slice(1); -}; - -export function RecentTransactionsWidget({ - data, -}: RecentTransactionsWidgetProps) { - return ( -
- {data.transactions.length === 0 ? ( - } - title="Nenhum lançamento encontrado" - description="Quando houver despesas registradas, elas aparecerão aqui." - /> - ) : ( -
    - {data.transactions.map((transaction) => { - return ( -
  • -
    - - -
    -

    - {transaction.name} -

    -

    - {formatTransactionDate(transaction.purchaseDate)} -

    -
    -
    - -
    - -
    -
  • - ); - })} -
- )} -
- ); -} diff --git a/components/lancamentos/index.ts b/components/lancamentos/index.ts deleted file mode 100644 index 822a933..0000000 --- a/components/lancamentos/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Main page component - -export { default as AnticipateInstallmentsDialog } from "./dialogs/anticipate-installments-dialog/anticipate-installments-dialog"; -export { default as BulkActionDialog } from "./dialogs/bulk-action-dialog"; -export { default as LancamentoDetailsDialog } from "./dialogs/lancamento-details-dialog"; - -// Main dialogs -export { default as LancamentoDialog } from "./dialogs/lancamento-dialog/lancamento-dialog"; -export type * from "./dialogs/lancamento-dialog/lancamento-dialog-types"; -export { default as MassAddDialog } from "./dialogs/mass-add-dialog"; -export { default as LancamentosPage } from "./page/lancamentos-page"; -export * from "./select-items"; -export { default as AnticipationCard } from "./shared/anticipation-card"; -// Shared components -export { default as EstabelecimentoInput } from "./shared/estabelecimento-input"; -export { default as InstallmentTimeline } from "./shared/installment-timeline"; -export { default as LancamentosFilters } from "./table/lancamentos-filters"; -// Table components -export { default as LancamentosTable } from "./table/lancamentos-table"; -// Types and utilities -export type * from "./types"; diff --git a/components/lancamentos/shared/index.ts b/components/lancamentos/shared/index.ts deleted file mode 100644 index 199b606..0000000 --- a/components/lancamentos/shared/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { AnticipationCard } from "./anticipation-card"; -export { EstabelecimentoInput } from "./estabelecimento-input"; -export { EstabelecimentoLogo } from "./estabelecimento-logo"; -export { InstallmentTimeline } from "./installment-timeline"; diff --git a/components/relatorios/index.ts b/components/relatorios/index.ts deleted file mode 100644 index 42f6a4f..0000000 --- a/components/relatorios/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -export { CategoryCell } from "./category-cell"; -export { CategoryReportCards } from "./category-report-cards"; -export { CategoryReportChart } from "./category-report-chart"; -export { CategoryReportExport } from "./category-report-export"; -export { CategoryReportFilters } from "./category-report-filters"; -export { CategoryReportPage } from "./category-report-page"; -export { CategoryReportTable } from "./category-report-table"; -export { CategoryTable } from "./category-table"; -export type { - CategoryOption, - CategoryReportFiltersProps, - FilterState, -} from "./types"; diff --git a/lib/dashboard/fetch-dashboard-data.ts b/lib/dashboard/fetch-dashboard-data.ts index c66fbb0..989a535 100644 --- a/lib/dashboard/fetch-dashboard-data.ts +++ b/lib/dashboard/fetch-dashboard-data.ts @@ -6,16 +6,16 @@ import { fetchIncomeByCategory } from "./categories/income-by-category"; import { fetchInstallmentExpenses } from "./expenses/installment-expenses"; import { fetchRecurringExpenses } from "./expenses/recurring-expenses"; import { fetchTopExpenses } from "./expenses/top-expenses"; +import { fetchGoalsProgressData } from "./goals-progress"; import { fetchIncomeExpenseBalance } from "./income-expense-balance"; import { fetchDashboardInvoices } from "./invoices"; import { fetchDashboardCardMetrics } from "./metrics"; -import { fetchDashboardNotifications } from "./notifications"; +import { fetchDashboardNotes } from "./notes"; import { fetchDashboardPagadores } from "./pagadores"; import { fetchPaymentConditions } from "./payments/payment-conditions"; import { fetchPaymentMethods } from "./payments/payment-methods"; import { fetchPaymentStatus } from "./payments/payment-status"; import { fetchPurchasesByCategory } from "./purchases-by-category"; -import { fetchRecentTransactions } from "./recent-transactions"; import { fetchTopEstablishments } from "./top-establishments"; async function fetchDashboardDataInternal(userId: string, period: string) { @@ -24,11 +24,11 @@ async function fetchDashboardDataInternal(userId: string, period: string) { accountsSnapshot, invoicesSnapshot, boletosSnapshot, - notificationsSnapshot, + goalsProgressData, paymentStatusData, incomeExpenseBalanceData, pagadoresSnapshot, - recentTransactionsData, + notesData, paymentConditionsData, paymentMethodsData, recurringExpensesData, @@ -44,11 +44,11 @@ async function fetchDashboardDataInternal(userId: string, period: string) { fetchDashboardAccounts(userId), fetchDashboardInvoices(userId, period), fetchDashboardBoletos(userId, period), - fetchDashboardNotifications(userId, period), + fetchGoalsProgressData(userId, period), fetchPaymentStatus(userId, period), fetchIncomeExpenseBalance(userId, period), fetchDashboardPagadores(userId, period), - fetchRecentTransactions(userId, period), + fetchDashboardNotes(userId), fetchPaymentConditions(userId, period), fetchPaymentMethods(userId, period), fetchRecurringExpenses(userId, period), @@ -66,11 +66,11 @@ async function fetchDashboardDataInternal(userId: string, period: string) { accountsSnapshot, invoicesSnapshot, boletosSnapshot, - notificationsSnapshot, + goalsProgressData, paymentStatusData, incomeExpenseBalanceData, pagadoresSnapshot, - recentTransactionsData, + notesData, paymentConditionsData, paymentMethodsData, recurringExpensesData, diff --git a/lib/dashboard/recent-transactions.ts b/lib/dashboard/recent-transactions.ts deleted file mode 100644 index 29bb8df..0000000 --- a/lib/dashboard/recent-transactions.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { and, desc, eq, isNull, or, sql } from "drizzle-orm"; -import { cartoes, contas, lancamentos } from "@/db/schema"; -import { - ACCOUNT_AUTO_INVOICE_NOTE_PREFIX, - INITIAL_BALANCE_NOTE, -} from "@/lib/accounts/constants"; -import { toNumber } from "@/lib/dashboard/common"; -import { db } from "@/lib/db"; -import { getAdminPagadorId } from "@/lib/pagadores/get-admin-id"; - -export type RecentTransaction = { - id: string; - name: string; - amount: number; - purchaseDate: Date; - cardLogo: string | null; - accountLogo: string | null; -}; - -export type RecentTransactionsData = { - transactions: RecentTransaction[]; -}; - -export async function fetchRecentTransactions( - userId: string, - period: string, -): Promise { - const adminPagadorId = await getAdminPagadorId(userId); - if (!adminPagadorId) { - return { transactions: [] }; - } - - const results = await db - .select({ - id: lancamentos.id, - name: lancamentos.name, - amount: lancamentos.amount, - purchaseDate: lancamentos.purchaseDate, - cardLogo: cartoes.logo, - accountLogo: contas.logo, - note: lancamentos.note, - }) - .from(lancamentos) - .leftJoin(cartoes, eq(lancamentos.cartaoId, cartoes.id)) - .leftJoin(contas, eq(lancamentos.contaId, contas.id)) - .where( - and( - eq(lancamentos.userId, userId), - eq(lancamentos.period, period), - eq(lancamentos.transactionType, "Despesa"), - eq(lancamentos.pagadorId, adminPagadorId), - or( - isNull(lancamentos.note), - and( - sql`${lancamentos.note} != ${INITIAL_BALANCE_NOTE}`, - sql`${lancamentos.note} NOT LIKE ${`${ACCOUNT_AUTO_INVOICE_NOTE_PREFIX}%`}`, - ), - ), - ), - ) - .orderBy(desc(lancamentos.purchaseDate), desc(lancamentos.createdAt)) - .limit(5); - - const transactions = results.map((row): RecentTransaction => { - return { - id: row.id, - name: row.name, - amount: Math.abs(toNumber(row.amount)), - purchaseDate: row.purchaseDate, - cardLogo: row.cardLogo, - accountLogo: row.accountLogo, - }; - }); - - return { - transactions, - }; -}