1import { r as reactExports, j as jsxRuntimeExports, R as React } from "./vendor-react-Bay9Y7Lb.js"; 2import { a as api } from "./index-w5lXls15.js"; 3import { cF as Key, cf as Plus, a$ as Shield, dP as Users, b7 as Check, e5 as ChartNoAxesColumnIncreasing, e4 as Bot, cm as OctagonAlert, ci as Database, bI as Hash, dQ as LifeBuoy, bH as Box, cl as HardDrive, dZ as Server, e2 as Palette, cg as Activity, bg as Music, f9 as Pen, b5 as Trash2, aW as X } from "./vendor-D0P4XgNj.js"; 4import "./vendor-i18n-BC7ZMXWQ.js"; 5const MODULE_PERMISSIONS = [ 6 { id: "dashboard", label: "Intelligence Dashboard", icon: ChartNoAxesColumnIncreasing }, 7 { id: "dev_agent", label: "AI Developer", icon: Bot }, 8 { id: "trust", label: "Trust & Safety", icon: OctagonAlert }, 9 { id: "users", label: "User Governance", icon: Users }, 10 { id: "media", label: "Content Assets", icon: Database }, 11 { id: "tags", label: "Tag Dictionary", icon: Hash }, 12 { id: "tickets", label: "Support Desk", icon: LifeBuoy }, 13 { id: "modules", label: "Admin Module Studio", icon: Box }, 14 { id: "files", label: "File System", icon: HardDrive }, 15 { id: "database", label: "Schema & Data", icon: Server }, 16 { id: "appearance", label: "Appearance Settings", icon: Palette }, 17 { id: "logs", label: "System Logs", icon: Activity }, 18 { id: "settings", label: "Admin Roles & Permissions", icon: Key }, 19 { id: "sheet_music", label: "Sheet Music Engine", icon: Music } 20]; 21const RoleModal = ({ isOpen, onClose, onSave, initialData }) => { 22 const [name, setName] = reactExports.useState(""); 23 const [pin, setPin] = reactExports.useState(""); 24 const [allowedModules, setAllowedModules] = reactExports.useState(/* @__PURE__ */ new Set()); 25 const [isLoading, setIsLoading] = reactExports.useState(false); 26 reactExports.useEffect(() => { 27 if (isOpen) { 28 if (initialData) { 29 setName(initialData.name); 30 setPin(""); 31 setAllowedModules(new Set(initialData.allowedModules)); 32 } else { 33 setName(""); 34 setPin(""); 35 setAllowedModules(/* @__PURE__ */ new Set()); 36 } 37 } 38 }, [isOpen, initialData]); 39 if (!isOpen) return null; 40 const togglePermission = (id) => { 41 setAllowedModules((prev) => { 42 const next = new Set(prev); 43 if (next.has(id)) next.delete(id); 44 else next.add(id); 45 return next; 46 }); 47 }; 48 const handleSubmit = async () => { 49 if (!name) { 50 alert("Please provide a role name."); 51 return; 52 } 53 if (!initialData && pin.length !== 6) { 54 alert("Please provide a 6-digit PIN for new roles."); 55 return; 56 } 57 setIsLoading(true); 58 const data = { name, allowedModules: Array.from(allowedModules) }; 59 if (pin && pin.length === 6) { 60 data.pin = pin; 61 } else if (initialData && pin && pin.length !== 6) { 62 alert("PIN must be 6 digits."); 63 setIsLoading(false); 64 return; 65 } 66 await onSave(data); 67 setIsLoading(false); 68 onClose(); 69 }; 70 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-[100] flex items-center justify-center p-4", children: [ 71 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute inset-0 bg-black/50 backdrop-blur-sm", onClick: onClose }), 72 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative w-full max-w-lg bg-white dark:bg-zinc-900 rounded-xl shadow-2xl p-6 border border-zinc-200 dark:border-zinc-800 animate-in zoom-in-95", children: [
73 /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "absolute top-4 right-4 p-2 hover:bg-zinc-100 dark:hover:bg-zinc-800 rounded-full text-zinc-500", children: /* @__PURE__ */ jsxRuntimeExports.jsx(X, { size: 20 }) }), 74 /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-xl font-bold mb-6 text-zinc-900 dark:text-white", children: initialData ? "Edit Role" : "Create New Role" }), 75 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [ 76 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 77 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs font-bold text-zinc-500 uppercase mb-1", children: "Role Name" }), 78 /* @__PURE__ */ jsxRuntimeExports.jsx("input", { value: name, onChange: (e) => setName(e.target.value), className: "w-full bg-zinc-50 dark:bg-black border border-zinc-300 dark:border-zinc-700 rounded p-2 text-sm outline-none focus:border-indigo-500 text-zinc-900 dark:text-white", placeholder: "e.g. Community Manager" }) 79 ] }),
80 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 81 /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block text-xs font-bold text-zinc-500 uppercase mb-1", children: [ 82 "6-Digit Security PIN ", 83 initialData && "(Leave blank to keep current)" 84 ] }), 85 /* @__PURE__ */ jsxRuntimeExports.jsx("input", { type: "password", value: pin, onChange: (e) => setPin(e.target.value.replace(/\D/g, "").slice(0, 6)), className: "w-full bg-zinc-50 dark:bg-black border border-zinc-300 dark:border-zinc-700 rounded p-2 text-sm outline-none focus:border-indigo-500 text-zinc-900 dark:text-white font-mono tracking-[1em]", maxLength: 6, placeholder: "******" }) 86 ] }), 87 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 88 /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-xs font-bold text-zinc-500 uppercase mb-2", children: "Permissions" }), 89 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-2 gap-2", children: MODULE_PERMISSIONS.map((mod) => /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: () => togglePermission(mod.id), className: `flex items-center gap-2 p-2 rounded-lg text-left text-sm transition-colors ${allowedModules.has(mod.id) ? "bg-indigo-50 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-300" : "bg-zinc-50 dark:bg-zinc-800/50 hover:bg-zinc-100 dark:hover:bg-zinc-800"}`, children: [
90 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-4 h-4 rounded border flex items-center justify-center ${allowedModules.has(mod.id) ? "bg-indigo-600 border-indigo-600" : "border-zinc-300"}`, children: allowedModules.has(mod.id) && /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 10, className: "text-white" }) }), 91 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: mod.label }) 92 ] }, mod.id)) }) 93 ] }) 94 ] }), 95 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-2 pt-6", children: [ 96 /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: onClose, className: "px-4 py-2 rounded-lg text-zinc-600 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800 font-bold text-sm", children: "Cancel" }), 97 /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleSubmit, disabled: isLoading, className: "px-4 py-2 rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white font-bold text-sm flex items-center gap-2", children: [ 98 isLoading && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-3 h-3 border-2 border-white/50 border-t-white rounded-full animate-spin" }), 99 initialData ? "Save Changes" : "Create Role" 100 ] }) 101 ] }) 102 ] }) 103 ] }); 104}; 105const AdminSettings = () => { 106 const [roles, setRoles] = reactExports.useState([]); 107 const [isModalOpen, setIsModalOpen] = reactExports.useState(false); 108 const [editingRole, setEditingRole] = reactExports.useState(null); 109 reactExports.useEffect(() => { 110 fetchRoles(); 111 }, []); 112 const fetchRoles = async () => { 113 const data = await api.getAdminRoles(); 114 setRoles(data); 115 }; 116 const handleCreate = () => { 117 setEditingRole(null); 118 setIsModalOpen(true); 119 }; 120 const handleEdit = (role) => { 121 setEditingRole(role); 122 setIsModalOpen(true); 123 }; 124 const handleDelete = async (id) => { 125 if (confirm("Are you sure you want to delete this role? Users assigned to this role may lose access.")) { 126 await api.deleteAdminRole(id); 127 fetchRoles(); 128 } 129 }; 130 const handleSave = async (data) => { 131 if (editingRole) { 132 const updates = { 133 name: data.name, 134 allowedModules: data.allowedModules 135 }; 136 if (data.pin) { 137 updates.pin = data.pin; 138 } 139 await api.updateAdminRole(editingRole.id, updates); 140 } else { 141 await api.createAdminRole(data); 142 } 143 fetchRoles(); 144 }; 145 return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [ 146 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6 h-full overflow-y-auto custom-scrollbar pr-2 animate-in fade-in", children: [
147 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center shrink-0", children: [ 148 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ 149 /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-xl font-bold text-zinc-900 dark:text-white flex items-center gap-2", children: [ 150 /* @__PURE__ */ jsxRuntimeExports.jsx(Key, { className: "text-indigo-500" }), 151 " Admin Roles & Permissions" 152 ] }), 153 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-zinc-500 dark:text-zinc-400 text-sm mt-1", children: "Manage access levels for different administrative staff." }) 154 ] }), 155 /* @__PURE__ */ jsxRuntimeExports.jsxs("button", { onClick: handleCreate, className: "bg-zinc-900 dark:bg-white text-white dark:text-black hover:opacity-90 px-4 py-2 rounded-lg font-bold flex items-center gap-2 transition-all text-sm", children: [ 156 /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { size: 16 }), 157 " Create Role" 158 ] }) 159 ] }),
160 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6", children: roles.map((role) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl p-5 shadow-sm flex flex-col hover:border-indigo-500 transition-colors group", children: [ 161 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-between items-start mb-3", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [ 162 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `w-10 h-10 rounded-lg flex items-center justify-center ${role.isSuperAdmin ? "bg-amber-100 text-amber-600" : "bg-indigo-50 dark:bg-indigo-900/30 text-indigo-600 dark:text-indigo-400"}`, children: role.isSuperAdmin ? /* @__PURE__ */ jsxRuntimeExports.jsx(Shield, { size: 20 }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Users, { size: 20 }) }), 163 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
164 /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "font-bold text-zinc-900 dark:text-white", children: role.name }), 165 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-500", children: role.isSuperAdmin ? "System Root" : `ID: ${role.id}` }) 166 ] }) 167 ] }) }), 168 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 mb-6", children: [ 169 /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs font-bold text-zinc-500 uppercase mb-2", children: "Access Capabilities" }), 170 role.isSuperAdmin ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-sm text-zinc-700 dark:text-zinc-300 bg-zinc-50 dark:bg-zinc-800 p-2 rounded", children: [ 171 /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { size: 14, className: "text-emerald-500" }), 172 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: "Full System Access" }) 173 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-wrap gap-1.5", children: role.allowedModules.length > 0 ? role.allowedModules.map((modId) => { 174 var _a; 175 return /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "px-2 py-1 rounded bg-zinc-100 dark:bg-zinc-800 text-[10px] font-medium text-zinc-600 dark:text-zinc-400 capitalize border border-zinc-200 dark:border-zinc-700 flex items-center gap-1", children: [ 176 ((_a = MODULE_PERMISSIONS.find((m) => m.id === modId)) == null ? void 0 : _a.icon) && React.createElement(MODULE_PERMISSIONS.find((m) => m.id === modId).icon, { size: 10 }), 177 modId 178 ] }, modId); 179 }) : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs text-zinc-400 italic", children: "No modules assigned" }) }) 180 ] }),
181 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 pt-4 border-t border-zinc-100 dark:border-zinc-800", children: [ 182 /* @__PURE__ */ jsxRuntimeExports.jsxs( 183 "button", 184 { 185 onClick: () => handleEdit(role), 186 disabled: role.isSuperAdmin, 187 className: "flex-1 flex items-center justify-center gap-2 text-xs bg-zinc-50 dark:bg-zinc-800 hover:bg-zinc-100 dark:hover:bg-zinc-700 py-2 rounded-lg font-bold text-zinc-700 dark:text-zinc-300 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", 188 children: [ 189 /* @__PURE__ */ jsxRuntimeExports.jsx(Pen, { size: 12 }), 190 " Edit" 191 ] 192 } 193 ), 194 !role.isSuperAdmin && /* @__PURE__ */ jsxRuntimeExports.jsx( 195 "button", 196 { 197 onClick: () => handleDelete(role.id), 198 className: "px-3 bg-red-50 dark:bg-red-900/10 hover:bg-red-100 dark:hover:bg-red-900/30 text-red-600 dark:text-red-400 rounded-lg flex items-center justify-center transition-colors", 199 children: /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { size: 14 }) 200 } 201 ) 202 ] }) 203 ] }, role.id)) }) 204 ] }), 205 /* @__PURE__ */ jsxRuntimeExports.jsx( 206 RoleModal, 207 { 208 isOpen: isModalOpen, 209 onClose: () => setIsModalOpen(false), 210 onSave: handleSave, 211 initialData: editingRole 212 } 213 ) 214 ] }); 215}; 216export { 217 AdminSettings as default 218};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.