From 8435c0346447f53b81bff57476bc57d125e8e376 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 00:59:19 +0000 Subject: [PATCH] Run SQL to add WhatsApp group features. --- src/App.tsx | 6 + src/components/layout/Sidebar.tsx | 9 +- src/components/ui/badge.tsx | 8 +- src/integrations/supabase/types.ts | 138 +---------------- src/pages/GruposWhatsApp.tsx | 205 ++++++++++++++++++++++++++ src/services/gruposWhatsAppService.ts | 74 ++++++++++ src/types/financialTypes.ts | 12 ++ 7 files changed, 314 insertions(+), 138 deletions(-) create mode 100644 src/pages/GruposWhatsApp.tsx create mode 100644 src/services/gruposWhatsAppService.ts diff --git a/src/App.tsx b/src/App.tsx index b910543..a4295f7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -8,6 +8,7 @@ import NotFound from '@/pages/NotFound'; import Auth from '@/pages/Auth'; import Metas from '@/pages/Metas'; import WhatsApp from '@/pages/WhatsApp'; +import GruposWhatsApp from '@/pages/GruposWhatsApp'; import { Toaster } from '@/components/ui/toaster'; import './App.css'; import ProtectedRoute from '@/components/auth/ProtectedRoute'; @@ -47,6 +48,11 @@ function App() { } /> + + + + } /> } /> } /> } /> diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index 66f2318..ebdd7f2 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -3,9 +3,9 @@ import React from 'react'; import { Link, useLocation } from 'react-router-dom'; import { cn } from '@/lib/utils'; import { Button } from "@/components/ui/button"; -import { ChevronLeft, ChevronRight, Home, CalendarDays, DollarSign, PieChart, Flag, MessageCircle } from 'lucide-react'; +import { ChevronLeft, ChevronRight, Home, CalendarDays, DollarSign, PieChart, Flag, MessageCircle, Users } from 'lucide-react'; -// Updated navItems with the new WhatsApp connection page +// Atualizado para incluir a página de grupos do WhatsApp const navItems = [ { name: 'Dashboard', @@ -37,6 +37,11 @@ const navItems = [ path: '/whatsapp', icon: }, + { + name: 'Grupos WhatsApp', + path: '/grupos-whatsapp', + icon: + }, ]; interface SidebarProps { diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index ef57637..97ff2b9 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -5,19 +5,19 @@ import { cva, type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" const badgeVariants = cva( - "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", { variants: { variant: { default: - "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", destructive: - "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", outline: "text-foreground", success: - "border-transparent bg-finance-green text-white shadow hover:bg-finance-green/80", + "border-transparent bg-green-500 text-white hover:bg-green-600", }, }, defaultVariants: { diff --git a/src/integrations/supabase/types.ts b/src/integrations/supabase/types.ts index ebcfbb1..cc77d46 100644 --- a/src/integrations/supabase/types.ts +++ b/src/integrations/supabase/types.ts @@ -124,22 +124,28 @@ export type Database = { Row: { created_at: string | null id: number + login: string | null nome_grupo: string | null remote_jid: string + status: string | null user_id: string } Insert: { created_at?: string | null id?: number + login?: string | null nome_grupo?: string | null remote_jid: string + status?: string | null user_id: string } Update: { created_at?: string | null id?: number + login?: string | null nome_grupo?: string | null remote_jid?: string + status?: string | null user_id?: string } Relationships: [] @@ -249,138 +255,6 @@ export type Database = { } Relationships: [] } - "transacoes_5f8e8181-e850-4551-88e4-bbbdc64a57ca": { - Row: { - categoria: string | null - created_at: string - detalhes: string | null - estabelecimento: string | null - id: number - quando: string | null - tipo: string | null - usuario_id: string | null - valor: number | null - } - Insert: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Update: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Relationships: [ - { - foreignKeyName: "transacoes_5f8e8181-e850-4551-88e4-bbbdc64a57ca_usuario_id_fkey" - columns: ["usuario_id"] - isOneToOne: false - referencedRelation: "usuarios" - referencedColumns: ["id"] - }, - ] - } - "transacoes_9f267008-9128-4a2f-b730-de0a0b5602a9": { - Row: { - categoria: string | null - created_at: string - detalhes: string | null - estabelecimento: string | null - id: number - quando: string | null - tipo: string | null - usuario_id: string | null - valor: number | null - } - Insert: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Update: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Relationships: [ - { - foreignKeyName: "transacoes_9f267008-9128-4a2f-b730-de0a0b5602a9_usuario_id_fkey" - columns: ["usuario_id"] - isOneToOne: false - referencedRelation: "usuarios" - referencedColumns: ["id"] - }, - ] - } - "transacoes_d2ca2174-fb8f-41d0-9897-a71a4af474a8": { - Row: { - categoria: string | null - created_at: string - detalhes: string | null - estabelecimento: string | null - id: number - quando: string | null - tipo: string | null - usuario_id: string | null - valor: number | null - } - Insert: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Update: { - categoria?: string | null - created_at?: string - detalhes?: string | null - estabelecimento?: string | null - id?: number - quando?: string | null - tipo?: string | null - usuario_id?: string | null - valor?: number | null - } - Relationships: [ - { - foreignKeyName: "transacoes_d2ca2174-fb8f-41d0-9897-a71a4af474a8_usuario_id_fkey" - columns: ["usuario_id"] - isOneToOne: false - referencedRelation: "usuarios" - referencedColumns: ["id"] - }, - ] - } usuarios: { Row: { created_at: string diff --git a/src/pages/GruposWhatsApp.tsx b/src/pages/GruposWhatsApp.tsx new file mode 100644 index 0000000..f15a354 --- /dev/null +++ b/src/pages/GruposWhatsApp.tsx @@ -0,0 +1,205 @@ + +import { useState, useEffect } from 'react'; +import Layout from '@/components/layout/Layout'; +import { Button } from '@/components/ui/button'; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card'; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; +import { Badge } from '@/components/ui/badge'; +import { Loader2, Plus, RefreshCw, MessageSquare } from 'lucide-react'; +import { cadastrarGrupoWhatsApp, listarGruposWhatsApp } from '@/services/gruposWhatsAppService'; +import { WhatsAppGroup } from '@/types/financialTypes'; +import { useToast } from '@/hooks/use-toast'; + +const GruposWhatsApp = () => { + const { toast } = useToast(); + const [grupos, setGrupos] = useState([]); + const [carregando, setCarregando] = useState(true); + const [cadastrando, setCadastrando] = useState(false); + const [userEmail, setUserEmail] = useState(''); + + // Buscar os grupos do usuário ao carregar a página + const buscarGrupos = async () => { + setCarregando(true); + try { + const gruposData = await listarGruposWhatsApp(); + setGrupos(gruposData); + } catch (error) { + console.error('Erro ao buscar grupos:', error); + toast({ + title: 'Erro', + description: 'Não foi possível carregar seus grupos do WhatsApp', + variant: 'destructive', + }); + } finally { + setCarregando(false); + } + }; + + useEffect(() => { + // Obter o email do usuário do localStorage + const email = localStorage.getItem('userEmail'); + if (email) { + setUserEmail(email.trim().toLowerCase()); + } + + buscarGrupos(); + }, []); + + // Cadastrar novo grupo + const handleCadastrarGrupo = async () => { + setCadastrando(true); + try { + const novoGrupo = await cadastrarGrupoWhatsApp(); + + if (novoGrupo) { + toast({ + title: 'Grupo registrado com sucesso', + description: 'Siga as instruções para completar o vínculo', + variant: 'default', + }); + + // Atualizar a lista de grupos + buscarGrupos(); + } else { + toast({ + title: 'Erro', + description: 'Não foi possível registrar o grupo', + variant: 'destructive', + }); + } + } catch (error) { + console.error('Erro ao cadastrar grupo:', error); + toast({ + title: 'Erro', + description: 'Não foi possível registrar o grupo', + variant: 'destructive', + }); + } finally { + setCadastrando(false); + } + }; + + return ( + +
+
+

Grupos do WhatsApp

+
+ + +
+
+ + + + Como cadastrar um grupo + + Siga os passos abaixo para vincular um grupo do WhatsApp à sua conta + + + +
    +
  1. Clique no botão "Cadastrar Grupo" acima
  2. +
  3. Adicione o número (61)99244-4275 ao grupo do WhatsApp que deseja automatizar
  4. +
  5. Envie uma mensagem neste grupo com o seguinte texto:
  6. +
+ +
+ {userEmail} +
+ +

+ Copie e cole o email exatamente como aparece acima +

+
+
+ + + + Seus grupos cadastrados + + Lista de grupos do WhatsApp que você cadastrou + + + + {carregando ? ( +
+ +
+ ) : grupos.length > 0 ? ( + + + + ID + Nome do grupo + Status + Cadastro + + + + {grupos.map((grupo) => ( + + {grupo.id} + + {grupo.nome_grupo || ( + + {grupo.remote_jid ? 'Sem nome definido' : 'Aguardando vínculo...'} + + )} + + + + {grupo.remote_jid ? 'Ativo' : 'Pendente'} + + + {new Date(grupo.created_at).toLocaleDateString()} + + ))} + +
+ ) : ( +
+ +

Você ainda não cadastrou nenhum grupo

+ +
+ )} +
+
+
+
+ ); +}; + +export default GruposWhatsApp; diff --git a/src/services/gruposWhatsAppService.ts b/src/services/gruposWhatsAppService.ts new file mode 100644 index 0000000..6b93d65 --- /dev/null +++ b/src/services/gruposWhatsAppService.ts @@ -0,0 +1,74 @@ + +import { supabase } from "@/integrations/supabase/client"; +import { WhatsAppGroup } from "@/types/financialTypes"; + +export async function cadastrarGrupoWhatsApp(): Promise { + try { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return null; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + // Criar registro na tabela grupos_whatsapp + const { data, error } = await supabase + .from('grupos_whatsapp') + .insert([ + { + user_id: localStorage.getItem('userId') || '', + login: normalizedEmail, + status: 'pendente' + } + ]) + .select(); + + if (error) { + console.error('Erro ao cadastrar grupo do WhatsApp:', error); + throw new Error('Não foi possível cadastrar o grupo de WhatsApp'); + } + + console.log('Grupo WhatsApp cadastrado com sucesso:', data); + return data[0]; + } catch (error) { + console.error('Erro ao cadastrar grupo do WhatsApp:', error); + return null; + } +} + +export async function listarGruposWhatsApp(): Promise { + try { + // Obter o email do usuário do localStorage + const userEmail = localStorage.getItem('userEmail'); + + if (!userEmail) { + console.error('Email do usuário não encontrado no localStorage'); + return []; + } + + // Normalizar o email (minúsculo e sem espaços) + const normalizedEmail = userEmail.trim().toLowerCase(); + + // Buscar grupos associados ao email do usuário + const { data, error } = await supabase + .from('grupos_whatsapp') + .select('*') + .eq('login', normalizedEmail) + .order('created_at', { ascending: false }); + + if (error) { + console.error('Erro ao listar grupos do WhatsApp:', error); + throw new Error('Não foi possível listar os grupos de WhatsApp'); + } + + console.log('Grupos WhatsApp encontrados:', data); + return data || []; + } catch (error) { + console.error('Erro ao listar grupos do WhatsApp:', error); + return []; + } +} diff --git a/src/types/financialTypes.ts b/src/types/financialTypes.ts index 6aac972..df2f016 100644 --- a/src/types/financialTypes.ts +++ b/src/types/financialTypes.ts @@ -1,4 +1,5 @@ + export interface Transaction { id: string; user: string; @@ -56,3 +57,14 @@ export interface ResultadoMeta { percentual_atingido: number; meta_batida: boolean; } + +export interface WhatsAppGroup { + id: number; + user_id: string; + remote_jid: string | null; + nome_grupo: string | null; + created_at: string; + status: string; + login: string; +} +