88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useMemo } from 'react';
|
|
import { useTranslations } from 'next-intl';
|
|
import { useAuth } from '@/lib/context/auth-context';
|
|
import { usePathname, useRouter } from '@/i18n/navigation';
|
|
import { AppShell } from '@/components/shell/app-shell';
|
|
import { buildAdminNav } from '@/components/shell/nav-config';
|
|
import { PageSpinner } from '@/components/ui/states';
|
|
|
|
export default function AdminLayout({ children }: { children: React.ReactNode }) {
|
|
const { user, logout, loading, isAuthenticated } = useAuth();
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
const tItems = useTranslations('components.adminPanelDropdown');
|
|
const tAdmin = useTranslations('admin');
|
|
const tShell = useTranslations('shell');
|
|
const tDashboard = useTranslations('dashboard');
|
|
|
|
// La page /admin/login vit sous ce segment mais doit s'afficher sans le
|
|
// chrome d'administration et sans declencher la garde de role.
|
|
const isLoginRoute = pathname === '/admin/login';
|
|
|
|
useEffect(() => {
|
|
if (isLoginRoute || loading) return;
|
|
if (!isAuthenticated) {
|
|
router.replace('/admin/login');
|
|
return;
|
|
}
|
|
if (user && user.role !== 'ADMIN') {
|
|
router.replace('/dashboard');
|
|
}
|
|
}, [isLoginRoute, loading, isAuthenticated, user, router]);
|
|
|
|
const groups = useMemo(() => buildAdminNav({ t: tItems, tShell }), [tItems, tShell]);
|
|
|
|
if (isLoginRoute) {
|
|
return <>{children}</>;
|
|
}
|
|
|
|
const authorized = isAuthenticated && user?.role === 'ADMIN';
|
|
|
|
if (loading || !authorized) {
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-neutral-50">
|
|
<PageSpinner />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<AppShell
|
|
variant="admin"
|
|
groups={groups}
|
|
pathname={pathname}
|
|
user={user}
|
|
onLogout={logout}
|
|
crossLink={{ href: '/dashboard', label: tAdmin('backToApp') }}
|
|
labels={{
|
|
navigation: tShell('navigation'),
|
|
openMenu: tShell('openMenu'),
|
|
closeMenu: tShell('closeMenu'),
|
|
collapseSidebar: tShell('collapseSidebar'),
|
|
expandSidebar: tShell('expandSidebar'),
|
|
userMenu: tShell('userMenu'),
|
|
breadcrumb: tShell('breadcrumb'),
|
|
rootLabel: tAdmin('title'),
|
|
search: tShell('search'),
|
|
searchPlaceholder: tShell('searchPlaceholder'),
|
|
noResults: tShell('noResults'),
|
|
lockedFeature: tShell('lockedFeature'),
|
|
profile: tShell('profile'),
|
|
logout: tAdmin('logout'),
|
|
more: tShell('more'),
|
|
moreTitle: tShell('moreTitle'),
|
|
bottomNav: {
|
|
home: tDashboard('bottomNav.home'),
|
|
bookings: tDashboard('bottomNav.bookings'),
|
|
documents: tDashboard('bottomNav.documents'),
|
|
tracking: tDashboard('bottomNav.tracking'),
|
|
},
|
|
}}
|
|
>
|
|
{children}
|
|
</AppShell>
|
|
);
|
|
}
|