@sudobility/entity_pages 0.0.8 → 0.0.11
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/index.d.ts +1 -2
- package/dist/index.esm.js +561 -0
- package/dist/index.umd.js +1 -0
- package/dist/pages/EntityListPage.d.ts +1 -6
- package/dist/pages/EntitySubscriptionsPage.d.ts +50 -0
- package/dist/pages/InvitationsPage.d.ts +0 -5
- package/dist/pages/MembersManagementPage.d.ts +1 -6
- package/dist/pages/index.d.ts +1 -1
- package/package.json +71 -38
- package/dist/index.cjs +0 -30
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/pages/EntityListPage.cjs +0 -58
- package/dist/pages/EntityListPage.d.ts.map +0 -1
- package/dist/pages/EntityListPage.js +0 -55
- package/dist/pages/EntityListPage.js.map +0 -1
- package/dist/pages/InvitationsPage.cjs +0 -42
- package/dist/pages/InvitationsPage.d.ts.map +0 -1
- package/dist/pages/InvitationsPage.js +0 -39
- package/dist/pages/InvitationsPage.js.map +0 -1
- package/dist/pages/MembersManagementPage.cjs +0 -76
- package/dist/pages/MembersManagementPage.d.ts.map +0 -1
- package/dist/pages/MembersManagementPage.js +0 -73
- package/dist/pages/MembersManagementPage.js.map +0 -1
- package/dist/pages/index.cjs +0 -13
- package/dist/pages/index.d.ts.map +0 -1
- package/dist/pages/index.js +0 -7
- package/dist/pages/index.js.map +0 -1
- package/dist/pages/index.test.cjs +0 -38
- package/dist/pages/index.test.d.ts +0 -5
- package/dist/pages/index.test.d.ts.map +0 -1
- package/dist/pages/index.test.js +0 -36
- package/dist/pages/index.test.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -20,5 +20,4 @@
|
|
|
20
20
|
* }
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
export { EntityListPage, type EntityListPageProps, MembersManagementPage, type MembersManagementPageProps, InvitationsPage, type InvitationsPageProps, } from './pages';
|
|
24
|
-
//# sourceMappingURL=index.d.ts.map
|
|
23
|
+
export { EntityListPage, type EntityListPageProps, MembersManagementPage, type MembersManagementPageProps, InvitationsPage, type InvitationsPageProps, EntitySubscriptionsPage, type EntitySubscriptionsPageProps, type SubscriptionProduct, type CurrentSubscription, type SubscriptionContextValue, type TranslationFunction, } from './pages';
|
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import { jsxs as a, jsx as i, Fragment as te } from "react/jsx-runtime";
|
|
2
|
+
import { useState as w, useEffect as ie, useCallback as x } from "react";
|
|
3
|
+
import { Plus as ne } from "lucide-react";
|
|
4
|
+
import { EntityList as j, InvitationForm as re, InvitationList as B, MemberList as ae } from "@sudobility/entity-components";
|
|
5
|
+
import { useEntities as se, useCreateEntity as le, useEntityMembers as oe, useUpdateMemberRole as ce, useRemoveMember as de, useEntityInvitations as ue, useCreateInvitation as me, useCancelInvitation as he, useMyInvitations as ye, useAcceptInvitation as ge, useDeclineInvitation as pe } from "@sudobility/entity_client";
|
|
6
|
+
import { SubscriptionLayout as fe, SubscriptionTile as O, SegmentedControl as be } from "@sudobility/subscription-components";
|
|
7
|
+
function Ie({
|
|
8
|
+
client: l,
|
|
9
|
+
onSelectEntity: r
|
|
10
|
+
}) {
|
|
11
|
+
const [e, h] = w(!1), [p, y] = w({
|
|
12
|
+
displayName: "",
|
|
13
|
+
description: ""
|
|
14
|
+
}), [N, o] = w(null), { data: s = [], isLoading: d } = se(l), c = le(l), I = s.filter((u) => u.entityType === "personal"), L = s.filter(
|
|
15
|
+
(u) => u.entityType === "organization"
|
|
16
|
+
);
|
|
17
|
+
return /* @__PURE__ */ a("div", { className: "space-y-8", children: [
|
|
18
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-between", children: [
|
|
19
|
+
/* @__PURE__ */ a("div", { children: [
|
|
20
|
+
/* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Workspaces" }),
|
|
21
|
+
/* @__PURE__ */ i("p", { className: "text-muted-foreground", children: "Manage your personal and organization workspaces" })
|
|
22
|
+
] }),
|
|
23
|
+
/* @__PURE__ */ a(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
type: "button",
|
|
27
|
+
onClick: () => h(!0),
|
|
28
|
+
className: "flex items-center gap-2 px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors",
|
|
29
|
+
children: [
|
|
30
|
+
/* @__PURE__ */ i(ne, { className: "h-4 w-4" }),
|
|
31
|
+
/* @__PURE__ */ i("span", { children: "New Organization" })
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
] }),
|
|
36
|
+
e && /* @__PURE__ */ i("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50", children: /* @__PURE__ */ a("div", { className: "w-full max-w-md rounded-lg bg-background p-6 shadow-lg", children: [
|
|
37
|
+
/* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-4", children: "Create Organization" }),
|
|
38
|
+
/* @__PURE__ */ a("form", { onSubmit: async (u) => {
|
|
39
|
+
if (u.preventDefault(), o(null), !p.displayName.trim()) {
|
|
40
|
+
o("Display name is required");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
await c.mutateAsync({
|
|
45
|
+
displayName: p.displayName.trim(),
|
|
46
|
+
description: p.description.trim() || void 0
|
|
47
|
+
}), h(!1), y({ displayName: "", description: "" });
|
|
48
|
+
} catch (v) {
|
|
49
|
+
o(v.message || "Failed to create organization");
|
|
50
|
+
}
|
|
51
|
+
}, className: "space-y-4", children: [
|
|
52
|
+
/* @__PURE__ */ a("div", { children: [
|
|
53
|
+
/* @__PURE__ */ i("label", { className: "block text-sm font-medium mb-1", children: "Display Name" }),
|
|
54
|
+
/* @__PURE__ */ i(
|
|
55
|
+
"input",
|
|
56
|
+
{
|
|
57
|
+
type: "text",
|
|
58
|
+
value: p.displayName,
|
|
59
|
+
onChange: (u) => y((v) => ({
|
|
60
|
+
...v,
|
|
61
|
+
displayName: u.target.value
|
|
62
|
+
})),
|
|
63
|
+
placeholder: "My Organization",
|
|
64
|
+
className: "w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary"
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
] }),
|
|
68
|
+
/* @__PURE__ */ a("div", { children: [
|
|
69
|
+
/* @__PURE__ */ i("label", { className: "block text-sm font-medium mb-1", children: "Description (optional)" }),
|
|
70
|
+
/* @__PURE__ */ i(
|
|
71
|
+
"textarea",
|
|
72
|
+
{
|
|
73
|
+
value: p.description,
|
|
74
|
+
onChange: (u) => y((v) => ({
|
|
75
|
+
...v,
|
|
76
|
+
description: u.target.value
|
|
77
|
+
})),
|
|
78
|
+
placeholder: "What is this organization for?",
|
|
79
|
+
rows: 3,
|
|
80
|
+
className: "w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary resize-none"
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
] }),
|
|
84
|
+
N && /* @__PURE__ */ i("p", { className: "text-sm text-destructive", children: N }),
|
|
85
|
+
/* @__PURE__ */ a("div", { className: "flex justify-end gap-2", children: [
|
|
86
|
+
/* @__PURE__ */ i(
|
|
87
|
+
"button",
|
|
88
|
+
{
|
|
89
|
+
type: "button",
|
|
90
|
+
onClick: () => {
|
|
91
|
+
h(!1), y({ displayName: "", description: "" }), o(null);
|
|
92
|
+
},
|
|
93
|
+
className: "px-4 py-2 rounded-lg border hover:bg-muted transition-colors",
|
|
94
|
+
children: "Cancel"
|
|
95
|
+
}
|
|
96
|
+
),
|
|
97
|
+
/* @__PURE__ */ i(
|
|
98
|
+
"button",
|
|
99
|
+
{
|
|
100
|
+
type: "submit",
|
|
101
|
+
disabled: c.isPending,
|
|
102
|
+
className: "px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50",
|
|
103
|
+
children: c.isPending ? "Creating..." : "Create"
|
|
104
|
+
}
|
|
105
|
+
)
|
|
106
|
+
] })
|
|
107
|
+
] })
|
|
108
|
+
] }) }),
|
|
109
|
+
I.length > 0 && /* @__PURE__ */ a("div", { children: [
|
|
110
|
+
/* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Personal Workspace" }),
|
|
111
|
+
/* @__PURE__ */ i(
|
|
112
|
+
j,
|
|
113
|
+
{
|
|
114
|
+
entities: I,
|
|
115
|
+
onSelect: r,
|
|
116
|
+
isLoading: d
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ a("div", { children: [
|
|
121
|
+
/* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Organizations" }),
|
|
122
|
+
L.length === 0 && !d ? /* @__PURE__ */ a("div", { className: "text-center py-8 text-muted-foreground border border-dashed rounded-lg", children: [
|
|
123
|
+
/* @__PURE__ */ i("p", { children: "No organizations yet" }),
|
|
124
|
+
/* @__PURE__ */ i(
|
|
125
|
+
"button",
|
|
126
|
+
{
|
|
127
|
+
type: "button",
|
|
128
|
+
onClick: () => h(!0),
|
|
129
|
+
className: "mt-2 text-primary hover:underline",
|
|
130
|
+
children: "Create your first organization"
|
|
131
|
+
}
|
|
132
|
+
)
|
|
133
|
+
] }) : /* @__PURE__ */ i(
|
|
134
|
+
j,
|
|
135
|
+
{
|
|
136
|
+
entities: L,
|
|
137
|
+
onSelect: r,
|
|
138
|
+
isLoading: d
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
] })
|
|
142
|
+
] });
|
|
143
|
+
}
|
|
144
|
+
function Le({
|
|
145
|
+
client: l,
|
|
146
|
+
entity: r,
|
|
147
|
+
currentUserId: e
|
|
148
|
+
}) {
|
|
149
|
+
const h = r.userRole === "admin", { data: p = [], isLoading: y } = oe(
|
|
150
|
+
l,
|
|
151
|
+
r.entitySlug
|
|
152
|
+
), N = ce(l), o = de(l), { data: s = [], isLoading: d } = ue(l, h ? r.entitySlug : null), c = me(l), I = he(l), L = async (g, f) => {
|
|
153
|
+
try {
|
|
154
|
+
await N.mutateAsync({
|
|
155
|
+
entitySlug: r.entitySlug,
|
|
156
|
+
memberId: g,
|
|
157
|
+
role: f
|
|
158
|
+
});
|
|
159
|
+
} catch (S) {
|
|
160
|
+
console.error("Failed to update role:", S);
|
|
161
|
+
}
|
|
162
|
+
}, P = async (g) => {
|
|
163
|
+
if (confirm("Are you sure you want to remove this member?"))
|
|
164
|
+
try {
|
|
165
|
+
await o.mutateAsync({
|
|
166
|
+
entitySlug: r.entitySlug,
|
|
167
|
+
memberId: g
|
|
168
|
+
});
|
|
169
|
+
} catch (f) {
|
|
170
|
+
console.error("Failed to remove member:", f);
|
|
171
|
+
}
|
|
172
|
+
}, u = async (g) => {
|
|
173
|
+
await c.mutateAsync({
|
|
174
|
+
entitySlug: r.entitySlug,
|
|
175
|
+
request: g
|
|
176
|
+
});
|
|
177
|
+
}, v = async (g) => {
|
|
178
|
+
try {
|
|
179
|
+
await I.mutateAsync({
|
|
180
|
+
entitySlug: r.entitySlug,
|
|
181
|
+
invitationId: g
|
|
182
|
+
});
|
|
183
|
+
} catch (f) {
|
|
184
|
+
console.error("Failed to cancel invitation:", f);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
return r.entityType === "personal" ? /* @__PURE__ */ a("div", { className: "text-center py-12 text-muted-foreground", children: [
|
|
188
|
+
/* @__PURE__ */ i("p", { children: "Personal workspaces cannot have additional members." }),
|
|
189
|
+
/* @__PURE__ */ i("p", { className: "mt-2", children: "Create an organization to collaborate with others." })
|
|
190
|
+
] }) : /* @__PURE__ */ a("div", { className: "space-y-8", children: [
|
|
191
|
+
/* @__PURE__ */ a("div", { children: [
|
|
192
|
+
/* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Members" }),
|
|
193
|
+
/* @__PURE__ */ a("p", { className: "text-muted-foreground", children: [
|
|
194
|
+
"Manage members and invitations for ",
|
|
195
|
+
r.displayName
|
|
196
|
+
] })
|
|
197
|
+
] }),
|
|
198
|
+
h && /* @__PURE__ */ a("div", { className: "rounded-lg border p-4", children: [
|
|
199
|
+
/* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-4", children: "Invite Members" }),
|
|
200
|
+
/* @__PURE__ */ i(
|
|
201
|
+
re,
|
|
202
|
+
{
|
|
203
|
+
onSubmit: u,
|
|
204
|
+
isSubmitting: c.isPending
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
] }),
|
|
208
|
+
h && /* @__PURE__ */ a("div", { children: [
|
|
209
|
+
/* @__PURE__ */ i("h2", { className: "text-lg font-semibold mb-3", children: "Pending Invitations" }),
|
|
210
|
+
/* @__PURE__ */ i(
|
|
211
|
+
B,
|
|
212
|
+
{
|
|
213
|
+
invitations: s,
|
|
214
|
+
mode: "admin",
|
|
215
|
+
onCancel: v,
|
|
216
|
+
isLoading: d,
|
|
217
|
+
emptyMessage: "No pending invitations"
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
] }),
|
|
221
|
+
/* @__PURE__ */ a("div", { children: [
|
|
222
|
+
/* @__PURE__ */ a("h2", { className: "text-lg font-semibold mb-3", children: [
|
|
223
|
+
"Current Members (",
|
|
224
|
+
p.length,
|
|
225
|
+
")"
|
|
226
|
+
] }),
|
|
227
|
+
/* @__PURE__ */ i(
|
|
228
|
+
ae,
|
|
229
|
+
{
|
|
230
|
+
members: p,
|
|
231
|
+
currentUserId: e,
|
|
232
|
+
canManage: h,
|
|
233
|
+
onRoleChange: L,
|
|
234
|
+
onRemove: P,
|
|
235
|
+
isLoading: y
|
|
236
|
+
}
|
|
237
|
+
)
|
|
238
|
+
] })
|
|
239
|
+
] });
|
|
240
|
+
}
|
|
241
|
+
function Me({
|
|
242
|
+
client: l,
|
|
243
|
+
onInvitationAccepted: r
|
|
244
|
+
}) {
|
|
245
|
+
const { data: e = [], isLoading: h } = ye(l), p = ge(l), y = pe(l), N = async (d) => {
|
|
246
|
+
try {
|
|
247
|
+
await p.mutateAsync(d), r?.();
|
|
248
|
+
} catch (c) {
|
|
249
|
+
console.error("Failed to accept invitation:", c);
|
|
250
|
+
}
|
|
251
|
+
}, o = async (d) => {
|
|
252
|
+
try {
|
|
253
|
+
await y.mutateAsync(d);
|
|
254
|
+
} catch (c) {
|
|
255
|
+
console.error("Failed to decline invitation:", c);
|
|
256
|
+
}
|
|
257
|
+
}, s = e.filter((d) => d.status === "pending").length;
|
|
258
|
+
return /* @__PURE__ */ a("div", { className: "space-y-6", children: [
|
|
259
|
+
/* @__PURE__ */ a("div", { children: [
|
|
260
|
+
/* @__PURE__ */ i("h1", { className: "text-2xl font-bold text-foreground", children: "Invitations" }),
|
|
261
|
+
/* @__PURE__ */ i("p", { className: "text-muted-foreground", children: s > 0 ? `You have ${s} pending invitation${s > 1 ? "s" : ""}` : "No pending invitations" })
|
|
262
|
+
] }),
|
|
263
|
+
/* @__PURE__ */ i(
|
|
264
|
+
B,
|
|
265
|
+
{
|
|
266
|
+
invitations: e,
|
|
267
|
+
mode: "user",
|
|
268
|
+
onAccept: N,
|
|
269
|
+
onDecline: o,
|
|
270
|
+
isLoading: h,
|
|
271
|
+
emptyMessage: "You don't have any pending invitations"
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
] });
|
|
275
|
+
}
|
|
276
|
+
const C = {
|
|
277
|
+
ultra_yearly: "bandwidth_ultra",
|
|
278
|
+
ultra_monthly: "bandwidth_ultra",
|
|
279
|
+
pro_yearly: "bandwidth_pro",
|
|
280
|
+
pro_monthly: "bandwidth_pro",
|
|
281
|
+
dev_yearly: "bandwidth_dev",
|
|
282
|
+
dev_monthly: "bandwidth_dev"
|
|
283
|
+
};
|
|
284
|
+
function Ae({
|
|
285
|
+
subscription: l,
|
|
286
|
+
rateLimitsConfig: r,
|
|
287
|
+
t: e,
|
|
288
|
+
onPurchaseSuccess: h,
|
|
289
|
+
onRestoreSuccess: p,
|
|
290
|
+
onError: y,
|
|
291
|
+
onWarning: N
|
|
292
|
+
}) {
|
|
293
|
+
const {
|
|
294
|
+
products: o,
|
|
295
|
+
currentSubscription: s,
|
|
296
|
+
isLoading: d,
|
|
297
|
+
error: c,
|
|
298
|
+
purchase: I,
|
|
299
|
+
restore: L,
|
|
300
|
+
clearError: P
|
|
301
|
+
} = l, [u, v] = w("monthly"), [g, f] = w(null), [S, F] = w(!1), [M, T] = w(!1);
|
|
302
|
+
ie(() => {
|
|
303
|
+
c && (y?.(e("common.error"), c), P());
|
|
304
|
+
}, [c, P, e, y]);
|
|
305
|
+
const k = o.filter((t) => {
|
|
306
|
+
if (!t.period) return !1;
|
|
307
|
+
const n = t.period.includes("Y") || t.period.includes("year");
|
|
308
|
+
return u === "yearly" ? n : !n;
|
|
309
|
+
}).sort((t, n) => parseFloat(t.price) - parseFloat(n.price)), Y = (t) => {
|
|
310
|
+
v(t), f(null);
|
|
311
|
+
}, $ = async () => {
|
|
312
|
+
if (g) {
|
|
313
|
+
F(!0), P();
|
|
314
|
+
try {
|
|
315
|
+
await I(g) && (h?.(), f(null));
|
|
316
|
+
} catch (t) {
|
|
317
|
+
y?.(
|
|
318
|
+
e("common.error"),
|
|
319
|
+
t instanceof Error ? t.message : e("purchase.error")
|
|
320
|
+
);
|
|
321
|
+
} finally {
|
|
322
|
+
F(!1);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}, W = async () => {
|
|
326
|
+
T(!0), P();
|
|
327
|
+
try {
|
|
328
|
+
await L() ? p?.() : N?.(e("common.error"), e("restore.noPurchases"));
|
|
329
|
+
} catch (t) {
|
|
330
|
+
y?.(
|
|
331
|
+
e("common.error"),
|
|
332
|
+
t instanceof Error ? t.message : e("restore.error")
|
|
333
|
+
);
|
|
334
|
+
} finally {
|
|
335
|
+
T(!1);
|
|
336
|
+
}
|
|
337
|
+
}, V = x((t) => t ? new Intl.DateTimeFormat(void 0, {
|
|
338
|
+
year: "numeric",
|
|
339
|
+
month: "long",
|
|
340
|
+
day: "numeric"
|
|
341
|
+
}).format(t) : "", []), G = x(
|
|
342
|
+
(t) => t ? t.includes("Y") || t.includes("year") ? e("periods.year") : t.includes("M") || t.includes("month") ? e("periods.month") : t.includes("W") || t.includes("week") ? e("periods.week") : "" : "",
|
|
343
|
+
[e]
|
|
344
|
+
), J = x(
|
|
345
|
+
(t) => {
|
|
346
|
+
if (!t) return;
|
|
347
|
+
const n = t.replace(/\D/g, "") || "1";
|
|
348
|
+
return t.includes("W") ? e("trial.weeks", { count: parseInt(n, 10) }) : t.includes("M") ? e("trial.months", { count: parseInt(n, 10) }) : e("trial.days", { count: parseInt(n, 10) });
|
|
349
|
+
},
|
|
350
|
+
[e]
|
|
351
|
+
), E = x(
|
|
352
|
+
(t) => {
|
|
353
|
+
if (!r?.tiers) return;
|
|
354
|
+
const n = C[t];
|
|
355
|
+
return n ? r.tiers.find(
|
|
356
|
+
(m) => m.entitlement === n
|
|
357
|
+
) : r.tiers.find((m) => m.entitlement === "none");
|
|
358
|
+
},
|
|
359
|
+
[r]
|
|
360
|
+
), b = x(
|
|
361
|
+
(t) => t === null ? e("rateLimits.unlimited", "Unlimited") : t.toLocaleString(),
|
|
362
|
+
[e]
|
|
363
|
+
), R = x(
|
|
364
|
+
(t) => {
|
|
365
|
+
const n = E(t);
|
|
366
|
+
if (!n) return [];
|
|
367
|
+
const m = [];
|
|
368
|
+
return n.limits.hourly !== null && m.push(
|
|
369
|
+
e("rateLimits.hourly", "{{limit}} requests/hour", {
|
|
370
|
+
limit: b(n.limits.hourly)
|
|
371
|
+
})
|
|
372
|
+
), n.limits.daily !== null && m.push(
|
|
373
|
+
e("rateLimits.daily", "{{limit}} requests/day", {
|
|
374
|
+
limit: b(n.limits.daily)
|
|
375
|
+
})
|
|
376
|
+
), n.limits.monthly !== null && m.push(
|
|
377
|
+
e("rateLimits.monthly", "{{limit}} requests/month", {
|
|
378
|
+
limit: b(n.limits.monthly)
|
|
379
|
+
})
|
|
380
|
+
), n.limits.hourly === null && n.limits.daily === null && n.limits.monthly === null && m.push(
|
|
381
|
+
e("rateLimits.unlimitedRequests", "Unlimited API requests")
|
|
382
|
+
), m;
|
|
383
|
+
},
|
|
384
|
+
[E, b, e]
|
|
385
|
+
), K = x(
|
|
386
|
+
(t) => R(t),
|
|
387
|
+
[R]
|
|
388
|
+
), H = x(() => {
|
|
389
|
+
const t = [
|
|
390
|
+
e("freeTier.schemaValidation", "JSON Schema-validated outputs"),
|
|
391
|
+
e(
|
|
392
|
+
"freeTier.allProviders",
|
|
393
|
+
"All LLM providers (OpenAI, Anthropic, Google)"
|
|
394
|
+
),
|
|
395
|
+
e("freeTier.endpointTesting", "Built-in endpoint testing"),
|
|
396
|
+
e("freeTier.analytics", "Basic usage analytics")
|
|
397
|
+
];
|
|
398
|
+
if (r?.tiers) {
|
|
399
|
+
const n = r.tiers.find(
|
|
400
|
+
(m) => m.entitlement === "none"
|
|
401
|
+
);
|
|
402
|
+
n && (n.limits.hourly !== null && t.push(
|
|
403
|
+
e("rateLimits.hourly", "{{limit}} requests/hour", {
|
|
404
|
+
limit: b(n.limits.hourly)
|
|
405
|
+
})
|
|
406
|
+
), n.limits.daily !== null && t.push(
|
|
407
|
+
e("rateLimits.daily", "{{limit}} requests/day", {
|
|
408
|
+
limit: b(n.limits.daily)
|
|
409
|
+
})
|
|
410
|
+
), n.limits.monthly !== null && t.push(
|
|
411
|
+
e("rateLimits.monthly", "{{limit}} requests/month", {
|
|
412
|
+
limit: b(n.limits.monthly)
|
|
413
|
+
})
|
|
414
|
+
));
|
|
415
|
+
}
|
|
416
|
+
return t;
|
|
417
|
+
}, [r, b, e]), Q = x(
|
|
418
|
+
(t) => {
|
|
419
|
+
const n = C[t];
|
|
420
|
+
if (!n) return;
|
|
421
|
+
const m = o.find(
|
|
422
|
+
(A) => A.identifier === t
|
|
423
|
+
);
|
|
424
|
+
if (!m) return;
|
|
425
|
+
const z = Object.entries(C).find(
|
|
426
|
+
([A, ee]) => ee === n && A.includes("monthly")
|
|
427
|
+
)?.[0];
|
|
428
|
+
if (!z) return;
|
|
429
|
+
const D = o.find(
|
|
430
|
+
(A) => A.identifier === z
|
|
431
|
+
);
|
|
432
|
+
if (!D) return;
|
|
433
|
+
const _ = parseFloat(m.price), q = parseFloat(D.price);
|
|
434
|
+
if (q <= 0 || _ <= 0) return;
|
|
435
|
+
const U = q * 12, Z = (U - _) / U * 100;
|
|
436
|
+
return Math.round(Z);
|
|
437
|
+
},
|
|
438
|
+
[o]
|
|
439
|
+
), X = [
|
|
440
|
+
{ value: "monthly", label: e("billingPeriod.monthly") },
|
|
441
|
+
{ value: "yearly", label: e("billingPeriod.yearly") }
|
|
442
|
+
];
|
|
443
|
+
return /* @__PURE__ */ i(
|
|
444
|
+
fe,
|
|
445
|
+
{
|
|
446
|
+
title: e("title"),
|
|
447
|
+
error: c,
|
|
448
|
+
currentStatusLabel: e("currentStatus.label"),
|
|
449
|
+
currentStatus: {
|
|
450
|
+
isActive: s?.isActive ?? !1,
|
|
451
|
+
activeContent: s?.isActive ? {
|
|
452
|
+
title: e("currentStatus.active"),
|
|
453
|
+
fields: [
|
|
454
|
+
{
|
|
455
|
+
label: e("currentStatus.plan"),
|
|
456
|
+
value: s.productIdentifier || e("currentStatus.premium")
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
label: e("currentStatus.expires"),
|
|
460
|
+
value: V(
|
|
461
|
+
s.expirationDate
|
|
462
|
+
)
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
label: e("currentStatus.willRenew"),
|
|
466
|
+
value: s.willRenew ? e("common.yes") : e("common.no")
|
|
467
|
+
},
|
|
468
|
+
...r ? [
|
|
469
|
+
{
|
|
470
|
+
label: e("currentStatus.monthlyUsage", "Monthly Usage"),
|
|
471
|
+
value: `${r.currentUsage.monthly.toLocaleString()} / ${b(r.currentLimits.monthly)}`
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
label: e("currentStatus.dailyUsage", "Daily Usage"),
|
|
475
|
+
value: `${r.currentUsage.daily.toLocaleString()} / ${b(r.currentLimits.daily)}`
|
|
476
|
+
}
|
|
477
|
+
] : []
|
|
478
|
+
]
|
|
479
|
+
} : void 0,
|
|
480
|
+
inactiveContent: s?.isActive ? void 0 : {
|
|
481
|
+
title: e("currentStatus.inactive"),
|
|
482
|
+
message: e("currentStatus.inactiveMessage")
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
aboveProducts: !d && o.length > 0 ? /* @__PURE__ */ i("div", { className: "flex justify-center mb-6", children: /* @__PURE__ */ i(
|
|
486
|
+
be,
|
|
487
|
+
{
|
|
488
|
+
options: X,
|
|
489
|
+
value: u,
|
|
490
|
+
onChange: Y
|
|
491
|
+
}
|
|
492
|
+
) }) : null,
|
|
493
|
+
primaryAction: {
|
|
494
|
+
label: e(S ? "buttons.purchasing" : "buttons.subscribe"),
|
|
495
|
+
onClick: $,
|
|
496
|
+
disabled: !g || S || M,
|
|
497
|
+
loading: S
|
|
498
|
+
},
|
|
499
|
+
secondaryAction: {
|
|
500
|
+
label: e(M ? "buttons.restoring" : "buttons.restore"),
|
|
501
|
+
onClick: W,
|
|
502
|
+
disabled: S || M,
|
|
503
|
+
loading: M
|
|
504
|
+
},
|
|
505
|
+
children: d ? /* @__PURE__ */ i("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ i("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" }) }) : o.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: e("noProducts") }) : k.length === 0 ? /* @__PURE__ */ i("div", { className: "text-center py-12 text-theme-text-secondary", children: e("noProductsForPeriod") }) : /* @__PURE__ */ a(te, { children: [
|
|
506
|
+
/* @__PURE__ */ i(
|
|
507
|
+
O,
|
|
508
|
+
{
|
|
509
|
+
id: "free",
|
|
510
|
+
title: e("freeTier.title"),
|
|
511
|
+
price: e("freeTier.price"),
|
|
512
|
+
periodLabel: e("periods.month"),
|
|
513
|
+
features: H(),
|
|
514
|
+
isSelected: !s?.isActive && g === null,
|
|
515
|
+
onSelect: () => f(null),
|
|
516
|
+
topBadge: s?.isActive ? void 0 : {
|
|
517
|
+
text: e("badges.currentPlan", "Current Plan"),
|
|
518
|
+
color: "green"
|
|
519
|
+
},
|
|
520
|
+
disabled: S || M,
|
|
521
|
+
hideSelectionIndicator: !0
|
|
522
|
+
},
|
|
523
|
+
"free"
|
|
524
|
+
),
|
|
525
|
+
k.map((t) => /* @__PURE__ */ i(
|
|
526
|
+
O,
|
|
527
|
+
{
|
|
528
|
+
id: t.identifier,
|
|
529
|
+
title: t.title,
|
|
530
|
+
price: t.priceString,
|
|
531
|
+
periodLabel: G(t.period),
|
|
532
|
+
features: K(t.identifier),
|
|
533
|
+
isSelected: g === t.identifier,
|
|
534
|
+
onSelect: () => f(t.identifier),
|
|
535
|
+
isBestValue: t.identifier.includes("pro"),
|
|
536
|
+
discountBadge: t.period?.includes("Y") ? (() => {
|
|
537
|
+
const n = Q(
|
|
538
|
+
t.identifier
|
|
539
|
+
);
|
|
540
|
+
return n && n > 0 ? {
|
|
541
|
+
text: e("badges.savePercent", "Save {{percent}}%", {
|
|
542
|
+
percent: n
|
|
543
|
+
}),
|
|
544
|
+
isBestValue: !0
|
|
545
|
+
} : void 0;
|
|
546
|
+
})() : void 0,
|
|
547
|
+
introPriceNote: t.freeTrialPeriod ? J(t.freeTrialPeriod) : t.introPrice ? e("intro.note", { price: t.introPrice }) : void 0,
|
|
548
|
+
disabled: S || M
|
|
549
|
+
},
|
|
550
|
+
t.identifier
|
|
551
|
+
))
|
|
552
|
+
] })
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
export {
|
|
557
|
+
Ie as EntityListPage,
|
|
558
|
+
Ae as EntitySubscriptionsPage,
|
|
559
|
+
Me as InvitationsPage,
|
|
560
|
+
Le as MembersManagementPage
|
|
561
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(l,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("react/jsx-runtime"),require("react"),require("lucide-react"),require("@sudobility/entity-components"),require("@sudobility/entity_client"),require("@sudobility/subscription-components")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","lucide-react","@sudobility/entity-components","@sudobility/entity_client","@sudobility/subscription-components"],e):(l=typeof globalThis<"u"?globalThis:l||self,e(l.EntityPages={},l.jsxRuntime,l.React,l.LucideReact,l.SudobilityEntityComponents,l.SudobilityEntityClient,l.SudobilitySubscriptionComponents))})(this,(function(l,e,s,_,I,b,A){"use strict";function $({client:o,onSelectEntity:r}){const[t,y]=s.useState(!1),[f,g]=s.useState({displayName:"",description:""}),[N,c]=s.useState(null),{data:a=[],isLoading:u}=b.useEntities(o),d=b.useCreateEntity(o),L=a.filter(m=>m.entityType==="personal"),M=a.filter(m=>m.entityType==="organization"),P=async m=>{if(m.preventDefault(),c(null),!f.displayName.trim()){c("Display name is required");return}try{await d.mutateAsync({displayName:f.displayName.trim(),description:f.description.trim()||void 0}),y(!1),g({displayName:"",description:""})}catch(x){c(x.message||"Failed to create organization")}};return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Workspaces"}),e.jsx("p",{className:"text-muted-foreground",children:"Manage your personal and organization workspaces"})]}),e.jsxs("button",{type:"button",onClick:()=>y(!0),className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors",children:[e.jsx(_.Plus,{className:"h-4 w-4"}),e.jsx("span",{children:"New Organization"})]})]}),t&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/50",children:e.jsxs("div",{className:"w-full max-w-md rounded-lg bg-background p-6 shadow-lg",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Create Organization"}),e.jsxs("form",{onSubmit:P,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Display Name"}),e.jsx("input",{type:"text",value:f.displayName,onChange:m=>g(x=>({...x,displayName:m.target.value})),placeholder:"My Organization",className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium mb-1",children:"Description (optional)"}),e.jsx("textarea",{value:f.description,onChange:m=>g(x=>({...x,description:m.target.value})),placeholder:"What is this organization for?",rows:3,className:"w-full px-3 py-2 rounded-lg border bg-background focus:outline-none focus:ring-2 focus:ring-primary resize-none"})]}),N&&e.jsx("p",{className:"text-sm text-destructive",children:N}),e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:()=>{y(!1),g({displayName:"",description:""}),c(null)},className:"px-4 py-2 rounded-lg border hover:bg-muted transition-colors",children:"Cancel"}),e.jsx("button",{type:"submit",disabled:d.isPending,className:"px-4 py-2 rounded-lg bg-primary text-primary-foreground font-medium hover:bg-primary/90 transition-colors disabled:opacity-50",children:d.isPending?"Creating...":"Create"})]})]})]})}),L.length>0&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Personal Workspace"}),e.jsx(I.EntityList,{entities:L,onSelect:r,isLoading:u})]}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Organizations"}),M.length===0&&!u?e.jsxs("div",{className:"text-center py-8 text-muted-foreground border border-dashed rounded-lg",children:[e.jsx("p",{children:"No organizations yet"}),e.jsx("button",{type:"button",onClick:()=>y(!0),className:"mt-2 text-primary hover:underline",children:"Create your first organization"})]}):e.jsx(I.EntityList,{entities:M,onSelect:r,isLoading:u})]})]})}function W({client:o,entity:r,currentUserId:t}){const y=r.userRole==="admin",{data:f=[],isLoading:g}=b.useEntityMembers(o,r.entitySlug),N=b.useUpdateMemberRole(o),c=b.useRemoveMember(o),{data:a=[],isLoading:u}=b.useEntityInvitations(o,y?r.entitySlug:null),d=b.useCreateInvitation(o),L=b.useCancelInvitation(o),M=async(p,v)=>{try{await N.mutateAsync({entitySlug:r.entitySlug,memberId:p,role:v})}catch(w){console.error("Failed to update role:",w)}},P=async p=>{if(confirm("Are you sure you want to remove this member?"))try{await c.mutateAsync({entitySlug:r.entitySlug,memberId:p})}catch(v){console.error("Failed to remove member:",v)}},m=async p=>{await d.mutateAsync({entitySlug:r.entitySlug,request:p})},x=async p=>{try{await L.mutateAsync({entitySlug:r.entitySlug,invitationId:p})}catch(v){console.error("Failed to cancel invitation:",v)}};return r.entityType==="personal"?e.jsxs("div",{className:"text-center py-12 text-muted-foreground",children:[e.jsx("p",{children:"Personal workspaces cannot have additional members."}),e.jsx("p",{className:"mt-2",children:"Create an organization to collaborate with others."})]}):e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Members"}),e.jsxs("p",{className:"text-muted-foreground",children:["Manage members and invitations for ",r.displayName]})]}),y&&e.jsxs("div",{className:"rounded-lg border p-4",children:[e.jsx("h2",{className:"text-lg font-semibold mb-4",children:"Invite Members"}),e.jsx(I.InvitationForm,{onSubmit:m,isSubmitting:d.isPending})]}),y&&e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold mb-3",children:"Pending Invitations"}),e.jsx(I.InvitationList,{invitations:a,mode:"admin",onCancel:x,isLoading:u,emptyMessage:"No pending invitations"})]}),e.jsxs("div",{children:[e.jsxs("h2",{className:"text-lg font-semibold mb-3",children:["Current Members (",f.length,")"]}),e.jsx(I.MemberList,{members:f,currentUserId:t,canManage:y,onRoleChange:M,onRemove:P,isLoading:g})]})]})}function V({client:o,onInvitationAccepted:r}){const{data:t=[],isLoading:y}=b.useMyInvitations(o),f=b.useAcceptInvitation(o),g=b.useDeclineInvitation(o),N=async u=>{try{await f.mutateAsync(u),r?.()}catch(d){console.error("Failed to accept invitation:",d)}},c=async u=>{try{await g.mutateAsync(u)}catch(d){console.error("Failed to decline invitation:",d)}},a=t.filter(u=>u.status==="pending").length;return e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Invitations"}),e.jsx("p",{className:"text-muted-foreground",children:a>0?`You have ${a} pending invitation${a>1?"s":""}`:"No pending invitations"})]}),e.jsx(I.InvitationList,{invitations:t,mode:"user",onAccept:N,onDecline:c,isLoading:y,emptyMessage:"You don't have any pending invitations"})]})}const T={ultra_yearly:"bandwidth_ultra",ultra_monthly:"bandwidth_ultra",pro_yearly:"bandwidth_pro",pro_monthly:"bandwidth_pro",dev_yearly:"bandwidth_dev",dev_monthly:"bandwidth_dev"};function G({subscription:o,rateLimitsConfig:r,t,onPurchaseSuccess:y,onRestoreSuccess:f,onError:g,onWarning:N}){const{products:c,currentSubscription:a,isLoading:u,error:d,purchase:L,restore:M,clearError:P}=o,[m,x]=s.useState("monthly"),[p,v]=s.useState(null),[w,E]=s.useState(!1),[k,F]=s.useState(!1);s.useEffect(()=>{d&&(g?.(t("common.error"),d),P())},[d,P,t,g]);const q=c.filter(i=>{if(!i.period)return!1;const n=i.period.includes("Y")||i.period.includes("year");return m==="yearly"?n:!n}).sort((i,n)=>parseFloat(i.price)-parseFloat(n.price)),J=i=>{x(i),v(null)},K=async()=>{if(p){E(!0),P();try{await L(p)&&(y?.(),v(null))}catch(i){g?.(t("common.error"),i instanceof Error?i.message:t("purchase.error"))}finally{E(!1)}}},H=async()=>{F(!0),P();try{await M()?f?.():N?.(t("common.error"),t("restore.noPurchases"))}catch(i){g?.(t("common.error"),i instanceof Error?i.message:t("restore.error"))}finally{F(!1)}},Q=s.useCallback(i=>i?new Intl.DateTimeFormat(void 0,{year:"numeric",month:"long",day:"numeric"}).format(i):"",[]),X=s.useCallback(i=>i?i.includes("Y")||i.includes("year")?t("periods.year"):i.includes("M")||i.includes("month")?t("periods.month"):i.includes("W")||i.includes("week")?t("periods.week"):"":"",[t]),Z=s.useCallback(i=>{if(!i)return;const n=i.replace(/\D/g,"")||"1";return i.includes("W")?t("trial.weeks",{count:parseInt(n,10)}):i.includes("M")?t("trial.months",{count:parseInt(n,10)}):t("trial.days",{count:parseInt(n,10)})},[t]),z=s.useCallback(i=>{if(!r?.tiers)return;const n=T[i];return n?r.tiers.find(h=>h.entitlement===n):r.tiers.find(h=>h.entitlement==="none")},[r]),S=s.useCallback(i=>i===null?t("rateLimits.unlimited","Unlimited"):i.toLocaleString(),[t]),D=s.useCallback(i=>{const n=z(i);if(!n)return[];const h=[];return n.limits.hourly!==null&&h.push(t("rateLimits.hourly","{{limit}} requests/hour",{limit:S(n.limits.hourly)})),n.limits.daily!==null&&h.push(t("rateLimits.daily","{{limit}} requests/day",{limit:S(n.limits.daily)})),n.limits.monthly!==null&&h.push(t("rateLimits.monthly","{{limit}} requests/month",{limit:S(n.limits.monthly)})),n.limits.hourly===null&&n.limits.daily===null&&n.limits.monthly===null&&h.push(t("rateLimits.unlimitedRequests","Unlimited API requests")),h},[z,S,t]),R=s.useCallback(i=>D(i),[D]),ee=s.useCallback(()=>{const i=[t("freeTier.schemaValidation","JSON Schema-validated outputs"),t("freeTier.allProviders","All LLM providers (OpenAI, Anthropic, Google)"),t("freeTier.endpointTesting","Built-in endpoint testing"),t("freeTier.analytics","Basic usage analytics")];if(r?.tiers){const n=r.tiers.find(h=>h.entitlement==="none");n&&(n.limits.hourly!==null&&i.push(t("rateLimits.hourly","{{limit}} requests/hour",{limit:S(n.limits.hourly)})),n.limits.daily!==null&&i.push(t("rateLimits.daily","{{limit}} requests/day",{limit:S(n.limits.daily)})),n.limits.monthly!==null&&i.push(t("rateLimits.monthly","{{limit}} requests/month",{limit:S(n.limits.monthly)})))}return i},[r,S,t]),te=s.useCallback(i=>{const n=T[i];if(!n)return;const h=c.find(C=>C.identifier===i);if(!h)return;const j=Object.entries(T).find(([C,re])=>re===n&&C.includes("monthly"))?.[0];if(!j)return;const O=c.find(C=>C.identifier===j);if(!O)return;const U=parseFloat(h.price),B=parseFloat(O.price);if(B<=0||U<=0)return;const Y=B*12,ne=(Y-U)/Y*100;return Math.round(ne)},[c]),ie=[{value:"monthly",label:t("billingPeriod.monthly")},{value:"yearly",label:t("billingPeriod.yearly")}];return e.jsx(A.SubscriptionLayout,{title:t("title"),error:d,currentStatusLabel:t("currentStatus.label"),currentStatus:{isActive:a?.isActive??!1,activeContent:a?.isActive?{title:t("currentStatus.active"),fields:[{label:t("currentStatus.plan"),value:a.productIdentifier||t("currentStatus.premium")},{label:t("currentStatus.expires"),value:Q(a.expirationDate)},{label:t("currentStatus.willRenew"),value:a.willRenew?t("common.yes"):t("common.no")},...r?[{label:t("currentStatus.monthlyUsage","Monthly Usage"),value:`${r.currentUsage.monthly.toLocaleString()} / ${S(r.currentLimits.monthly)}`},{label:t("currentStatus.dailyUsage","Daily Usage"),value:`${r.currentUsage.daily.toLocaleString()} / ${S(r.currentLimits.daily)}`}]:[]]}:void 0,inactiveContent:a?.isActive?void 0:{title:t("currentStatus.inactive"),message:t("currentStatus.inactiveMessage")}},aboveProducts:!u&&c.length>0?e.jsx("div",{className:"flex justify-center mb-6",children:e.jsx(A.SegmentedControl,{options:ie,value:m,onChange:J})}):null,primaryAction:{label:t(w?"buttons.purchasing":"buttons.subscribe"),onClick:K,disabled:!p||w||k,loading:w},secondaryAction:{label:t(k?"buttons.restoring":"buttons.restore"),onClick:H,disabled:w||k,loading:k},children:u?e.jsx("div",{className:"flex items-center justify-center py-12",children:e.jsx("div",{className:"animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"})}):c.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:t("noProducts")}):q.length===0?e.jsx("div",{className:"text-center py-12 text-theme-text-secondary",children:t("noProductsForPeriod")}):e.jsxs(e.Fragment,{children:[e.jsx(A.SubscriptionTile,{id:"free",title:t("freeTier.title"),price:t("freeTier.price"),periodLabel:t("periods.month"),features:ee(),isSelected:!a?.isActive&&p===null,onSelect:()=>v(null),topBadge:a?.isActive?void 0:{text:t("badges.currentPlan","Current Plan"),color:"green"},disabled:w||k,hideSelectionIndicator:!0},"free"),q.map(i=>e.jsx(A.SubscriptionTile,{id:i.identifier,title:i.title,price:i.priceString,periodLabel:X(i.period),features:R(i.identifier),isSelected:p===i.identifier,onSelect:()=>v(i.identifier),isBestValue:i.identifier.includes("pro"),discountBadge:i.period?.includes("Y")?(()=>{const n=te(i.identifier);return n&&n>0?{text:t("badges.savePercent","Save {{percent}}%",{percent:n}),isBestValue:!0}:void 0})():void 0,introPriceNote:i.freeTrialPeriod?Z(i.freeTrialPeriod):i.introPrice?t("intro.note",{price:i.introPrice}):void 0,disabled:w||k},i.identifier))]})})}l.EntityListPage=$,l.EntitySubscriptionsPage=G,l.InvitationsPage=V,l.MembersManagementPage=W,Object.defineProperty(l,Symbol.toStringTag,{value:"Module"})}));
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Entity List Page
|
|
3
|
-
* @description Page container for listing all user's entities
|
|
4
|
-
*/
|
|
5
1
|
import { EntityClient } from '@sudobility/entity_client';
|
|
6
|
-
import
|
|
2
|
+
import { EntityWithRole } from '@sudobility/types';
|
|
7
3
|
export interface EntityListPageProps {
|
|
8
4
|
/** Entity API client */
|
|
9
5
|
client: EntityClient;
|
|
@@ -16,4 +12,3 @@ export interface EntityListPageProps {
|
|
|
16
12
|
* Page for listing all user's entities with create functionality.
|
|
17
13
|
*/
|
|
18
14
|
export declare function EntityListPage({ client, onSelectEntity, }: EntityListPageProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
//# sourceMappingURL=EntityListPage.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { RateLimitsConfigData } from '@sudobility/types';
|
|
2
|
+
/** Product from subscription provider */
|
|
3
|
+
export interface SubscriptionProduct {
|
|
4
|
+
identifier: string;
|
|
5
|
+
title: string;
|
|
6
|
+
price: string;
|
|
7
|
+
priceString: string;
|
|
8
|
+
period?: string;
|
|
9
|
+
freeTrialPeriod?: string;
|
|
10
|
+
introPrice?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Current subscription state */
|
|
13
|
+
export interface CurrentSubscription {
|
|
14
|
+
isActive: boolean;
|
|
15
|
+
productIdentifier?: string;
|
|
16
|
+
expirationDate?: Date;
|
|
17
|
+
willRenew?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/** Subscription context value passed from consumer */
|
|
20
|
+
export interface SubscriptionContextValue {
|
|
21
|
+
products: SubscriptionProduct[];
|
|
22
|
+
currentSubscription: CurrentSubscription | null;
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
error: string | null;
|
|
25
|
+
purchase: (productId: string) => Promise<boolean>;
|
|
26
|
+
restore: () => Promise<boolean>;
|
|
27
|
+
clearError: () => void;
|
|
28
|
+
}
|
|
29
|
+
/** Translation function type */
|
|
30
|
+
export type TranslationFunction = (key: string, defaultValueOrOptions?: string | Record<string, unknown>, options?: Record<string, unknown>) => string;
|
|
31
|
+
export interface EntitySubscriptionsPageProps {
|
|
32
|
+
/** Subscription context value */
|
|
33
|
+
subscription: SubscriptionContextValue;
|
|
34
|
+
/** Rate limit configuration */
|
|
35
|
+
rateLimitsConfig?: RateLimitsConfigData | null;
|
|
36
|
+
/** Translation function */
|
|
37
|
+
t: TranslationFunction;
|
|
38
|
+
/** Called when purchase succeeds */
|
|
39
|
+
onPurchaseSuccess?: () => void;
|
|
40
|
+
/** Called when restore succeeds */
|
|
41
|
+
onRestoreSuccess?: () => void;
|
|
42
|
+
/** Called on error */
|
|
43
|
+
onError?: (title: string, message: string) => void;
|
|
44
|
+
/** Called on warning */
|
|
45
|
+
onWarning?: (title: string, message: string) => void;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Page for managing entity subscriptions.
|
|
49
|
+
*/
|
|
50
|
+
export declare function EntitySubscriptionsPage({ subscription, rateLimitsConfig, t, onPurchaseSuccess, onRestoreSuccess, onError, onWarning, }: EntitySubscriptionsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Invitations Page
|
|
3
|
-
* @description Page for viewing and responding to pending invitations
|
|
4
|
-
*/
|
|
5
1
|
import { EntityClient } from '@sudobility/entity_client';
|
|
6
2
|
export interface InvitationsPageProps {
|
|
7
3
|
/** Entity API client */
|
|
@@ -13,4 +9,3 @@ export interface InvitationsPageProps {
|
|
|
13
9
|
* Page for viewing and responding to pending invitations.
|
|
14
10
|
*/
|
|
15
11
|
export declare function InvitationsPage({ client, onInvitationAccepted, }: InvitationsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
-
//# sourceMappingURL=InvitationsPage.d.ts.map
|