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:
parent
1d1135cbe4
commit
7b39bcd5aa
@ -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>
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user