Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
75 lines
2.6 KiB
TypeScript
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
|