admin/components/layouts/DashboardShell.tsx
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

75 lines
2.6 KiB
TypeScript

'use client'
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion'
import React, { useMemo } from 'react'
import { usePathname } from 'next/navigation'
import AdminRoleGuard from '@/components/auth/AdminRoleGuard'
import PendingUserGuard from '@/components/auth/PendingUserGuard'
import Sidebar from '@/components/layouts/Sidebar'
import SessionProviders from '@/components/providers/SessionProviders'
import { SIDEBAR_WIDTH } from '@/config/sidebar'
import { AlertModalProvider } from '@/context/AlertModalContext'
const DashboardShell = ({ children }: { children: React.ReactNode }) => {
const pathname = usePathname()
const reduceMotion = useReducedMotion()
// Extract key for animation - main routes only
const animationKey = useMemo(() => {
const segments = pathname.split('/').filter(Boolean)
const mainSegments = segments
// If on project route, key is just project/[id]
if (mainSegments[0] === 'project' && mainSegments[1]) {
return `project/${mainSegments[1]}`
}
// If on match route, key is just match/[id]
if (mainSegments[0] === 'match' && mainSegments[1]) {
return `match/${mainSegments[1]}`
}
// For other routes, first segment only
return mainSegments[0] || 'root'
}, [pathname])
return (
<SessionProviders>
<AlertModalProvider>
<PendingUserGuard>
<AdminRoleGuard>
<section
className="flex min-h-[100dvh] w-full bg-[var(--admin-page-bg)] text-right"
data-scrollbar="thin"
data-theme="ghabilee-admin"
style={{ ['--sidebar-width' as string]: `${SIDEBAR_WIDTH}px` }}
>
<Sidebar />
<div className="fixed end-0 flex h-[100dvh] w-full flex-col md:w-[calc(100vw-var(--sidebar-width))]">
<AnimatePresence mode="wait">
<motion.div
key={animationKey}
animate={{
y: 0,
opacity: 1,
}}
className="h-full overflow-y-auto bg-[var(--admin-page-bg)]"
id="mainContent"
initial={reduceMotion ? false : { y: 8, opacity: 0 }}
transition={{ duration: reduceMotion ? 0 : 0.18, ease: 'easeOut' }}
>
{children}
</motion.div>
</AnimatePresence>
</div>
</section>
</AdminRoleGuard>
</PendingUserGuard>
</AlertModalProvider>
</SessionProviders>
)
}
export default DashboardShell