budget-view-finance/src/pages/Index.tsx
gpt-engineer-app[bot] 7d0dc19eb9 Fix: Resolve dynamic import fetch error
The AI addressed a "Failed to fetch dynamically imported module" error related to `src/pages/Index.tsx`. This likely involves checking the import path, ensuring the file is correctly served, and verifying the build configuration.
2025-06-06 18:40:04 +00:00

198 lines
7.2 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import Layout from '@/components/layout/Layout';
import SummaryCard from '@/components/dashboard/SummaryCard';
import TransactionsTable from '@/components/dashboard/TransactionsTable';
import CategoryChart from '@/components/dashboard/CategoryChart';
import MonthlyChart from '@/components/dashboard/MonthlyChart';
import { MonthFilter } from '@/components/filters/MonthFilter';
import { Wallet, ArrowUp, ArrowDown, PiggyBank } from 'lucide-react';
import { Transaction, CategorySummary, MonthlyData } from '@/types/financialTypes';
import { useToast } from "@/components/ui/use-toast";
import {
getTransacoes,
getTransactionSummary,
getCategorySummary,
getMonthlyData
} from '@/services/transacao';
import { getCartoes } from '@/services/cartaoCreditoService';
const Dashboard = () => {
const [isLoading, setIsLoading] = useState(true);
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [categories, setCategories] = useState<CategorySummary[]>([]);
const [monthlyData, setMonthlyData] = useState<MonthlyData[]>([]);
const [totals, setTotals] = useState({ receitas: 0, despesas: 0, saldo: 0, cartoes: 0 });
const { toast } = useToast();
// Função para obter o mês atual no formato YYYY-MM
const getCurrentMonth = () => {
const now = new Date();
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
};
const [selectedMonth, setSelectedMonth] = useState<string>(getCurrentMonth());
// Use useCallback to ensure this function doesn't change on every render
const setupUserId = useCallback(() => {
const storedUserId = localStorage.getItem('userId');
const finDashUser = localStorage.getItem('finDashUser');
if (!storedUserId && finDashUser) {
localStorage.setItem('userId', finDashUser);
} else if (!storedUserId && !finDashUser) {
const defaultId = '9f267008-9128-4a2f-b730-de0a0b5602a9';
localStorage.setItem('userId', defaultId);
}
}, []);
// Run the userId setup only once
useEffect(() => {
setupUserId();
}, [setupUserId]);
// Load data when component mounts or month changes
useEffect(() => {
async function loadData() {
try {
setIsLoading(true);
console.log("Iniciando carregamento de dados para o mês:", selectedMonth);
// Buscar todos os dados necessários com filtro de mês
const [transacoesData, totalsData, categoriesData, monthlyDataResult, cartoesData] = await Promise.all([
getTransacoes(selectedMonth),
getTransactionSummary(selectedMonth),
getCategorySummary('despesa', selectedMonth),
getMonthlyData(), // Monthly data não precisa de filtro pois já mostra todos os meses
getCartoes()
]);
// Calcular total dos cartões
const totalCartoes = cartoesData.reduce((sum, cartao) => sum + (cartao.total_despesas || 0), 0);
console.log("Dados obtidos com sucesso:", {
transacoes: transacoesData.length,
totals: totalsData,
categories: categoriesData.length,
monthlyData: monthlyDataResult.length,
cartoes: cartoesData.length,
totalCartoes: totalCartoes,
mesEscolhido: selectedMonth
});
setTransactions(transacoesData);
setTotals({
...totalsData,
cartoes: totalCartoes,
// Atualiza o saldo incluindo despesas de cartão
saldo: totalsData.receitas - totalsData.despesas - totalCartoes
});
setCategories(categoriesData);
setMonthlyData(monthlyDataResult);
toast({
title: "Dados carregados com sucesso",
description: `Dados financeiros de ${selectedMonth} foram atualizados`
});
} catch (error) {
console.error("Erro ao carregar dados:", error);
toast({
title: "Erro ao carregar dados",
description: "Verifique a conexão com o Supabase",
variant: "destructive"
});
} finally {
setIsLoading(false);
}
}
loadData();
}, [selectedMonth, toast]);
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('pt-BR', {
style: 'currency',
currency: 'BRL',
}).format(value);
};
// Calculate total of all expenses (regular + credit cards)
const totalDespesasGeral = totals.despesas + totals.cartoes;
// Função para formatar o mês para exibição
const formatMonthDisplay = (month: string) => {
const [year, monthNum] = month.split('-');
const months = [
'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
];
return `${months[parseInt(monthNum) - 1]} ${year}`;
};
return (
<Layout>
<div className="space-y-6">
<div className="flex justify-between items-center">
<div className="space-y-1">
<h1 className="text-2xl font-bold tracking-tight">Dashboard Financeiro</h1>
<p className="text-sm text-muted-foreground">
Dados de: {formatMonthDisplay(selectedMonth)}
</p>
</div>
<MonthFilter
selectedMonth={selectedMonth}
onMonthChange={setSelectedMonth}
/>
</div>
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
<SummaryCard
title="Receitas"
value={formatCurrency(totals.receitas)}
icon={<ArrowUp size={20} className="text-finance-green" />}
trend={5}
iconClass="bg-finance-green/10"
valueClass="text-finance-green"
/>
<SummaryCard
title="Despesas"
value={formatCurrency(totalDespesasGeral)}
secondaryValue={`Cartões: ${formatCurrency(totals.cartoes)}`}
icon={<ArrowDown size={20} className="text-finance-red" />}
trend={-2}
iconClass="bg-finance-red/10"
valueClass="text-finance-red"
/>
<SummaryCard
title="Saldo"
value={formatCurrency(totals.saldo)}
icon={<Wallet size={20} className="text-finance-blue" />}
iconClass="bg-finance-blue/10"
valueClass="text-finance-blue"
/>
<SummaryCard
title="Economia"
value={`${totals.receitas > 0 ? ((totals.saldo / totals.receitas) * 100).toFixed(1) : 0}%`}
secondaryValue={formatCurrency(totals.saldo)}
icon={<PiggyBank size={20} className="text-finance-purple" />}
iconClass="bg-finance-purple/10"
valueClass="text-finance-purple"
/>
</div>
<div className="grid gap-4 md:grid-cols-2">
<CategoryChart categories={categories} isLoading={isLoading} />
<MonthlyChart data={monthlyData} isLoading={isLoading} />
</div>
<div className="space-y-2">
<h2 className="text-xl font-semibold">Transações Recentes</h2>
<TransactionsTable transactions={transactions} isLoading={isLoading} />
</div>
</div>
</Layout>
);
};
export default Dashboard;