Fix: Onboarding tour behavior and button style
Fixes the onboarding tour looping issue and adjusts the button style for better visibility. The tour now correctly opens only once per session until the required conditions are met (connected instance and active group).
This commit is contained in:
parent
6a9e57eb9a
commit
71026e9b63
@ -1,70 +1,31 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { LogOut, User } from 'lucide-react';
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
|
||||
const Header = () => {
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
const [userName, setUserName] = useState('Usuário');
|
||||
import { Menu } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useIsMobile } from '@/hooks/use-mobile';
|
||||
|
||||
useEffect(() => {
|
||||
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
|
||||
setUserName(session?.user?.email || 'Usuário');
|
||||
});
|
||||
|
||||
return () => subscription.unsubscribe();
|
||||
}, []);
|
||||
interface HeaderProps {
|
||||
onMenuToggle: () => void;
|
||||
}
|
||||
|
||||
const handleLogout = async () => {
|
||||
const { error } = await supabase.auth.signOut();
|
||||
|
||||
if (error) {
|
||||
console.error('Error logging out:', error);
|
||||
toast({
|
||||
title: "Erro no logout",
|
||||
description: "Não foi possível desconectar. Tente novamente.",
|
||||
variant: 'destructive'
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: "Logout realizado",
|
||||
description: "Você foi desconectado com sucesso"
|
||||
});
|
||||
navigate('/auth', { replace: true });
|
||||
}
|
||||
};
|
||||
export default function Header({ onMenuToggle }: HeaderProps) {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<div className="flex justify-end items-center p-4 border-b">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="flex items-center gap-2">
|
||||
<User size={18} />
|
||||
<span>{userName}</span>
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
<DropdownMenuLabel>Minha conta</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={handleLogout} className="text-red-500 cursor-pointer">
|
||||
<LogOut className="mr-2 h-4 w-4" />
|
||||
<span>Sair</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<div className="flex h-14 items-center gap-4 border-b px-4 lg:h-[60px] lg:px-6">
|
||||
{isMobile && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
className="shrink-0 md:hidden"
|
||||
onClick={onMenuToggle}
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle navigation menu</span>
|
||||
</Button>
|
||||
)}
|
||||
<div className="w-full flex-1">
|
||||
<h1 className="text-lg font-semibold md:text-2xl">Finance Home</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
}
|
||||
|
||||
@ -88,9 +88,10 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
||||
width: rect.width + 20,
|
||||
height: rect.height + 20,
|
||||
borderRadius: '8px',
|
||||
boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 20px rgba(59, 130, 246, 0.8)',
|
||||
boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.8), 0 0 30px rgba(59, 130, 246, 1), inset 0 0 0 3px rgba(59, 130, 246, 0.8)',
|
||||
pointerEvents: 'none' as const,
|
||||
zIndex: 9998
|
||||
zIndex: 9998,
|
||||
border: '2px solid rgba(59, 130, 246, 0.9)'
|
||||
};
|
||||
};
|
||||
|
||||
@ -98,7 +99,7 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
||||
<>
|
||||
{/* Overlay escuro */}
|
||||
<div
|
||||
className="fixed inset-0 bg-black bg-opacity-70 z-[9997]"
|
||||
className="fixed inset-0 bg-black bg-opacity-80 z-[9997]"
|
||||
style={{ zIndex: 9997 }}
|
||||
/>
|
||||
|
||||
@ -109,7 +110,7 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
||||
|
||||
{/* Card do tour */}
|
||||
<div className="fixed inset-0 flex items-center justify-center z-[9999] p-4">
|
||||
<Card className="w-full max-w-md bg-white shadow-2xl">
|
||||
<Card className="w-full max-w-md bg-white shadow-2xl border-2 border-blue-200">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex justify-between items-start mb-4">
|
||||
<h3 className="text-xl font-bold text-gray-800">
|
||||
@ -142,10 +143,17 @@ const OnboardingTour: React.FC<OnboardingTourProps> = ({
|
||||
</div>
|
||||
|
||||
<div className="flex space-x-2">
|
||||
<Button variant="outline" onClick={onSkip}>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={onSkip}
|
||||
className="hover:bg-gray-100 transition-colors"
|
||||
>
|
||||
Pular Tour
|
||||
</Button>
|
||||
<Button onClick={onNext}>
|
||||
<Button
|
||||
onClick={onNext}
|
||||
className="bg-blue-600 hover:bg-blue-700 text-white font-semibold px-6 transition-colors shadow-lg"
|
||||
>
|
||||
{currentStep === steps.length - 1 ? 'Finalizar' : 'Próximo'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@ -4,16 +4,29 @@ import { useLocation } from 'react-router-dom';
|
||||
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
|
||||
import { listWhatsAppGroups } from '@/services/whatsAppGroupsService';
|
||||
|
||||
const TOUR_SESSION_KEY = 'onboarding_tour_shown';
|
||||
|
||||
export const useOnboardingTour = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [shouldShowTour, setShouldShowTour] = useState(false);
|
||||
const [tourShownThisSession, setTourShownThisSession] = useState(false);
|
||||
const location = useLocation();
|
||||
const { instances } = useWhatsAppInstances();
|
||||
|
||||
// Verificar se o tour deve ser exibido
|
||||
const checkTourConditions = async () => {
|
||||
try {
|
||||
// Verificar se já foi mostrado nesta sessão
|
||||
const shownThisSession = sessionStorage.getItem(TOUR_SESSION_KEY) === 'true';
|
||||
|
||||
if (shownThisSession) {
|
||||
console.log('Tour já foi exibido nesta sessão');
|
||||
setShouldShowTour(false);
|
||||
setTourShownThisSession(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verificar se há instâncias conectadas
|
||||
const hasConnectedInstance = instances.some(instance =>
|
||||
instance.status === 'connected' || instance.connectionState === 'open'
|
||||
@ -30,16 +43,19 @@ export const useOnboardingTour = () => {
|
||||
hasConnectedInstance,
|
||||
hasGroups,
|
||||
shouldShow,
|
||||
instances: instances.length
|
||||
instances: instances.length,
|
||||
shownThisSession
|
||||
});
|
||||
|
||||
setShouldShowTour(shouldShow);
|
||||
|
||||
// Se deve mostrar o tour e não está aberto, abrir automaticamente
|
||||
if (shouldShow && !isOpen) {
|
||||
// Se deve mostrar o tour e não foi mostrado ainda, abrir automaticamente
|
||||
if (shouldShow && !shownThisSession && !isOpen) {
|
||||
setIsOpen(true);
|
||||
setCurrentStep(0);
|
||||
} else if (!shouldShow && isOpen) {
|
||||
setTourShownThisSession(true);
|
||||
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
||||
} else if (!shouldShow) {
|
||||
// Se as condições foram atendidas, fechar o tour
|
||||
setIsOpen(false);
|
||||
}
|
||||
@ -56,11 +72,10 @@ export const useOnboardingTour = () => {
|
||||
}
|
||||
}, [instances]);
|
||||
|
||||
// Verificar condições periodicamente
|
||||
// Verificar condições na inicialização
|
||||
useEffect(() => {
|
||||
const interval = setInterval(checkTourConditions, 5000); // A cada 5 segundos
|
||||
return () => clearInterval(interval);
|
||||
}, [instances]);
|
||||
checkTourConditions();
|
||||
}, []);
|
||||
|
||||
const nextStep = () => {
|
||||
if (currentStep < 2) {
|
||||
@ -77,6 +92,9 @@ export const useOnboardingTour = () => {
|
||||
const closeTour = () => {
|
||||
setIsOpen(false);
|
||||
setCurrentStep(0);
|
||||
// Marcar como exibido nesta sessão
|
||||
sessionStorage.setItem(TOUR_SESSION_KEY, 'true');
|
||||
setTourShownThisSession(true);
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user