From 5c53379568f34883146dc0e4e73e6325ec04115e Mon Sep 17 00:00:00 2001 From: Gabriel Santana de Menezes Date: Sat, 16 May 2026 10:58:21 -0400 Subject: [PATCH] fix: centralizar OnboardingModal em /organizations e evitar reabertura (#15) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O modal de onboarding era disparado tanto na LoginPage quanto no AppShell com navegação conflitante, fazendo ele fechar e reabrir ao escolher uma opção. Agora o login sem org redireciona para /organizations, o AppShell redireciona usuários sem org para lá, e o modal é exibido uma única vez pela OrganizationsPage. Co-Authored-By: Claude Opus 4.7 --- frontend/src/components/AppShell.tsx | 26 +++++++++++------------- frontend/src/pages/LoginPage.tsx | 11 +--------- frontend/src/pages/OrganizationsPage.tsx | 9 ++++++++ 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/AppShell.tsx b/frontend/src/components/AppShell.tsx index 3186f3e..8de0282 100644 --- a/frontend/src/components/AppShell.tsx +++ b/frontend/src/components/AppShell.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import { useState } from "react"; import { Layout, ListTodo, @@ -18,9 +18,8 @@ import { Users, PlusCircle, } from "lucide-react"; -import { NavLink, Outlet, Navigate, Link } from "react-router-dom"; +import { NavLink, Outlet, Navigate, Link, useLocation } from "react-router-dom"; import { useAuth } from "../contexts/AuthContext"; -import { OnboardingModal } from "./OnboardingModal"; import { cn } from "../lib/utils"; import { motion } from "framer-motion"; @@ -44,7 +43,7 @@ const dropdownItemClassName = ({ isActive }: { isActive: boolean }) => export function AppShell() { const { user, isAuthenticated, isLoading, logout, activeOrg, setActiveOrg } = useAuth(); - const [showOrgModal, setShowOrgModal] = useState(false); + const location = useLocation(); const [showOrgSwitcher, setShowOrgSwitcher] = useState(false); const [showTasksDropdown, setShowTasksDropdown] = useState(false); const [showTeamDropdown, setShowTeamDropdown] = useState(false); @@ -53,12 +52,6 @@ export function AppShell() { const isAdmin = activeOrg?.roles.includes("OWNER") || activeOrg?.roles.includes("ADMIN"); - React.useEffect(() => { - if (isAuthenticated && user && user.organizations.length === 0) { - setShowOrgModal(true); - } - }, [isAuthenticated, user]); - if (isLoading) { return (
@@ -71,6 +64,15 @@ export function AppShell() { return ; } + if ( + isAuthenticated && + user && + user.organizations.length === 0 && + location.pathname !== "/organizations" + ) { + return ; + } + return (
{/* Top Navigation */} @@ -622,10 +624,6 @@ export function AppShell() {
- setShowOrgModal(false)} - />
); } diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx index e8921b0..3f65bdf 100644 --- a/frontend/src/pages/LoginPage.tsx +++ b/frontend/src/pages/LoginPage.tsx @@ -3,13 +3,11 @@ import { useNavigate, Link } from 'react-router-dom' import { motion } from 'framer-motion' import { Mail, Lock, LogIn, Layout } from 'lucide-react' import { useAuth } from '../contexts/AuthContext' -import { OnboardingModal } from '../components/OnboardingModal' export const LoginPage: React.FC = () => { const [email, setEmail] = useState('') const [password, setPassword] = useState('') const [isLoading, setIsLoading] = useState(false) - const [showOnboarding, setShowOnboarding] = useState(false) const navigate = useNavigate() const { login } = useAuth() @@ -20,7 +18,7 @@ export const LoginPage: React.FC = () => { try { const response = await login(email, password) if (response.organizations.length === 0) { - setShowOnboarding(true) + navigate('/organizations') } else { navigate('/') } @@ -113,13 +111,6 @@ export const LoginPage: React.FC = () => { - { - setShowOnboarding(false) - navigate('/') - }} - /> ) } diff --git a/frontend/src/pages/OrganizationsPage.tsx b/frontend/src/pages/OrganizationsPage.tsx index ada6e28..c9dbe5b 100644 --- a/frontend/src/pages/OrganizationsPage.tsx +++ b/frontend/src/pages/OrganizationsPage.tsx @@ -19,9 +19,13 @@ import { Link } from 'react-router-dom' import { useAuth } from '../contexts/AuthContext' import { cn } from '../lib/utils' import { organizationService } from '../services/organizationService' +import { OnboardingModal } from '../components/OnboardingModal' export function OrganizationsPage() { const { user, activeOrg, setActiveOrg, refreshUser } = useAuth() + const [showOnboarding, setShowOnboarding] = useState( + () => (user?.organizations.length ?? 0) === 0, + ) const [showCreateModal, setShowCreateModal] = useState(false) const [newOrgName, setNewOrgName] = useState('') const [isCreating, setIsCreating] = useState(false) @@ -250,6 +254,11 @@ export function OrganizationsPage() { + setShowOnboarding(false)} + /> + {/* Create Organization Modal */} {showCreateModal && (