feat(navigation): integrate roles into app navigation

- Add all roles routes to App.tsx
- Add roles menu item to sidebar with Shield icon
- Update user display to use AdminUser properties
- Fix TypeScript compatibility issues with new auth types
This commit is contained in:
hosseintaromi 2025-07-18 14:03:07 +03:30
parent ebd2c3c8f7
commit f43e7ca0e5
3 changed files with 30 additions and 9 deletions

View File

@ -16,6 +16,12 @@ import { Reports } from './pages/Reports';
import { Notifications } from './pages/Notifications'; import { Notifications } from './pages/Notifications';
import { Layout } from './components/layout/Layout'; import { Layout } from './components/layout/Layout';
// Roles Pages
import RolesListPage from './pages/roles/roles-list/RolesListPage';
import RoleFormPage from './pages/roles/role-form/RoleFormPage';
import RoleDetailPage from './pages/roles/role-detail/RoleDetailPage';
import RolePermissionsPage from './pages/roles/role-permissions/RolePermissionsPage';
const ProtectedRoute = ({ children }: { children: any }) => { const ProtectedRoute = ({ children }: { children: any }) => {
const { user } = useAuth(); const { user } = useAuth();
return user ? children : <Navigate to="/login" replace />; return user ? children : <Navigate to="/login" replace />;
@ -36,6 +42,13 @@ const AppRoutes = () => {
<Route path="orders" element={<Orders />} /> <Route path="orders" element={<Orders />} />
<Route path="reports" element={<Reports />} /> <Route path="reports" element={<Reports />} />
<Route path="notifications" element={<Notifications />} /> <Route path="notifications" element={<Notifications />} />
{/* Roles Routes */}
<Route path="roles" element={<RolesListPage />} />
<Route path="roles/create" element={<RoleFormPage />} />
<Route path="roles/:id" element={<RoleDetailPage />} />
<Route path="roles/:id/edit" element={<RoleFormPage />} />
<Route path="roles/:id/permissions" element={<RolePermissionsPage />} />
</Route> </Route>
</Routes> </Routes>
); );

View File

@ -51,11 +51,11 @@ export const Header = ({ onMenuClick }: HeaderProps) => {
> >
<div className="w-8 h-8 bg-primary-600 rounded-full flex items-center justify-center"> <div className="w-8 h-8 bg-primary-600 rounded-full flex items-center justify-center">
<span className="text-white text-sm font-medium"> <span className="text-white text-sm font-medium">
{user?.name?.charAt(0) || 'A'} {user?.first_name?.charAt(0) || 'A'}
</span> </span>
</div> </div>
<span className="text-sm font-medium text-gray-700 dark:text-gray-300 hidden md:block"> <span className="text-sm font-medium text-gray-700 dark:text-gray-300 hidden md:block">
{user?.name || 'کاربر'} {user?.first_name} {user?.last_name}
</span> </span>
</button> </button>
@ -64,10 +64,10 @@ export const Header = ({ onMenuClick }: HeaderProps) => {
<div className="py-1"> <div className="py-1">
<div className="px-4 py-2 border-b border-gray-200 dark:border-gray-700"> <div className="px-4 py-2 border-b border-gray-200 dark:border-gray-700">
<p className="text-sm font-medium text-gray-900 dark:text-gray-100"> <p className="text-sm font-medium text-gray-900 dark:text-gray-100">
{user?.name} {user?.first_name} {user?.last_name}
</p> </p>
<p className="text-xs text-gray-500 dark:text-gray-400"> <p className="text-xs text-gray-500 dark:text-gray-400">
{user?.email} {user?.username}
</p> </p>
</div> </div>
<button className="w-full text-right px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center"> <button className="w-full text-right px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center">

View File

@ -8,7 +8,8 @@ import {
FileText, FileText,
Bell, Bell,
X, X,
ChevronDown ChevronDown,
Shield
} from 'lucide-react'; } from 'lucide-react';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import { PermissionWrapper } from '../common/PermissionWrapper'; import { PermissionWrapper } from '../common/PermissionWrapper';
@ -28,6 +29,13 @@ const menuItems: MenuItem[] = [
path: '/users', path: '/users',
permission: 10, permission: 10,
}, },
{
id: 'roles',
label: 'نقش‌ها',
icon: Shield,
path: '/roles',
permission: 5,
},
{ {
id: 'products', id: 'products',
label: 'محصولات', label: 'محصولات',
@ -64,7 +72,7 @@ interface SidebarProps {
} }
export const Sidebar = ({ isOpen, onClose }: SidebarProps) => { export const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
const { user } = useAuth(); const { user, hasPermission } = useAuth();
const [expandedItems, setExpandedItems] = useState<string[]>([]); const [expandedItems, setExpandedItems] = useState<string[]>([]);
const toggleExpanded = (itemId: string) => { const toggleExpanded = (itemId: string) => {
@ -189,15 +197,15 @@ export const Sidebar = ({ isOpen, onClose }: SidebarProps) => {
<div className="flex items-center mb-6 p-3 bg-gray-50 dark:bg-gray-700 rounded-lg"> <div className="flex items-center mb-6 p-3 bg-gray-50 dark:bg-gray-700 rounded-lg">
<div className="w-10 h-10 bg-primary-600 rounded-full flex items-center justify-center"> <div className="w-10 h-10 bg-primary-600 rounded-full flex items-center justify-center">
<span className="text-white font-medium"> <span className="text-white font-medium">
{user?.name?.charAt(0) || 'A'} {user?.first_name?.charAt(0) || 'A'}
</span> </span>
</div> </div>
<div className="mr-3"> <div className="mr-3">
<p className="text-sm font-medium text-gray-900 dark:text-gray-100"> <p className="text-sm font-medium text-gray-900 dark:text-gray-100">
{user?.name || 'کاربر'} {user?.first_name} {user?.last_name}
</p> </p>
<p className="text-xs text-gray-500 dark:text-gray-400"> <p className="text-xs text-gray-500 dark:text-gray-400">
{user?.role || 'مدیر'} {user?.username}
</p> </p>
</div> </div>
</div> </div>