feat: implement role-based access control for KYC workflows and add permissions documentation

This commit is contained in:
sazzadulalambd
2026-05-09 12:51:28 +06:00
parent 4f58fba36d
commit c0916cd3a2
4 changed files with 129 additions and 22 deletions

View File

@@ -2,7 +2,7 @@
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { useState } from 'react';
import { useState, useEffect } from 'react';
import {
Bike,
Settings,
@@ -24,6 +24,18 @@ import {
Calculator,
Wrench
} from 'lucide-react';
import { getUserName, getUserRole, logout } from '@/lib/auth';
const ROLE_LABELS: Record<string, string> = {
super_admin: 'Super Admin',
admin_manager: 'Admin Manager',
staff: 'Front Desk',
accountant: 'Accountant',
investor: 'Investor',
biker: 'Biker',
'swap-station': 'Swap Station',
merchant: 'Merchant',
};
const adminNavItems = [
{ label: 'Dashboard', href: '/admin', icon: BarChart3 },
@@ -67,11 +79,20 @@ export default function Sidebar() {
const pathname = usePathname();
const [mobileOpen, setMobileOpen] = useState(false);
const [expandedMenu, setExpandedMenu] = useState<string | null>(null);
const [userName, setUserName] = useState('User');
const [userRole, setUserRole] = useState('admin');
useEffect(() => {
setUserName(getUserName() || 'User');
setUserRole(getUserRole() || 'staff');
}, []);
const isAdmin = pathname.startsWith('/admin');
const isInvestor = pathname.startsWith('/investor');
const isShop = pathname.startsWith('/shop');
const roleLabel = ROLE_LABELS[userRole] || userRole;
const navItems = isAdmin ? adminNavItems :
isInvestor ? investorNavItems :
isShop ? shopNavItems : bikerNavItems;
@@ -109,7 +130,7 @@ export default function Sidebar() {
</div>
<div className="flex items-center gap-2">
<div className="px-2 py-1 bg-accent-light rounded text-xs font-semibold text-accent">
{isAdmin ? 'Admin' : isInvestor ? 'Investor' : isShop ? 'Shop' : 'Biker'}
{roleLabel}
</div>
<button
onClick={() => setMobileOpen(false)}
@@ -148,23 +169,16 @@ export default function Sidebar() {
<div className="absolute bottom-0 left-0 right-0 p-3 border-t border-slate-100 bg-white">
<Link href="/admin/users/USR-001" className="flex items-center gap-3 px-3 py-2 hover:bg-slate-50 rounded-lg -mx-1">
<div className="w-8 h-8 rounded-full bg-accent-light flex items-center justify-center">
<span className="text-sm font-bold text-accent">A</span>
<span className="text-sm font-bold text-accent">{userName.charAt(0).toUpperCase()}</span>
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-slate-700 truncate">Admin User</p>
<p className="text-xs text-slate-400">admin@jaiben.com</p>
<p className="text-sm font-medium text-slate-700 truncate">{userName}</p>
<p className="text-xs text-slate-400">{roleLabel}</p>
</div>
<button
onClick={() => {
// Import and call logout function
// Note: We can't use client-only imports in server components directly
// For now, we'll just clear sessionStorage and redirect
if (typeof window !== 'undefined') {
window.sessionStorage.removeItem('authToken');
window.sessionStorage.removeItem('userRole');
window.sessionStorage.removeItem('userName');
window.location.href = '/login';
}
logout();
window.location.href = '/login';
}}
className="p-1.5 hover:bg-slate-100 rounded-lg"
>