import { useState, useEffect } from 'react' import api from '@/services/api' import { useAuth } from '@/hooks/useAuth' interface Permission { id: number name: string description: string category: string } interface Role { id: number name: string description: string | null is_global: boolean | null permission_ids: number[] } export default function RoleEditorPage() { const { user } = useAuth() const [roles, setRoles] = useState([]) const [permissions, setPermissions] = useState([]) const [selectedRole, setSelectedRole] = useState(null) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [message, setMessage] = useState('') const [showCreateForm, setShowCreateForm] = useState(false) const [newRoleName, setNewRoleName] = useState('') const [newRoleDesc, setNewRoleDesc] = useState('') const [creating, setCreating] = useState(false) const isAdmin = user?.is_admin === true useEffect(() => { fetchData() }, []) const fetchData = async () => { try { const [rolesRes, permsRes] = await Promise.all([ api.get('/roles'), api.get('/roles/permissions') ]) setRoles(rolesRes.data) setPermissions(permsRes.data) } catch (err) { console.error('Failed to fetch data:', err) } finally { setLoading(false) } } const handlePermissionToggle = (permId: number) => { if (!selectedRole) return const newPermIds = selectedRole.permission_ids.includes(permId) ? selectedRole.permission_ids.filter(id => id !== permId) : [...selectedRole.permission_ids, permId] setSelectedRole({ ...selectedRole, permission_ids: newPermIds }) } const handleSave = async () => { if (!selectedRole) return setSaving(true) setMessage('') try { await api.post(`/roles/${selectedRole.id}/permissions`, { permission_ids: selectedRole.permission_ids }) setMessage('Saved successfully!') fetchData() } catch (err: any) { setMessage(err.response?.data?.detail || 'Failed to save') } finally { setSaving(false) } } const handleDeleteRole = async () => { if (!selectedRole || !confirm(`Are you sure you want to delete the "${selectedRole.name}" role?`)) return setSaving(true) setMessage('') try { await api.delete(`/roles/${selectedRole.id}`) setMessage('Role deleted successfully!') setSelectedRole(null) fetchData() } catch (err: any) { setMessage(err.response?.data?.detail || 'Failed to delete role') } finally { setSaving(false) } } const canDeleteRole = selectedRole && !['admin', 'guest', 'account-manager'].includes(selectedRole.name) && isAdmin const handleCreateRole = async () => { if (!newRoleName.trim()) return setCreating(true) setMessage('') try { await api.post('/roles', { name: newRoleName.trim(), description: newRoleDesc.trim() || null, is_global: false }) setMessage('Role created successfully!') setShowCreateForm(false) setNewRoleName('') setNewRoleDesc('') fetchData() } catch (err: any) { setMessage(err.response?.data?.detail || 'Failed to create role') } finally { setCreating(false) } } const groupedPermissions = permissions.reduce((acc, p) => { if (!acc[p.category]) acc[p.category] = [] acc[p.category].push(p) return acc }, {} as Record) if (loading) return
Loading...
return (

🔐 Role Editor

Configure permissions for each role. Only admins can edit roles.

{isAdmin && !showCreateForm && ( )} {showCreateForm && (

Create New Role

setNewRoleName(e.target.value)} placeholder="e.g., developer, manager" style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }} />
setNewRoleDesc(e.target.value)} placeholder="Role description" style={{ width: '100%', padding: '8px', borderRadius: '4px', border: '1px solid #ddd' }} />
)} {message && (
{message}
)}
{/* Role List */}

Roles

{roles.map(role => (
setSelectedRole({ ...role })} style={{ padding: '12px', border: selectedRole?.id === role.id ? '2px solid #007bff' : '1px solid #ddd', borderRadius: '6px', cursor: 'pointer', backgroundColor: selectedRole?.id === role.id ? '#f0f8ff' : 'white' }} > {role.name} {role.is_global && 🌟}
{role.description}
{role.permission_ids.length} permissions
))}
{/* Permission Editor */}
{selectedRole ? ( <>

Permissions for: {selectedRole.name}

{Object.entries(groupedPermissions).map(([category, perms]) => (

{category}

{perms.map(perm => ( ))}
))}
{canDeleteRole && ( )} ) : (
Select a role to edit its permissions
)}
) }