@burdenoff/microfe-subscriberbot 2026.827.1 → 2026.1014.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/subscriberbot/admin/AdminDashboardPage.d.ts.map +1 -1
- package/dist/subscriberbot/admin/AdminDashboardPage.js +80 -83
- package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
- package/dist/subscriberbot/hooks/index.d.ts +1 -0
- package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
- package/dist/subscriberbot/hooks/index.js +1 -0
- package/dist/subscriberbot/hooks/useTr.d.ts +17 -0
- package/dist/subscriberbot/hooks/useTr.d.ts.map +1 -0
- package/dist/subscriberbot/hooks/useTr.js +14 -0
- package/dist/subscriberbot/hooks/useTr.js.map +1 -0
- package/dist/subscriberbot/pages/AssetVaultPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/AssetVaultPage.js +111 -109
- package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -1
- package/dist/subscriberbot/pages/DashboardPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/DashboardPage.js +113 -105
- package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
- package/dist/subscriberbot/pages/InboxPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/InboxPage.js +404 -369
- package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
- package/dist/subscriberbot/pages/InsightsPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/InsightsPage.js +94 -93
- package/dist/subscriberbot/pages/InsightsPage.js.map +1 -1
- package/dist/subscriberbot/pages/InvoicesPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/InvoicesPage.js +360 -366
- package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
- package/dist/subscriberbot/pages/WorkflowsPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/WorkflowsPage.js +209 -193
- package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js +268 -236
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentNewPage.js +96 -76
- package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentsListPage.js +145 -161
- package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +514 -441
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderNewPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderNewPage.js +167 -129
- package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProvidersListPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/providers/ProvidersListPage.js +171 -218
- package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +340 -279
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipNewPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +185 -166
- package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipsListPage.d.ts.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +153 -182
- package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AdminDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAuCpD,eAAO,MAAM,kBAAkB,EAAE,EA0dhC,CAAC"}
|
|
@@ -1,38 +1,39 @@
|
|
|
1
1
|
import { PageLayout as e } from "../components/PageLayout.js";
|
|
2
2
|
import { formatDate as t } from "../utils/formatters.js";
|
|
3
3
|
import { StatusBadge as n } from "../components/StatusBadge.js";
|
|
4
|
-
import { useAdapterSubmissions as r, useApproveAdapter as i, useMarketplaceReports as
|
|
4
|
+
import { useAdapterSubmissions as r, useApproveAdapter as i, useMarketplaceReports as a, useModerateListing as ee, useProviders as te, useRejectAdapter as ne, useUpdateProvider as re } from "../hooks/useSubscriberBotApi.js";
|
|
5
|
+
import { useTr as o } from "../hooks/useTr.js";
|
|
5
6
|
import "../hooks/index.js";
|
|
6
7
|
import { Fragment as s, useState as c } from "react";
|
|
7
|
-
import { CheckCircle2 as l, Plug as u, Settings2 as
|
|
8
|
+
import { CheckCircle2 as l, Plug as u, Settings2 as ie, Store as d, XCircle as ae } from "lucide-react";
|
|
8
9
|
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
9
|
-
import { Button as m, Card as h, CardContent as g, CardDescription as _, CardHeader as v, CardTitle as y, EmptyState as b, Spinner as x, Table as S, TableBody as C, TableCell as w, TableHead as T, TableHeader as E, TableRow as D, Tabs as
|
|
10
|
+
import { Button as m, Card as h, CardContent as g, CardDescription as _, CardHeader as v, CardTitle as y, EmptyState as b, Spinner as x, Table as S, TableBody as C, TableCell as w, TableHead as T, TableHeader as E, TableRow as D, Tabs as oe, TabsContent as O, TabsList as se, TabsTrigger as k, Textarea as A } from "@burdenoff/fe-libs/ui";
|
|
10
11
|
//#region src/subscriberbot/admin/AdminDashboardPage.tsx
|
|
11
|
-
var
|
|
12
|
-
let [
|
|
13
|
-
|
|
12
|
+
var j = () => {
|
|
13
|
+
let j = o(), [M, ce] = c("providers"), { data: le, isLoading: ue } = te({ pagination: { limit: 50 } }), N = re(), P = (e) => {
|
|
14
|
+
N.mutate({
|
|
14
15
|
id: e,
|
|
15
16
|
input: { status: "VERIFIED" }
|
|
16
17
|
});
|
|
17
|
-
},
|
|
18
|
-
|
|
18
|
+
}, F = (e) => {
|
|
19
|
+
N.mutate({
|
|
19
20
|
id: e,
|
|
20
21
|
input: { status: "DEPRECATED" }
|
|
21
22
|
});
|
|
22
|
-
}, I =
|
|
23
|
+
}, I = le?.items ?? [], { data: L, isLoading: R } = r({ pagination: { limit: 50 } }), z = i(), B = ne(), [V, H] = c(null), [U, W] = c(""), G = L?.items ?? [], de = (e) => {
|
|
23
24
|
z.mutate({ id: e });
|
|
24
|
-
},
|
|
25
|
+
}, fe = (e) => {
|
|
25
26
|
H(e), W("");
|
|
26
|
-
},
|
|
27
|
+
}, pe = (e) => {
|
|
27
28
|
U.trim() && B.mutate({
|
|
28
29
|
id: e,
|
|
29
30
|
reason: U.trim()
|
|
30
31
|
}, { onSuccess: () => {
|
|
31
32
|
H(null), W("");
|
|
32
33
|
} });
|
|
33
|
-
}, { data:
|
|
34
|
+
}, { data: me, isLoading: he } = a({ pagination: { limit: 50 } }), K = ee(), [ge, q] = c(null), [J, Y] = c(null), [X, Z] = c(""), Q = me?.items ?? [], $ = (e, t) => {
|
|
34
35
|
q(e), Y(t), Z("");
|
|
35
|
-
},
|
|
36
|
+
}, _e = (e) => {
|
|
36
37
|
!J || !X.trim() || K.mutate({
|
|
37
38
|
id: e,
|
|
38
39
|
action: J,
|
|
@@ -42,52 +43,52 @@ var N = () => {
|
|
|
42
43
|
} });
|
|
43
44
|
};
|
|
44
45
|
return /* @__PURE__ */ f(e, {
|
|
45
|
-
title: "SubscriberBot Admin",
|
|
46
|
-
description: "Provider registry curation, adapter approvals, and marketplace moderation.",
|
|
47
|
-
children: /* @__PURE__ */ p(
|
|
48
|
-
value:
|
|
49
|
-
onValueChange:
|
|
46
|
+
title: j("admin.title", "SubscriberBot Admin"),
|
|
47
|
+
description: j("admin.description", "Provider registry curation, adapter approvals, and marketplace moderation."),
|
|
48
|
+
children: /* @__PURE__ */ p(oe, {
|
|
49
|
+
value: M,
|
|
50
|
+
onValueChange: ce,
|
|
50
51
|
className: "w-full",
|
|
51
52
|
children: [
|
|
52
|
-
/* @__PURE__ */ p(
|
|
53
|
+
/* @__PURE__ */ p(se, {
|
|
53
54
|
className: "mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex",
|
|
54
55
|
children: [
|
|
55
|
-
/* @__PURE__ */ p(
|
|
56
|
+
/* @__PURE__ */ p(k, {
|
|
56
57
|
value: "providers",
|
|
57
58
|
className: "gap-2",
|
|
58
|
-
children: [/* @__PURE__ */ f(
|
|
59
|
+
children: [/* @__PURE__ */ f(ie, { size: 16 }), j("admin.tabs.providers", "Provider Registry")]
|
|
59
60
|
}),
|
|
60
|
-
/* @__PURE__ */ p(
|
|
61
|
+
/* @__PURE__ */ p(k, {
|
|
61
62
|
value: "adapters",
|
|
62
63
|
className: "gap-2",
|
|
63
|
-
children: [/* @__PURE__ */ f(u, { size: 16 }), "Adapter Approvals"]
|
|
64
|
+
children: [/* @__PURE__ */ f(u, { size: 16 }), j("admin.tabs.adapters", "Adapter Approvals")]
|
|
64
65
|
}),
|
|
65
|
-
/* @__PURE__ */ p(
|
|
66
|
+
/* @__PURE__ */ p(k, {
|
|
66
67
|
value: "marketplace",
|
|
67
68
|
className: "gap-2",
|
|
68
|
-
children: [/* @__PURE__ */ f(d, { size: 16 }), "Marketplace Moderation"]
|
|
69
|
+
children: [/* @__PURE__ */ f(d, { size: 16 }), j("admin.tabs.marketplace", "Marketplace Moderation")]
|
|
69
70
|
})
|
|
70
71
|
]
|
|
71
72
|
}),
|
|
72
|
-
/* @__PURE__ */ f(
|
|
73
|
+
/* @__PURE__ */ f(O, {
|
|
73
74
|
value: "providers",
|
|
74
|
-
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: "Provider registry" }), /* @__PURE__ */ f(_, { children: "Curate the global provider catalog. Verify submitted providers or deprecate stale entries." })] }), /* @__PURE__ */ f(g, { children:
|
|
75
|
+
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.providers.title", "Provider registry") }), /* @__PURE__ */ f(_, { children: j("admin.providers.description", "Curate the global provider catalog. Verify submitted providers or deprecate stale entries.") })] }), /* @__PURE__ */ f(g, { children: ue ? /* @__PURE__ */ f("div", {
|
|
75
76
|
className: "flex min-h-[200px] items-center justify-center",
|
|
76
77
|
children: /* @__PURE__ */ f(x, { size: "lg" })
|
|
77
78
|
}) : I.length === 0 ? /* @__PURE__ */ f(b, {
|
|
78
79
|
icon: /* @__PURE__ */ f(d, { className: "size-6 text-action-primary-bg" }),
|
|
79
|
-
title: "No providers yet",
|
|
80
|
-
description: "Once providers are created or claimed they will appear here for curation."
|
|
80
|
+
title: j("admin.providers.emptyTitle", "No providers yet"),
|
|
81
|
+
description: j("admin.providers.emptyDescription", "Once providers are created or claimed they will appear here for curation.")
|
|
81
82
|
}) : /* @__PURE__ */ f("div", {
|
|
82
83
|
className: "overflow-x-auto",
|
|
83
84
|
children: /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(E, { children: /* @__PURE__ */ p(D, { children: [
|
|
84
|
-
/* @__PURE__ */ f(T, { children: "Name" }),
|
|
85
|
-
/* @__PURE__ */ f(T, { children: "Category" }),
|
|
86
|
-
/* @__PURE__ */ f(T, { children: "Status" }),
|
|
87
|
-
/* @__PURE__ */ f(T, { children: "Created" }),
|
|
85
|
+
/* @__PURE__ */ f(T, { children: j("admin.providers.table.name", "Name") }),
|
|
86
|
+
/* @__PURE__ */ f(T, { children: j("admin.providers.table.category", "Category") }),
|
|
87
|
+
/* @__PURE__ */ f(T, { children: j("admin.providers.table.status", "Status") }),
|
|
88
|
+
/* @__PURE__ */ f(T, { children: j("admin.providers.table.created", "Created") }),
|
|
88
89
|
/* @__PURE__ */ f(T, {
|
|
89
90
|
className: "text-right",
|
|
90
|
-
children: "Actions"
|
|
91
|
+
children: j("admin.providers.table.actions", "Actions")
|
|
91
92
|
})
|
|
92
93
|
] }) }), /* @__PURE__ */ f(C, { children: I.map((e) => /* @__PURE__ */ p(D, { children: [
|
|
93
94
|
/* @__PURE__ */ f(w, {
|
|
@@ -110,43 +111,43 @@ var N = () => {
|
|
|
110
111
|
children: [e.status !== "VERIFIED" && /* @__PURE__ */ p(m, {
|
|
111
112
|
size: "sm",
|
|
112
113
|
variant: "outline",
|
|
113
|
-
onClick: () =>
|
|
114
|
-
disabled:
|
|
114
|
+
onClick: () => P(e.id),
|
|
115
|
+
disabled: N.isPending,
|
|
115
116
|
children: [/* @__PURE__ */ f(l, {
|
|
116
117
|
size: 14,
|
|
117
118
|
className: "mr-1"
|
|
118
|
-
}), "Verify"]
|
|
119
|
+
}), j("admin.providers.verify", "Verify")]
|
|
119
120
|
}), e.status !== "DEPRECATED" && /* @__PURE__ */ f(m, {
|
|
120
121
|
size: "sm",
|
|
121
122
|
variant: "secondary",
|
|
122
|
-
onClick: () =>
|
|
123
|
-
disabled:
|
|
124
|
-
children: "Deprecate"
|
|
123
|
+
onClick: () => F(e.id),
|
|
124
|
+
disabled: N.isPending,
|
|
125
|
+
children: j("admin.providers.deprecate", "Deprecate")
|
|
125
126
|
})]
|
|
126
127
|
})
|
|
127
128
|
})
|
|
128
129
|
] }, e.id)) })] })
|
|
129
130
|
}) })] })
|
|
130
131
|
}),
|
|
131
|
-
/* @__PURE__ */ f(
|
|
132
|
+
/* @__PURE__ */ f(O, {
|
|
132
133
|
value: "adapters",
|
|
133
|
-
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: "Adapter approvals" }), /* @__PURE__ */ f(_, { children: "Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace." })] }), /* @__PURE__ */ f(g, { children: R ? /* @__PURE__ */ f("div", {
|
|
134
|
+
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.adapters.title", "Adapter approvals") }), /* @__PURE__ */ f(_, { children: j("admin.adapters.description", "Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.") })] }), /* @__PURE__ */ f(g, { children: R ? /* @__PURE__ */ f("div", {
|
|
134
135
|
className: "flex min-h-[200px] items-center justify-center",
|
|
135
136
|
children: /* @__PURE__ */ f(x, { size: "lg" })
|
|
136
137
|
}) : G.length === 0 ? /* @__PURE__ */ f(b, {
|
|
137
138
|
icon: /* @__PURE__ */ f(u, { className: "size-6 text-action-primary-bg" }),
|
|
138
|
-
title: "No adapter submissions",
|
|
139
|
-
description: "Submitted integration adapters will appear here for review."
|
|
139
|
+
title: j("admin.adapters.emptyTitle", "No adapter submissions"),
|
|
140
|
+
description: j("admin.adapters.emptyDescription", "Submitted integration adapters will appear here for review.")
|
|
140
141
|
}) : /* @__PURE__ */ f("div", {
|
|
141
142
|
className: "overflow-x-auto",
|
|
142
143
|
children: /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(E, { children: /* @__PURE__ */ p(D, { children: [
|
|
143
|
-
/* @__PURE__ */ f(T, { children: "Adapter" }),
|
|
144
|
-
/* @__PURE__ */ f(T, { children: "Submitting workspace" }),
|
|
145
|
-
/* @__PURE__ */ f(T, { children: "Submitted" }),
|
|
146
|
-
/* @__PURE__ */ f(T, { children: "Status" }),
|
|
144
|
+
/* @__PURE__ */ f(T, { children: j("admin.adapters.table.adapter", "Adapter") }),
|
|
145
|
+
/* @__PURE__ */ f(T, { children: j("admin.adapters.table.workspace", "Submitting workspace") }),
|
|
146
|
+
/* @__PURE__ */ f(T, { children: j("admin.adapters.table.submitted", "Submitted") }),
|
|
147
|
+
/* @__PURE__ */ f(T, { children: j("admin.adapters.table.status", "Status") }),
|
|
147
148
|
/* @__PURE__ */ f(T, {
|
|
148
149
|
className: "text-right",
|
|
149
|
-
children: "Actions"
|
|
150
|
+
children: j("admin.adapters.table.actions", "Actions")
|
|
150
151
|
})
|
|
151
152
|
] }) }), /* @__PURE__ */ f(C, { children: G.map((e) => /* @__PURE__ */ p(s, { children: [/* @__PURE__ */ p(D, { children: [
|
|
152
153
|
/* @__PURE__ */ f(w, {
|
|
@@ -169,21 +170,21 @@ var N = () => {
|
|
|
169
170
|
children: [/* @__PURE__ */ p(m, {
|
|
170
171
|
size: "sm",
|
|
171
172
|
variant: "outline",
|
|
172
|
-
onClick: () =>
|
|
173
|
+
onClick: () => de(e.id),
|
|
173
174
|
disabled: z.isPending || B.isPending,
|
|
174
175
|
children: [/* @__PURE__ */ f(l, {
|
|
175
176
|
size: 14,
|
|
176
177
|
className: "mr-1"
|
|
177
|
-
}), "Approve"]
|
|
178
|
+
}), j("admin.adapters.approve", "Approve")]
|
|
178
179
|
}), /* @__PURE__ */ p(m, {
|
|
179
180
|
size: "sm",
|
|
180
181
|
variant: "secondary",
|
|
181
|
-
onClick: () =>
|
|
182
|
+
onClick: () => fe(e.id),
|
|
182
183
|
disabled: z.isPending || B.isPending,
|
|
183
|
-
children: [/* @__PURE__ */ f(
|
|
184
|
+
children: [/* @__PURE__ */ f(ae, {
|
|
184
185
|
size: 14,
|
|
185
186
|
className: "mr-1"
|
|
186
|
-
}), "Reject"]
|
|
187
|
+
}), j("admin.adapters.reject", "Reject")]
|
|
187
188
|
})]
|
|
188
189
|
})
|
|
189
190
|
})
|
|
@@ -192,10 +193,10 @@ var N = () => {
|
|
|
192
193
|
className: "bg-bg-sunken",
|
|
193
194
|
children: /* @__PURE__ */ p("div", {
|
|
194
195
|
className: "flex flex-col gap-2 py-1 sm:flex-row sm:items-start",
|
|
195
|
-
children: [/* @__PURE__ */ f(
|
|
196
|
+
children: [/* @__PURE__ */ f(A, {
|
|
196
197
|
value: U,
|
|
197
198
|
onChange: (e) => W(e.target.value),
|
|
198
|
-
placeholder: "Reason for rejecting this adapter submission (required)",
|
|
199
|
+
placeholder: j("admin.adapters.rejectPlaceholder", "Reason for rejecting this adapter submission (required)"),
|
|
199
200
|
className: "min-h-[60px] flex-1",
|
|
200
201
|
autoFocus: !0
|
|
201
202
|
}), /* @__PURE__ */ p("div", {
|
|
@@ -203,41 +204,41 @@ var N = () => {
|
|
|
203
204
|
children: [/* @__PURE__ */ f(m, {
|
|
204
205
|
size: "sm",
|
|
205
206
|
variant: "destructive",
|
|
206
|
-
onClick: () =>
|
|
207
|
+
onClick: () => pe(e.id),
|
|
207
208
|
disabled: !U.trim() || B.isPending,
|
|
208
|
-
children: "Confirm reject"
|
|
209
|
+
children: j("admin.adapters.confirmReject", "Confirm reject")
|
|
209
210
|
}), /* @__PURE__ */ f(m, {
|
|
210
211
|
size: "sm",
|
|
211
212
|
variant: "outline",
|
|
212
213
|
onClick: () => H(null),
|
|
213
214
|
disabled: B.isPending,
|
|
214
|
-
children: "Cancel"
|
|
215
|
+
children: j("admin.adapters.cancel", "Cancel")
|
|
215
216
|
})]
|
|
216
217
|
})]
|
|
217
218
|
})
|
|
218
219
|
}) }, `${e.id}-reject`)] }, e.id)) })] })
|
|
219
220
|
}) })] })
|
|
220
221
|
}),
|
|
221
|
-
/* @__PURE__ */ f(
|
|
222
|
+
/* @__PURE__ */ f(O, {
|
|
222
223
|
value: "marketplace",
|
|
223
|
-
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: "Marketplace moderation" }), /* @__PURE__ */ f(_, { children: "Review reported marketplace listings and take moderation actions." })] }), /* @__PURE__ */ f(g, { children:
|
|
224
|
+
children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.marketplace.title", "Marketplace moderation") }), /* @__PURE__ */ f(_, { children: j("admin.marketplace.description", "Review reported marketplace listings and take moderation actions.") })] }), /* @__PURE__ */ f(g, { children: he ? /* @__PURE__ */ f("div", {
|
|
224
225
|
className: "flex min-h-[200px] items-center justify-center",
|
|
225
226
|
children: /* @__PURE__ */ f(x, { size: "lg" })
|
|
226
227
|
}) : Q.length === 0 ? /* @__PURE__ */ f(b, {
|
|
227
228
|
icon: /* @__PURE__ */ f(d, { className: "size-6 text-action-primary-bg" }),
|
|
228
|
-
title: "No reported listings",
|
|
229
|
-
description: "Reported marketplace listings will appear here for moderation."
|
|
229
|
+
title: j("admin.marketplace.emptyTitle", "No reported listings"),
|
|
230
|
+
description: j("admin.marketplace.emptyDescription", "Reported marketplace listings will appear here for moderation.")
|
|
230
231
|
}) : /* @__PURE__ */ f("div", {
|
|
231
232
|
className: "overflow-x-auto",
|
|
232
233
|
children: /* @__PURE__ */ p(S, { children: [/* @__PURE__ */ f(E, { children: /* @__PURE__ */ p(D, { children: [
|
|
233
|
-
/* @__PURE__ */ f(T, { children: "Listing" }),
|
|
234
|
-
/* @__PURE__ */ f(T, { children: "Reporting workspace" }),
|
|
235
|
-
/* @__PURE__ */ f(T, { children: "Reported" }),
|
|
236
|
-
/* @__PURE__ */ f(T, { children: "Reason" }),
|
|
237
|
-
/* @__PURE__ */ f(T, { children: "Status" }),
|
|
234
|
+
/* @__PURE__ */ f(T, { children: j("admin.marketplace.table.listing", "Listing") }),
|
|
235
|
+
/* @__PURE__ */ f(T, { children: j("admin.marketplace.table.workspace", "Reporting workspace") }),
|
|
236
|
+
/* @__PURE__ */ f(T, { children: j("admin.marketplace.table.reported", "Reported") }),
|
|
237
|
+
/* @__PURE__ */ f(T, { children: j("admin.marketplace.table.reason", "Reason") }),
|
|
238
|
+
/* @__PURE__ */ f(T, { children: j("admin.marketplace.table.status", "Status") }),
|
|
238
239
|
/* @__PURE__ */ f(T, {
|
|
239
240
|
className: "text-right",
|
|
240
|
-
children: "Actions"
|
|
241
|
+
children: j("admin.marketplace.table.actions", "Actions")
|
|
241
242
|
})
|
|
242
243
|
] }) }), /* @__PURE__ */ f(C, { children: Q.map((e) => /* @__PURE__ */ p(s, { children: [/* @__PURE__ */ p(D, { children: [
|
|
243
244
|
/* @__PURE__ */ f(w, {
|
|
@@ -266,45 +267,41 @@ var N = () => {
|
|
|
266
267
|
variant: "outline",
|
|
267
268
|
onClick: () => $(e.id, "DISMISS"),
|
|
268
269
|
disabled: K.isPending,
|
|
269
|
-
children: "Dismiss"
|
|
270
|
+
children: j("admin.marketplace.dismiss", "Dismiss")
|
|
270
271
|
}), /* @__PURE__ */ f(m, {
|
|
271
272
|
size: "sm",
|
|
272
273
|
variant: "destructive",
|
|
273
274
|
onClick: () => $(e.id, "REMOVE_LISTING"),
|
|
274
275
|
disabled: K.isPending,
|
|
275
|
-
children: "Remove"
|
|
276
|
+
children: j("admin.marketplace.remove", "Remove")
|
|
276
277
|
})]
|
|
277
278
|
})
|
|
278
279
|
})
|
|
279
|
-
] }),
|
|
280
|
+
] }), ge === e.id && /* @__PURE__ */ f(D, { children: /* @__PURE__ */ f(w, {
|
|
280
281
|
colSpan: 6,
|
|
281
282
|
className: "bg-bg-sunken",
|
|
282
283
|
children: /* @__PURE__ */ p("div", {
|
|
283
284
|
className: "flex flex-col gap-2 py-1 sm:flex-row sm:items-start",
|
|
284
|
-
children: [/* @__PURE__ */ f(
|
|
285
|
+
children: [/* @__PURE__ */ f(A, {
|
|
285
286
|
value: X,
|
|
286
287
|
onChange: (e) => Z(e.target.value),
|
|
287
|
-
placeholder:
|
|
288
|
+
placeholder: J === "REMOVE_LISTING" ? j("admin.marketplace.reasonPlaceholderRemove", "Reason to remove this listing (required)") : j("admin.marketplace.reasonPlaceholderDismiss", "Reason to dismiss this report (required)"),
|
|
288
289
|
className: "min-h-[60px] flex-1",
|
|
289
290
|
autoFocus: !0
|
|
290
291
|
}), /* @__PURE__ */ p("div", {
|
|
291
292
|
className: "flex gap-2 sm:flex-col",
|
|
292
|
-
children: [/* @__PURE__ */
|
|
293
|
+
children: [/* @__PURE__ */ f(m, {
|
|
293
294
|
size: "sm",
|
|
294
295
|
variant: J === "REMOVE_LISTING" ? "destructive" : "outline",
|
|
295
|
-
onClick: () =>
|
|
296
|
+
onClick: () => _e(e.id),
|
|
296
297
|
disabled: !X.trim() || K.isPending,
|
|
297
|
-
children:
|
|
298
|
-
"Confirm",
|
|
299
|
-
" ",
|
|
300
|
-
J === "REMOVE_LISTING" ? "removal" : "dismissal"
|
|
301
|
-
]
|
|
298
|
+
children: J === "REMOVE_LISTING" ? j("admin.marketplace.confirmRemoval", "Confirm removal") : j("admin.marketplace.confirmDismissal", "Confirm dismissal")
|
|
302
299
|
}), /* @__PURE__ */ f(m, {
|
|
303
300
|
size: "sm",
|
|
304
301
|
variant: "outline",
|
|
305
302
|
onClick: () => q(null),
|
|
306
303
|
disabled: K.isPending,
|
|
307
|
-
children: "Cancel"
|
|
304
|
+
children: j("admin.marketplace.cancel", "Cancel")
|
|
308
305
|
})]
|
|
309
306
|
})]
|
|
310
307
|
})
|
|
@@ -316,6 +313,6 @@ var N = () => {
|
|
|
316
313
|
});
|
|
317
314
|
};
|
|
318
315
|
//#endregion
|
|
319
|
-
export {
|
|
316
|
+
export { j as AdminDashboardPage };
|
|
320
317
|
|
|
321
318
|
//# sourceMappingURL=AdminDashboardPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdminDashboardPage.js","names":[],"sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"sourcesContent":["/**\n * SubscriberBot Admin Dashboard\n * @module subscriberbot/admin\n *\n * Product-specific admin surface mounted inside `admin-app`. It exposes the\n * three governance operations requested for SubscriberBot, all wired to the\n * real `wspace-subscriberbot-svc` admin governance schema (BOFF-3237):\n * 1. Provider registry curation — `subListProviders` / `subUpdateProvider`.\n * 2. Adapter approval queue — `subListAdapterSubmissions` /\n * `subApproveAdapter` / `subRejectAdapter`.\n * 3. Marketplace moderation queue — `subListMarketplaceReports` /\n * `subModerateListing`.\n */\n\nimport { Fragment, useState, type FC } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmptyState,\n Spinner,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { CheckCircle2, Plug, Settings2, Store, XCircle } from 'lucide-react';\n\nimport { PageLayout } from '../components/PageLayout';\nimport { StatusBadge } from '../components/StatusBadge';\nimport {\n useAdapterSubmissions,\n useApproveAdapter,\n useMarketplaceReports,\n useModerateListing,\n useProviders,\n useRejectAdapter,\n useUpdateProvider,\n} from '../hooks';\nimport { formatDate } from '../utils/formatters';\nimport type { SubModerationAction, SubProvider } from '../types';\n\nexport const AdminDashboardPage: FC = () => {\n const [activeTab, setActiveTab] = useState('providers');\n\n // --- Provider registry ----------------------------------------------\n const { data: providersData, isLoading: providersLoading } = useProviders({\n pagination: { limit: 50 },\n });\n const updateProvider = useUpdateProvider();\n\n const handleVerify = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'VERIFIED' } });\n };\n\n const handleDeprecate = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'DEPRECATED' } });\n };\n\n const providers = providersData?.items ?? [];\n\n // --- Adapter approvals -------------------------------------------------\n const { data: adapterSubmissionsData, isLoading: adaptersLoading } = useAdapterSubmissions({\n pagination: { limit: 50 },\n });\n const approveAdapter = useApproveAdapter();\n const rejectAdapter = useRejectAdapter();\n const [rejectingAdapterId, setRejectingAdapterId] = useState<string | null>(null);\n const [adapterRejectReason, setAdapterRejectReason] = useState('');\n\n const adapterSubmissions = adapterSubmissionsData?.items ?? [];\n\n const handleApproveAdapter = (id: string) => {\n approveAdapter.mutate({ id });\n };\n\n const handleStartRejectAdapter = (id: string) => {\n setRejectingAdapterId(id);\n setAdapterRejectReason('');\n };\n\n const handleConfirmRejectAdapter = (id: string) => {\n if (!adapterRejectReason.trim()) return;\n rejectAdapter.mutate(\n { id, reason: adapterRejectReason.trim() },\n {\n onSuccess: () => {\n setRejectingAdapterId(null);\n setAdapterRejectReason('');\n },\n }\n );\n };\n\n // --- Marketplace moderation ---------------------------------------------\n const { data: marketplaceReportsData, isLoading: reportsLoading } = useMarketplaceReports({\n pagination: { limit: 50 },\n });\n const moderateListing = useModerateListing();\n const [moderatingReportId, setModeratingReportId] = useState<string | null>(null);\n const [moderateAction, setModerateAction] = useState<SubModerationAction | null>(null);\n const [moderateReason, setModerateReason] = useState('');\n\n const marketplaceReports = marketplaceReportsData?.items ?? [];\n\n const handleStartModerate = (id: string, action: SubModerationAction) => {\n setModeratingReportId(id);\n setModerateAction(action);\n setModerateReason('');\n };\n\n const handleConfirmModerate = (id: string) => {\n if (!moderateAction || !moderateReason.trim()) return;\n moderateListing.mutate(\n { id, action: moderateAction, reason: moderateReason.trim() },\n {\n onSuccess: () => {\n setModeratingReportId(null);\n setModerateAction(null);\n setModerateReason('');\n },\n }\n );\n };\n\n return (\n <PageLayout\n title=\"SubscriberBot Admin\"\n description=\"Provider registry curation, adapter approvals, and marketplace moderation.\"\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex\">\n <TabsTrigger value=\"providers\" className=\"gap-2\">\n <Settings2 size={16} />\n Provider Registry\n </TabsTrigger>\n <TabsTrigger value=\"adapters\" className=\"gap-2\">\n <Plug size={16} />\n Adapter Approvals\n </TabsTrigger>\n <TabsTrigger value=\"marketplace\" className=\"gap-2\">\n <Store size={16} />\n Marketplace Moderation\n </TabsTrigger>\n </TabsList>\n\n {/* Provider registry curation — backed by real GraphQL queries. */}\n <TabsContent value=\"providers\">\n <Card>\n <CardHeader>\n <CardTitle>Provider registry</CardTitle>\n <CardDescription>\n Curate the global provider catalog. Verify submitted providers or deprecate stale\n entries.\n </CardDescription>\n </CardHeader>\n <CardContent>\n {providersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : providers.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title=\"No providers yet\"\n description=\"Once providers are created or claimed they will appear here for curation.\"\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Name</TableHead>\n <TableHead>Category</TableHead>\n <TableHead>Status</TableHead>\n <TableHead>Created</TableHead>\n <TableHead className=\"text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {providers.map((provider: SubProvider) => (\n <TableRow key={provider.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {provider.name}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{provider.category}</TableCell>\n <TableCell>\n <StatusBadge status={provider.status} />\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(provider.createdAt)}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex justify-end gap-2\">\n {provider.status !== 'VERIFIED' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleVerify(provider.id)}\n disabled={updateProvider.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n Verify\n </Button>\n )}\n {provider.status !== 'DEPRECATED' && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleDeprecate(provider.id)}\n disabled={updateProvider.isPending}\n >\n Deprecate\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Adapter approval queue — backed by real GraphQL queries. */}\n <TabsContent value=\"adapters\">\n <Card>\n <CardHeader>\n <CardTitle>Adapter approvals</CardTitle>\n <CardDescription>\n Review submitted integration adapters before they are published to the SubscriberBot\n adapter marketplace.\n </CardDescription>\n </CardHeader>\n <CardContent>\n {adaptersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : adapterSubmissions.length === 0 ? (\n <EmptyState\n icon={<Plug className=\"size-6 text-action-primary-bg\" />}\n title=\"No adapter submissions\"\n description=\"Submitted integration adapters will appear here for review.\"\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Adapter</TableHead>\n <TableHead>Submitting workspace</TableHead>\n <TableHead>Submitted</TableHead>\n <TableHead>Status</TableHead>\n <TableHead className=\"text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {adapterSubmissions.map((submission) => (\n <Fragment key={submission.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {submission.adapterId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {submission.submitterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(submission.createdAt)}\n </TableCell>\n <TableCell>\n <StatusBadge status={submission.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {submission.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleApproveAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleStartRejectAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <XCircle size={14} className=\"mr-1\" />\n Reject\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {rejectingAdapterId === submission.id && (\n <TableRow key={`${submission.id}-reject`}>\n <TableCell colSpan={5} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={adapterRejectReason}\n onChange={(event) => setAdapterRejectReason(event.target.value)}\n placeholder=\"Reason for rejecting this adapter submission (required)\"\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleConfirmRejectAdapter(submission.id)}\n disabled={\n !adapterRejectReason.trim() || rejectAdapter.isPending\n }\n >\n Confirm reject\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRejectingAdapterId(null)}\n disabled={rejectAdapter.isPending}\n >\n Cancel\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Marketplace moderation — backed by real GraphQL queries. */}\n <TabsContent value=\"marketplace\">\n <Card>\n <CardHeader>\n <CardTitle>Marketplace moderation</CardTitle>\n <CardDescription>\n Review reported marketplace listings and take moderation actions.\n </CardDescription>\n </CardHeader>\n <CardContent>\n {reportsLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : marketplaceReports.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title=\"No reported listings\"\n description=\"Reported marketplace listings will appear here for moderation.\"\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>Listing</TableHead>\n <TableHead>Reporting workspace</TableHead>\n <TableHead>Reported</TableHead>\n <TableHead>Reason</TableHead>\n <TableHead>Status</TableHead>\n <TableHead className=\"text-right\">Actions</TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {marketplaceReports.map((report) => (\n <Fragment key={report.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {report.listingId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {report.reporterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(report.createdAt)}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{report.reason}</TableCell>\n <TableCell>\n <StatusBadge status={report.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {report.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartModerate(report.id, 'DISMISS')}\n disabled={moderateListing.isPending}\n >\n Dismiss\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleStartModerate(report.id, 'REMOVE_LISTING')}\n disabled={moderateListing.isPending}\n >\n Remove\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {moderatingReportId === report.id && (\n <TableRow key={`${report.id}-moderate`}>\n <TableCell colSpan={6} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={moderateReason}\n onChange={(event) => setModerateReason(event.target.value)}\n placeholder={`Reason to ${moderateAction === 'REMOVE_LISTING' ? 'remove this listing' : 'dismiss this report'} (required)`}\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant={\n moderateAction === 'REMOVE_LISTING'\n ? 'destructive'\n : 'outline'\n }\n onClick={() => handleConfirmModerate(report.id)}\n disabled={!moderateReason.trim() || moderateListing.isPending}\n >\n Confirm{' '}\n {moderateAction === 'REMOVE_LISTING'\n ? 'removal'\n : 'dismissal'}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setModeratingReportId(null)}\n disabled={moderateListing.isPending}\n >\n Cancel\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AdminDashboardPage.js","names":[],"sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"sourcesContent":["/**\n * SubscriberBot Admin Dashboard\n * @module subscriberbot/admin\n *\n * Product-specific admin surface mounted inside `admin-app`. It exposes the\n * three governance operations requested for SubscriberBot, all wired to the\n * real `wspace-subscriberbot-svc` admin governance schema (BOFF-3237):\n * 1. Provider registry curation — `subListProviders` / `subUpdateProvider`.\n * 2. Adapter approval queue — `subListAdapterSubmissions` /\n * `subApproveAdapter` / `subRejectAdapter`.\n * 3. Marketplace moderation queue — `subListMarketplaceReports` /\n * `subModerateListing`.\n */\n\nimport { Fragment, useState, type FC } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmptyState,\n Spinner,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { CheckCircle2, Plug, Settings2, Store, XCircle } from 'lucide-react';\n\nimport { PageLayout } from '../components/PageLayout';\nimport { StatusBadge } from '../components/StatusBadge';\nimport {\n useAdapterSubmissions,\n useApproveAdapter,\n useMarketplaceReports,\n useModerateListing,\n useProviders,\n useRejectAdapter,\n useUpdateProvider,\n} from '../hooks';\nimport { formatDate } from '../utils/formatters';\nimport { useTr } from '../hooks/useTr';\nimport type { SubModerationAction, SubProvider } from '../types';\n\nexport const AdminDashboardPage: FC = () => {\n const tr = useTr();\n const [activeTab, setActiveTab] = useState('providers');\n\n // --- Provider registry ----------------------------------------------\n const { data: providersData, isLoading: providersLoading } = useProviders({\n pagination: { limit: 50 },\n });\n const updateProvider = useUpdateProvider();\n\n const handleVerify = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'VERIFIED' } });\n };\n\n const handleDeprecate = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'DEPRECATED' } });\n };\n\n const providers = providersData?.items ?? [];\n\n // --- Adapter approvals -------------------------------------------------\n const { data: adapterSubmissionsData, isLoading: adaptersLoading } = useAdapterSubmissions({\n pagination: { limit: 50 },\n });\n const approveAdapter = useApproveAdapter();\n const rejectAdapter = useRejectAdapter();\n const [rejectingAdapterId, setRejectingAdapterId] = useState<string | null>(null);\n const [adapterRejectReason, setAdapterRejectReason] = useState('');\n\n const adapterSubmissions = adapterSubmissionsData?.items ?? [];\n\n const handleApproveAdapter = (id: string) => {\n approveAdapter.mutate({ id });\n };\n\n const handleStartRejectAdapter = (id: string) => {\n setRejectingAdapterId(id);\n setAdapterRejectReason('');\n };\n\n const handleConfirmRejectAdapter = (id: string) => {\n if (!adapterRejectReason.trim()) return;\n rejectAdapter.mutate(\n { id, reason: adapterRejectReason.trim() },\n {\n onSuccess: () => {\n setRejectingAdapterId(null);\n setAdapterRejectReason('');\n },\n }\n );\n };\n\n // --- Marketplace moderation ---------------------------------------------\n const { data: marketplaceReportsData, isLoading: reportsLoading } = useMarketplaceReports({\n pagination: { limit: 50 },\n });\n const moderateListing = useModerateListing();\n const [moderatingReportId, setModeratingReportId] = useState<string | null>(null);\n const [moderateAction, setModerateAction] = useState<SubModerationAction | null>(null);\n const [moderateReason, setModerateReason] = useState('');\n\n const marketplaceReports = marketplaceReportsData?.items ?? [];\n\n const handleStartModerate = (id: string, action: SubModerationAction) => {\n setModeratingReportId(id);\n setModerateAction(action);\n setModerateReason('');\n };\n\n const handleConfirmModerate = (id: string) => {\n if (!moderateAction || !moderateReason.trim()) return;\n moderateListing.mutate(\n { id, action: moderateAction, reason: moderateReason.trim() },\n {\n onSuccess: () => {\n setModeratingReportId(null);\n setModerateAction(null);\n setModerateReason('');\n },\n }\n );\n };\n\n return (\n <PageLayout\n title={tr('admin.title', 'SubscriberBot Admin')}\n description={tr(\n 'admin.description',\n 'Provider registry curation, adapter approvals, and marketplace moderation.'\n )}\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex\">\n <TabsTrigger value=\"providers\" className=\"gap-2\">\n <Settings2 size={16} />\n {tr('admin.tabs.providers', 'Provider Registry')}\n </TabsTrigger>\n <TabsTrigger value=\"adapters\" className=\"gap-2\">\n <Plug size={16} />\n {tr('admin.tabs.adapters', 'Adapter Approvals')}\n </TabsTrigger>\n <TabsTrigger value=\"marketplace\" className=\"gap-2\">\n <Store size={16} />\n {tr('admin.tabs.marketplace', 'Marketplace Moderation')}\n </TabsTrigger>\n </TabsList>\n\n {/* Provider registry curation — backed by real GraphQL queries. */}\n <TabsContent value=\"providers\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.providers.title', 'Provider registry')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.providers.description',\n 'Curate the global provider catalog. Verify submitted providers or deprecate stale entries.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {providersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : providers.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.providers.emptyTitle', 'No providers yet')}\n description={tr(\n 'admin.providers.emptyDescription',\n 'Once providers are created or claimed they will appear here for curation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.providers.table.name', 'Name')}</TableHead>\n <TableHead>{tr('admin.providers.table.category', 'Category')}</TableHead>\n <TableHead>{tr('admin.providers.table.status', 'Status')}</TableHead>\n <TableHead>{tr('admin.providers.table.created', 'Created')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.providers.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {providers.map((provider: SubProvider) => (\n <TableRow key={provider.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {provider.name}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{provider.category}</TableCell>\n <TableCell>\n <StatusBadge status={provider.status} />\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(provider.createdAt)}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex justify-end gap-2\">\n {provider.status !== 'VERIFIED' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleVerify(provider.id)}\n disabled={updateProvider.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.providers.verify', 'Verify')}\n </Button>\n )}\n {provider.status !== 'DEPRECATED' && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleDeprecate(provider.id)}\n disabled={updateProvider.isPending}\n >\n {tr('admin.providers.deprecate', 'Deprecate')}\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Adapter approval queue — backed by real GraphQL queries. */}\n <TabsContent value=\"adapters\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.adapters.title', 'Adapter approvals')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.adapters.description',\n 'Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {adaptersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : adapterSubmissions.length === 0 ? (\n <EmptyState\n icon={<Plug className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.adapters.emptyTitle', 'No adapter submissions')}\n description={tr(\n 'admin.adapters.emptyDescription',\n 'Submitted integration adapters will appear here for review.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.adapters.table.adapter', 'Adapter')}</TableHead>\n <TableHead>\n {tr('admin.adapters.table.workspace', 'Submitting workspace')}\n </TableHead>\n <TableHead>{tr('admin.adapters.table.submitted', 'Submitted')}</TableHead>\n <TableHead>{tr('admin.adapters.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.adapters.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {adapterSubmissions.map((submission) => (\n <Fragment key={submission.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {submission.adapterId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {submission.submitterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(submission.createdAt)}\n </TableCell>\n <TableCell>\n <StatusBadge status={submission.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {submission.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleApproveAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.adapters.approve', 'Approve')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleStartRejectAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <XCircle size={14} className=\"mr-1\" />\n {tr('admin.adapters.reject', 'Reject')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {rejectingAdapterId === submission.id && (\n <TableRow key={`${submission.id}-reject`}>\n <TableCell colSpan={5} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={adapterRejectReason}\n onChange={(event) => setAdapterRejectReason(event.target.value)}\n placeholder={tr(\n 'admin.adapters.rejectPlaceholder',\n 'Reason for rejecting this adapter submission (required)'\n )}\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleConfirmRejectAdapter(submission.id)}\n disabled={\n !adapterRejectReason.trim() || rejectAdapter.isPending\n }\n >\n {tr('admin.adapters.confirmReject', 'Confirm reject')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRejectingAdapterId(null)}\n disabled={rejectAdapter.isPending}\n >\n {tr('admin.adapters.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Marketplace moderation — backed by real GraphQL queries. */}\n <TabsContent value=\"marketplace\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.marketplace.title', 'Marketplace moderation')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.marketplace.description',\n 'Review reported marketplace listings and take moderation actions.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {reportsLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : marketplaceReports.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.marketplace.emptyTitle', 'No reported listings')}\n description={tr(\n 'admin.marketplace.emptyDescription',\n 'Reported marketplace listings will appear here for moderation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.marketplace.table.listing', 'Listing')}</TableHead>\n <TableHead>\n {tr('admin.marketplace.table.workspace', 'Reporting workspace')}\n </TableHead>\n <TableHead>{tr('admin.marketplace.table.reported', 'Reported')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.reason', 'Reason')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.marketplace.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {marketplaceReports.map((report) => (\n <Fragment key={report.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {report.listingId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {report.reporterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(report.createdAt)}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{report.reason}</TableCell>\n <TableCell>\n <StatusBadge status={report.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {report.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartModerate(report.id, 'DISMISS')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.dismiss', 'Dismiss')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleStartModerate(report.id, 'REMOVE_LISTING')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.remove', 'Remove')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {moderatingReportId === report.id && (\n <TableRow key={`${report.id}-moderate`}>\n <TableCell colSpan={6} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={moderateReason}\n onChange={(event) => setModerateReason(event.target.value)}\n placeholder={\n moderateAction === 'REMOVE_LISTING'\n ? tr(\n 'admin.marketplace.reasonPlaceholderRemove',\n 'Reason to remove this listing (required)'\n )\n : tr(\n 'admin.marketplace.reasonPlaceholderDismiss',\n 'Reason to dismiss this report (required)'\n )\n }\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant={\n moderateAction === 'REMOVE_LISTING'\n ? 'destructive'\n : 'outline'\n }\n onClick={() => handleConfirmModerate(report.id)}\n disabled={!moderateReason.trim() || moderateListing.isPending}\n >\n {moderateAction === 'REMOVE_LISTING'\n ? tr('admin.marketplace.confirmRemoval', 'Confirm removal')\n : tr(\n 'admin.marketplace.confirmDismissal',\n 'Confirm dismissal'\n )}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setModeratingReportId(null)}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;AAqDA,IAAa,UAA+B;CAC1C,IAAM,IAAK,GAAO,EACZ,CAAC,GAAW,MAAgB,EAAS,YAAY,EAGjD,EAAE,MAAM,IAAe,WAAW,OAAqB,GAAa,EACxE,YAAY,EAAE,OAAO,IAAI,EAC1B,CAAC,EACI,IAAiB,IAAmB,EAEpC,KAAgB,MAAe;AACnC,IAAe,OAAO;GAAE;GAAI,OAAO,EAAE,QAAQ,YAAY;GAAE,CAAC;IAGxD,KAAmB,MAAe;AACtC,IAAe,OAAO;GAAE;GAAI,OAAO,EAAE,QAAQ,cAAc;GAAE,CAAC;IAG1D,IAAY,IAAe,SAAS,EAAE,EAGtC,EAAE,MAAM,GAAwB,WAAW,MAAoB,EAAsB,EACzF,YAAY,EAAE,OAAO,IAAI,EAC1B,CAAC,EACI,IAAiB,GAAmB,EACpC,IAAgB,IAAkB,EAClC,CAAC,GAAoB,KAAyB,EAAwB,KAAK,EAC3E,CAAC,GAAqB,KAA0B,EAAS,GAAG,EAE5D,IAAqB,GAAwB,SAAS,EAAE,EAExD,MAAwB,MAAe;AAC3C,IAAe,OAAO,EAAE,OAAI,CAAC;IAGzB,MAA4B,MAAe;AAE/C,EADA,EAAsB,EAAG,EACzB,EAAuB,GAAG;IAGtB,MAA8B,MAAe;AAC5C,IAAoB,MAAM,IAC/B,EAAc,OACZ;GAAE;GAAI,QAAQ,EAAoB,MAAM;GAAE,EAC1C,EACE,iBAAiB;AAEf,GADA,EAAsB,KAAK,EAC3B,EAAuB,GAAG;KAE7B,CACF;IAIG,EAAE,MAAM,IAAwB,WAAW,OAAmB,EAAsB,EACxF,YAAY,EAAE,OAAO,IAAI,EAC1B,CAAC,EACI,IAAkB,IAAoB,EACtC,CAAC,IAAoB,KAAyB,EAAwB,KAAK,EAC3E,CAAC,GAAgB,KAAqB,EAAqC,KAAK,EAChF,CAAC,GAAgB,KAAqB,EAAS,GAAG,EAElD,IAAqB,IAAwB,SAAS,EAAE,EAExD,KAAuB,GAAY,MAAgC;AAGvE,EAFA,EAAsB,EAAG,EACzB,EAAkB,EAAO,EACzB,EAAkB,GAAG;IAGjB,MAAyB,MAAe;AACxC,GAAC,KAAkB,CAAC,EAAe,MAAM,IAC7C,EAAgB,OACd;GAAE;GAAI,QAAQ;GAAgB,QAAQ,EAAe,MAAM;GAAE,EAC7D,EACE,iBAAiB;AAGf,GAFA,EAAsB,KAAK,EAC3B,EAAkB,KAAK,EACvB,EAAkB,GAAG;KAExB,CACF;;AAGH,QACE,kBAAC,GAAD;EACE,OAAO,EAAG,eAAe,sBAAsB;EAC/C,aAAa,EACX,qBACA,6EACD;YAED,kBAAC,IAAD;GAAM,OAAO;GAAW,eAAe;GAAc,WAAU;aAA/D;IACE,kBAAC,IAAD;KAAU,WAAU;eAApB;MACE,kBAAC,GAAD;OAAa,OAAM;OAAY,WAAU;iBAAzC,CACE,kBAAC,IAAD,EAAW,MAAM,IAAM,CAAA,EACtB,EAAG,wBAAwB,oBAAoB,CACpC;;MACd,kBAAC,GAAD;OAAa,OAAM;OAAW,WAAU;iBAAxC,CACE,kBAAC,GAAD,EAAM,MAAM,IAAM,CAAA,EACjB,EAAG,uBAAuB,oBAAoB,CACnC;;MACd,kBAAC,GAAD;OAAa,OAAM;OAAc,WAAU;iBAA3C,CACE,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA,EAClB,EAAG,0BAA0B,yBAAyB,CAC3C;;MACL;;IAGX,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,yBAAyB,oBAAoB,EAAa,CAAA,EACzE,kBAAC,GAAD,EAAA,UACG,EACC,+BACA,6FACD,EACe,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;MACjB,CAAA,GACJ,EAAU,WAAW,IACvB,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAO,WAAU,iCAAkC,CAAA;MACzD,OAAO,EAAG,8BAA8B,mBAAmB;MAC3D,aAAa,EACX,oCACA,4EACD;MACD,CAAA,GAEF,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,8BAA8B,OAAO,EAAa,CAAA;OACjE,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,WAAW,EAAa,CAAA;OACzE,kBAAC,GAAD,EAAA,UAAY,EAAG,gCAAgC,SAAS,EAAa,CAAA;OACrE,kBAAC,GAAD,EAAA,UAAY,EAAG,iCAAiC,UAAU,EAAa,CAAA;OACvE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,iCAAiC,UAAU;QACrC,CAAA;OACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAU,KAAK,MACd,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAS;QACA,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAAuB,EAAS;QAAqB,CAAA;OAC1E,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAS,QAAU,CAAA,EAC9B,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAS,UAAU;QACrB,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBACnB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACG,EAAS,WAAW,cACnB,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAa,EAAS,GAAG;UACxC,UAAU,EAAe;oBAJ3B,CAME,kBAAC,GAAD;WAAc,MAAM;WAAI,WAAU;WAAS,CAAA,EAC1C,EAAG,0BAA0B,SAAS,CAChC;aAEV,EAAS,WAAW,gBACnB,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAgB,EAAS,GAAG;UAC3C,UAAU,EAAe;oBAExB,EAAG,6BAA6B,YAAY;UACtC,CAAA,CAEP;;QACI,CAAA;OACH,EAAA,EApCI,EAAS,GAoCb,CACX,EACQ,CAAA,CACN,EAAA,CAAA;MACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IAGd,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,wBAAwB,oBAAoB,EAAa,CAAA,EACxE,kBAAC,GAAD,EAAA,UACG,EACC,8BACA,4GACD,EACe,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,IACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;MACjB,CAAA,GACJ,EAAmB,WAAW,IAChC,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAM,WAAU,iCAAkC,CAAA;MACxD,OAAO,EAAG,6BAA6B,yBAAyB;MAChE,aAAa,EACX,mCACA,8DACD;MACD,CAAA,GAEF,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,gCAAgC,UAAU,EAAa,CAAA;OACtE,kBAAC,GAAD,EAAA,UACG,EAAG,kCAAkC,uBAAuB,EACnD,CAAA;OACZ,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,YAAY,EAAa,CAAA;OAC1E,kBAAC,GAAD,EAAA,UAAY,EAAG,+BAA+B,SAAS,EAAa,CAAA;OACpE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,gCAAgC,UAAU;QACpC,CAAA;OACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAmB,KAAK,MACvB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW;QACF,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW;QACF,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAW,UAAU;QACvB,CAAA;OACZ,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAW,QAAU,CAAA,EAChC,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,WAAW,aACrB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAAqB,EAAW,GAAG;UAClD,UAAU,EAAe,aAAa,EAAc;oBAJtD,CAME,kBAAC,GAAD;WAAc,MAAM;WAAI,WAAU;WAAS,CAAA,EAC1C,EAAG,0BAA0B,UAAU,CACjC;aACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAAyB,EAAW,GAAG;UACtD,UAAU,EAAe,aAAa,EAAc;oBAJtD,CAME,kBAAC,IAAD;WAAS,MAAM;WAAI,WAAU;WAAS,CAAA,EACrC,EAAG,yBAAyB,SAAS,CAC/B;YACL;;QAEE,CAAA;OACH,EAAA,CAAA,EACV,MAAuB,EAAW,MACjC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,SAAS;OAAG,WAAU;iBAC/B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,OAAO;SACP,WAAW,MAAU,EAAuB,EAAM,OAAO,MAAM;SAC/D,aAAa,EACX,oCACA,0DACD;SACD,WAAU;SACV,WAAA;SACA,CAAA,EACF,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAA2B,EAAW,GAAG;UACxD,UACE,CAAC,EAAoB,MAAM,IAAI,EAAc;oBAG9C,EAAG,gCAAgC,iBAAiB;UAC9C,CAAA,EACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAsB,KAAK;UAC1C,UAAU,EAAc;oBAEvB,EAAG,yBAAyB,SAAS;UAC/B,CAAA,CACL;WACF;;OACI,CAAA,EACH,EAnCI,GAAG,EAAW,GAAG,SAmCrB,CAEJ,EAAA,EA7EI,EAAW,GA6Ef,CACX,EACQ,CAAA,CACN,EAAA,CAAA;MACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IAGd,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,2BAA2B,yBAAyB,EAAa,CAAA,EAChF,kBAAC,GAAD,EAAA,UACG,EACC,iCACA,oEACD,EACe,CAAA,CACP,EAAA,CAAA,EACb,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;MACjB,CAAA,GACJ,EAAmB,WAAW,IAChC,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAO,WAAU,iCAAkC,CAAA;MACzD,OAAO,EAAG,gCAAgC,uBAAuB;MACjE,aAAa,EACX,sCACA,iEACD;MACD,CAAA,GAEF,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,mCAAmC,UAAU,EAAa,CAAA;OACzE,kBAAC,GAAD,EAAA,UACG,EAAG,qCAAqC,sBAAsB,EACrD,CAAA;OACZ,kBAAC,GAAD,EAAA,UAAY,EAAG,oCAAoC,WAAW,EAAa,CAAA;OAC3E,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,SAAS,EAAa,CAAA;OACvE,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,SAAS,EAAa,CAAA;OACvE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,mCAAmC,UAAU;QACvC,CAAA;OACH,EAAA,CAAA,EACC,CAAA,EACd,kBAAC,GAAD,EAAA,UACG,EAAmB,KAAK,MACvB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO;QACE,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO;QACE,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAO,UAAU;QACnB,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAAuB,EAAO;QAAmB,CAAA;OACtE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAO,QAAU,CAAA,EAC5B,CAAA;OACZ,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO,WAAW,aACjB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAoB,EAAO,IAAI,UAAU;UACxD,UAAU,EAAgB;oBAEzB,EAAG,6BAA6B,UAAU;UACpC,CAAA,EACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAoB,EAAO,IAAI,iBAAiB;UAC/D,UAAU,EAAgB;oBAEzB,EAAG,4BAA4B,SAAS;UAClC,CAAA,CACL;;QAEE,CAAA;OACH,EAAA,CAAA,EACV,OAAuB,EAAO,MAC7B,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,SAAS;OAAG,WAAU;iBAC/B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,OAAO;SACP,WAAW,MAAU,EAAkB,EAAM,OAAO,MAAM;SAC1D,aACE,MAAmB,mBACf,EACE,6CACA,2CACD,GACD,EACE,8CACA,2CACD;SAEP,WAAU;SACV,WAAA;SACA,CAAA,EACF,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SACE,MAAmB,mBACf,gBACA;UAEN,eAAe,GAAsB,EAAO,GAAG;UAC/C,UAAU,CAAC,EAAe,MAAM,IAAI,EAAgB;oBAEnD,MAAmB,mBAChB,EAAG,oCAAoC,kBAAkB,GACzD,EACE,sCACA,oBACD;UACE,CAAA,EACT,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAsB,KAAK;UAC1C,UAAU,EAAgB;oBAEzB,EAAG,4BAA4B,SAAS;UAClC,CAAA,CACL;WACF;;OACI,CAAA,EACH,EAjDI,GAAG,EAAO,GAAG,WAiDjB,CAEJ,EAAA,EA1FI,EAAO,GA0FX,CACX,EACQ,CAAA,CACN,EAAA,CAAA;MACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;KACK,CAAA;IACT;;EACI,CAAA"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* SubscriberBot hooks barrel
|
|
3
3
|
* @module subscriberbot/hooks
|
|
4
4
|
*/
|
|
5
|
+
export { useTr } from './useTr';
|
|
5
6
|
export { useRelationships, useRelationship, useCreateRelationship, useUpdateRelationship, useTransitionRelationship, useCancelRelationship, useRenewalEvents, useEntitlements, useCreateEntitlement, useAssets, useCreateAsset, useUploadFile, useFileDownloadUrl, useProviders, useProvider, useCreateProvider, useUpdateProvider, useArchiveProvider, usePlans, useCreatePlan, useBenchmarkDataPoints, useInboxMessages, useMarkMessageRead, useIngestMessage, useInvoices, useMarkInvoicePaid, useCreateInvoice, usePaymentInstruments, useCreatePaymentInstrument, useRemovePaymentInstrument, useChannels, useCreateChannel, useVerifyChannel, useAgents, useAgent, useCreateAgent, useSetAgentStatus, useCreatePolicy, useWorkflows, useCreateWorkflow, useActivateWorkflow, useAdapterSubmissions, useApproveAdapter, useRejectAdapter, useMarketplaceReports, useModerateListing, } from './useSubscriberBotApi';
|
|
6
7
|
export type { RelationshipListFilters, ProviderListFilters, InboxListFilters, InvoiceListFilters, AgentListFilters, AdapterSubmissionListFilters, MarketplaceReportListFilters, } from './useSubscriberBotApi';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EAEnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EAEnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useTr — translation hook with fallback semantics.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `useI18n().t()` so that when a key has no translation (i.e. the
|
|
5
|
+
* provider returns the key itself), the caller's English fallback is used
|
|
6
|
+
* instead. This keeps consumer call sites consistent and avoids leaking
|
|
7
|
+
* untranslated keys into the UI.
|
|
8
|
+
*
|
|
9
|
+
* Supports optional interpolation params using `{{key}}` placeholders.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* const tr = useTr();
|
|
13
|
+
* return <h1>{tr('dashboard.title', 'Overview')}</h1>;
|
|
14
|
+
* return <p>{tr('dashboard.openInvoices.label', '{{count}} open invoices', { count: 5 })}</p>;
|
|
15
|
+
*/
|
|
16
|
+
export declare function useTr(): (key: string, fallback: string, params?: Record<string, string | number>) => string;
|
|
17
|
+
//# sourceMappingURL=useTr.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTr.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/useTr.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,IAAI,CACvB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KACrC,MAAM,CAcV"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useCallback as e } from "react";
|
|
2
|
+
import { useI18n as t } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
3
|
+
//#region src/subscriberbot/hooks/useTr.ts
|
|
4
|
+
function n() {
|
|
5
|
+
let { t: n } = t();
|
|
6
|
+
return e((e, t, r) => {
|
|
7
|
+
let i = n(e), a = i === e ? t : i;
|
|
8
|
+
return r ? Object.entries(r).reduce((e, [t, n]) => e.replace(RegExp(`\\{\\{${t}\\}\\}`, "g"), String(n)), a) : a;
|
|
9
|
+
}, [n]);
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { n as useTr };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=useTr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTr.js","names":[],"sources":["../../../src/subscriberbot/hooks/useTr.ts"],"sourcesContent":["import { useCallback } from 'react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\n/**\n * useTr — translation hook with fallback semantics.\n *\n * Wraps `useI18n().t()` so that when a key has no translation (i.e. the\n * provider returns the key itself), the caller's English fallback is used\n * instead. This keeps consumer call sites consistent and avoids leaking\n * untranslated keys into the UI.\n *\n * Supports optional interpolation params using `{{key}}` placeholders.\n *\n * @example\n * const tr = useTr();\n * return <h1>{tr('dashboard.title', 'Overview')}</h1>;\n * return <p>{tr('dashboard.openInvoices.label', '{{count}} open invoices', { count: 5 })}</p>;\n */\nexport function useTr(): (\n key: string,\n fallback: string,\n params?: Record<string, string | number>\n) => string {\n const { t } = useI18n();\n return useCallback(\n (key: string, fallback: string, params?: Record<string, string | number>): string => {\n const translated = t(key);\n const raw = translated === key ? fallback : translated;\n if (!params) return raw;\n return Object.entries(params).reduce(\n (str, [k, v]) => str.replace(new RegExp(`\\\\{\\\\{${k}\\\\}\\\\}`, 'g'), String(v)),\n raw\n );\n },\n [t]\n );\n}\n"],"mappings":";;;AAkBA,SAAgB,IAIJ;CACV,IAAM,EAAE,SAAM,GAAS;AACvB,QAAO,GACJ,GAAa,GAAkB,MAAqD;EACnF,IAAM,IAAa,EAAE,EAAI,EACnB,IAAM,MAAe,IAAM,IAAW;AAE5C,SADK,IACE,OAAO,QAAQ,EAAO,CAAC,QAC3B,GAAK,CAAC,GAAG,OAAO,EAAI,QAAY,OAAO,SAAS,EAAE,SAAS,IAAI,EAAE,OAAO,EAAE,CAAC,EAC5E,EACD,GAJmB;IAMtB,CAAC,EAAE,CACJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssetVaultPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/pages/AssetVaultPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"AssetVaultPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/pages/AssetVaultPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAsHnD,eAAO,MAAM,cAAc,EAAE,EAsM5B,CAAC"}
|