From 31659a215793d15b3a2f75da2dbfa4667cc5fb20 Mon Sep 17 00:00:00 2001
From: "gpt-engineer-app[bot]"
<159125892+gpt-engineer-app[bot]@users.noreply.github.com>
Date: Wed, 25 Jun 2025 00:39:07 +0000
Subject: [PATCH] feat: Implement category and transaction card styling
Styled the category page and transaction summary cards to match the provided print.
---
.../transacoes/TransactionSummaryCards.tsx | 93 +++---
src/pages/Categorias.tsx | 307 ++++++++----------
2 files changed, 186 insertions(+), 214 deletions(-)
diff --git a/src/components/transacoes/TransactionSummaryCards.tsx b/src/components/transacoes/TransactionSummaryCards.tsx
index d39ea72..7a1e7d6 100644
--- a/src/components/transacoes/TransactionSummaryCards.tsx
+++ b/src/components/transacoes/TransactionSummaryCards.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { ArrowUp, ArrowDown, CreditCard } from 'lucide-react';
-import { SimpleCard } from '@/components/ui/simple-card';
interface TransactionSummaryCardsProps {
totalReceitas: number;
@@ -16,66 +15,58 @@ export const TransactionSummaryCards = ({
totalCartoes,
formatCurrency
}: TransactionSummaryCardsProps) => {
- // Calculate the grand total of all expenses
const totalGeral = totalDespesas + totalCartoes;
return (
-
-
-
-
-
- Ganhos do mês
+
+ {/* Card Ganhos do mês */}
+
+
-
-
- {formatCurrency(totalReceitas)}
+
+ {formatCurrency(totalReceitas)}
+
+
+
+ {/* Card Gastos do mês */}
+
+
+
+ {formatCurrency(totalDespesas)}
+
+
+
+ {/* Card Gastos em cartões */}
+
+
+
+
+
+
Gastos em cartões
+
+
+
+ {formatCurrency(totalCartoes)}
-
-
-
-
-
-
-
- Despesas:
-
- {formatCurrency(totalDespesas)}
-
-
- {totalCartoes > 0 && (
-
-
Cartões:
-
- {formatCurrency(totalCartoes)}
+
+
+ Total geral:
+
+ {formatCurrency(totalGeral)}
- )}
-
-
-
-
-
-
-
- {formatCurrency(totalGeral)}
-
-
- Despesas + Cartões
-
-
-
+
);
};
diff --git a/src/pages/Categorias.tsx b/src/pages/Categorias.tsx
index 6edf987..7f80fcb 100644
--- a/src/pages/Categorias.tsx
+++ b/src/pages/Categorias.tsx
@@ -2,49 +2,44 @@
import React, { useState, useEffect } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Badge } from "@/components/ui/badge";
-import { Plus, Search, Edit, Trash2 } from 'lucide-react';
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { useToast } from "@/hooks/use-toast";
-import { SimpleCard } from "@/components/ui/simple-card";
+import { getCategorySummary } from '@/services/transacao';
+import { CategorySummary } from '@/types/financialTypes';
-interface Categoria {
- id: string;
+interface CategoryCard {
nome: string;
- tipo: 'receita' | 'despesa';
+ valor: number;
+ percentual: number;
cor: string;
- total?: number;
}
const Categorias = () => {
- const [categorias, setCategorias] = useState([]);
- const [searchTerm, setSearchTerm] = useState('');
+ const [categories, setCategories] = useState([]);
+ const [filtro, setFiltro] = useState<'despesa' | 'receita'>('despesa');
const [isLoading, setIsLoading] = useState(true);
const { toast } = useToast();
- // Mock data - replace with actual API calls
- useEffect(() => {
- const mockCategorias: Categoria[] = [
- { id: '1', nome: 'Alimentação', tipo: 'despesa', cor: '#ef4444', total: 850.50 },
- { id: '2', nome: 'Transporte', tipo: 'despesa', cor: '#f97316', total: 420.30 },
- { id: '3', nome: 'Lazer', tipo: 'despesa', cor: '#eab308', total: 300.00 },
- { id: '4', nome: 'Salário', tipo: 'receita', cor: '#22c55e', total: 5000.00 },
- { id: '5', nome: 'Freelance', tipo: 'receita', cor: '#10b981', total: 1200.00 },
- { id: '6', nome: 'Educação', tipo: 'despesa', cor: '#3b82f6', total: 450.00 },
- ];
-
- setTimeout(() => {
- setCategorias(mockCategorias);
+ const loadCategories = async () => {
+ try {
+ setIsLoading(true);
+ const data = await getCategorySummary(filtro);
+ setCategories(data);
+ } catch (error) {
+ console.error("Erro ao carregar categorias:", error);
+ toast({
+ title: "Erro ao carregar categorias",
+ description: "Não foi possível obter os dados das categorias",
+ variant: "destructive"
+ });
+ } finally {
setIsLoading(false);
- }, 1000);
- }, []);
+ }
+ };
- const filteredCategorias = categorias.filter(categoria =>
- categoria.nome.toLowerCase().includes(searchTerm.toLowerCase())
- );
-
- const receitas = filteredCategorias.filter(cat => cat.tipo === 'receita');
- const despesas = filteredCategorias.filter(cat => cat.tipo === 'despesa');
+ useEffect(() => {
+ loadCategories();
+ }, [filtro]);
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('pt-BR', {
@@ -53,29 +48,22 @@ const Categorias = () => {
}).format(value);
};
- const handleEdit = (categoria: Categoria) => {
- toast({
- title: "Editar categoria",
- description: `Função de edição para ${categoria.nome} será implementada`,
- });
+ const formatPercentage = (value: number) => {
+ return `${(value * 100).toFixed(1)}%`;
};
- const handleDelete = (categoria: Categoria) => {
- toast({
- title: "Excluir categoria",
- description: `Função de exclusão para ${categoria.nome} será implementada`,
- });
- };
+ const totalGeral = categories.reduce((sum, cat) => sum + cat.valor, 0);
if (isLoading) {
return (
Categorias
-
+
{[1, 2, 3, 4, 5, 6].map((i) => (
@@ -98,125 +86,118 @@ const Categorias = () => {
Categorias
-
-
-
-
-
-
-
setSearchTerm(e.target.value)}
- className="pl-10"
- />
+
+ Filtrar por:
+
-
-
-
-
-
- {receitas.length === 0 ? (
-
- Nenhuma categoria de receita encontrada
-
- ) : (
- receitas.map((categoria) => (
-
-
-
-
-
{categoria.nome}
-
- {categoria.total ? formatCurrency(categoria.total) : 'R$ 0,00'}
-
-
-
-
-
- {categoria.tipo}
-
-
-
-
-
- ))
- )}
-
-
-
-
-
- {despesas.length === 0 ? (
-
- Nenhuma categoria de despesa encontrada
-
- ) : (
- despesas.map((categoria) => (
-
-
-
-
-
{categoria.nome}
-
- {categoria.total ? formatCurrency(categoria.total) : 'R$ 0,00'}
-
-
-
-
-
- {categoria.tipo}
-
-
-
-
-
- ))
- )}
-
-
+
+ {/* Cards das Categorias */}
+
+ {categories.map((categoria, index) => (
+
+
+
+
+
{categoria.categoria}
+
+
+
+ {formatCurrency(categoria.valor)}
+
+
+
+
+ {formatPercentage(categoria.percentage)} do total
+
+
+
+
+
+ ))}
+
+
+ {/* Resumo de Categorias */}
+ {categories.length > 0 && (
+
+
+
+ Resumo de Categorias ({filtro === 'despesa' ? 'Despesas' : 'Receitas'})
+
+
+
+
+
+
+
+ | Categoria |
+ Valor |
+ Percentual |
+
+
+
+ {categories.map((categoria) => (
+
+
+
+
+ {categoria.categoria}
+
+ |
+
+ {formatCurrency(categoria.valor)}
+ |
+
+ {formatPercentage(categoria.percentage)}
+ |
+
+ ))}
+
+ | Total |
+ {formatCurrency(totalGeral)} |
+ 100% |
+
+
+
+
+
+
+ )}
+
+ {categories.length === 0 && !isLoading && (
+
+
+
+ Nenhuma categoria encontrada para {filtro === 'despesa' ? 'despesas' : 'receitas'}.
+
+
+ Adicione algumas transações para ver as categorias aqui.
+
+
+
+ )}
);
};