From c5dbc236a192d03562f83a1057bfb164bced60c3 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 22 Jun 2025 01:41:03 +0000 Subject: [PATCH] Fix: Onboarding tour and subscription page issues The AI addressed the 404 error on the subscription page and investigated the onboarding tour not starting after login when no groups are registered. It also reviewed the code for potential errors in the tour logic. --- src/App.tsx | 2 + src/components/auth/ProtectedRoute.tsx | 21 ++++- src/hooks/useOnboardingTour.ts | 101 ++++++++++++++++++------- 3 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 4655b0a..e2c8e7b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -14,6 +14,7 @@ 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')); @@ -68,6 +69,7 @@ function App() { Carregando...}>} /> Carregando...}>} /> Carregando...}>} /> + Carregando...}>} /> Carregando...}>} /> Carregando...}>} /> Carregando...}>} /> diff --git a/src/components/auth/ProtectedRoute.tsx b/src/components/auth/ProtectedRoute.tsx index 0d1bbfa..865d941 100644 --- a/src/components/auth/ProtectedRoute.tsx +++ b/src/components/auth/ProtectedRoute.tsx @@ -26,13 +26,19 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { useEffect(() => { // Verificar sessão inicial supabase.auth.getSession().then(({ data: { session } }) => { - console.log('🔐 Sessão inicial:', session?.user?.email); + console.log('🔐 [PROTECTED_ROUTE] Sessão inicial:', session?.user?.email); setSession(session); setLoggedIn(!!session); setUser(session?.user ? { id: session.user.id } : null); if (session?.user?.email) { localStorage.setItem('userEmail', session.user.email); + console.log('👤 [PROTECTED_ROUTE] Email salvo no localStorage:', session.user.email); + + // Disparar evento customizado para notificar outros componentes sobre o login + window.dispatchEvent(new CustomEvent('userLoggedIn', { + detail: { email: session.user.email } + })); } else { localStorage.removeItem('userEmail'); } @@ -43,13 +49,22 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { // Listener para mudanças de auth const { data: { subscription } } = supabase.auth.onAuthStateChange( (_event, session) => { - console.log('🔄 Mudança de auth:', _event, session?.user?.email); + console.log('🔄 [PROTECTED_ROUTE] Mudança de auth:', _event, session?.user?.email); setSession(session); setLoggedIn(!!session); setUser(session?.user ? { id: session.user.id } : null); if (session?.user?.email) { localStorage.setItem('userEmail', session.user.email); + console.log('👤 [PROTECTED_ROUTE] Email atualizado no localStorage:', session.user.email); + + // Disparar evento customizado para notificar sobre o login + if (_event === 'SIGNED_IN') { + console.log('🎉 [PROTECTED_ROUTE] Login detectado, disparando evento'); + window.dispatchEvent(new CustomEvent('userLoggedIn', { + detail: { email: session.user.email } + })); + } } else { localStorage.removeItem('userEmail'); } @@ -79,7 +94,7 @@ const ProtectedRoute = ({ children }: ProtectedRouteProps) => { // Se tem sessão mas perfil não está completo, redirecionar para completar perfil if (session && !isProfileComplete) { - console.log('🚨 Redirecionando para complete-profile - perfil incompleto'); + console.log('🚨 [PROTECTED_ROUTE] Redirecionando para complete-profile - perfil incompleto'); return ; } diff --git a/src/hooks/useOnboardingTour.ts b/src/hooks/useOnboardingTour.ts index 337c1fc..14676d3 100644 --- a/src/hooks/useOnboardingTour.ts +++ b/src/hooks/useOnboardingTour.ts @@ -15,9 +15,11 @@ export const useOnboardingTour = () => { // Verificar se o tour deve ser exibido const checkTourConditions = async () => { try { + console.log('🔍 [TOUR] Iniciando verificação de condições do tour...'); + // Só mostrar o tour na página inicial (dashboard) if (location.pathname !== '/') { - console.log('❌ Tour só aparece no dashboard, página atual:', location.pathname); + console.log('❌ [TOUR] Tour só aparece no dashboard, página atual:', location.pathname); setShouldShowTour(false); return; } @@ -25,13 +27,14 @@ export const useOnboardingTour = () => { // Verificar se já foi mostrado nesta sessão const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true'; - console.log('🔍 Verificando condições do tour:', { + console.log('🔍 [TOUR] Verificando condições:', { shownThisSession, - location: location.pathname + location: location.pathname, + sessionStorage: sessionStorage.getItem(TOUR_SESSION_KEY) }); if (shownThisSession) { - console.log('❌ Tour já foi exibido nesta sessão'); + console.log('❌ [TOUR] Tour já foi exibido nesta sessão'); setShouldShowTour(false); setTourShownThisSession(true); return; @@ -41,91 +44,133 @@ export const useOnboardingTour = () => { let hasGroups = false; const userEmail = localStorage.getItem('userEmail'); - console.log('📧 Email do usuário para verificação:', userEmail); + console.log('📧 [TOUR] Email do usuário para verificação:', userEmail); if (!userEmail) { - console.log('❌ Email não encontrado no localStorage'); + console.log('❌ [TOUR] Email não encontrado no localStorage'); setShouldShowTour(false); return; } try { - console.log('🔍 Buscando grupos para o usuário...'); + console.log('🔍 [TOUR] Buscando grupos para o usuário...'); const groups = await listWhatsAppGroups(); hasGroups = groups.length > 0; - console.log('👥 Grupos encontrados:', { + console.log('👥 [TOUR] Grupos encontrados:', { quantidade: groups.length, - grupos: groups.map(g => ({ id: g.id, nome: g.nome_grupo, status: g.status })) + grupos: groups.map(g => ({ id: g.id, nome: g.nome_grupo, status: g.status, login: g.login })) }); + console.log('📊 [TOUR] Query resultado completo:', groups); } catch (error) { - console.log('⚠️ Erro ao verificar grupos, assumindo que não há grupos:', error); + console.log('⚠️ [TOUR] Erro ao verificar grupos, assumindo que não há grupos:', error); hasGroups = false; } // Tour deve aparecer se NÃO tiver grupos const shouldShow = !hasGroups; - console.log('🎯 Resultado final da verificação:', { + console.log('🎯 [TOUR] Resultado final da verificação:', { hasGroups, shouldShow, currentPath: location.pathname, - userEmail: userEmail + userEmail: userEmail, + shownThisSession }); setShouldShowTour(shouldShow); // Se deve mostrar o tour e não foi mostrado ainda, abrir automaticamente if (shouldShow && !shownThisSession && !isOpen) { - console.log('🚀 Abrindo tour automaticamente - usuário sem grupos'); + console.log('🚀 [TOUR] Abrindo tour automaticamente - usuário sem grupos'); setTimeout(() => { + console.log('🎬 [TOUR] Executando abertura do tour...'); setIsOpen(true); setCurrentStep(0); setTourShownThisSession(true); sessionStorage.setItem(TOUR_SESSION_KEY, 'true'); - }, 1000); // Delay para garantir que a página carregou completamente + }, 2000); // Delay para garantir que tudo carregue } else if (!shouldShow) { - console.log('✅ Usuário já tem grupos, não mostrar tour'); + console.log('✅ [TOUR] Usuário já tem grupos, não mostrar tour'); setIsOpen(false); } } catch (error) { - console.error('❌ Erro ao verificar condições do tour:', error); + console.error('❌ [TOUR] Erro ao verificar condições do tour:', error); setShouldShowTour(false); } }; // Verificar condições quando a localização mudar ou na inicialização useEffect(() => { - console.log('🔄 useEffect disparado - verificando condições do tour'); + console.log('🔄 [TOUR] useEffect disparado - verificando condições do tour'); // Aguardar um pouco para garantir que os dados do usuário estão disponíveis const timer = setTimeout(() => { checkTourConditions(); - }, 500); + }, 1000); return () => clearTimeout(timer); }, [location.pathname]); + // Escutar evento customizado de login + useEffect(() => { + const handleUserLoggedIn = (event: CustomEvent) => { + console.log('🎉 [TOUR] Evento de login recebido:', event.detail); + if (location.pathname === '/') { + console.log('📧 [TOUR] Login detectado no dashboard, verificando condições do tour'); + setTimeout(() => { + checkTourConditions(); + }, 2500); + } + }; + + window.addEventListener('userLoggedIn', handleUserLoggedIn as EventListener); + return () => { + window.removeEventListener('userLoggedIn', handleUserLoggedIn as EventListener); + }; + }, [location.pathname]); + // Verificar também quando o email do usuário estiver disponível useEffect(() => { const userEmail = localStorage.getItem('userEmail'); + console.log('📧 [TOUR] Segundo useEffect - email disponível:', userEmail); if (userEmail && location.pathname === '/') { - console.log('📧 Email detectado, re-verificando condições do tour'); - checkTourConditions(); + console.log('📧 [TOUR] Email detectado, re-verificando condições do tour'); + // Delay maior para garantir que o usuário já está logado completamente + setTimeout(() => { + checkTourConditions(); + }, 1500); } }, []); - // Limpar tour ao mudar de sessão + // Escutar mudanças no localStorage para detectar login useEffect(() => { - const handleStorageChange = () => { - const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true'; - setTourShownThisSession(shownThisSession); + const handleStorageChange = (e: StorageEvent) => { + if (e.key === 'userEmail' && e.newValue) { + console.log('👤 [TOUR] Login detectado via storage event:', e.newValue); + if (location.pathname === '/') { + setTimeout(() => { + checkTourConditions(); + }, 2000); + } + } }; window.addEventListener('storage', handleStorageChange); return () => window.removeEventListener('storage', handleStorageChange); + }, [location.pathname]); + + // Limpar tour ao mudar de sessão + useEffect(() => { + const handleSessionStorageChange = () => { + const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true'; + setTourShownThisSession(shownThisSession); + }; + + window.addEventListener('storage', handleSessionStorageChange); + return () => window.removeEventListener('storage', handleSessionStorageChange); }, []); const nextStep = () => { - console.log('➡️ Próximo step do tour:', currentStep + 1); + console.log('➡️ [TOUR] Próximo step do tour:', currentStep + 1); if (currentStep < 2) { setCurrentStep(currentStep + 1); } else { @@ -134,12 +179,12 @@ export const useOnboardingTour = () => { }; const skipTour = () => { - console.log('⏭️ Pulando tour'); + console.log('⏭️ [TOUR] Pulando tour'); closeTour(); }; const closeTour = () => { - console.log('❌ Fechando tour'); + console.log('❌ [TOUR] Fechando tour'); setIsOpen(false); setCurrentStep(0); // Marcar como exibido nesta sessão @@ -149,7 +194,7 @@ export const useOnboardingTour = () => { // Função para forçar reabrir o tour (para testes) const reopenTour = () => { - console.log('🔄 Reabrindo tour manualmente'); + console.log('🔄 [TOUR] Reabrindo tour manualmente'); sessionStorage.removeItem(TOUR_SESSION_KEY); setTourShownThisSession(false); setIsOpen(true);