diff --git a/src/components/credito/DespesaCartaoFormSelect.tsx b/src/components/credito/DespesaCartaoFormSelect.tsx new file mode 100644 index 0000000..1ec44b4 --- /dev/null +++ b/src/components/credito/DespesaCartaoFormSelect.tsx @@ -0,0 +1,202 @@ + +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import * as z from 'zod'; +import { useToast } from '@/components/ui/use-toast'; +import { criarDespesa } from '@/services/cartaoCreditoService'; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage +} from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { CartaoCredito } from '@/types/cartaoTypes'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; + +const despesaSchema = z.object({ + cartaoId: z.string().min(1, { message: 'Cartão é obrigatório' }), + valor: z.string().min(1, { message: 'Valor é obrigatório' }), + data_despesa: z.string().min(1, { message: 'Data é obrigatória' }), + descricao: z.string().min(1, { message: 'Descrição é obrigatória' }), +}); + +type DespesaFormValues = z.infer; + +interface DespesaCartaoFormSelectProps { + cartoes: CartaoCredito[]; + onSuccess: () => void; + onCancel: () => void; +} + +export function DespesaCartaoFormSelect({ cartoes, onSuccess, onCancel }: DespesaCartaoFormSelectProps) { + const [isSubmitting, setIsSubmitting] = useState(false); + const { toast } = useToast(); + + const form = useForm({ + resolver: zodResolver(despesaSchema), + defaultValues: { + cartaoId: '', + valor: '', + data_despesa: new Date().toISOString().split('T')[0], + descricao: '', + } + }); + + async function onSubmit(data: DespesaFormValues) { + setIsSubmitting(true); + + try { + const valorNumerico = parseFloat(data.valor.replace(',', '.')); + + if (isNaN(valorNumerico)) { + toast({ + title: "Erro no formulário", + description: "O valor precisa ser um número válido", + variant: "destructive" + }); + setIsSubmitting(false); + return; + } + + const resultado = await criarDespesa( + data.cartaoId, + valorNumerico, + data.data_despesa, + data.descricao + ); + + if (resultado) { + toast({ + title: "Despesa adicionada", + description: "Despesa do cartão cadastrada com sucesso", + }); + onSuccess(); + } else { + toast({ + title: "Erro ao salvar", + description: "Não foi possível salvar a despesa do cartão", + variant: "destructive" + }); + } + } catch (error) { + console.error('Erro ao processar formulário:', error); + toast({ + title: "Erro inesperado", + description: "Ocorreu um erro ao processar sua solicitação", + variant: "destructive" + }); + } finally { + setIsSubmitting(false); + } + } + + const selectedCartaoNome = form.watch('cartaoId') ? + cartoes.find(cartao => cartao.id === form.watch('cartaoId'))?.nome : ''; + + return ( +
+ + ( + + Cartão de Crédito + + + + )} + /> + + {selectedCartaoNome && ( +
+

Cartão selecionado: {selectedCartaoNome}

+
+ )} + + ( + + Valor + + + + + + )} + /> + + ( + + Data + + + + + + )} + /> + + ( + + Descrição + + + + + + )} + /> + +
+ + +
+ + + ); +} diff --git a/src/pages/Transacoes.tsx b/src/pages/Transacoes.tsx index cd965eb..fded534 100644 --- a/src/pages/Transacoes.tsx +++ b/src/pages/Transacoes.tsx @@ -7,7 +7,7 @@ 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 { PlusCircle, CreditCard } from 'lucide-react'; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Dialog, @@ -16,6 +16,9 @@ import { DialogHeader, DialogTitle, } from "@/components/ui/dialog"; +import { CartaoCredito } from '@/types/cartaoTypes'; +import { getCartoes } from '@/services/cartaoCreditoService'; +import { DespesaCartaoFormSelect } from '@/components/credito/DespesaCartaoFormSelect'; const TransacoesPage = () => { const [transactions, setTransactions] = useState([]); @@ -24,6 +27,8 @@ const TransacoesPage = () => { const [tipoForm, setTipoForm] = useState<'receita' | 'despesa'>('despesa'); const [selectedTransaction, setSelectedTransaction] = useState(null); const [isEditing, setIsEditing] = useState(false); + const [isCartaoCreditoDialogOpen, setIsCartaoCreditoDialogOpen] = useState(false); + const [cartoes, setCartoes] = useState([]); const { toast } = useToast(); const loadTransactions = async () => { @@ -45,8 +50,23 @@ const TransacoesPage = () => { } }; + const loadCartoes = async () => { + try { + const data = await getCartoes(); + setCartoes(data); + } catch (error) { + console.error("Erro ao carregar cartões:", error); + toast({ + title: "Erro ao carregar cartões", + description: "Não foi possível obter os dados dos cartões", + variant: "destructive" + }); + } + }; + useEffect(() => { loadTransactions(); + loadCartoes(); }, []); const handleTransactionSuccess = () => { @@ -62,6 +82,16 @@ const TransacoesPage = () => { }); }; + const handleDespesaCartaoSuccess = () => { + setIsCartaoCreditoDialogOpen(false); + loadCartoes(); // Recarregar lista de cartões + loadTransactions(); // Recarregar transações + toast({ + title: "Despesa de cartão registrada", + description: "A despesa do cartão foi adicionada com sucesso", + }); + }; + const handleEditTransaction = (transaction: Transaction) => { setSelectedTransaction(transaction); setTipoForm(transaction.tipo as 'receita' | 'despesa'); @@ -75,6 +105,10 @@ const TransacoesPage = () => { setIsEditing(false); }; + const handleCloseCartaoCreditoDialog = () => { + setIsCartaoCreditoDialogOpen(false); + }; + // Separar transações em receitas e despesas const receitas = transactions.filter(t => t.tipo === 'receita'); const despesas = transactions.filter(t => t.tipo === 'despesa'); @@ -97,6 +131,10 @@ const TransacoesPage = () => { setIsDialogOpen(true); }; + const handleOpenCartaoCreditoDialog = () => { + setIsCartaoCreditoDialogOpen(true); + }; + return (
@@ -117,6 +155,13 @@ const TransacoesPage = () => { Nova Despesa +
@@ -161,6 +206,7 @@ const TransacoesPage = () => { /> + {/* Dialog para transações */} @@ -186,6 +232,23 @@ const TransacoesPage = () => { /> + + {/* Dialog para despesas de cartão */} + + + + Nova Despesa de Cartão + + Selecione o cartão e preencha os detalhes da despesa. + + + + +
);