fix layout

This commit is contained in:
yotakii
2026-03-02 14:35:36 +03:00
parent cdb69af654
commit 03ec18c5e6
2 changed files with 79 additions and 142 deletions

View File

@@ -1,8 +1,7 @@
'use client'
import dynamic from 'next/dynamic'
import ProtectedRoute from '@/components/ProtectedRoute'
import { AuthProvider, useAuth } from '@/contexts/AuthContext'
import { useAuth } from '@/contexts/AuthContext'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import {
@@ -17,8 +16,7 @@ import {
Clock,
Building2,
LogOut,
LayoutDashboard,
Users2
LayoutDashboard
} from 'lucide-react'
function AdminLayoutContent({ children }: { children: React.ReactNode }) {
@@ -29,7 +27,6 @@ function AdminLayoutContent({ children }: { children: React.ReactNode }) {
{ icon: LayoutDashboard, label: 'لوحة التحكم', href: '/admin', exact: true },
{ icon: Users, label: 'إدارة المستخدمين', href: '/admin/users' },
{ icon: Shield, label: 'الأدوار والصلاحيات', href: '/admin/roles' },
{ icon: Users2, label: 'مجموعات الصلاحيات', href: '/admin/permission-groups' },
{ icon: Database, label: 'النسخ الاحتياطي', href: '/admin/backup' },
{ icon: Settings, label: 'إعدادات النظام', href: '/admin/settings' },
{ icon: FileText, label: 'سجل العمليات', href: '/admin/audit-logs' },
@@ -40,7 +37,9 @@ function AdminLayoutContent({ children }: { children: React.ReactNode }) {
]
const isActive = (href: string, exact?: boolean) => {
if (exact) return pathname === href
if (exact) {
return pathname === href
}
return pathname.startsWith(href)
}
@@ -58,7 +57,6 @@ function AdminLayoutContent({ children }: { children: React.ReactNode }) {
<p className="text-xs text-gray-600">System Admin</p>
</div>
</div>
<div className="bg-red-50 border border-red-200 rounded-lg p-3">
<p className="text-xs font-semibold text-red-900">{user?.username}</p>
<p className="text-xs text-red-700">{user?.role?.name}</p>
@@ -74,7 +72,9 @@ function AdminLayoutContent({ children }: { children: React.ReactNode }) {
key={item.href}
href={item.href}
className={`flex items-center gap-3 px-4 py-3 rounded-lg mb-2 transition-all ${
active ? 'bg-red-600 text-white shadow-md' : 'text-gray-700 hover:bg-gray-100'
active
? 'bg-red-600 text-white shadow-md'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
<Icon className="h-5 w-5" />
@@ -104,30 +104,18 @@ function AdminLayoutContent({ children }: { children: React.ReactNode }) {
</aside>
{/* Main Content */}
<main className="mr-64 flex-1 p-8">{children}</main>
<main className="mr-64 flex-1 p-8">
{children}
</main>
</div>
)
}
const AdminLayoutClient = dynamic(
() =>
Promise.resolve(function AdminLayoutClient({
children
}: {
children: React.ReactNode
}) {
export default function AdminLayout({ children }: { children: React.ReactNode }) {
return (
<AuthProvider>
<ProtectedRoute>
<AdminLayoutContent>{children}</AdminLayoutContent>
</ProtectedRoute>
</AuthProvider>
)
}),
{ ssr: false }
)
export default function AdminLayout({ children }: { children: React.ReactNode }) {
return <AdminLayoutClient>{children}</AdminLayoutClient>
}

View File

@@ -1,120 +1,69 @@
'use client'
import type { Metadata } from 'next'
import { Cairo, Readex_Pro } from 'next/font/google'
import './globals.css'
import { Providers } from './providers'
import { AuthProvider } from '@/contexts/AuthContext'
import { LanguageProvider } from '@/contexts/LanguageContext'
import { Toaster } from 'react-hot-toast'
import ProtectedRoute from '@/components/ProtectedRoute'
import { useAuth } from '@/contexts/AuthContext'
import Link from 'next/link'
import { usePathname } from 'next/navigation'
import {
Users,
Shield,
Database,
Settings,
FileText,
Activity,
Mail,
Key,
Clock,
Building2,
LogOut,
LayoutDashboard,
Users2
} from 'lucide-react'
const cairo = Cairo({
subsets: ['latin', 'arabic'],
variable: '--font-cairo',
display: 'swap',
})
function AdminLayoutContent({ children }: { children: React.ReactNode }) {
const { user, logout } = useAuth()
const pathname = usePathname()
const readexPro = Readex_Pro({
subsets: ['latin', 'arabic'],
variable: '--font-readex',
display: 'swap',
})
const menuItems = [
{ icon: LayoutDashboard, label: 'لوحة التحكم', href: '/admin', exact: true },
{ icon: Users, label: 'إدارة المستخدمين', href: '/admin/users' },
{ icon: Shield, label: 'الأدوار والصلاحيات', href: '/admin/roles' },
{ icon: Users2, label: 'مجموعات الصلاحيات', href: '/admin/permission-groups' },
{ icon: Database, label: 'النسخ الاحتياطي', href: '/admin/backup' },
{ icon: Settings, label: 'إعدادات النظام', href: '/admin/settings' },
{ icon: FileText, label: 'سجل العمليات', href: '/admin/audit-logs' },
{ icon: Activity, label: 'صحة النظام', href: '/admin/health' },
{ icon: Mail, label: 'إعدادات البريد', href: '/admin/email' },
{ icon: Key, label: 'مفاتيح API', href: '/admin/api-keys' },
{ icon: Clock, label: 'المهام المجدولة', href: '/admin/scheduled-jobs' }
]
const isActive = (href: string, exact?: boolean) => {
if (exact) {
return pathname === href
}
return pathname.startsWith(href)
}
export const metadata: Metadata = {
title: 'Z.CRM - نظام إدارة علاقات العملاء',
description: 'Enterprise CRM System for Contact Management, Sales, HR, Inventory, Projects, and Marketing',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<div className="min-h-screen bg-gray-50 flex">
<aside className="w-64 bg-white border-l shadow-lg fixed h-full overflow-y-auto">
<div className="p-6 border-b">
<div className="flex items-center gap-3 mb-4">
<div className="bg-red-600 p-2 rounded-lg">
<Shield className="h-6 w-6 text-white" />
</div>
<div>
<h2 className="text-lg font-bold text-gray-900">لوحة الإدارة</h2>
<p className="text-xs text-gray-600">System Admin</p>
</div>
</div>
<div className="bg-red-50 border border-red-200 rounded-lg p-3">
<p className="text-xs font-semibold text-red-900">{user?.username}</p>
<p className="text-xs text-red-700">{user?.role?.name}</p>
</div>
</div>
<nav className="p-4">
{menuItems.map((item) => {
const Icon = item.icon
const active = isActive(item.href, item.exact)
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 px-4 py-3 rounded-lg mb-2 transition-all ${
active
? 'bg-red-600 text-white shadow-md'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
<Icon className="h-5 w-5" />
<span className="font-medium">{item.label}</span>
</Link>
)
})}
<hr className="my-4 border-gray-200" />
<Link
href="/dashboard"
className="flex items-center gap-3 px-4 py-3 rounded-lg mb-2 text-gray-700 hover:bg-gray-100 transition-all"
>
<Building2 className="h-5 w-5" />
<span className="font-medium">العودة للنظام</span>
</Link>
<button
onClick={logout}
className="w-full flex items-center gap-3 px-4 py-3 rounded-lg text-red-600 hover:bg-red-50 transition-all"
>
<LogOut className="h-5 w-5" />
<span className="font-medium">تسجيل الخروج</span>
</button>
</nav>
</aside>
<main className="mr-64 flex-1 p-8">
{children}
</main>
</div>
<html lang="en">
<body className={`${readexPro.variable} ${cairo.variable} font-readex`}>
<LanguageProvider>
<AuthProvider>
<Providers>{children}</Providers>
<Toaster
position="top-center"
reverseOrder={false}
toastOptions={{
duration: 4000,
style: {
background: '#fff',
color: '#363636',
fontFamily: 'var(--font-readex)',
},
success: {
duration: 3000,
iconTheme: {
primary: '#10B981',
secondary: '#fff',
},
},
error: {
duration: 5000,
iconTheme: {
primary: '#EF4444',
secondary: '#fff',
},
},
}}
/>
</AuthProvider>
</LanguageProvider>
</body>
</html>
)
}
export default function AdminLayout({ children }: { children: React.ReactNode }) {
return (
<ProtectedRoute>
<AdminLayoutContent>{children}</AdminLayoutContent>
</ProtectedRoute>
)
}