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