feat: topbar de navegação como experimento de UI (v1.7.0)

- Substitui header fixo por topbar com backdrop blur e navegação agrupada em 5 seções
- Adiciona FerramentasDropdown consolidando calculadora e modo privacidade
- NotificationBell expandida com orçamentos e pré-lançamentos
- Remove logout-button, header-dashboard e privacy-mode-toggle como componentes separados
- Logo refatorado com variante compact; topbar com links em lowercase
- Adiciona dependência radix-ui ^1.4.3
- Atualiza CHANGELOG para v1.7.0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-02-24 15:43:14 +00:00
parent af7dd6f737
commit 1b90be6b54
54 changed files with 1492 additions and 787 deletions

View File

@@ -1,9 +1,9 @@
import { and, eq, inArray, isNull, or, sql } from "drizzle-orm";
import { categorias, lancamentos, pagadores } from "@/db/schema";
import { categorias, lancamentos } from "@/db/schema";
import { ACCOUNT_AUTO_INVOICE_NOTE_PREFIX } from "@/lib/accounts/constants";
import { toNumber } from "@/lib/dashboard/common";
import { db } from "@/lib/db";
import { PAGADOR_ROLE_ADMIN } from "@/lib/pagadores/constants";
import { getAdminPagadorId } from "@/lib/pagadores/get-admin-id";
import type {
CategoryReportData,
CategoryReportFilters,
@@ -28,11 +28,16 @@ export async function fetchCategoryReport(
// Generate all periods in the range
const periods = generatePeriodRange(startPeriod, endPeriod);
const adminPagadorId = await getAdminPagadorId(userId);
if (!adminPagadorId) {
return { categories: [], periods, totals: new Map(), grandTotal: 0 };
}
// Build WHERE conditions
const whereConditions = [
eq(lancamentos.userId, userId),
eq(lancamentos.pagadorId, adminPagadorId),
inArray(lancamentos.period, periods),
eq(pagadores.role, PAGADOR_ROLE_ADMIN),
or(eq(categorias.type, "despesa"), eq(categorias.type, "receita")),
or(
isNull(lancamentos.note),
@@ -56,7 +61,6 @@ export async function fetchCategoryReport(
total: sql<number>`coalesce(sum(${lancamentos.amount}), 0)`,
})
.from(lancamentos)
.innerJoin(pagadores, eq(lancamentos.pagadorId, pagadores.id))
.innerJoin(categorias, eq(lancamentos.categoriaId, categorias.id))
.where(and(...whereConditions))
.groupBy(