From 247c510f4878669ca6f5c6de8d4c42080119ea2d 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 02:21:13 +0000 Subject: [PATCH] Fix: App crashes after login and subscription page The AI addressed the app crashing after login and investigated the subscription page issue, focusing on resolving the problem to display the purchase page, without providing logs. --- src/components/onboarding/OnboardingTour.tsx | 62 +++++++------- src/hooks/useOnboardingTour.ts | 4 - src/pages/Assinatura.tsx | 85 ++++++++++++++------ 3 files changed, 93 insertions(+), 58 deletions(-) diff --git a/src/components/onboarding/OnboardingTour.tsx b/src/components/onboarding/OnboardingTour.tsx index ea4818e..07f9ed6 100644 --- a/src/components/onboarding/OnboardingTour.tsx +++ b/src/components/onboarding/OnboardingTour.tsx @@ -21,29 +21,6 @@ const OnboardingTour: React.FC = ({ }) => { const cleanupRef = useRef<() => void>(); - // Função para remover estilos de highlight - const removeHighlightStyle = () => { - const elements = document.querySelectorAll('[data-tour]') as NodeListOf; - elements.forEach(element => { - element.style.backgroundColor = ''; - element.style.color = ''; - element.style.fontWeight = ''; - element.style.boxShadow = ''; - element.style.border = ''; - element.style.borderRadius = ''; - element.style.position = ''; - element.style.zIndex = ''; - }); - }; - - if (!isOpen) { - // Limpar estilos quando o tour não estiver aberto - useEffect(() => { - removeHighlightStyle(); - }, []); - return null; - } - const steps = [ { title: "Passo 1 - Conecte seu WhatsApp", @@ -95,16 +72,29 @@ const OnboardingTour: React.FC = ({ } ]; - const currentStepData = steps[currentStep]; + // Função para remover estilos de highlight + const removeHighlightStyle = () => { + const elements = document.querySelectorAll('[data-tour]') as NodeListOf; + elements.forEach(element => { + element.style.backgroundColor = ''; + element.style.color = ''; + element.style.fontWeight = ''; + element.style.boxShadow = ''; + element.style.border = ''; + element.style.borderRadius = ''; + element.style.position = ''; + element.style.zIndex = ''; + }); + }; // Aplicar highlight no elemento const highlightElementStyle = () => { - if (!currentStepData.spotlight) return; + const currentStepData = steps[currentStep]; + if (!currentStepData?.spotlight) return; const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`) as HTMLElement; if (!element) return; - // Aplicar estilos diretamente no elemento element.style.backgroundColor = '#ffffff'; element.style.color = '#000000'; element.style.fontWeight = '600'; @@ -115,13 +105,18 @@ const OnboardingTour: React.FC = ({ element.style.zIndex = '9999'; }; - // Aplicar ou remover highlight baseado no step atual + // Effect para aplicar/remover highlight useEffect(() => { + if (!isOpen) { + removeHighlightStyle(); + return; + } + // Limpar estilos anteriores removeHighlightStyle(); - if (currentStepData.spotlight) { - // Pequeno delay para garantir que o DOM foi renderizado + const currentStepData = steps[currentStep]; + if (currentStepData?.spotlight) { const timer = setTimeout(() => { highlightElementStyle(); }, 100); @@ -132,13 +127,12 @@ const OnboardingTour: React.FC = ({ }; } - // Cleanup quando o componente for desmontado ou step mudar return () => { if (cleanupRef.current) { cleanupRef.current(); } }; - }, [currentStep, currentStepData.spotlight]); + }, [isOpen, currentStep]); // Cleanup quando o componente for desmontado useEffect(() => { @@ -147,6 +141,12 @@ const OnboardingTour: React.FC = ({ }; }, []); + if (!isOpen) { + return null; + } + + const currentStepData = steps[currentStep]; + return ( <> {/* Overlay escuro */} diff --git a/src/hooks/useOnboardingTour.ts b/src/hooks/useOnboardingTour.ts index 4328402..15d3d2e 100644 --- a/src/hooks/useOnboardingTour.ts +++ b/src/hooks/useOnboardingTour.ts @@ -30,7 +30,6 @@ export const useOnboardingTour = () => { if (location.pathname !== '/') { console.log('❌ [TOUR] Tour só aparece no dashboard, página atual:', location.pathname); setShouldShowTour(false); - isCheckingRef.current = false; return; } @@ -41,7 +40,6 @@ export const useOnboardingTour = () => { if (!userEmail) { console.log('❌ [TOUR] Email não encontrado no localStorage'); setShouldShowTour(false); - isCheckingRef.current = false; return; } @@ -50,7 +48,6 @@ export const useOnboardingTour = () => { if (shownThisSession) { console.log('❌ [TOUR] Tour já foi exibido nesta sessão'); setShouldShowTour(false); - isCheckingRef.current = false; return; } @@ -74,7 +71,6 @@ export const useOnboardingTour = () => { if (hasGroups) { console.log('✅ [TOUR] Usuário já tem grupos, não mostrar tour'); setShouldShowTour(false); - isCheckingRef.current = false; return; } diff --git a/src/pages/Assinatura.tsx b/src/pages/Assinatura.tsx index b18b5f1..d74df3d 100644 --- a/src/pages/Assinatura.tsx +++ b/src/pages/Assinatura.tsx @@ -27,49 +27,88 @@ const Assinatura = () => { const handleSubscribe = async () => { setIsSubscribing(true); try { - // Puxa os dados mais atuais do usuário logado NO MOMENTO do click! - const { data: { user } } = await supabase.auth.getUser(); - - if (!user || !user.id || !user.email) { - toast.error("Sessão inválida. Por favor, faça login novamente."); - setIsSubscribing(false); + console.log('🔄 [ASSINATURA] Iniciando processo de assinatura...'); + + // Verificar sessão do usuário + const { data: { user }, error: userError } = await supabase.auth.getUser(); + + if (userError) { + console.error('❌ [ASSINATURA] Erro de autenticação:', userError); + toast.error("Erro de autenticação. Faça login novamente."); return; } - // log para debug - remova depois de testar! - console.log("Assinatura MercadoPago - email enviado:", user.email, "id:", user.id); + if (!user || !user.id || !user.email) { + console.error('❌ [ASSINATURA] Usuário não autenticado'); + toast.error("Sessão inválida. Por favor, faça login novamente."); + return; + } + console.log('✅ [ASSINATURA] Usuário autenticado:', { id: user.id, email: user.email }); + + // Chamar a função do MercadoPago + console.log('📞 [ASSINATURA] Chamando função mercado-pago-subscribe...'); const { data, error } = await supabase.functions.invoke('mercado-pago-subscribe', { - body: { email: user.email, userId: user.id }, + body: { + email: user.email, + userId: user.id + }, }); if (error) { - console.error("Erro completo:", error); - throw new Error(`Erro de comunicação: ${error.message}`); + console.error('❌ [ASSINATURA] Erro na função:', error); + + // Tratar diferentes tipos de erro + if (error.message?.includes('fetch')) { + toast.error("Erro de conexão. Verifique sua internet e tente novamente."); + } else if (error.message?.includes('401')) { + toast.error("Sessão expirada. Faça login novamente."); + } else { + toast.error(`Erro: ${error.message || 'Erro desconhecido'}`); + } + return; } - if (data.error) { - throw new Error(data.error); + if (data?.error) { + console.error('❌ [ASSINATURA] Erro nos dados:', data.error); + + // Tratar erros específicos do MercadoPago + if (data.error.includes('temporariamente indisponível')) { + toast.error("Serviço temporariamente indisponível para sua região. Entre em contato conosco."); + } else if (data.error.includes('Token')) { + toast.error("Erro de configuração. Entre em contato com o suporte."); + } else { + toast.error(data.error); + } + return; } - if (data.init_point) { - console.log("Redirecionando para:", data.init_point); - window.location.href = data.init_point; + if (data?.init_point) { + console.log('✅ [ASSINATURA] URL de checkout recebida:', data.init_point); + toast.success("Redirecionando para o pagamento..."); + + // Redirecionar para o MercadoPago + setTimeout(() => { + window.location.href = data.init_point; + }, 1000); } else { - throw new Error("Não foi possível obter a URL de checkout. Tente novamente."); + console.error('❌ [ASSINATURA] URL de checkout não encontrada'); + toast.error("Não foi possível gerar o link de pagamento. Tente novamente."); } } catch (error: any) { - console.error("Erro ao criar a assinatura:", error); + console.error('💥 [ASSINATURA] Erro geral:', error); - // Mensagem mais amigável para erro de região - if (error.message?.includes('temporariamente indisponível')) { - toast.error("Serviço temporariamente indisponível para sua região. Tente novamente em alguns minutos."); + // Mensagens de erro mais específicas + if (error.name === 'NetworkError' || error.message?.includes('fetch')) { + toast.error("Erro de conexão. Verifique sua internet e tente novamente."); + } else if (error.message?.includes('JSON')) { + toast.error("Erro de comunicação. Tente novamente."); } else { - toast.error(error.message || "Ocorreu um erro inesperado. Por favor, tente mais tarde."); + toast.error("Erro inesperado. Tente novamente mais tarde."); } } finally { - setIsSubscribing(false); + setIsSubscribing(false); } };