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.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-22 02:21:13 +00:00
parent 1b4a148142
commit 247c510f48
3 changed files with 93 additions and 58 deletions

View File

@ -21,29 +21,6 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
}) => { }) => {
const cleanupRef = useRef<() => void>(); const cleanupRef = useRef<() => void>();
// Função para remover estilos de highlight
const removeHighlightStyle = () => {
const elements = document.querySelectorAll('[data-tour]') as NodeListOf<HTMLElement>;
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 = [ const steps = [
{ {
title: "Passo 1 - Conecte seu WhatsApp", title: "Passo 1 - Conecte seu WhatsApp",
@ -95,16 +72,29 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
} }
]; ];
const currentStepData = steps[currentStep]; // Função para remover estilos de highlight
const removeHighlightStyle = () => {
const elements = document.querySelectorAll('[data-tour]') as NodeListOf<HTMLElement>;
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 // Aplicar highlight no elemento
const highlightElementStyle = () => { const highlightElementStyle = () => {
if (!currentStepData.spotlight) return; const currentStepData = steps[currentStep];
if (!currentStepData?.spotlight) return;
const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`) as HTMLElement; const element = document.querySelector(`[data-tour="${currentStepData.spotlight}"]`) as HTMLElement;
if (!element) return; if (!element) return;
// Aplicar estilos diretamente no elemento
element.style.backgroundColor = '#ffffff'; element.style.backgroundColor = '#ffffff';
element.style.color = '#000000'; element.style.color = '#000000';
element.style.fontWeight = '600'; element.style.fontWeight = '600';
@ -115,13 +105,18 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
element.style.zIndex = '9999'; element.style.zIndex = '9999';
}; };
// Aplicar ou remover highlight baseado no step atual // Effect para aplicar/remover highlight
useEffect(() => { useEffect(() => {
if (!isOpen) {
removeHighlightStyle();
return;
}
// Limpar estilos anteriores // Limpar estilos anteriores
removeHighlightStyle(); removeHighlightStyle();
if (currentStepData.spotlight) { const currentStepData = steps[currentStep];
// Pequeno delay para garantir que o DOM foi renderizado if (currentStepData?.spotlight) {
const timer = setTimeout(() => { const timer = setTimeout(() => {
highlightElementStyle(); highlightElementStyle();
}, 100); }, 100);
@ -132,13 +127,12 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
}; };
} }
// Cleanup quando o componente for desmontado ou step mudar
return () => { return () => {
if (cleanupRef.current) { if (cleanupRef.current) {
cleanupRef.current(); cleanupRef.current();
} }
}; };
}, [currentStep, currentStepData.spotlight]); }, [isOpen, currentStep]);
// Cleanup quando o componente for desmontado // Cleanup quando o componente for desmontado
useEffect(() => { useEffect(() => {
@ -147,6 +141,12 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
}; };
}, []); }, []);
if (!isOpen) {
return null;
}
const currentStepData = steps[currentStep];
return ( return (
<> <>
{/* Overlay escuro */} {/* Overlay escuro */}

View File

@ -30,7 +30,6 @@ export const useOnboardingTour = () => {
if (location.pathname !== '/') { if (location.pathname !== '/') {
console.log('❌ [TOUR] 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); setShouldShowTour(false);
isCheckingRef.current = false;
return; return;
} }
@ -41,7 +40,6 @@ export const useOnboardingTour = () => {
if (!userEmail) { if (!userEmail) {
console.log('❌ [TOUR] Email não encontrado no localStorage'); console.log('❌ [TOUR] Email não encontrado no localStorage');
setShouldShowTour(false); setShouldShowTour(false);
isCheckingRef.current = false;
return; return;
} }
@ -50,7 +48,6 @@ export const useOnboardingTour = () => {
if (shownThisSession) { if (shownThisSession) {
console.log('❌ [TOUR] Tour já foi exibido nesta sessão'); console.log('❌ [TOUR] Tour já foi exibido nesta sessão');
setShouldShowTour(false); setShouldShowTour(false);
isCheckingRef.current = false;
return; return;
} }
@ -74,7 +71,6 @@ export const useOnboardingTour = () => {
if (hasGroups) { if (hasGroups) {
console.log('✅ [TOUR] Usuário já tem grupos, não mostrar tour'); console.log('✅ [TOUR] Usuário já tem grupos, não mostrar tour');
setShouldShowTour(false); setShouldShowTour(false);
isCheckingRef.current = false;
return; return;
} }

View File

@ -27,49 +27,88 @@ const Assinatura = () => {
const handleSubscribe = async () => { const handleSubscribe = async () => {
setIsSubscribing(true); setIsSubscribing(true);
try { try {
// Puxa os dados mais atuais do usuário logado NO MOMENTO do click! console.log('🔄 [ASSINATURA] Iniciando processo de assinatura...');
const { data: { user } } = await supabase.auth.getUser();
// Verificar sessão do usuário
if (!user || !user.id || !user.email) { const { data: { user }, error: userError } = await supabase.auth.getUser();
toast.error("Sessão inválida. Por favor, faça login novamente.");
setIsSubscribing(false); if (userError) {
console.error('❌ [ASSINATURA] Erro de autenticação:', userError);
toast.error("Erro de autenticação. Faça login novamente.");
return; return;
} }
// log para debug - remova depois de testar! if (!user || !user.id || !user.email) {
console.log("Assinatura MercadoPago - email enviado:", user.email, "id:", user.id); 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', { 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) { if (error) {
console.error("Erro completo:", error); console.error('❌ [ASSINATURA] Erro na função:', error);
throw new Error(`Erro de comunicação: ${error.message}`);
// 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) { if (data?.error) {
throw new Error(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) { if (data?.init_point) {
console.log("Redirecionando para:", data.init_point); console.log('✅ [ASSINATURA] URL de checkout recebida:', data.init_point);
window.location.href = data.init_point; toast.success("Redirecionando para o pagamento...");
// Redirecionar para o MercadoPago
setTimeout(() => {
window.location.href = data.init_point;
}, 1000);
} else { } 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) { } 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 // Mensagens de erro mais específicas
if (error.message?.includes('temporariamente indisponível')) { if (error.name === 'NetworkError' || error.message?.includes('fetch')) {
toast.error("Serviço temporariamente indisponível para sua região. Tente novamente em alguns minutos."); 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 { } else {
toast.error(error.message || "Ocorreu um erro inesperado. Por favor, tente mais tarde."); toast.error("Erro inesperado. Tente novamente mais tarde.");
} }
} finally { } finally {
setIsSubscribing(false); setIsSubscribing(false);
} }
}; };