refactor(sidebar): reorganizar navegação e aplicar formatação Biome

- Simplifica estrutura da sidebar combinando seções "Visão Geral" e "Gestão Financeira"
- Renomeia itens de relatórios para maior clareza ("Tendências", "Uso de Cartões")
- Aplica correções de formatação do Biome (ordenação de imports, quebras de linha)
- Remove código comentado não utilizado
- Adiciona migração 0014 do Drizzle

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Felipe Coutinho
2026-01-29 13:16:39 +00:00
parent 120da3659b
commit df1d149e4a
43 changed files with 4446 additions and 2515 deletions

View File

@@ -1,7 +1,7 @@
"use client";
import { RiCalendarCheckLine, RiLoader4Line } from "@remixicon/react";
import { useEffect, useState } from "react";
import { useCallback, useEffect, useState } from "react";
import { toast } from "sonner";
import { getInstallmentAnticipationsAction } from "@/app/(dashboard)/lancamentos/anticipation-actions";
import {
@@ -52,14 +52,8 @@ export function AnticipationHistoryDialog({
onOpenChange,
);
// Buscar antecipações ao abrir o dialog
useEffect(() => {
if (dialogOpen) {
loadAnticipations();
}
}, [dialogOpen, loadAnticipations]);
const loadAnticipations = async () => {
// Define loadAnticipations before it's used in useEffect
const loadAnticipations = useCallback(async () => {
setIsLoading(true);
try {
@@ -80,7 +74,14 @@ export function AnticipationHistoryDialog({
} finally {
setIsLoading(false);
}
};
}, [seriesId]);
// Buscar antecipações ao abrir o dialog
useEffect(() => {
if (dialogOpen) {
loadAnticipations();
}
}, [dialogOpen, loadAnticipations]);
const handleCanceled = () => {
// Recarregar lista após cancelamento

View File

@@ -24,7 +24,6 @@ import {
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils/ui";
import type { InboxItem } from "./types";
interface InboxCardProps {
@@ -41,7 +40,6 @@ export function InboxCard({
onViewDetails,
}: InboxCardProps) {
const amount = item.parsedAmount ? parseFloat(item.parsedAmount) : null;
const isReceita = item.parsedTransactionType === "Receita";
// O timestamp vem do app Android em horário local mas salvo como UTC
// Precisamos interpretar o valor UTC como se fosse horário de Brasília
@@ -78,16 +76,7 @@ export function InboxCard({
</span>
</CardTitle>
{amount !== null && (
<MoneyValues
amount={isReceita ? amount : -amount}
showPositiveSign={isReceita}
className={cn(
"text-sm",
isReceita
? "text-green-600 dark:text-green-400"
: "text-foreground",
)}
/>
<MoneyValues amount={amount} className="text-sm" />
)}
</div>

View File

@@ -3,7 +3,6 @@
import { format } from "date-fns";
import { ptBR } from "date-fns/locale";
import MoneyValues from "@/components/money-values";
import { TypeBadge } from "@/components/type-badge";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
@@ -15,7 +14,6 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator";
import { cn } from "@/lib/utils/ui";
import type { InboxItem } from "./types";
interface InboxDetailsDialogProps {
@@ -32,7 +30,6 @@ export function InboxDetailsDialog({
if (!item) return null;
const amount = item.parsedAmount ? parseFloat(item.parsedAmount) : null;
const isReceita = item.parsedTransactionType === "Receita";
return (
<Dialog open={open} onOpenChange={onOpenChange}>
@@ -86,30 +83,11 @@ export function InboxDetailsDialog({
<div className="flex justify-between items-center">
<span className="text-muted-foreground">Valor</span>
{amount !== null ? (
<MoneyValues
amount={isReceita ? amount : -amount}
showPositiveSign={isReceita}
className={cn(
"text-sm",
isReceita
? "text-green-600 dark:text-green-400"
: "text-foreground",
)}
/>
<MoneyValues amount={amount} className="text-sm" />
) : (
<span className="text-muted-foreground">Não extraído</span>
)}
</div>
<div className="flex justify-between items-center">
<span className="text-muted-foreground">Tipo</span>
{item.parsedTransactionType ? (
<TypeBadge type={item.parsedTransactionType} />
) : (
<span className="text-muted-foreground">
Não identificado
</span>
)}
</div>
</div>
</div>

View File

@@ -139,9 +139,6 @@ export function InboxPage({
? String(Math.abs(Number(itemToProcess.parsedAmount)))
: null;
const defaultTransactionType =
itemToProcess?.parsedTransactionType === "Receita" ? "Receita" : "Despesa";
return (
<>
<div className="flex w-full flex-col gap-6">
@@ -182,7 +179,6 @@ export function InboxPage({
defaultPurchaseDate={defaultPurchaseDate}
defaultName={defaultName}
defaultAmount={defaultAmount}
defaultTransactionType={defaultTransactionType}
forceShowTransactionType
onSuccess={handleLancamentoSuccess}
/>

View File

@@ -1,5 +1,3 @@
import type { SelectOption as LancamentoSelectOption } from "@/components/lancamentos/types";
export interface InboxItem {
@@ -11,7 +9,6 @@ export interface InboxItem {
notificationTimestamp: Date;
parsedName: string | null;
parsedAmount: string | null;
parsedTransactionType: string | null;
status: string;
lancamentoId: string | null;
processedAt: Date | null;
@@ -25,7 +22,6 @@ export interface ProcessInboxInput {
name: string;
amount: number;
purchaseDate: string;
transactionType: "Despesa" | "Receita";
condition: string;
paymentMethod: string;
categoriaId: string;

View File

@@ -53,7 +53,7 @@ export function AppSidebar({
<SidebarMenuItem>
<SidebarMenuButton
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-4 justify-center hover:scale-105 transition-all duration-200"
>
<a href="/dashboard">
<LogoContent />

View File

@@ -85,18 +85,13 @@ export function createSidebarNavData(
return {
navMain: [
{
title: "Visão Geral",
title: "Gestão Financeira",
items: [
{
title: "Dashboard",
url: "/dashboard",
icon: RiDashboardLine,
},
],
},
{
title: "Gestão Financeira",
items: [
{
title: "Lançamentos",
url: "/lancamentos",
@@ -164,11 +159,6 @@ export function createSidebarNavData(
url: "/categorias",
icon: RiPriceTag3Line,
},
],
},
{
title: "Análise e Anotações",
items: [
{
title: "Anotações",
url: "/anotacoes",
@@ -182,23 +172,23 @@ export function createSidebarNavData(
},
],
},
],
},
{
title: "Análise",
items: [
{
title: "Insights",
url: "/insights",
icon: RiSparklingLine,
},
],
},
{
title: "Relatórios",
items: [
{
title: "Categorias",
title: "Tendências",
url: "/relatorios/categorias",
icon: RiFileChartLine,
},
{
title: "Cartões",
title: "Uso de Cartões",
url: "/relatorios/cartoes",
icon: RiBankCard2Line,
},
@@ -206,11 +196,6 @@ export function createSidebarNavData(
},
],
navSecondary: [
// {
// title: "Changelog",
// url: "/changelog",
// icon: RiGitCommitLine,
// },
{
title: "Ajustes",
url: "/ajustes",

View File

@@ -113,9 +113,11 @@ export function NavMain({ sections }: { sections: NavSection[] }) {
return (
<>
{sections.map((section) => (
{sections.map((section, index) => (
<SidebarGroup key={section.title}>
<SidebarGroupLabel>{section.title}</SidebarGroupLabel>
<SidebarGroupLabel className="text-xs text-muted-foreground/60">
{section.title}
</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{section.items.map((item) => {