PageSourceSearch

https://www.hamienet.com/assets/TrustSafety-cHE1J5RX.js

js hamienet.com collected 2026-09-24 19:01:05 UTC 17,309 bytes, 189 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { a as api } from "./index-D0Bmh-UX.js";
3import { U as UserAvatar } from "./UserAvatar-BQN4jlY-.js";
4import { bL as Clock, g3 as UserX, cI as Flag, cl as OctagonAlert, bv as CircleCheckBig, cf as Activity, bc as MessageSquare, a$ as Shield, e7 as CircleX, c3 as RotateCcw } from "./vendor-dVNaLJx_.js";
5import "./vendor-i18n-R-bMoYp_.js";
6const StatCard = ({ label, value, icon: Icon, color }) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `p-4 rounded-xl border flex items-center justify-between ${color.replace("border", "bg-opacity-1 bg")}`, children: [
7  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
8    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-500 uppercase font-bold tracking-wider", children: label }),
9    /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-2xl font-bold text-zinc-900 dark:text-white mt-1", children: value })
10  ] }),
11  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `p-3 rounded-full opacity-20 ${color.replace("border", "bg")}`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { size: 24, className: color.replace("border", "text").replace("-200", "-600") }) })
12] });
13const TrustSafety = () => {
14  const [summary, setSummary] = reactExports.useState({ atRiskUsers: 0, flaggedTracks: 0, pendingItems: 0 });
15  const [activeTab, setActiveTab] = reactExports.useState("queue");
16  const [queue, setQueue] = reactExports.useState({ tracks: [], comments: [] });
17  const [flagged, setFlagged] = reactExports.useState({ users: [], tracks: [] });
18  const [reports, setReports] = reactExports.useState([]);
19  const refresh = async () => {
20    const s = await api.getTrustSafetySummary();
21    setSummary(s);
22    if (activeTab === "queue") {
23      const q = await api.getPendingContent();
24      setQueue(q);
25    } else if (activeTab === "reports") {
26      const r = await api.getReports("pending");
27      setReports(r);
28    } else {
29      const f = await api.getFlaggedContent();
30      setFlagged(f);
31    }
32  };
33  reactExports.useEffect(() => {
34    refresh();
35  }, [activeTab]);
36  const handleAction = async (type, id, action) => {
37    await api.resolveTrustItem(type, id, action);
38    refresh();
39  };
40  const handleResolveReport = async (report, action) => {
41    await api.resolveReport(report.id, action);
42    refresh();
43  };
44  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6 animate-in fade-in", children: [
45    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-4 gap-6", children: [
46      /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Moderation Queue", value: summary.pendingItems, icon: Clock, color: "border-indigo-200 dark:border-indigo-800" }),
47      /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "At-Risk Users", value: summary.atRiskUsers, icon: UserX, color: "border-red-200 dark:border-red-800" }),
48      /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Flagged Content", value: summary.flaggedTracks, icon: Flag, color: "border-amber-200 dark:border-amber-800" }),
49      /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Pending Reports", value: reports.length, icon: OctagonAlert, color: "border-orange-200 dark:border-orange-800" })
50    ] }),
51    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 rounded-xl overflow-hidden shadow-sm flex flex-col min-h-[600px]", children: [
52      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-b border-zinc-200 dark:border-zinc-800 px-6 py-4 flex items-center gap-6 bg-zinc-50 dark:bg-zinc-950 overflow-x-auto", children: [
53        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setActiveTab("queue"), className: `pb-1 text-sm font-bold border-b-2 transition-all whitespace-nowrap ${activeTab === "queue" ? "border-indigo-500 text-indigo-600 dark:text-indigo-400" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`, children: "Approval Queue" }),
54        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setActiveTab("reports"), className: `pb-1 text-sm font-bold border-b-2 transition-all whitespace-nowrap ${activeTab === "reports" ? "border-orange-500 text-orange-600 dark:text-orange-400" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`, children: "User Reports" }),
55        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setActiveTab("content"), className: `pb-1 text-sm font-bold border-b-2 transition-all whitespace-nowrap ${activeTab === "content" ? "border-amber-500 text-amber-600 dark:text-amber-400" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`, children: "Flagged Content" }),
56        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setActiveTab("users"), className: `pb-1 text-sm font-bold border-b-2 transition-all whitespace-nowrap ${activeTab === "users" ? "border-red-500 text-red-600 dark:text-red-400" : "border-transparent text-zinc-500 hover:text-zinc-800 dark:hover:text-zinc-200"}`, children: "High-Risk Users" })
57      ] }),
58      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 flex-1 bg-zinc-50/50 dark:bg-black/20 overflow-y-auto", children: [
59        activeTab === "queue" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
60          queue.tracks.length === 0 && queue.comments.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-20 text-zinc-400 flex flex-col items-center gap-3", children: [
61            /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheckBig, { size: 48, className: "text-emerald-500 opacity-50" }),
62            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "All caught up! No pending items." })
63          ] }),
64          queue.tracks.map((track) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-800 p-4 rounded-lg shadow-sm border border-zinc-200 dark:border-zinc-700 flex justify-between items-center", children: [
65            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
66              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 bg-indigo-50 dark:bg-indigo-900/20 rounded-lg text-indigo-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 20 }) }),
67              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
68                /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "font-bold text-sm text-zinc-900 dark:text-white", children: [
69                  "Track: ",
70                  track.title
71                ] }),
72                /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-zinc-500", children: [
73                  "by ",
74                  track.uploader.name,
75                  " • Low Trust User"
76                ] })
77              ] })
78            ] }),
79            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
80              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("track", track.id, "reject"), className: "px-4 py-2 bg-red-100 hover:bg-red-200 text-red-700 rounded-lg text-xs font-bold transition-colors", children: "Reject" }),
81              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("track", track.id, "approve"), className: "px-4 py-2 bg-emerald-100 hover:bg-emerald-200 text-emerald-700 rounded-lg text-xs font-bold transition-colors", children: "Approve" })
82            ] })
83          ] }, track.id)),
84          queue.comments.map((comment) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-800 p-4 rounded-lg shadow-sm border border-zinc-200 dark:border-zinc-700 flex justify-between items-center", children: [
85            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
86              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 bg-blue-50 dark:bg-blue-900/20 rounded-lg text-blue-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(MessageSquare, { size: 20 }) }),
87              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
88                /* @__PURE__ */ jsxRuntimeExports.jsxs("h4", { className: "font-bold text-sm text-zinc-900 dark:text-white line-clamp-1 max-w-md", children: [
89                  '"',
90                  comment.text,
91                  '"'
92                ] }),
93                /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-zinc-500", children: [
94                  "by ",
95                  comment.user,
96                  " • Pending Comment"
97                ] })
98              ] })
99            ] }),
100            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
101              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("comment", comment.id, "reject"), className: "px-4 py-2 bg-red-100 hover:bg-red-200 text-red-700 rounded-lg text-xs font-bold transition-colors", children: "Hide" }),
102              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("comment", comment.id, "approve"), className: "px-4 py-2 bg-emerald-100 hover:bg-emerald-200 text-emerald-700 rounded-lg text-xs font-bold transition-colors", children: "Approve" })
103            ] })
104          ] }, comment.id))
105        ] }),
106        activeTab === "reports" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
107          reports.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-20 text-zinc-400 flex flex-col items-center gap-3", children: [
108            /* @__PURE__ */ jsxRuntimeExports.jsx(Shield, { size: 48, className: "text-emerald-500 opacity-50" }),
109            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "No open reports. Good job!" })
110          ] }),
111          reports.map((report) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-800 p-4 rounded-lg shadow-sm border border-l-4 border-l-orange-500 border-zinc-200 dark:border-zinc-700 flex justify-between items-center", children: [
112            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-4", children: [
113              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "p-3 bg-orange-50 dark:bg-orange-900/20 rounded-lg text-orange-600", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Flag, { size: 20 }) }),
114              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
115                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
116                  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-bold text-sm text-zinc-900 dark:text-white uppercase", children: report.targetType }),
117                  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-xs bg-zinc-100 dark:bg-zinc-900 px-2 py-0.5 rounded text-zinc-500", children: [
118                    "ID: ",
119                    report.targetId
120                  ] })
121                ] }),
122                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-bold text-zinc-800 dark:text-zinc-200 mt-1", children: report.reason }),
123                report.details && /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-zinc-600 dark:text-zinc-400 mt-1 italic", children: [
124                  '"',
125                  report.details,
126                  '"'
127                ] }),
128                /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-zinc-500 mt-1", children: new Date(report.createdAt).toLocaleString() })
129              ] })
130            ] }),
131            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
132              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleResolveReport(report, "dismiss"), className: "px-4 py-2 bg-zinc-100 hover:bg-zinc-200 dark:bg-zinc-700 dark:hover:bg-zinc-600 text-zinc-700 dark:text-zinc-200 rounded-lg text-xs font-bold transition-colors", children: "Dismiss" }),
133              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleResolveReport(report, "resolve"), className: "px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white rounded-lg text-xs font-bold transition-colors", children: "Take Action" })
134            ] })
135          ] }, report.id))
136        ] }),
137        activeTab === "content" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
138          flagged.tracks.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-center py-20 text-zinc-400", children: "No flagged content found." }),
139          flagged.tracks.map((track) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-800 p-4 rounded-lg shadow-sm border border-l-4 border-l-amber-500 border-zinc-200 dark:border-zinc-700 flex justify-between items-center", children: [
140            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
141              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
142                /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-bold text-zinc-900 dark:text-white", children: track.title }),
143                track.visibility === "suspended" && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-[10px] bg-red-100 text-red-600 px-2 py-0.5 rounded font-bold uppercase", children: "Suspended" })
144              ] }),
145              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-zinc-500 flex items-center gap-3", children: [
146                /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "flex items-center gap-1", children: [
147                  /* @__PURE__ */ jsxRuntimeExports.jsx(Activity, { size: 12, className: "text-red-500" }),
148                  " Health: ",
149                  track.healthScore,
150                  "/100"
151                ] }),
152                track.suspensionReason && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-red-500 font-medium", children: [
153                  "Reason: ",
154                  track.suspensionReason
155                ] })
156              ] })
157            ] }),
158            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [
159              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("track", track.id, "ban"), className: "p-2 hover:bg-red-100 text-red-500 rounded-lg", title: "Suspend", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleX, { size: 18 }) }),
160              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("track", track.id, "heal"), className: "p-2 hover:bg-emerald-100 text-emerald-500 rounded-lg", title: "Restore Health", children: /* @__PURE__ */ jsxRuntimeExports.jsx(RotateCcw, { size: 18 }) })
161            ] })
162          ] }, track.id))
163        ] }),
164        activeTab === "users" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: [
165          flagged.users.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "col-span-full text-center py-20 text-zinc-400", children: "No high-risk users found." }),
166          flagged.users.map((user) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-800 p-4 rounded-lg border border-red-200 dark:border-red-900/30 flex flex-col gap-3", children: [
167            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3", children: [
168              /* @__PURE__ */ jsxRuntimeExports.jsx(UserAvatar, { src: user.avatar, name: user.username, size: 40 }),
169              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
170                /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-bold text-sm text-zinc-900 dark:text-white", children: user.username }),
171                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-xs text-red-500 font-bold", children: [
172                  "Trust Score: ",
173                  user.trustScore
174                ] })
175              ] })
176            ] }),
177            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2 mt-auto", children: [
178              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("user", user.id, "ban"), className: "flex-1 py-1.5 bg-red-50 hover:bg-red-100 text-red-600 rounded text-xs font-bold", children: "Ban" }),
179              /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => handleAction("user", user.id, "heal"), className: "flex-1 py-1.5 bg-zinc-100 hover:bg-zinc-200 text-zinc-600 rounded text-xs font-bold", children: "Reset Score" })
180            ] })
181          ] }, user.id))
182        ] })
183      ] })
184    ] })
185  ] });
186};
187export {
188  TrustSafety as default
189};

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.