From 1f3197caf510f894b4146bd88ad623e5b0c25cb6 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 02:25:49 +0000
Subject: [PATCH] feat: Move user button and integrate webhook
Move the logged-in user button above the month filter on the dashboard. Integrate a webhook call to send contact form data to a specified URL.
---
.../dashboard/UserProfileButton.tsx | 97 +++++++++++++++++++
src/components/help/ContactForm.tsx | 31 +++++-
src/components/layout/ModernLayout.tsx | 86 ----------------
src/pages/Index.tsx | 13 ++-
src/services/webhookService.ts | 70 +++++++++++++
5 files changed, 205 insertions(+), 92 deletions(-)
create mode 100644 src/components/dashboard/UserProfileButton.tsx
create mode 100644 src/services/webhookService.ts
diff --git a/src/components/dashboard/UserProfileButton.tsx b/src/components/dashboard/UserProfileButton.tsx
new file mode 100644
index 0000000..a2a92c1
--- /dev/null
+++ b/src/components/dashboard/UserProfileButton.tsx
@@ -0,0 +1,97 @@
+
+import React, { useState, useEffect } from 'react';
+import {
+ DropdownMenu,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuTrigger,
+} from "@/components/ui/dropdown-menu";
+import { Button } from '@/components/ui/button';
+import { LogOut, User } from 'lucide-react';
+import { supabase } from '@/integrations/supabase/client';
+import { useToast } from '@/hooks/use-toast';
+import { useNavigate } from 'react-router-dom';
+
+const UserProfileButton = () => {
+ const [userEmail, setUserEmail] = useState('');
+ const [dropdownOpen, setDropdownOpen] = useState(false);
+ const { toast } = useToast();
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ // Buscar dados do usuário logado
+ const getUserData = async () => {
+ const { data: { user } } = await supabase.auth.getUser();
+ if (user?.email) {
+ setUserEmail(user.email);
+ }
+ };
+
+ getUserData();
+ }, []);
+
+ const handleLogout = async () => {
+ try {
+ const { error } = await supabase.auth.signOut();
+ if (error) throw error;
+
+ // Limpar localStorage
+ localStorage.removeItem('userEmail');
+
+ toast({
+ title: "Logout realizado",
+ description: "Você foi desconectado com sucesso"
+ });
+
+ navigate('/auth');
+ } catch (error) {
+ console.error('Erro no logout:', error);
+ toast({
+ title: "Erro no logout",
+ description: "Ocorreu um erro ao sair da conta",
+ variant: "destructive"
+ });
+ }
+ };
+
+ return (
+
+
+
+
+
+ {
+ e.preventDefault();
+ e.stopPropagation();
+ setDropdownOpen(false);
+ handleLogout();
+ }}
+ className="flex items-center gap-2 text-red-600 hover:text-red-700 hover:bg-red-50 cursor-pointer"
+ >
+
+ Sair
+
+
+
+ );
+};
+
+export default UserProfileButton;
diff --git a/src/components/help/ContactForm.tsx b/src/components/help/ContactForm.tsx
index 0d09879..68f9b18 100644
--- a/src/components/help/ContactForm.tsx
+++ b/src/components/help/ContactForm.tsx
@@ -4,6 +4,7 @@ import { ArrowLeft } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/hooks/use-toast';
import { supabase } from '@/integrations/supabase/client';
+import { enviarFaleConoscoParaWebhook } from '@/utils/webhookService';
import ContactFormFields from './ContactFormFields';
import ContactFormHeader from './ContactFormHeader';
@@ -37,6 +38,15 @@ const ContactForm = ({ onBack }: ContactFormProps) => {
try {
let anexoUrl = null;
+ let userId = null;
+ let userEmail = null;
+
+ // Obter dados do usuário
+ const { data: { user } } = await supabase.auth.getUser();
+ if (user) {
+ userId = user.id;
+ userEmail = user.email;
+ }
// Upload do anexo se existe
if (formData.anexo) {
@@ -64,12 +74,31 @@ const ContactForm = ({ onBack }: ContactFormProps) => {
motivo: formData.motivo,
mensagem: formData.mensagem,
anexo_url: anexoUrl,
- user_id: (await supabase.auth.getUser()).data.user?.id,
+ user_id: userId,
status: 'pendente'
});
if (error) throw error;
+ // Enviar dados para o webhook do N8N
+ const webhookData = {
+ assunto: formData.assunto,
+ motivo: formData.motivo,
+ mensagem: formData.mensagem,
+ anexo_url: anexoUrl,
+ user_id: userId,
+ user_email: userEmail,
+ data_envio: new Date().toISOString()
+ };
+
+ try {
+ await enviarFaleConoscoParaWebhook(webhookData);
+ console.log("Dados enviados para webhook N8N com sucesso");
+ } catch (webhookError) {
+ console.error("Erro ao enviar para webhook N8N:", webhookError);
+ // Não interrompe o fluxo se o webhook falhar
+ }
+
toast({
title: "Mensagem enviada!",
description: "Você vai receber a resposta no e-mail que cadastrou aqui. Obrigado!",
diff --git a/src/components/layout/ModernLayout.tsx b/src/components/layout/ModernLayout.tsx
index 6abbb27..171ae3c 100644
--- a/src/components/layout/ModernLayout.tsx
+++ b/src/components/layout/ModernLayout.tsx
@@ -78,10 +78,6 @@ export default function ModernLayout({ children }: ModernLayoutProps) {
const [open, setOpen] = useState(false);
const location = useLocation();
const isMobile = useIsMobile();
- const { toast } = useToast();
- const navigate = useNavigate();
- const [userEmail, setUserEmail] = useState('');
- const [dropdownOpen, setDropdownOpen] = useState(false);
const {
isOpen: tourOpen,
@@ -91,42 +87,6 @@ export default function ModernLayout({ children }: ModernLayoutProps) {
closeTour
} = useOnboardingTour();
- useEffect(() => {
- // Buscar dados do usuário logado
- const getUserData = async () => {
- const { data: { user } } = await supabase.auth.getUser();
- if (user?.email) {
- setUserEmail(user.email);
- }
- };
-
- getUserData();
- }, []);
-
- const handleLogout = async () => {
- try {
- const { error } = await supabase.auth.signOut();
- if (error) throw error;
-
- // Limpar localStorage
- localStorage.removeItem('userEmail');
-
- toast({
- title: "Logout realizado",
- description: "Você foi desconectado com sucesso"
- });
-
- navigate('/auth');
- } catch (error) {
- console.error('Erro no logout:', error);
- toast({
- title: "Erro no logout",
- description: "Ocorreu um erro ao sair da conta",
- variant: "destructive"
- });
- }
- };
-
const mainLinks = [
{
id: "dashboard",
@@ -260,52 +220,6 @@ export default function ModernLayout({ children }: ModernLayoutProps) {
className="space-y-1"
iconContainerClassName={!open ? "justify-center" : ""}
/>
-
- {/* User Profile */}
-
-
-
-
-
-
- {
- e.preventDefault();
- e.stopPropagation();
- setDropdownOpen(false);
- handleLogout();
- }}
- className="flex items-center gap-2 text-red-600 hover:text-red-700 hover:bg-red-50 cursor-pointer"
- >
-
- Sair
-
-
-
-
diff --git a/src/pages/Index.tsx b/src/pages/Index.tsx
index 47a5dee..79026bd 100644
--- a/src/pages/Index.tsx
+++ b/src/pages/Index.tsx
@@ -1,10 +1,10 @@
-
import { useState, useEffect } from 'react';
import Layout from '@/components/layout/Layout';
import SummaryCard from '@/components/dashboard/SummaryCard';
import TransactionsTable from '@/components/dashboard/TransactionsTable';
import CategoryChart from '@/components/dashboard/CategoryChart';
import MonthlyChart from '@/components/dashboard/MonthlyChart';
+import UserProfileButton from '@/components/dashboard/UserProfileButton';
import { MonthFilter } from '@/components/filters/MonthFilter';
import { OnboardingTour, useOnboardingTour } from '@/components/onboarding';
import { Wallet, ArrowUp, ArrowDown, PiggyBank } from 'lucide-react';
@@ -154,10 +154,13 @@ const Dashboard = () => {
Dados de: {formatMonthDisplay(selectedMonth)}
-
+
+
+
+
{/* Resumo em cards */}
diff --git a/src/services/webhookService.ts b/src/services/webhookService.ts
new file mode 100644
index 0000000..43b6a7d
--- /dev/null
+++ b/src/services/webhookService.ts
@@ -0,0 +1,70 @@
+
+// URL do webhook para notificação de novo cadastro
+const WEBHOOK_URL = "https://hook.us1.make.com/j6y1odto82tyo38qv3jh4579kkluhsx7";
+
+// URL do webhook para fale conosco
+const FALE_CONOSCO_WEBHOOK_URL = "https://webhookn8n.innova1001.com.br/webhook/faleconosco";
+
+interface UserData {
+ nome: string;
+ empresa?: string;
+ email: string;
+ whatsapp?: string;
+ data_cadastro: string;
+ origem: string;
+}
+
+interface FaleConoscoData {
+ assunto: string;
+ motivo: string;
+ mensagem: string;
+ anexo_url?: string;
+ user_id?: string;
+ user_email?: string;
+ data_envio: string;
+}
+
+// Função para enviar dados do usuário para o webhook
+export const enviarDadosParaWebhook = async (dadosUsuario: UserData) => {
+ try {
+ console.log("Enviando dados do usuário para webhook:", dadosUsuario);
+
+ await fetch(WEBHOOK_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ mode: 'no-cors', // Necessário para webhooks externos
+ body: JSON.stringify(dadosUsuario),
+ });
+
+ console.log("Dados enviados com sucesso para o webhook");
+ } catch (error) {
+ console.error("Erro ao enviar dados para o webhook:", error);
+ }
+};
+
+// Função para enviar dados do Fale Conosco para o webhook do N8N
+export const enviarFaleConoscoParaWebhook = async (dadosFaleConosco: FaleConoscoData) => {
+ try {
+ console.log("Enviando dados do Fale Conosco para webhook N8N:", dadosFaleConosco);
+
+ const response = await fetch(FALE_CONOSCO_WEBHOOK_URL, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(dadosFaleConosco),
+ });
+
+ if (!response.ok) {
+ throw new Error(`HTTP error! status: ${response.status}`);
+ }
+
+ console.log("Dados do Fale Conosco enviados com sucesso para o webhook N8N");
+ return true;
+ } catch (error) {
+ console.error("Erro ao enviar dados do Fale Conosco para o webhook N8N:", error);
+ throw error;
+ }
+};