mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-18 06:17:56 +00:00
249 lines
7.4 KiB
TypeScript
249 lines
7.4 KiB
TypeScript
import React from 'react';
|
|
import { Outlet, NavLink, useNavigate } from 'react-router-dom';
|
|
import {
|
|
LayoutDashboard,
|
|
BookOpen,
|
|
Settings,
|
|
LogOut,
|
|
School,
|
|
Trophy,
|
|
History,
|
|
Menu,
|
|
X,
|
|
ChevronLeft,
|
|
ChevronRight,
|
|
PenTool
|
|
} from 'lucide-react';
|
|
import { useAuth } from '../../hooks/useAuth';
|
|
import * as Dialog from '@radix-ui/react-dialog';
|
|
import { TextCaseToggle } from '../../components/ui/text-case-toggle';
|
|
import { useUppercasePreference } from '../../hooks/useUppercasePreference';
|
|
import { useSession } from '../../hooks/useSession';
|
|
|
|
export function StudentDashboardLayout() {
|
|
const navigate = useNavigate();
|
|
const { signOut } = useAuth();
|
|
const [isCollapsed, setIsCollapsed] = React.useState(false);
|
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
|
|
const { session } = useSession();
|
|
const { isUpperCase, toggleUppercase, isLoading } = useUppercasePreference(session?.user?.id);
|
|
|
|
const handleLogout = async () => {
|
|
await signOut();
|
|
navigate('/');
|
|
};
|
|
|
|
const handleNavigation = () => {
|
|
setIsMobileMenuOpen(false);
|
|
};
|
|
|
|
const NavItems = () => (
|
|
<nav className="p-4 space-y-1">
|
|
<NavLink
|
|
to="/aluno"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<BookOpen className="h-5 w-5" />
|
|
{!isCollapsed && <span>Minhas Histórias</span>}
|
|
</NavLink>
|
|
|
|
<NavLink
|
|
to="/aluno/redacoes"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<PenTool className="h-5 w-5" />
|
|
{!isCollapsed && <span>Redações</span>}
|
|
</NavLink>
|
|
|
|
<NavLink
|
|
to="/aluno/painel"
|
|
end
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<LayoutDashboard className="h-5 w-5" />
|
|
{!isCollapsed && <span>Painel</span>}
|
|
</NavLink>
|
|
|
|
{/* <NavLink
|
|
to="/aluno/conquistas"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<Trophy className="h-5 w-5" />
|
|
{!isCollapsed && <span>Conquistas</span>}
|
|
</NavLink>
|
|
|
|
<NavLink
|
|
to="/aluno/historico"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<History className="h-5 w-5" />
|
|
{!isCollapsed && <span>Histórico</span>}
|
|
</NavLink>
|
|
|
|
<NavLink
|
|
to="/aluno/fonicos"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<BookOpen className="h-5 w-5" />
|
|
{!isCollapsed && <span>Exercícios Fônicos</span>}
|
|
</NavLink>
|
|
|
|
<NavLink
|
|
to="/aluno/fonicos/progresso"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-700'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<Trophy className="h-5 w-5" />
|
|
{!isCollapsed && <span>Progresso Fônico</span>}
|
|
</NavLink>
|
|
*/}
|
|
<NavLink
|
|
to="/aluno/configuracoes"
|
|
onClick={handleNavigation}
|
|
className={({ isActive }) =>
|
|
`flex items-center gap-2 px-4 py-2 rounded-lg text-sm ${
|
|
isActive
|
|
? 'bg-purple-50 text-purple-600'
|
|
: 'text-gray-600 hover:bg-gray-50'
|
|
}`
|
|
}
|
|
>
|
|
<Settings className="h-5 w-5" />
|
|
{!isCollapsed && <span>Configurações</span>}
|
|
</NavLink>
|
|
|
|
<button
|
|
onClick={() => {
|
|
handleNavigation();
|
|
handleLogout();
|
|
}}
|
|
className="flex items-center gap-2 px-4 py-2 rounded-lg text-sm text-gray-600 hover:bg-gray-50 w-full mt-4"
|
|
>
|
|
<LogOut className="h-5 w-5" />
|
|
{!isCollapsed && <span>Sair</span>}
|
|
</button>
|
|
</nav>
|
|
);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gray-50">
|
|
{/* Mobile Menu Button */}
|
|
<button
|
|
onClick={() => setIsMobileMenuOpen(true)}
|
|
className="fixed top-4 left-4 p-2 bg-white rounded-lg shadow-sm border border-gray-200 lg:hidden z-50"
|
|
>
|
|
<Menu className="h-6 w-6 text-gray-600" />
|
|
</button>
|
|
|
|
{/* Desktop Sidebar */}
|
|
<aside
|
|
className={`fixed left-0 top-0 h-full bg-white border-r border-gray-200 transition-all duration-300 hidden lg:block ${
|
|
isCollapsed ? 'w-20' : 'w-64'
|
|
}`}
|
|
>
|
|
<div className="flex items-center gap-2 p-6 border-b border-gray-200">
|
|
<School className="h-8 w-8 text-purple-600" />
|
|
{!isCollapsed && (
|
|
<span className="font-semibold text-gray-900">Leiturama</span>
|
|
)}
|
|
</div>
|
|
|
|
<NavItems />
|
|
|
|
{/* Collapse Button */}
|
|
<button
|
|
onClick={() => setIsCollapsed(!isCollapsed)}
|
|
className="absolute bottom-4 -right-4 p-2 bg-white rounded-full shadow-sm border border-gray-200"
|
|
>
|
|
{isCollapsed ? (
|
|
<ChevronRight className="h-4 w-4 text-gray-600" />
|
|
) : (
|
|
<ChevronLeft className="h-4 w-4 text-gray-600" />
|
|
)}
|
|
</button>
|
|
</aside>
|
|
|
|
{/* Mobile Menu Dialog */}
|
|
<Dialog.Root open={isMobileMenuOpen} onOpenChange={setIsMobileMenuOpen}>
|
|
<Dialog.Portal>
|
|
<Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
|
|
<Dialog.Content className="fixed inset-y-0 left-0 w-64 bg-white shadow-xl z-50 lg:hidden">
|
|
<div className="flex items-center justify-between p-6 border-b border-gray-200">
|
|
<div className="flex items-center gap-2">
|
|
<School className="h-8 w-8 text-purple-600" />
|
|
<span className="font-semibold text-gray-900">
|
|
Leiturama
|
|
</span>
|
|
</div>
|
|
<button
|
|
onClick={() => setIsMobileMenuOpen(false)}
|
|
className="p-2 hover:bg-gray-100 rounded-lg"
|
|
>
|
|
<X className="h-5 w-5 text-gray-600" />
|
|
</button>
|
|
</div>
|
|
|
|
<NavItems />
|
|
</Dialog.Content>
|
|
</Dialog.Portal>
|
|
</Dialog.Root>
|
|
|
|
{/* Main Content */}
|
|
<main
|
|
className={`transition-all duration-300 ${
|
|
isCollapsed ? 'lg:ml-20' : 'lg:ml-64'
|
|
} p-8`}
|
|
>
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|