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:
parent
1b4a148142
commit
247c510f48
@ -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 */}
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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();
|
|
||||||
|
|
||||||
if (!user || !user.id || !user.email) {
|
// Verificar sessão do usuário
|
||||||
toast.error("Sessão inválida. Por favor, faça login novamente.");
|
const { data: { user }, error: userError } = await supabase.auth.getUser();
|
||||||
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user