import { A, useNavigate } from '@solidjs/router'; import { createMemo, createResource, createSignal, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; import { STATIC_PERMISSIONS, type Permission } from '~/lib/admin-modules'; const API = '/api/gateway'; async function loadPermissions(): Promise { try { const res = await fetch(`${API}/api/admin/permissions`); if (!res.ok) return STATIC_PERMISSIONS; const data = await res.json(); const rows: Permission[] = Array.isArray(data) ? data : (data.permissions || []); return rows.length > 0 ? rows : STATIC_PERMISSIONS; } catch { return STATIC_PERMISSIONS; } } 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

Create a new internal role and choose what it can access.

{error()}
{/* Role Details */}

Role Basics

Start by giving this role a clear name.

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

Area Access

Select which areas this role can access. You can set permissions for selected areas below.

Loading available areas...

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

No areas available.

{/* Permission Table */} 0}>

Permissions

Choose what this role can do in each selected area.

{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 ( ); })}
Area 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 */}
Cancel
); }