'use client'; import { useState } from 'react'; import { Shield, Plus, Search, X, Edit, Trash2, Copy, Check, ChevronDown, ChevronRight, BookOpen, FileSearch, Settings, BarChart3, Bike, Users, Briefcase, Truck, Store, BatteryCharging, Building2, Wrench, DollarSign, TrendingUp, UserCog } from 'lucide-react'; interface Permission { key: string; label: string; enabled: boolean; divider?: boolean; pair?: boolean; } interface PermissionPair { label: string; view: Permission; edit: Permission; } interface PermissionGroup { id: string; title: string; description: string; icon: React.ComponentType<{ className?: string }>; permissions: Permission[]; permissionPairs?: PermissionPair[]; } interface Role { id: string; name: string; description: string; isDefault: boolean; permissionGroups: PermissionGroup[]; } const buildDefaultGroups = (): PermissionGroup[] => [ { id: 'kyc', title: 'KYC Requests & Verification', description: 'The Biker user will request from the app. Investor, Shop, Merchant will request from the website. Front desk officers (hub/head office) can request for Biker, Investor, Shop, Merchant and can upload remaining documents. Admin officers (head office) will approve or reject documents with notes and "make a Biker | Investor | Shop | Merchant".', icon: FileSearch, permissions: [ { key: 'kyc.request', label: 'KYC Request', enabled: false }, { key: 'kyc.view', label: 'View KYC Requests', enabled: false }, { key: 'kyc.doc_upload', label: 'Document Upload', enabled: false }, { key: 'kyc.doc_approve', label: 'Document Approve', enabled: false }, { key: 'kyc.doc_reject', label: 'Document Reject', enabled: false }, { key: 'kyc.make_valid_user', label: 'Make a Biker | Make an Investor | Make a Shop | Make a Merchant', enabled: false }, ] }, { id: 'settings', title: 'Settings', description: 'Manage KYC documents, plans, company policies, and system configuration', icon: Settings, permissionPairs: [ { label: 'KYC Documents', view: { key: 'settings.kyc_documents_view', label: 'View', enabled: false }, edit: { key: 'settings.kyc_documents_config', label: 'Config', enabled: false }, }, { label: 'Plan Selection with Condition', view: { key: 'settings.plan_selection_with_condition_view', label: 'View', enabled: false }, edit: { key: 'settings.plan_selection_with_condition_config', label: 'Config', enabled: false }, }, { label: 'Investment Plan', view: { key: 'settings.investment_plan_view', label: 'View', enabled: false }, edit: { key: 'settings.investment_plan_config', label: 'Config', enabled: false }, }, { label: 'Swap Station Plan', view: { key: 'settings.swap_station_plan_view', label: 'View', enabled: false }, edit: { key: 'settings.swap_station_plan_config', label: 'Config', enabled: false }, }, { label: 'Rider Request Plan for Merchant', view: { key: 'settings.rider_request_plan_for_merchant_view', label: 'View', enabled: false }, edit: { key: 'settings.rider_request_plan_for_merchant_config', label: 'Config', enabled: false }, }, { label: 'Company Policy', view: { key: 'settings.company_policy_view', label: 'View', enabled: false }, edit: { key: 'settings.company_policy_config', label: 'Config', enabled: false }, }, ], permissions: [], }, { id: 'dashboard', title: 'Dashboard', description: 'Access to main dashboard', icon: BarChart3, permissions: [ { key: 'dashboard.view', label: 'View Dashboard', enabled: false }, ] }, { id: 'rentals', title: 'Rentals', description: 'Manage rental operations', icon: Bike, permissions: [ { key: 'rentals.view', label: 'View', enabled: false }, { key: 'rentals.create', label: 'Create', enabled: false }, { key: 'rentals.edit', label: 'Edit', enabled: false }, { key: 'rentals.delete', label: 'Delete', enabled: false }, ] }, { id: 'bikers', title: 'Bikers', description: 'Manage bikers', icon: Users, permissions: [ { key: 'bikers.view', label: 'View', enabled: false }, { key: 'bikers.create', label: 'Create', enabled: false }, { key: 'bikers.edit', label: 'Edit', enabled: false }, { key: 'bikers.delete', label: 'Delete', enabled: false }, ] }, { id: 'investors', title: 'Investors', description: 'Manage investors', icon: Briefcase, permissions: [ { key: 'investors.view', label: 'View', enabled: false }, { key: 'investors.create', label: 'Create', enabled: false }, { key: 'investors.edit', label: 'Edit', enabled: false }, { key: 'investors.delete', label: 'Delete', enabled: false }, ] }, { id: 'fleet', title: 'Fleet', description: 'Manage fleet vehicles', icon: Truck, permissions: [ { key: 'fleet.view', label: 'View', enabled: false }, { key: 'fleet.create', label: 'Create', enabled: false }, { key: 'fleet.edit', label: 'Edit', enabled: false }, { key: 'fleet.delete', label: 'Delete', enabled: false }, ] }, { id: 'merchants', title: 'Merchants', description: 'Manage merchants', icon: Store, permissions: [ { key: 'merchants.view', label: 'View', enabled: false }, { key: 'merchants.create', label: 'Create', enabled: false }, { key: 'merchants.edit', label: 'Edit', enabled: false }, { key: 'merchants.delete', label: 'Delete', enabled: false }, ] }, { id: 'swap_stations', title: 'Swap Stations', description: 'Manage swap stations', icon: BatteryCharging, permissions: [ { key: 'swap_stations.view', label: 'View', enabled: false }, { key: 'swap_stations.create', label: 'Create', enabled: false }, { key: 'swap_stations.edit', label: 'Edit', enabled: false }, { key: 'swap_stations.delete', label: 'Delete', enabled: false }, ] }, { id: 'hubs', title: 'Hubs', description: 'Manage hubs', icon: Building2, permissions: [ { key: 'hubs.view', label: 'View', enabled: false }, { key: 'hubs.create', label: 'Create', enabled: false }, { key: 'hubs.edit', label: 'Edit', enabled: false }, { key: 'hubs.delete', label: 'Delete', enabled: false }, ] }, { id: 'maintenance', title: 'Maintenance', description: 'Manage maintenance requests', icon: Wrench, permissions: [ { key: 'maintenance.view', label: 'View', enabled: false }, { key: 'maintenance.create', label: 'Create', enabled: false }, { key: 'maintenance.edit', label: 'Edit', enabled: false }, { key: 'maintenance.delete', label: 'Delete', enabled: false }, ] }, { id: 'accounting', title: 'Accounting', description: 'Manage financial records', icon: DollarSign, permissions: [ { key: 'accounting.view', label: 'View', enabled: false }, { key: 'accounting.create', label: 'Create', enabled: false }, { key: 'accounting.edit', label: 'Edit', enabled: false }, { key: 'accounting.delete', label: 'Delete', enabled: false }, ] }, { id: 'reports', title: 'Reports', description: 'View and generate reports', icon: TrendingUp, permissions: [ { key: 'reports.view', label: 'View', enabled: false }, { key: 'reports.export', label: 'Export', enabled: false }, ] }, { id: 'users', title: 'Users', description: 'Manage system users', icon: UserCog, permissions: [ { key: 'users.view', label: 'View', enabled: false }, { key: 'users.create', label: 'Create', enabled: false }, { key: 'users.edit', label: 'Edit', enabled: false }, { key: 'users.delete', label: 'Delete', enabled: false }, ] }, ]; const mockRoles: Role[] = [ { id: 'ROLE-001', name: 'Admin', description: 'Full system access with all permissions', isDefault: false, permissionGroups: buildDefaultGroups().map(g => ({ ...g, permissions: g.permissions.map(p => ({ ...p, enabled: true })) })) }, { id: 'ROLE-002', name: 'Manager', description: 'Management access with limited delete permissions', isDefault: false, permissionGroups: buildDefaultGroups().map(g => ({ ...g, permissions: g.permissions.map(p => ({ ...p, enabled: !p.key.includes('delete') })) })) }, { id: 'ROLE-003', name: 'Front Desk Officer', description: 'Hub/head office officer - can request KYC and upload documents', isDefault: false, permissionGroups: buildDefaultGroups().map(g => { if (g.id === 'kyc') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: ['kyc.request', 'kyc.view', 'kyc.doc_upload'].includes(p.key) })) }; } if (g.id === 'dashboard') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: true })) }; } return g; }) }, { id: 'ROLE-004', name: 'Admin Officer', description: 'Head office officer - can approve/reject KYC documents and make valid users', isDefault: false, permissionGroups: buildDefaultGroups().map(g => { if (g.id === 'kyc') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: ['kyc.view', 'kyc.doc_approve', 'kyc.doc_reject', 'kyc.make_valid_user'].includes(p.key) })) }; } if (g.id === 'dashboard') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: true })) }; } return g; }) }, { id: 'ROLE-005', name: 'Biker', description: 'Limited access for bike riders - can view dashboard, request KYC, manage rentals', isDefault: false, permissionGroups: buildDefaultGroups().map(g => { if (g.id === 'dashboard') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: true })) }; } if (g.id === 'kyc') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: ['kyc.request', 'kyc.view'].includes(p.key) })) }; } if (g.id === 'rentals') { return { ...g, permissions: g.permissions.map(p => ({ ...p, enabled: ['rentals.view', 'rentals.create'].includes(p.key) })) }; } return g; }) }, ]; function Toggle({ checked, onChange, color = 'blue' }: { checked: boolean; onChange: () => void; color?: string }) { const colors: Record = { blue: checked ? 'bg-blue-600' : 'bg-slate-200', green: checked ? 'bg-green-600' : 'bg-slate-200', amber: checked ? 'bg-amber-600' : 'bg-slate-200', red: checked ? 'bg-red-600' : 'bg-slate-200', }; return ( ); } export default function RolesPage() { const [roles, setRoles] = useState(mockRoles); const [search, setSearch] = useState(''); const [showCreateModal, setShowCreateModal] = useState(false); const [editingRole, setEditingRole] = useState(null); const [selectedRole, setSelectedRole] = useState(null); const [expandedGroups, setExpandedGroups] = useState>({}); const [formData, setFormData] = useState({ name: '', description: '' }); const filteredRoles = roles.filter(r => r.name.toLowerCase().includes(search.toLowerCase()) || r.description.toLowerCase().includes(search.toLowerCase()) ); const handleSave = () => { if (!formData.name) return; if (editingRole) { setRoles(roles.map(r => r.id === editingRole.id ? { ...r, ...formData, isDefault: false } : r)); } else { const newRole: Role = { id: `ROLE-${String(roles.length + 1).padStart(3, '0')}`, ...formData, isDefault: false, permissionGroups: buildDefaultGroups() }; setRoles([...roles, newRole]); } setShowCreateModal(false); setEditingRole(null); setFormData({ name: '', description: '' }); }; const handleDelete = (id: string) => { if (confirm('Are you sure you want to delete this role?')) { setRoles(roles.filter(r => r.id !== id)); setSelectedRole(null); } }; const handleDuplicate = (role: Role) => { const newRole: Role = { id: `ROLE-${String(roles.length + 1).padStart(3, '0')}`, name: `${role.name} (Copy)`, description: role.description, isDefault: false, permissionGroups: role.permissionGroups.map(g => ({ ...g, permissions: g.permissions.map(p => ({ ...p })) })) }; setRoles([...roles, newRole]); setSelectedRole(newRole); }; const openEdit = (role: Role) => { setEditingRole(role); setFormData({ name: role.name, description: role.description }); setShowCreateModal(true); }; const togglePermission = (groupIndex: number, permIndex: number) => { if (!selectedRole) return; const updated = [...selectedRole.permissionGroups]; const perm = updated[groupIndex].permissions[permIndex]; perm.enabled = !perm.enabled; setSelectedRole({ ...selectedRole, permissionGroups: updated }); setRoles(roles.map(r => r.id === selectedRole.id ? { ...selectedRole, permissionGroups: updated } : r)); }; const togglePermissionPair = (groupIndex: number, pairIndex: number, type: 'view' | 'edit') => { if (!selectedRole) return; const updated = [...selectedRole.permissionGroups]; const pair = updated[groupIndex].permissionPairs![pairIndex]; pair[type].enabled = !pair[type].enabled; setSelectedRole({ ...selectedRole, permissionGroups: updated }); setRoles(roles.map(r => r.id === selectedRole.id ? { ...selectedRole, permissionGroups: updated } : r)); }; const toggleGroupAll = (groupIndex: number, enabled: boolean) => { if (!selectedRole) return; const updated = [...selectedRole.permissionGroups]; const group = updated[groupIndex]; if (group.permissionPairs) { group.permissionPairs = group.permissionPairs.map(p => ({ ...p, view: { ...p.view, enabled }, edit: { ...p.edit, enabled }, })); } else { group.permissions = group.permissions.map(p => ({ ...p, enabled })); } setSelectedRole({ ...selectedRole, permissionGroups: updated }); setRoles(roles.map(r => r.id === selectedRole.id ? { ...selectedRole, permissionGroups: updated } : r)); }; const isGroupAllEnabled = (group: PermissionGroup) => { if (group.permissionPairs) { return group.permissionPairs.every(p => p.view.enabled && p.edit.enabled); } return group.permissions.every(p => p.enabled); }; const getEnabledCount = (group: PermissionGroup) => { if (group.permissionPairs) { return group.permissionPairs.filter(p => p.view.enabled && p.edit.enabled).length; } return group.permissions.filter(p => p.enabled).length; }; const getTotalCount = (group: PermissionGroup) => { if (group.permissionPairs) { return group.permissionPairs.length; } return group.permissions.length; }; const getTotalEnabled = (role: Role) => role.permissionGroups.reduce((a, g) => { if (g.permissionPairs) { return a + g.permissionPairs.filter(p => p.view.enabled && p.edit.enabled).length; } return a + g.permissions.filter(p => p.enabled).length; }, 0); const toggleGroup = (groupId: string) => { setExpandedGroups(prev => ({ ...prev, [groupId]: !prev[groupId] })); }; return (

Roles & Permissions

Manage roles and access permissions

{roles.length}

Total Roles

{roles.filter(r => r.isDefault).length}

Default Roles

{roles.reduce((a, r) => a + getTotalEnabled(r), 0)}

Total Permissions

{selectedRole ? getTotalEnabled(selectedRole) : '-'}

Selected Role Perms

setSearch(e.target.value)} className="w-full pl-10 pr-4 py-2 border border-slate-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-accent focus:border-transparent" />
{filteredRoles.map(role => (
setSelectedRole(role)} >

{role.name}

{role.description}

{role.isDefault && ( Default )}
{getTotalEnabled(role)} permissions
))}
{selectedRole ? ( <>

{selectedRole.name}

{selectedRole.description}

{!selectedRole.isDefault && ( )}
{selectedRole.permissionGroups.map((group, gi) => (
toggleGroup(group.id)} >

{group.title}

{getEnabledCount(group)}/{getTotalCount(group)} enabled

{expandedGroups[group.id] ? ( ) : ( )}
{expandedGroups[group.id] && (

{group.description}

{group.permissionPairs ? (
{group.permissionPairs.map((pair, pairIdx) => (
{pair.label}
{pair.view.enabled ? ( ) : ( )} {pair.view.label} togglePermissionPair(gi, pairIdx, 'view')} />
{pair.edit.enabled ? ( ) : ( )} {pair.edit.label} togglePermissionPair(gi, pairIdx, 'edit')} />
{pairIdx < (group.permissionPairs?.length || 0) - 1 && (
)}
))}
) : (
{group.permissions.map((perm, pi) => (
{perm.enabled ? ( ) : ( )} {perm.label} {perm.key}
togglePermission(gi, pi)} />
))}
)}
)}
))}
) : (

Select a role to view and edit permissions

)}
{showCreateModal && (

{editingRole ? 'Edit Role' : 'Create New Role'}

setFormData({ ...formData, name: e.target.value })} className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mt-1" placeholder="e.g., Super Manager" />