85 lines
2.6 KiB
TypeScript
85 lines
2.6 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 { useSubscription } from '@/lib/context/subscription-context';
|
|
import { AppShell } from '@/components/shell/app-shell';
|
|
import { buildAppNav } from '@/components/shell/nav-config';
|
|
import { PageSpinner } from '@/components/ui/states';
|
|
|
|
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
|
|
const { user, logout, loading, isAuthenticated } = useAuth();
|
|
const { hasFeature, subscription } = useSubscription();
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
const t = useTranslations('dashboard');
|
|
const tShell = useTranslations('shell');
|
|
|
|
useEffect(() => {
|
|
if (!loading && !isAuthenticated) {
|
|
router.replace(`/login?redirect=${encodeURIComponent(pathname)}`);
|
|
}
|
|
}, [loading, isAuthenticated, router, pathname]);
|
|
|
|
const groups = useMemo(
|
|
() => buildAppNav({ t, tShell, role: user?.role }),
|
|
[t, tShell, user?.role]
|
|
);
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="flex min-h-screen items-center justify-center bg-neutral-50">
|
|
<PageSpinner />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isAuthenticated) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<AppShell
|
|
variant="app"
|
|
groups={groups}
|
|
pathname={pathname}
|
|
user={user}
|
|
statusBadge={subscription?.planDetails?.statusBadge}
|
|
hasFeature={hasFeature}
|
|
onLogout={logout}
|
|
showBottomNav
|
|
crossLink={
|
|
user?.role === 'ADMIN' ? { href: '/admin', label: t('nav.admin') } : undefined
|
|
}
|
|
labels={{
|
|
navigation: tShell('navigation'),
|
|
openMenu: tShell('openMenu'),
|
|
closeMenu: tShell('closeMenu'),
|
|
collapseSidebar: tShell('collapseSidebar'),
|
|
expandSidebar: tShell('expandSidebar'),
|
|
userMenu: tShell('userMenu'),
|
|
breadcrumb: tShell('breadcrumb'),
|
|
rootLabel: t('nav.dashboard'),
|
|
search: tShell('search'),
|
|
searchPlaceholder: tShell('searchPlaceholder'),
|
|
noResults: tShell('noResults'),
|
|
lockedFeature: tShell('lockedFeature'),
|
|
profile: tShell('profile'),
|
|
logout: t('logout'),
|
|
more: tShell('more'),
|
|
moreTitle: tShell('moreTitle'),
|
|
bottomNav: {
|
|
home: t('bottomNav.home'),
|
|
bookings: t('bottomNav.bookings'),
|
|
documents: t('bottomNav.documents'),
|
|
tracking: t('bottomNav.tracking'),
|
|
},
|
|
}}
|
|
>
|
|
{children}
|
|
</AppShell>
|
|
);
|
|
}
|