Reverted to commit 937b27de6c
This commit is contained in:
parent
9a4b6a2a9e
commit
07d370b1b8
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { X } from 'lucide-react';
|
import { X } from 'lucide-react';
|
||||||
@ -19,32 +19,6 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
|||||||
onSkip,
|
onSkip,
|
||||||
onClose
|
onClose
|
||||||
}) => {
|
}) => {
|
||||||
// Definir a função ANTES de usá-la
|
|
||||||
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 = '';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Cleanup de estilos quando o componente for desmontado ou tour fechado
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isOpen) {
|
|
||||||
removeHighlightStyle();
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
removeHighlightStyle();
|
|
||||||
};
|
|
||||||
}, [isOpen]);
|
|
||||||
|
|
||||||
if (!isOpen) return null;
|
if (!isOpen) return null;
|
||||||
|
|
||||||
const steps = [
|
const steps = [
|
||||||
@ -100,38 +74,6 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
|||||||
|
|
||||||
const currentStepData = steps[currentStep];
|
const currentStepData = steps[currentStep];
|
||||||
|
|
||||||
// Estilo para destacar o elemento com fundo branco e texto preto
|
|
||||||
const highlightElementStyle = () => {
|
|
||||||
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';
|
|
||||||
element.style.boxShadow = '0 0 20px rgba(59, 130, 246, 0.6)';
|
|
||||||
element.style.border = '2px solid rgba(59, 130, 246, 0.8)';
|
|
||||||
element.style.borderRadius = '8px';
|
|
||||||
element.style.position = 'relative';
|
|
||||||
element.style.zIndex = '9999';
|
|
||||||
};
|
|
||||||
|
|
||||||
// Aplicar ou remover highlight baseado no step atual
|
|
||||||
useEffect(() => {
|
|
||||||
if (currentStepData.spotlight) {
|
|
||||||
// Primeiro remover qualquer highlight anterior
|
|
||||||
removeHighlightStyle();
|
|
||||||
// Pequeno delay para garantir que o DOM foi renderizado
|
|
||||||
setTimeout(() => {
|
|
||||||
highlightElementStyle();
|
|
||||||
}, 100);
|
|
||||||
} else {
|
|
||||||
removeHighlightStyle();
|
|
||||||
}
|
|
||||||
}, [currentStep, currentStepData.spotlight]);
|
|
||||||
|
|
||||||
const getSpotlightStyle = () => {
|
const getSpotlightStyle = () => {
|
||||||
if (!currentStepData.spotlight) return {};
|
if (!currentStepData.spotlight) return {};
|
||||||
|
|
||||||
@ -174,6 +116,7 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
|||||||
const deltaX = elementCenterX - cardCenterX;
|
const deltaX = elementCenterX - cardCenterX;
|
||||||
const deltaY = elementCenterY - cardCenterY;
|
const deltaY = elementCenterY - cardCenterY;
|
||||||
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI);
|
||||||
|
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
|
|
||||||
// Posicionar a seta no meio do caminho
|
// Posicionar a seta no meio do caminho
|
||||||
const arrowX = cardCenterX + (deltaX * 0.6);
|
const arrowX = cardCenterX + (deltaX * 0.6);
|
||||||
@ -234,6 +177,56 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Estilo para destacar o elemento com fundo branco e texto preto
|
||||||
|
const highlightElementStyle = () => {
|
||||||
|
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';
|
||||||
|
element.style.boxShadow = '0 0 20px rgba(59, 130, 246, 0.6)';
|
||||||
|
element.style.border = '2px solid rgba(59, 130, 246, 0.8)';
|
||||||
|
element.style.borderRadius = '8px';
|
||||||
|
element.style.position = 'relative';
|
||||||
|
element.style.zIndex = '9999';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remover estilos quando não há spotlight
|
||||||
|
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 ou remover highlight baseado no step atual
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (currentStepData.spotlight) {
|
||||||
|
// Pequeno delay para garantir que o DOM foi renderizado
|
||||||
|
setTimeout(() => {
|
||||||
|
highlightElementStyle();
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
removeHighlightStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup quando o componente for desmontado
|
||||||
|
return () => {
|
||||||
|
removeHighlightStyle();
|
||||||
|
};
|
||||||
|
}, [currentStep, currentStepData.spotlight]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Overlay escuro */}
|
{/* Overlay escuro */}
|
||||||
|
|||||||
@ -10,19 +10,11 @@ export const useOnboardingTour = () => {
|
|||||||
const [currentStep, setCurrentStep] = useState(0);
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
const [shouldShowTour, setShouldShowTour] = useState(false);
|
const [shouldShowTour, setShouldShowTour] = useState(false);
|
||||||
const [tourShownThisSession, setTourShownThisSession] = useState(false);
|
const [tourShownThisSession, setTourShownThisSession] = useState(false);
|
||||||
const [isCheckingConditions, setIsCheckingConditions] = useState(false);
|
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
||||||
// Verificar se o tour deve ser exibido
|
// Verificar se o tour deve ser exibido
|
||||||
const checkTourConditions = async () => {
|
const checkTourConditions = async () => {
|
||||||
// Evitar múltiplas verificações simultâneas
|
|
||||||
if (isCheckingConditions) {
|
|
||||||
console.log('🔄 [TOUR] Verificação já em andamento, ignorando...');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsCheckingConditions(true);
|
|
||||||
console.log('🔍 [TOUR] Iniciando verificação de condições do tour...');
|
console.log('🔍 [TOUR] Iniciando verificação de condições do tour...');
|
||||||
|
|
||||||
// Só mostrar o tour na página inicial (dashboard)
|
// Só mostrar o tour na página inicial (dashboard)
|
||||||
@ -32,12 +24,6 @@ export const useOnboardingTour = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se tour já está aberto, não verificar novamente
|
|
||||||
if (isOpen) {
|
|
||||||
console.log('🚫 [TOUR] Tour já está aberto, ignorando verificação');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verificar se existe email no localStorage
|
// Verificar se existe email no localStorage
|
||||||
const userEmail = localStorage.getItem('userEmail');
|
const userEmail = localStorage.getItem('userEmail');
|
||||||
console.log('📧 [TOUR] Email do usuário para verificação:', userEmail);
|
console.log('📧 [TOUR] Email do usuário para verificação:', userEmail);
|
||||||
@ -48,7 +34,7 @@ export const useOnboardingTour = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SEMPRE verificar se há grupos cadastrados
|
// SEMPRE verificar se há grupos cadastrados (ignorar sessionStorage inicialmente)
|
||||||
let hasGroups = false;
|
let hasGroups = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -74,10 +60,10 @@ export const useOnboardingTour = () => {
|
|||||||
|
|
||||||
// Se não tem grupos, verificar se já foi mostrado nesta sessão
|
// Se não tem grupos, verificar se já foi mostrado nesta sessão
|
||||||
const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true';
|
const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true';
|
||||||
console.log('🔍 [TOUR] Usuário SEM grupos. Tour já exibido nesta sessão:', shownThisSession);
|
console.log('🔍 [TOUR] Usuário SEM grupos. Verificando se tour já foi exibido nesta sessão:', shownThisSession);
|
||||||
|
|
||||||
if (shownThisSession) {
|
if (shownThisSession) {
|
||||||
console.log('❌ [TOUR] Tour já foi exibido nesta sessão');
|
console.log('❌ [TOUR] Tour já foi exibido nesta sessão para este usuário sem grupos');
|
||||||
setShouldShowTour(false);
|
setShouldShowTour(false);
|
||||||
setTourShownThisSession(true);
|
setTourShownThisSession(true);
|
||||||
return;
|
return;
|
||||||
@ -87,32 +73,20 @@ export const useOnboardingTour = () => {
|
|||||||
console.log('🎯 [TOUR] CONDIÇÕES ATENDIDAS - Usuário sem grupos e tour não exibido ainda');
|
console.log('🎯 [TOUR] CONDIÇÕES ATENDIDAS - Usuário sem grupos e tour não exibido ainda');
|
||||||
setShouldShowTour(true);
|
setShouldShowTour(true);
|
||||||
|
|
||||||
// Abrir tour automaticamente após um pequeno delay, mas apenas se não estiver já aberto
|
// Abrir tour automaticamente após um pequeno delay
|
||||||
if (!isOpen) {
|
|
||||||
console.log('🚀 [TOUR] Abrindo tour automaticamente - usuário sem grupos');
|
console.log('🚀 [TOUR] Abrindo tour automaticamente - usuário sem grupos');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Verificar novamente se não foi aberto enquanto esperava
|
|
||||||
setIsOpen(prevIsOpen => {
|
|
||||||
if (!prevIsOpen) {
|
|
||||||
console.log('🎬 [TOUR] Executando abertura do tour...');
|
console.log('🎬 [TOUR] Executando abertura do tour...');
|
||||||
|
setIsOpen(true);
|
||||||
setCurrentStep(0);
|
setCurrentStep(0);
|
||||||
// Marcar como exibido quando realmente abrir
|
// SÓ marcar como exibido quando realmente abrir
|
||||||
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
||||||
setTourShownThisSession(true);
|
setTourShownThisSession(true);
|
||||||
return true;
|
}, 2000);
|
||||||
} else {
|
|
||||||
console.log('🚫 [TOUR] Tour já estava aberto, não abrindo novamente');
|
|
||||||
return prevIsOpen;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ [TOUR] Erro ao verificar condições do tour:', error);
|
console.error('❌ [TOUR] Erro ao verificar condições do tour:', error);
|
||||||
setShouldShowTour(false);
|
setShouldShowTour(false);
|
||||||
} finally {
|
|
||||||
setIsCheckingConditions(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -123,7 +97,6 @@ export const useOnboardingTour = () => {
|
|||||||
setShouldShowTour(false);
|
setShouldShowTour(false);
|
||||||
sessionStorage.removeItem(TOUR_SESSION_KEY);
|
sessionStorage.removeItem(TOUR_SESSION_KEY);
|
||||||
setTourShownThisSession(false);
|
setTourShownThisSession(false);
|
||||||
setCurrentStep(0);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Verificar condições quando a localização mudar ou na inicialização
|
// Verificar condições quando a localização mudar ou na inicialização
|
||||||
@ -133,24 +106,21 @@ export const useOnboardingTour = () => {
|
|||||||
checkTourConditions();
|
checkTourConditions();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
return () => {
|
return () => clearTimeout(timer);
|
||||||
clearTimeout(timer);
|
|
||||||
setIsCheckingConditions(false);
|
|
||||||
};
|
|
||||||
}, [location.pathname]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
// Escutar evento customizado de login
|
// Escutar evento customizado de login
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleUserLoggedIn = (event: CustomEvent) => {
|
const handleUserLoggedIn = (event: CustomEvent) => {
|
||||||
console.log('🎉 [TOUR] Evento de login recebido:', event.detail);
|
console.log('🎉 [TOUR] Evento de login recebido:', event.detail);
|
||||||
if (location.pathname === '/' && !isOpen) {
|
if (location.pathname === '/') {
|
||||||
console.log('📧 [TOUR] Login detectado no dashboard, re-verificando condições do tour');
|
console.log('📧 [TOUR] Login detectado no dashboard, re-verificando condições do tour');
|
||||||
// Limpar sessionStorage para nova verificação após login
|
// Limpar sessionStorage para nova verificação após login
|
||||||
sessionStorage.removeItem(TOUR_SESSION_KEY);
|
sessionStorage.removeItem(TOUR_SESSION_KEY);
|
||||||
setTourShownThisSession(false);
|
setTourShownThisSession(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
checkTourConditions();
|
checkTourConditions();
|
||||||
}, 2000);
|
}, 2500);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -158,14 +128,17 @@ export const useOnboardingTour = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('userLoggedIn', handleUserLoggedIn as EventListener);
|
window.removeEventListener('userLoggedIn', handleUserLoggedIn as EventListener);
|
||||||
};
|
};
|
||||||
}, [location.pathname, isOpen]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
// Verificar também quando o email do usuário estiver disponível
|
// Verificar também quando o email do usuário estiver disponível
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const userEmail = localStorage.getItem('userEmail');
|
const userEmail = localStorage.getItem('userEmail');
|
||||||
console.log('📧 [TOUR] Segundo useEffect - email disponível:', userEmail);
|
console.log('📧 [TOUR] Segundo useEffect - email disponível:', userEmail);
|
||||||
if (userEmail && location.pathname === '/' && !isOpen && !tourShownThisSession) {
|
if (userEmail && location.pathname === '/') {
|
||||||
console.log('📧 [TOUR] Email detectado, re-verificando condições do tour');
|
console.log('📧 [TOUR] Email detectado, re-verificando condições do tour');
|
||||||
|
// Limpar sessionStorage para nova verificação
|
||||||
|
sessionStorage.removeItem(TOUR_SESSION_KEY);
|
||||||
|
setTourShownThisSession(false);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
checkTourConditions();
|
checkTourConditions();
|
||||||
}, 1500);
|
}, 1500);
|
||||||
@ -175,7 +148,7 @@ export const useOnboardingTour = () => {
|
|||||||
// Escutar mudanças no localStorage para detectar login
|
// Escutar mudanças no localStorage para detectar login
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleStorageChange = (e: StorageEvent) => {
|
const handleStorageChange = (e: StorageEvent) => {
|
||||||
if (e.key === 'userEmail' && e.newValue && !isOpen) {
|
if (e.key === 'userEmail' && e.newValue) {
|
||||||
console.log('👤 [TOUR] Login detectado via storage event:', e.newValue);
|
console.log('👤 [TOUR] Login detectado via storage event:', e.newValue);
|
||||||
if (location.pathname === '/') {
|
if (location.pathname === '/') {
|
||||||
// Limpar sessionStorage para nova verificação após mudança de usuário
|
// Limpar sessionStorage para nova verificação após mudança de usuário
|
||||||
@ -190,7 +163,7 @@ export const useOnboardingTour = () => {
|
|||||||
|
|
||||||
window.addEventListener('storage', handleStorageChange);
|
window.addEventListener('storage', handleStorageChange);
|
||||||
return () => window.removeEventListener('storage', handleStorageChange);
|
return () => window.removeEventListener('storage', handleStorageChange);
|
||||||
}, [location.pathname, isOpen]);
|
}, [location.pathname]);
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = () => {
|
||||||
console.log('➡️ [TOUR] Próximo step do tour:', currentStep + 1);
|
console.log('➡️ [TOUR] Próximo step do tour:', currentStep + 1);
|
||||||
@ -210,8 +183,7 @@ export const useOnboardingTour = () => {
|
|||||||
console.log('❌ [TOUR] Fechando tour');
|
console.log('❌ [TOUR] Fechando tour');
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
setCurrentStep(0);
|
setCurrentStep(0);
|
||||||
setShouldShowTour(false);
|
// Marcar como exibido nesta sessão apenas quando fechar
|
||||||
// Garantir que está marcado como exibido
|
|
||||||
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
||||||
setTourShownThisSession(true);
|
setTourShownThisSession(true);
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user