From a4f8efc4209c3a1321f59d2c44d672acbf434489 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 23:37:48 +0000 Subject: [PATCH] Connect to transactions table --- src/pages/Index.tsx | 65 ++++++++++----- src/services/transacaoService.ts | 131 +++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 18 deletions(-) create mode 100644 src/services/transacaoService.ts diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx index b610896..00a0b76 100644 --- a/src/pages/Index.tsx +++ b/src/pages/Index.tsx @@ -6,24 +6,53 @@ import TransactionsTable from '@/components/dashboard/TransactionsTable'; import CategoryChart from '@/components/dashboard/CategoryChart'; import MonthlyChart from '@/components/dashboard/MonthlyChart'; import { DollarSign, TrendingUp, TrendingDown, PiggyBank } from 'lucide-react'; -import { mockTransactions, mockCategories, mockMonthlyData, mockTotals } from '@/data/mockData'; +import { Transaction, CategorySummary, MonthlyData } from '@/types/financialTypes'; import { useToast } from "@/components/ui/use-toast"; +import { getTransacoes, getTransactionSummary, getCategorySummary, getMonthlyData } from '@/services/transacaoService'; const Dashboard = () => { const [isLoading, setIsLoading] = useState(true); + const [transactions, setTransactions] = useState([]); + const [categories, setCategories] = useState([]); + const [monthlyData, setMonthlyData] = useState([]); + const [totals, setTotals] = useState({ receitas: 0, despesas: 0, saldo: 0 }); const { toast } = useToast(); useEffect(() => { - // Simulando carregamento de dados - const timer = setTimeout(() => { - setIsLoading(false); - toast({ - title: "Dados carregados com sucesso", - description: "Conecte ao Supabase para ver seus dados reais" - }); - }, 1500); - - return () => clearTimeout(timer); + async function loadData() { + try { + setIsLoading(true); + + // Buscar todos os dados necessários + const [transacoesData, totalsData, categoriesData, monthlyDataResult] = await Promise.all([ + getTransacoes(), + getTransactionSummary(), + getCategorySummary(), + getMonthlyData() + ]); + + setTransactions(transacoesData); + setTotals(totalsData); + setCategories(categoriesData); + setMonthlyData(monthlyDataResult); + + toast({ + title: "Dados carregados com sucesso", + description: "Seus dados financeiros 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(); }, [toast]); const formatCurrency = (value: number) => { @@ -46,7 +75,7 @@ const Dashboard = () => {
} trend={5} iconClass="bg-finance-green/10" @@ -54,7 +83,7 @@ const Dashboard = () => { /> } trend={-2} iconClass="bg-finance-red/10" @@ -62,14 +91,14 @@ const Dashboard = () => { /> } iconClass="bg-finance-blue/10" valueClass="text-finance-blue" /> 0 ? ((totals.saldo / totals.receitas) * 100).toFixed(1) : 0}%`} icon={} iconClass="bg-finance-purple/10" valueClass="text-finance-purple" @@ -77,13 +106,13 @@ const Dashboard = () => {
- - + +

Transações Recentes

- +
diff --git a/src/services/transacaoService.ts b/src/services/transacaoService.ts new file mode 100644 index 0000000..b9ebfe5 --- /dev/null +++ b/src/services/transacaoService.ts @@ -0,0 +1,131 @@ + +import { supabase } from "@/integrations/supabase/client"; +import { Transaction } from "@/types/financialTypes"; + +export async function getTransacoes(): Promise { + const { data, error } = await supabase + .from('transacoes') + .select('*') + .order('quando', { ascending: false }); + + if (error) { + console.error('Erro ao buscar transações:', error); + throw new Error('Não foi possível carregar as transações'); + } + + // Transformar os dados recebidos para o formato esperado + return data.map((item) => ({ + id: item.id.toString(), + user: item.user || '', + created_at: item.created_at, + valor: item.valor || 0, + quando: item.quando || new Date().toISOString(), + detalhes: item.detalhes || '', + estabelecimento: item.estabelecimento || '', + tipo: (item.tipo === 'entrada' || item.tipo === 'saida') ? item.tipo : 'saida', + categoria: item.categoria || 'Outros' + })); +} + +export async function getTransactionSummary() { + const { data, error } = await supabase + .from('transacoes') + .select('tipo, valor'); + + if (error) { + console.error('Erro ao buscar resumo das transações:', error); + throw new Error('Não foi possível carregar o resumo das transações'); + } + + const totalReceitas = data + .filter(item => item.tipo === 'entrada') + .reduce((sum, item) => sum + (item.valor || 0), 0); + + const totalDespesas = data + .filter(item => item.tipo === 'saida') + .reduce((sum, item) => sum + (item.valor || 0), 0); + + return { + receitas: totalReceitas, + despesas: totalDespesas, + saldo: totalReceitas - totalDespesas + }; +} + +export async function getCategorySummary() { + const { data, error } = await supabase + .from('transacoes') + .select('categoria, valor, tipo') + .eq('tipo', 'saida'); + + if (error) { + console.error('Erro ao buscar resumo de categorias:', error); + throw new Error('Não foi possível carregar o resumo por categoria'); + } + + // Agrupar por categoria + const categorias: Record = {}; + data.forEach(item => { + if (item.categoria && item.valor) { + if (!categorias[item.categoria]) { + categorias[item.categoria] = 0; + } + categorias[item.categoria] += item.valor; + } + }); + + // Calcular o total para porcentagens + const total = Object.values(categorias).reduce((sum, valor) => sum + valor, 0); + + // Cores para categorias (reuse das cores no mockData) + const cores = ["#F59E0B", "#60A5FA", "#8B5CF6", "#EF4444", "#10B981", "#6366F1", "#EC4899", "#14B8A6"]; + + // Mapear para o formato esperado + return Object.entries(categorias).map(([categoria, valor], index) => ({ + categoria, + valor, + percentage: total > 0 ? valor / total : 0, + color: cores[index % cores.length] + })); +} + +export async function getMonthlyData() { + const { data, error } = await supabase + .from('transacoes') + .select('quando, valor, tipo'); + + if (error) { + console.error('Erro ao buscar dados mensais:', error); + throw new Error('Não foi possível carregar os dados mensais'); + } + + const meses: Record = {}; + const nomesMeses = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez']; + + // Inicializar meses + nomesMeses.forEach(mes => { + meses[mes] = { receitas: 0, despesas: 0 }; + }); + + // Agrupar por mês + data.forEach(item => { + if (item.quando && item.valor) { + const data = new Date(item.quando); + const mesIndex = data.getMonth(); + const nomeMes = nomesMeses[mesIndex]; + + if (item.tipo === 'entrada') { + meses[nomeMes].receitas += item.valor; + } else { + meses[nomeMes].despesas += item.valor; + } + } + }); + + // Converter para o formato esperado + return Object.entries(meses).map(([month, values]) => ({ + month, + receitas: values.receitas, + despesas: values.despesas + })); +}