Fix: Dashboard and Transactions page improvements

- Fixed missing "Despesas" category in the pie chart.
- Re-added month/year filter to Dashboard and Transactions pages.
- Improved responsiveness of summary cards on smaller screens.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-25 18:18:03 +00:00
parent 1d1135cbe4
commit 7b39bcd5aa
4 changed files with 56 additions and 27 deletions

View File

@ -16,7 +16,7 @@ const DashboardSummaryCards: React.FC<DashboardSummaryCardsProps> = ({ resumo, f
const saldo = resumo ? resumo.totalReceitas - resumo.totalDespesas - (resumo.totalCartoes || 0) : 0;
return (
<div className="grid gap-4 sm:gap-6 grid-cols-1 sm:grid-cols-2 lg:grid-cols-4">
<div className="grid gap-4 sm:gap-6 grid-cols-1 sm:grid-cols-2 xl:grid-cols-4">
{/* Card Receitas - Clicável */}
<Card
className="relative overflow-hidden border-2 border-green-200 bg-gradient-to-br from-green-50 to-emerald-100 shadow-lg hover:shadow-xl transition-all duration-300 cursor-pointer group transform hover:scale-105"
@ -34,7 +34,7 @@ const DashboardSummaryCards: React.FC<DashboardSummaryCardsProps> = ({ resumo, f
</div>
<div className="space-y-1 sm:space-y-2">
<p className="text-xs sm:text-sm font-semibold text-green-700">Receitas</p>
<p className="text-lg sm:text-2xl lg:text-3xl font-bold text-green-600 break-words">
<p className="text-base sm:text-xl xl:text-2xl font-bold text-green-600 leading-tight">
{resumo ? formatCurrency(resumo.totalReceitas) : 'R$ 0,00'}
</p>
<p className="text-xs text-green-600 opacity-80">Clique para ver detalhes</p>
@ -59,7 +59,7 @@ const DashboardSummaryCards: React.FC<DashboardSummaryCardsProps> = ({ resumo, f
</div>
<div className="space-y-1 sm:space-y-2">
<p className="text-xs sm:text-sm font-semibold text-red-700">Despesas</p>
<p className="text-lg sm:text-2xl lg:text-3xl font-bold text-red-600 break-words">
<p className="text-base sm:text-xl xl:text-2xl font-bold text-red-600 leading-tight">
{resumo ? formatCurrency(resumo.totalDespesas) : 'R$ 0,00'}
</p>
{resumo && resumo.totalCartoes > 0 && (
@ -86,7 +86,7 @@ const DashboardSummaryCards: React.FC<DashboardSummaryCardsProps> = ({ resumo, f
</div>
<div className="space-y-1 sm:space-y-2">
<p className="text-xs sm:text-sm font-semibold text-blue-700">Saldo</p>
<p className={`text-lg sm:text-2xl lg:text-3xl font-bold break-words ${
<p className={`text-base sm:text-xl xl:text-2xl font-bold leading-tight ${
saldo >= 0 ? 'text-blue-600' : 'text-red-600'
}`}>
{resumo ? formatCurrency(saldo) : 'R$ 0,00'}
@ -106,10 +106,10 @@ const DashboardSummaryCards: React.FC<DashboardSummaryCardsProps> = ({ resumo, f
</div>
<div className="space-y-1 sm:space-y-2">
<p className="text-xs sm:text-sm font-semibold text-purple-700">Economia</p>
<p className="text-lg sm:text-2xl lg:text-3xl font-bold text-purple-600 break-words">
<p className="text-base sm:text-xl xl:text-2xl font-bold text-purple-600 leading-tight">
-22.2%
</p>
<p className="text-xs text-purple-500 break-words">{resumo ? formatCurrency(Math.abs(saldo)) : 'R$ 0,00'}</p>
<p className="text-xs text-purple-500 leading-tight">{resumo ? formatCurrency(Math.abs(saldo)) : 'R$ 0,00'}</p>
</div>
</CardContent>
</Card>

View File

@ -9,17 +9,21 @@ import DashboardLoadingState from "@/components/dashboard/DashboardLoadingState"
import DashboardSummaryCards from "@/components/dashboard/DashboardSummaryCards";
import DashboardCharts from "@/components/dashboard/DashboardCharts";
import DashboardRecentTransactions from "@/components/dashboard/DashboardRecentTransactions";
import { MonthFilter } from "@/components/filters/MonthFilter";
const Dashboard = () => {
const [resumo, setResumo] = useState<ResumoFinanceiro | null>(null);
const [categories, setCategories] = useState<CategorySummary[]>([]);
const [monthlyData, setMonthlyData] = useState<MonthlyData[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [selectedMonth, setSelectedMonth] = useState(() => {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
});
const { toast } = useToast();
const getCurrentMonth = () => {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
return selectedMonth;
};
const {
@ -69,7 +73,7 @@ const Dashboard = () => {
useEffect(() => {
loadResumo();
}, [toast]);
}, [toast, selectedMonth]);
if (isLoading) {
return <DashboardLoadingState />;
@ -79,6 +83,15 @@ const Dashboard = () => {
<div className="space-y-6" data-tour="dashboard-content">
<DashboardHeader />
{/* Filtro de Mês/Ano */}
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold">Dashboard</h2>
<MonthFilter
selectedMonth={selectedMonth}
onMonthChange={setSelectedMonth}
/>
</div>
<DashboardSummaryCards
resumo={resumo}
formatCurrency={formatCurrency}

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { useTransactions } from '@/hooks/useTransactions';
import { TransactionSummaryCards } from '@/components/transacoes/TransactionSummaryCards';
@ -7,9 +7,15 @@ import { TransactionDialogs } from '@/components/transacoes/TransactionDialogs';
import { TransactionHeader } from '@/components/transacoes/TransactionHeader';
import TransactionsTable from '@/components/dashboard/TransactionsTable';
import { SimpleCard } from "@/components/ui/simple-card";
import { MonthFilter } from "@/components/filters/MonthFilter";
const Transacoes = () => {
const location = useLocation();
const [selectedMonth, setSelectedMonth] = useState(() => {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
});
const {
transactions,
isLoading,
@ -31,7 +37,7 @@ const Transacoes = () => {
handleOpenDialog,
handleOpenCartaoCreditoDialog,
loadTransactions
} = useTransactions();
} = useTransactions({ monthFilter: selectedMonth });
// Aplicar filtro inicial se vier do dashboard
useEffect(() => {
@ -54,6 +60,14 @@ const Transacoes = () => {
return (
<div className="space-y-6">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold">Transações</h1>
<MonthFilter
selectedMonth={selectedMonth}
onMonthChange={setSelectedMonth}
/>
</div>
<TransactionHeader
onOpenDialog={handleOpenDialog}
onOpenCartaoCreditoDialog={handleOpenCartaoCreditoDialog}

View File

@ -1,3 +1,4 @@
import { supabase } from "@/integrations/supabase/client";
import { CategorySummary, MonthlyData, ResumoFinanceiro } from "@/types/financialTypes";
import { getUserEmail, getUserGroups } from "./baseService";
@ -164,37 +165,38 @@ export async function getCategorySummary(tipo: string = 'despesa'): Promise<Cate
return [];
}
console.log(`📋 [getCategorySummary] Dados recebidos:`, data.map(d => ({ categoria: d.categoria, valor: d.valor, tipo: d.tipo })));
console.log(`📋 [getCategorySummary] Dados recebidos (${data.length} registros):`, data.slice(0, 5));
// Group by category and sum values
const categoryMap: { [key: string]: number } = {};
let total = 0;
data.forEach((transaction) => {
// Usar a categoria exata ou 'Outros' se for null/undefined/vazia
const categoria = transaction.categoria && transaction.categoria.trim() !== ''
? transaction.categoria.trim()
: 'Outros';
// Tratar categorias vazias, nulas ou indefinidas
let categoria = 'Outros';
if (transaction.categoria && typeof transaction.categoria === 'string') {
const cleanCategory = transaction.categoria.trim();
if (cleanCategory.length > 0) {
categoria = cleanCategory;
}
}
const valor = Math.abs(Number(transaction.valor || 0));
console.log(`📋 [getCategorySummary] Processando: categoria='${categoria}', valor=${valor}`);
categoryMap[categoria] = (categoryMap[categoria] || 0) + valor;
total += valor;
if (valor > 0) {
categoryMap[categoria] = (categoryMap[categoria] || 0) + valor;
total += valor;
}
});
console.log(`📋 [getCategorySummary] Mapeamento final de categorias:`, categoryMap);
console.log(`📋 [getCategorySummary] Categorias encontradas:`, Object.keys(categoryMap));
console.log(`📋 [getCategorySummary] Total geral: ${total}`);
// Enhanced color palette with more distinct colors - avoiding white/light colors
const colors = [
'#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
'#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9',
'#F8C471', '#82E0AA', '#F1948A', '#85C1E9', '#D7BDE2',
'#A3E4D7', '#FAD7A0', '#D5A6BD', '#AED6F1', '#A9DFBF',
'#FF8A80', '#80CBC4', '#81C784', '#FFB74D', '#F48FB1',
'#CE93D8', '#90CAF9', '#A5D6A7', '#FFCC02', '#FFAB40'
'#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9'
];
// Convert to CategorySummary array with colors
@ -207,7 +209,7 @@ export async function getCategorySummary(tipo: string = 'despesa'): Promise<Cate
}))
.sort((a, b) => b.valor - a.valor);
console.log(`📋 [getCategorySummary] ${categoryArray.length} categorias processadas:`, categoryArray);
console.log(`📋 [getCategorySummary] Resultado final:`, categoryArray);
return categoryArray;
} catch (error) {
console.error('💥 [getCategorySummary] Erro geral:', error);