import { createMemo, createResource, createSignal, For, Show } from 'solid-js'; import AdminShell from '~/components/AdminShell'; const API = '/api/gateway'; type ModuleRecord = { id: string; name: string; key: string; description?: string; isActive: boolean; }; type ModuleForm = { name: string; key: string; description: string; isActive: boolean; }; const EMPTY_FORM: ModuleForm = { name: '', key: '', description: '', isActive: true }; async function fetchModules(): Promise { const res = await fetch(`${API}/api/modules`); if (!res.ok) return []; const data = await res.json(); return Array.isArray(data) ? data : data?.modules || []; } export default function ModulesPage() { const [refreshToken, setRefreshToken] = createSignal(0); const [isModalOpen, setIsModalOpen] = createSignal(false); const [editing, setEditing] = createSignal(null); const [form, setForm] = createSignal({ ...EMPTY_FORM }); const [error, setError] = createSignal(''); const [submitting, setSubmitting] = createSignal(false); const [modules] = createResource(refreshToken, fetchModules); const modalTitle = createMemo(() => editing() ? 'Edit Module' : 'Create Module'); function openModal(item?: ModuleRecord) { if (item) { setEditing(item); setForm({ name: item.name || '', key: item.key || '', description: item.description || '', isActive: Boolean(item.isActive), }); } else { setEditing(null); setForm({ ...EMPTY_FORM }); } setError(''); setIsModalOpen(true); } function closeModal() { setIsModalOpen(false); setEditing(null); setForm({ ...EMPTY_FORM }); setError(''); } async function submitForm(event: Event) { event.preventDefault(); const current = form(); if (!current.name.trim() || !current.key.trim()) { setError('Name and key are required.'); return; } setSubmitting(true); setError(''); try { const target = editing(); const method = target ? 'PATCH' : 'POST'; const url = target ? `${API}/api/modules/${target.id}` : `${API}/api/modules`; const res = await fetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(current), }); if (!res.ok) { const message = await res.text(); throw new Error(message || 'Failed to save module'); } closeModal(); setRefreshToken((value) => value + 1); } catch (nextError: any) { setError(nextError?.message || 'Failed to save module'); } finally { setSubmitting(false); } } async function removeModule(id: string) { if (!confirm('Are you sure you want to delete this module?')) return; try { const res = await fetch(`${API}/api/modules/${id}`, { method: 'DELETE' }); if (!res.ok) throw new Error('Delete failed'); setRefreshToken((value) => value + 1); } catch { setError('Failed to delete module.'); } } return (

Module Registry

Manage internal module definitions and activation state.

{error()}

Loading modules...

0} fallback={ }> {(item) => ( )}
Name Key Description Status Actions
No modules found.
{item.name} {item.key} {item.description || '—'} {item.isActive ? 'Active' : 'Inactive'}