budget-view-finance/src/pages/Transacoes.tsx
gpt-engineer-app[bot] c5f3a3d161 Feat: Add group name input and transaction actions
- Added an input field in the GruposWhatsApp menu for users to name their WhatsApp groups, and store the name in the database.
- Added delete and edit buttons to the transactions table, with database integration.
2025-05-20 20:13:08 +00:00

195 lines
6.5 KiB
TypeScript

import { useState, useEffect } from 'react';
import Layout from '@/components/layout/Layout';
import TransactionsTable from '@/components/dashboard/TransactionsTable';
import { TransactionForm } from '@/components/dashboard/TransactionForm';
import { Transaction } from '@/types/financialTypes';
import { useToast } from "@/hooks/use-toast";
import { getTransacoes } from '@/services/transacaoService';
import { Button } from '@/components/ui/button';
import { PlusCircle } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
const TransacoesPage = () => {
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [tipoForm, setTipoForm] = useState<'receita' | 'despesa'>('despesa');
const [selectedTransaction, setSelectedTransaction] = useState<Transaction | null>(null);
const [isEditing, setIsEditing] = useState(false);
const { toast } = useToast();
const loadTransactions = async () => {
try {
setIsLoading(true);
console.log("Carregando todas as transações...");
const data = await getTransacoes();
console.log(`${data.length} transações carregadas com sucesso`);
setTransactions(data);
} catch (error) {
console.error("Erro ao carregar transações:", error);
toast({
title: "Erro ao carregar transações",
description: "Não foi possível obter os dados do Supabase",
variant: "destructive"
});
} finally {
setIsLoading(false);
}
};
useEffect(() => {
loadTransactions();
}, []);
const handleTransactionSuccess = () => {
setIsDialogOpen(false);
setSelectedTransaction(null);
setIsEditing(false);
loadTransactions();
toast({
title: isEditing ? "Transação atualizada" : "Transação registrada",
description: isEditing
? "A transação foi atualizada com sucesso"
: "A nova transação foi adicionada com sucesso",
});
};
const handleEditTransaction = (transaction: Transaction) => {
setSelectedTransaction(transaction);
setTipoForm(transaction.tipo as 'receita' | 'despesa');
setIsEditing(true);
setIsDialogOpen(true);
};
const handleCloseDialog = () => {
setIsDialogOpen(false);
setSelectedTransaction(null);
setIsEditing(false);
};
// Separar transações em receitas e despesas
const receitas = transactions.filter(t => t.tipo === 'receita');
const despesas = transactions.filter(t => t.tipo === 'despesa');
// Calcular totais
const totalReceitas = receitas.reduce((sum, t) => sum + Math.abs(t.valor), 0);
const totalDespesas = despesas.reduce((sum, t) => sum + Math.abs(t.valor), 0);
const formatCurrency = (value: number) => {
return new Intl.NumberFormat('pt-BR', {
style: 'currency',
currency: 'BRL',
}).format(value);
};
const handleOpenDialog = (tipo: 'receita' | 'despesa') => {
setTipoForm(tipo);
setIsEditing(false);
setSelectedTransaction(null);
setIsDialogOpen(true);
};
return (
<Layout>
<div className="space-y-6">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold tracking-tight">Todas as Transações</h1>
<div className="flex gap-2">
<Button
className="flex items-center gap-2 bg-finance-green hover:bg-finance-green/90"
onClick={() => handleOpenDialog('receita')}
>
<PlusCircle className="h-4 w-4" />
Nova Receita
</Button>
<Button
className="flex items-center gap-2 bg-finance-red hover:bg-finance-red/90"
onClick={() => handleOpenDialog('despesa')}
>
<PlusCircle className="h-4 w-4" />
Nova Despesa
</Button>
</div>
</div>
{/* Resumo em Cards */}
<div className="grid gap-4 md:grid-cols-2">
<Card>
<CardHeader className="pb-2 bg-green-50">
<CardTitle className="text-finance-green flex items-center">
Ganhos do mês
</CardTitle>
</CardHeader>
<CardContent className="pt-4">
<p className="text-2xl font-bold text-finance-green">
{formatCurrency(totalReceitas)}
</p>
</CardContent>
</Card>
<Card>
<CardHeader className="pb-2 bg-red-50">
<CardTitle className="text-finance-red flex items-center">
Gastos do mês
</CardTitle>
</CardHeader>
<CardContent className="pt-4">
<p className="text-2xl font-bold text-finance-red">
{formatCurrency(totalDespesas)}
</p>
</CardContent>
</Card>
</div>
{/* Tabela completa de transações */}
<div className="space-y-4">
<h2 className="text-xl font-semibold">Todas as Transações</h2>
<TransactionsTable
transactions={transactions}
isLoading={isLoading}
showPagination={true}
onEdit={handleEditTransaction}
onDelete={loadTransactions}
/>
</div>
<Dialog open={isDialogOpen} onOpenChange={handleCloseDialog}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<DialogTitle>
{isEditing
? `Editar ${tipoForm === 'receita' ? 'Receita' : 'Despesa'}`
: `Nova ${tipoForm === 'receita' ? 'Receita' : 'Despesa'}`
}
</DialogTitle>
<DialogDescription>
{isEditing
? 'Edite os campos para atualizar a transação.'
: `Preencha os campos para registrar uma nova ${tipoForm === 'receita' ? 'receita' : 'despesa'}.`
}
</DialogDescription>
</DialogHeader>
<TransactionForm
onSuccess={handleTransactionSuccess}
onCancel={handleCloseDialog}
defaultTipo={tipoForm}
transaction={selectedTransaction}
isEditing={isEditing}
/>
</DialogContent>
</Dialog>
</div>
</Layout>
);
};
export default TransacoesPage;