PageSourceSearch

https://www.hamienet.com/assets/AdminSettings-35H5SUoJ.js

js hamienet.com collected 2026-10-02 05:01:23 UTC 14,235 bytes, 218 lines download raw bytes

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.