From ee2273383b21bdd4eae8eb5b36b1336db9423982 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 21:39:47 +0000 Subject: [PATCH] Apply SQL schema changes Apply the SQL schema changes to create tables for recurring payment reminders, including tables for recurring accounts and sent reminders, along with necessary indexes and RLS policies. --- src/App.tsx | 175 +++++++-------- src/components/avisos/ContaRecorrenteForm.tsx | 194 ++++++++++++++++ .../avisos/ContasRecorrentesList.tsx | 197 +++++++++++++++++ src/components/layout/Sidebar.tsx | 207 ++++++------------ src/integrations/supabase/types.ts | 83 +++++++ src/pages/AvisosContas.tsx | 86 ++++++++ .../functions/avisos-financeiros/index.ts | 188 ++++++++++++++++ ...7-707e61ed-0dd2-4677-95c0-10c2053c2ca4.sql | 67 ++++++ 8 files changed, 961 insertions(+), 236 deletions(-) create mode 100644 src/components/avisos/ContaRecorrenteForm.tsx create mode 100644 src/components/avisos/ContasRecorrentesList.tsx create mode 100644 src/pages/AvisosContas.tsx create mode 100644 supabase/functions/avisos-financeiros/index.ts create mode 100644 supabase/migrations/20250623213757-707e61ed-0dd2-4677-95c0-10c2053c2ca4.sql diff --git a/src/App.tsx b/src/App.tsx index 98a591b..3c1d150 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,101 +1,92 @@ -import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom'; -import { Suspense, lazy } from 'react'; import { Toaster } from "@/components/ui/sonner"; -import Auth from './pages/Auth'; -import Landing from './pages/Landing'; -import EmailConfirmation from './pages/EmailConfirmation'; -import CompleteProfile from './pages/CompleteProfile'; -import ProtectedRoute from './components/auth/ProtectedRoute'; -import { authStore } from './stores/authStore'; +import { TooltipProvider } from "@/components/ui/tooltip"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { useEffect } from "react"; +import { supabase } from "@/integrations/supabase/client"; +import { useAuthStore } from "@/stores/authStore"; +import ProtectedRoute from "@/components/auth/ProtectedRoute"; +import Layout from "@/components/layout/Layout"; -// Lazy-loaded components -const Dashboard = lazy(() => import('./pages/Index')); -const Transacoes = lazy(() => import('./pages/Transacoes')); -const Categorias = lazy(() => import('./pages/Categorias')); -const Metas = lazy(() => import('./pages/Metas')); -const Calendario = lazy(() => import('./pages/Calendario')); -const Assinatura = lazy(() => import('./pages/Assinatura')); -const WhatsApp = lazy(() => import('./pages/WhatsApp')); -const GruposWhatsApp = lazy(() => import('./pages/GruposWhatsApp')); -const NotFound = lazy(() => import('./pages/NotFound')); -const CartoesCredito = lazy(() => import('./pages/CartoesCredito')); -const Configuracoes = lazy(() => import('./pages/Configuracoes')); -const AdminFAQ = lazy(() => import('./pages/AdminFAQ')); +// Pages +import Index from "./pages/Index"; +import Auth from "./pages/Auth"; +import Landing from "./pages/Landing"; +import Transacoes from "./pages/Transacoes"; +import CartoesCredito from "./pages/CartoesCredito"; +import Configuracoes from "./pages/Configuracoes"; +import Metas from "./pages/Metas"; +import Calendario from "./pages/Calendario"; +import WhatsApp from "./pages/WhatsApp"; +import GruposWhatsApp from "./pages/GruposWhatsApp"; +import EmailConfirmation from "./pages/EmailConfirmation"; +import CompleteProfile from "./pages/CompleteProfile"; +import NotFound from "./pages/NotFound"; +import Categorias from "./pages/Categorias"; +import AdminFAQ from "./pages/AdminFAQ"; +import Assinatura from "./pages/Assinatura"; +import AvisosContas from "./pages/AvisosContas"; + +const queryClient = new QueryClient(); function App() { - const isLoggedIn = authStore((state) => state.isLoggedIn); - + const { setUser, setSession } = useAuthStore(); + + useEffect(() => { + // Verificar sessão inicial + supabase.auth.getSession().then(({ data: { session } }) => { + setSession(session); + setUser(session?.user ?? null); + }); + + // Escutar mudanças de autenticação + const { + data: { subscription }, + } = supabase.auth.onAuthStateChange((_event, session) => { + setSession(session); + setUser(session?.user ?? null); + }); + + return () => subscription.unsubscribe(); + }, [setUser, setSession]); + return ( - - - - - {/* Landing page - só mostra se não estiver logado */} - : } - /> - - {/* Auth route - redireciona para dashboard se já estiver logado */} - : } - /> - - {/* Email confirmation route */} - } - /> - - {/* Complete profile route - deve ser acessível para usuários logados */} - } - /> - - {/* Protected routes */} - - Carregando...}> - - - - } /> - - - Carregando...}> - - - - } /> - - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - Carregando...}>} /> - - Carregando...}> - - - - } /> - - {/* Not found route */} - Carregando...}> - - - } /> - - + + + + + + {/* Rotas públicas */} + } /> + } /> + } /> + + {/* Rotas protegidas */} + }> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + {/* Rota 404 */} + } /> + + + + ); } diff --git a/src/components/avisos/ContaRecorrenteForm.tsx b/src/components/avisos/ContaRecorrenteForm.tsx new file mode 100644 index 0000000..9d9e936 --- /dev/null +++ b/src/components/avisos/ContaRecorrenteForm.tsx @@ -0,0 +1,194 @@ + +import React from 'react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Textarea } from '@/components/ui/textarea'; +import { X, Save } from 'lucide-react'; +import { useForm } from 'react-hook-form'; +import { supabase } from '@/integrations/supabase/client'; +import { toast } from 'sonner'; +import { useAuthStore } from '@/stores/authStore'; + +interface ContaRecorrenteFormProps { + onClose: () => void; + onSuccess: () => void; +} + +interface FormData { + nome_conta: string; + descricao: string; + valor: number; + dia_vencimento: number; + hora_aviso: string; + dias_antecedencia: number; +} + +const ContaRecorrenteForm = ({ onClose, onSuccess }: ContaRecorrenteFormProps) => { + const { user } = useAuthStore(); + const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm({ + defaultValues: { + hora_aviso: '09:00', + dias_antecedencia: 1 + } + }); + + const onSubmit = async (data: FormData) => { + if (!user?.id) { + toast.error('Usuário não encontrado. Faça login novamente.'); + return; + } + + try { + const { error } = await supabase + .from('contas_recorrentes') + .insert([{ + ...data, + user_id: user.id, + valor: data.valor || null + }]); + + if (error) throw error; + + toast.success('Conta recorrente cadastrada com sucesso!'); + onSuccess(); + } catch (error) { + console.error('Erro ao cadastrar conta:', error); + toast.error('Erro ao cadastrar conta. Tente novamente.'); + } + }; + + return ( + + +
+
+ Nova Conta Recorrente + + Configure uma conta que será cobrada mensalmente no mesmo dia + +
+ +
+
+ +
+
+
+ + + {errors.nome_conta && ( +

{errors.nome_conta.message}

+ )} +
+ +
+ + + {errors.valor && ( +

{errors.valor.message}

+ )} +
+
+ +
+ +