import { useNavigate } from '@solidjs/router'; import { createMemo, createResource, createSignal, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; const API = '/api/gateway'; type Permission = { id: string; module: string; action: string }; async function loadPermissions(): Promise { const res = await fetch(`${API}/api/admin/permissions`); if (!res.ok) return []; const data = await res.json(); const rows = Array.isArray(data) ? data : (data.permissions || []); return rows; } export default function CreateInternalRolePage() { const navigate = useNavigate(); const [permissions] = createResource(loadPermissions); const [roleName, setRoleName] = createSignal(''); const [description, setDescription] = createSignal(''); const [assignedModules, setAssignedModules] = createSignal([]); const [permissionIds, setPermissionIds] = createSignal([]); const [saving, setSaving] = createSignal(false); const [error, setError] = createSignal(''); const permsByModule = createMemo(() => { const map: Record = {}; (permissions() || []).forEach((p) => { if (!map[p.module]) map[p.module] = []; map[p.module].push(p); }); return map; }); const allModules = createMemo(() => Object.keys(permsByModule()).sort()); const toggleModule = (mod: string) => { const current = assignedModules(); if (current.includes(mod)) { setAssignedModules(current.filter((m) => m !== mod)); // remove permissions for this module const idsToRemove = (permsByModule()[mod] || []).map((p) => p.id); setPermissionIds(permissionIds().filter((id) => !idsToRemove.includes(id))); } else { setAssignedModules([...current, mod]); } }; const togglePermission = (id: string) => { const current = permissionIds(); if (current.includes(id)) { setPermissionIds(current.filter((p) => p !== id)); } else { setPermissionIds([...current, id]); } }; const handleSave = async () => { if (!roleName().trim()) { setError('Role name is required'); return; } if (assignedModules().length === 0) { setError('Select at least one module'); return; } if (permissionIds().length === 0) { setError('Assign at least one permission'); return; } try { setSaving(true); setError(''); const res = await fetch(`${API}/api/admin/roles`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: roleName().trim(), description: description().trim(), audience: 'INTERNAL', modules: assignedModules(), permissionIds: permissionIds(), }), }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.message || 'Failed to create role'); } navigate('/admin/roles'); } catch (err: any) { setError(err.message || 'Failed to create role'); } finally { setSaving(false); } }; return (

Create Internal Role

Add a new internal role with module access and permissions.

Back to Roles
{error()}
{/* Role Details */}

Role Details

Start by giving the role a simple business name.

setRoleName(e.currentTarget.value)} placeholder="e.g. Customer Support Rep" />
setDescription(e.currentTarget.value)} placeholder="Short description of this role" />
{/* Module Access */}

Module Access

Select which modules this role can access. Only selected modules will appear in the permission table below.

Loading modules...

0}>
{allModules().map((mod) => ( ))}

No modules available. Is the backend running?

{/* Permission Table */} 0}>

Permissions

Set Read / Create / Update / Delete access for each assigned module.

{assignedModules().sort().map((mod) => { const perms = permsByModule()[mod] || []; const actionMap: Record = {}; perms.forEach((p) => { actionMap[p.action] = p.id; }); const hasRead = !!actionMap['Read'] && permissionIds().includes(actionMap['Read']); const hasCreate = !!actionMap['Create'] && permissionIds().includes(actionMap['Create']); const hasUpdate = !!actionMap['Update'] && permissionIds().includes(actionMap['Update']); const hasDelete = !!actionMap['Delete'] && permissionIds().includes(actionMap['Delete']); const noAccess = !hasRead && !hasCreate && !hasUpdate && !hasDelete; return ( ); })}
Name of the module No Access Read Create Update Delete
{mod} {actionMap['Read'] ? togglePermission(actionMap['Read'])} aria-label={`${mod} read`} /> : } {actionMap['Create'] ? togglePermission(actionMap['Create'])} aria-label={`${mod} create`} /> : } {actionMap['Update'] ? togglePermission(actionMap['Update'])} aria-label={`${mod} update`} /> : } {actionMap['Delete'] ? togglePermission(actionMap['Delete'])} aria-label={`${mod} delete`} /> : }
{/* Save */}
); }