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.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-22 01:41:03 +00:00
parent bc4e03e7c2
commit c5dbc236a1
3 changed files with 93 additions and 31 deletions

View File

@ -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() {
<Route path="/categorias" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><Categorias /></Suspense></ProtectedRoute>} />
<Route path="/metas" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><Metas /></Suspense></ProtectedRoute>} />
<Route path="/calendario" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><Calendario /></Suspense></ProtectedRoute>} />
<Route path="/assinatura" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><Assinatura /></Suspense></ProtectedRoute>} />
<Route path="/whatsapp" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><WhatsApp /></Suspense></ProtectedRoute>} />
<Route path="/grupos-whatsapp" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><GruposWhatsApp /></Suspense></ProtectedRoute>} />
<Route path="/admin-faq" element={<ProtectedRoute><Suspense fallback={<div>Carregando...</div>}><AdminFAQ /></Suspense></ProtectedRoute>} />

View File

@ -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 <Navigate to="/complete-profile" replace />;
}

View File

@ -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);