Migração completa para Logto - Remoção de Clerk finalizada

This commit is contained in:
2026-03-31 10:32:42 +00:00
parent 87a87ae228
commit 49538cfbd4
21 changed files with 371 additions and 688 deletions
+32 -64
View File
@@ -2,13 +2,11 @@ import React, { useState } from 'react';
import NotificationBell from './NotificationBell';
import { TeamPresence } from './TeamPresence';
import { Link, useLocation, useNavigate } from 'react-router-dom';
import { Menu, X, FolderOpen, Layers, ClipboardCheck, LogOut, TrendingUp, Sun, Moon, HelpCircle, Shield, Wrench, Terminal, LayoutDashboard, Package, Thermometer } from 'lucide-react';
import { Menu, X, FolderOpen, Layers, ClipboardCheck, LogOut, TrendingUp, Sun, Moon, HelpCircle, Shield, Wrench, Terminal, LayoutDashboard, Package, Thermometer, User } from 'lucide-react';
import { clsx } from 'clsx';
import { useClerk, UserButton, useUser, OrganizationSwitcher, useOrganization } from '@clerk/clerk-react';
import { useLogto } from '@logto/react';
import { TechnicalManual } from './TechnicalManual';
import { useAuth } from '../context/useAuth';
// import { useSystemSettings } from '../context/SystemSettingsContext';
import { setApiOrgData } from '../services/api';
interface LayoutProps {
children: React.ReactNode;
@@ -22,21 +20,8 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
return saved === 'dark' || (!saved && window.matchMedia('(prefers-color-scheme: dark)').matches);
});
const location = useLocation();
const { signOut } = useClerk();
const { user } = useUser();
const { organization } = useOrganization();
const { isAdmin, isUser, isDeveloper, appUser } = useAuth();
// const { settings } = useSystemSettings();
// Sync Organization ID with API client
React.useEffect(() => {
if (organization?.id) {
setApiOrgData(organization.id, organization.name);
} else {
setApiOrgData(null);
}
}, [organization]);
const { signOut } = useLogto();
const { isAdmin, isUser, isDeveloper, appUser, isSignedIn } = useAuth();
// Helper to get role display name
const getRoleDisplay = () => {
@@ -69,6 +54,14 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
}
}, [appUser, location.pathname, navigate]);
// Redirect to login if not signed in (except for login and callback pages)
React.useEffect(() => {
const publicPaths = ['/login', '/callback'];
if (!isSignedIn && !publicPaths.includes(location.pathname)) {
navigate('/login');
}
}, [isSignedIn, location.pathname, navigate]);
interface NavItem {
icon: React.ElementType;
label: string;
@@ -94,6 +87,14 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
return false;
};
const handleLogout = () => {
signOut(window.location.origin);
};
if (location.pathname === '/login' || location.pathname === '/callback') {
return <>{children}</>;
}
return (
<div className="min-h-screen bg-surface-soft flex font-sans selection:bg-primary/30">
{/* Sidebar Desktop - Fixed */}
@@ -117,47 +118,6 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
</div>
</div>
<div className="px-6 mb-2">
{isAdmin() ? (
<OrganizationSwitcher
hidePersonal={true}
afterSelectOrganizationUrl="/"
afterCreateOrganizationUrl="/"
afterLeaveOrganizationUrl="/"
appearance={{
elements: {
rootBox: "w-full",
organizationSwitcherTrigger: "w-full justify-between bg-surface-hover/50 hover:bg-surface-hover p-2 rounded-xl border border-border/50 text-text-main transition-all",
organizationPreviewTextContainer: "text-text-main",
organizationPreviewMainIdentifier: "text-text-main font-semibold",
organizationSwitcherPopoverCard: "bg-surface border border-border/40 shadow-2xl",
organizationSwitcherPopoverActions: "bg-surface-soft/50",
organizationSwitcherPopoverActionButton: "text-text-main hover:bg-surface-hover transition-colors",
organizationPreview: "hover:bg-surface-hover cursor-pointer transition-colors px-4 py-3",
organizationPreviewSecondaryIdentifier: "text-text-muted",
organizationSwitcherPopoverFooter: "hidden",
userPreviewMainIdentifier: "text-text-main font-bold",
userPreviewSecondaryIdentifier: "text-text-muted",
}
}}
/>
) : (
<div className="w-full flex items-center gap-3 p-2 rounded-xl border border-border/50 bg-surface-hover/50 text-text-main opacity-80 cursor-default" title="Apenas visualização">
{organization?.imageUrl ? (
<img src={organization.imageUrl} alt={organization.name} className="w-8 h-8 rounded-lg object-cover bg-surface-soft" />
) : (
<div className="w-8 h-8 rounded-lg bg-surface-soft flex items-center justify-center font-bold text-xs">
{organization?.name?.substring(0, 2).toUpperCase()}
</div>
)}
<div className="flex-1 min-w-0">
<p className="text-sm font-semibold truncate">{organization?.name || 'Carregando...'}</p>
<p className="text-[10px] text-text-muted uppercase tracking-wider">Organização</p>
</div>
</div>
)}
</div>
{/* Team Presence - Shows all members with online/offline status */}
<TeamPresence />
@@ -257,7 +217,7 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
</button>
<button
onClick={() => signOut()}
onClick={handleLogout}
className="flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold text-text-secondary hover:text-error hover:bg-error/5 transition-all w-full"
>
<LogOut size={18} />
@@ -268,9 +228,11 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
<div className="flex items-center gap-2">
<NotificationBell />
<div className="w-px h-6 bg-border/50 mx-1"></div>
<UserButton afterSignOutUrl="/" />
<div className="w-8 h-8 rounded-full bg-primary/20 flex items-center justify-center text-primary">
<User size={16} />
</div>
<div className="flex flex-col">
<span className="text-[10px] text-text-main font-bold truncate max-w-[100px]">{user?.firstName || 'Usuário'}</span>
<span className="text-[10px] text-text-main font-bold truncate max-w-[100px]">{appUser?.name || 'Usuário'}</span>
<span className="text-[8px] text-text-muted">v2.1.0</span>
</div>
</div>
@@ -386,6 +348,13 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
{isDarkMode ? <Sun size={20} className="text-yellow-500" /> : <Moon size={20} className="text-primary" />}
{isDarkMode ? 'Modo Claro' : 'Modo Escuro'}
</button>
<button
onClick={handleLogout}
className="flex items-center gap-4 w-full text-text-main font-bold"
>
<LogOut size={20} />
Sair
</button>
</div>
</div>
@@ -415,4 +384,3 @@ export const Layout: React.FC<LayoutProps> = ({ children }) => {
</div>
);
};