// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential. // Module Manager — Supreme Admin CRUD for XCU Module Registry // Dynamic: Add, Deactivate, Search modules. Data from xcu_iam PostgreSQL. import { useState } from 'react'; import { useModuleRegistry } from '../context/ModuleRegistryContext'; import DangerModal from './DangerModal'; export default function ModuleManager() { const { registry, allModules, totalModules, loading, source, addModule, deleteModule, refreshRegistry } = useModuleRegistry(); const [showAddForm, setShowAddForm] = useState(false); const [searchQuery, setSearchQuery] = useState(''); const [deleteTarget, setDeleteTarget] = useState(null); // Add module form state const [newId, setNewId] = useState(''); const [newName, setNewName] = useState(''); const [newGroupId, setNewGroupId] = useState('group1'); const [newGroupName, setNewGroupName] = useState(''); const [newSortOrder, setNewSortOrder] = useState(100); const [isSubmitting, setIsSubmitting] = useState(false); // Derive available groups const groups = Object.entries(registry).map(([key, val]) => ({ id: key, name: val.name })); const handleAddModule = async () => { if (!newId || !newName) return; setIsSubmitting(true); const groupName = newGroupName || (groups.find(g => g.id === newGroupId)?.name || newGroupId); const success = await addModule({ id: newId, name: newName, group_id: newGroupId, group_name: groupName, sort_order: Number(newSortOrder) }); if (success) { setNewId(''); setNewName(''); setNewSortOrder(totalModules + 1); setNewGroupName(''); setShowAddForm(false); } setIsSubmitting(false); }; const handleDeleteConfirm = async () => { if (!deleteTarget) return; await deleteModule(deleteTarget); setDeleteTarget(null); }; // Filter modules const q = searchQuery.toLowerCase(); const filteredGroups = Object.entries(registry).map(([key, group]) => ({ key, name: group.name, modules: (group.modules || []).filter(m => !q || m.id.toLowerCase().includes(q) || m.name.toLowerCase().includes(q) ) })).filter(g => g.modules.length > 0); const filteredCount = filteredGroups.reduce((sum, g) => sum + g.modules.length, 0); if (loading) { return (
LOADING SOVEREIGN MODULE REGISTRY...
); } return (
setDeleteTarget(null)} confirmText="DEACTIVATE MODULE" /> {/* Header */}

SOVEREIGN MODULE REGISTRY

Dynamic Module CRUD — Source: {source === 'API' ? 'xcu_iam PostgreSQL' : 'Static Fallback'}

{/* Stats */}
{totalModules}
ACTIVE MODULES
{Object.keys(registry).length}
GROUPS
{/* Add Module Form */} {showAddForm && (

FORGE NEW MODULE

setNewId(e.target.value)} placeholder="m100" style={{width: '100%', padding: '10px', background: 'var(--hover-bg)', border: '1px solid var(--table-border)', color: 'var(--text-main)', borderRadius: '6px', fontFamily: 'monospace'}} />
setNewName(e.target.value)} placeholder="Quantum Flux Capacitor" style={{width: '100%', padding: '10px', background: 'var(--hover-bg)', border: '1px solid var(--table-border)', color: 'var(--text-main)', borderRadius: '6px', fontFamily: 'monospace'}} />
{newGroupId === 'new' && (
setNewGroupName(e.target.value)} placeholder="KELOMPOK IX: ..." style={{width: '100%', padding: '10px', background: 'var(--hover-bg)', border: '1px solid var(--table-border)', color: 'var(--text-main)', borderRadius: '6px', fontFamily: 'monospace'}} />
)}
setNewSortOrder(e.target.value)} style={{width: '100%', padding: '10px', background: 'var(--hover-bg)', border: '1px solid var(--table-border)', color: 'var(--text-main)', borderRadius: '6px', fontFamily: 'monospace'}} />
)} {/* Search */}
setSearchQuery(e.target.value)} placeholder="Search modules by ID or name..." style={{ width: '100%', padding: '12px 20px', background: 'var(--hover-bg)', border: '1px solid var(--table-border)', color: 'var(--text-main)', borderRadius: '8px', fontFamily: 'monospace', fontSize: '0.9rem', outline: 'none' }} /> {searchQuery && ( {filteredCount} / {totalModules} )}
{/* Module Grid */}
{filteredGroups.map(group => { const groupColors = { group1: '#00f3ff', group2: '#ffea00', group3: '#ff003c', group4: '#a855f7', group5: '#10b981', group6: '#3b82f6', group7: '#f97316', group8: '#ef4444' }; const color = groupColors[group.key] || '#00f3ff'; return (

{group.name} [{group.modules.length}]

{group.modules.map(mod => (
{mod.name} {mod.id}
))}
); })}
); }