strapi-plugin-magic-sessionmanager 4.0.1 → 4.0.2

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.
Files changed (57) hide show
  1. package/README.md +2 -2
  2. package/admin/src/components/OnlineUsersWidget.jsx +11 -7
  3. package/admin/src/components/SessionDetailModal.jsx +42 -38
  4. package/admin/src/components/SessionInfoPanel.jsx +29 -20
  5. package/admin/src/index.js +9 -0
  6. package/admin/src/pages/HomePage.jsx +128 -161
  7. package/admin/src/pages/License.jsx +3 -3
  8. package/admin/src/pages/Settings.jsx +139 -135
  9. package/admin/src/pages/UpgradePage.jsx +448 -0
  10. package/admin/src/pluginId.js +1 -0
  11. package/admin/src/translations/de.json +294 -15
  12. package/admin/src/translations/en.json +293 -14
  13. package/admin/src/translations/es.json +284 -18
  14. package/admin/src/translations/fr.json +284 -18
  15. package/admin/src/translations/pt.json +284 -18
  16. package/admin/src/utils/theme.js +85 -0
  17. package/dist/_chunks/{Analytics-Dv9f_0eZ.mjs → Analytics-DTE_zmRV.mjs} +2 -2
  18. package/dist/_chunks/{Analytics-BBdv1I5y.js → Analytics-lw_JaOVy.js} +2 -2
  19. package/dist/_chunks/{App-CJaZPNjt.js → App-DDKYCjKw.js} +216 -206
  20. package/dist/_chunks/{App-CIQ-7sa7.mjs → App-DJW1ZNl5.mjs} +216 -206
  21. package/dist/_chunks/{License-nrmFxoBm.mjs → License-DaOFuImm.mjs} +4 -8
  22. package/dist/_chunks/{License-D24rgaZQ.js → License-Tk-6UfPl.js} +4 -8
  23. package/dist/_chunks/{OnlineUsersWidget-B8JS1xZu.js → OnlineUsersWidget-C1qTpsws.js} +11 -7
  24. package/dist/_chunks/{OnlineUsersWidget-ArMl0nen.mjs → OnlineUsersWidget-CADphbXG.mjs} +11 -7
  25. package/dist/_chunks/{Settings-D5dLEGc_.mjs → Settings-C9xvckgq.mjs} +191 -179
  26. package/dist/_chunks/{Settings-CqxgjU0y.js → Settings-DyEAuTNQ.js} +191 -179
  27. package/dist/_chunks/UpgradePage-Dssk8A0Z.js +354 -0
  28. package/dist/_chunks/UpgradePage-cINvE9zY.mjs +352 -0
  29. package/dist/_chunks/de-CDA1V0rF.mjs +292 -0
  30. package/dist/_chunks/de-I-Q-pWqu.js +292 -0
  31. package/dist/_chunks/en-Bd7_h-4e.js +292 -0
  32. package/dist/_chunks/en-DzmOCyzQ.mjs +292 -0
  33. package/dist/_chunks/es-BcAx18XG.js +277 -0
  34. package/dist/_chunks/es-Cx-SN6qV.mjs +277 -0
  35. package/dist/_chunks/fr-DCzYMuJ-.js +277 -0
  36. package/dist/_chunks/fr-DXlXE5Eo.mjs +277 -0
  37. package/dist/_chunks/{index-WH04CS1c.js → index-CWcvrfXc.js} +45 -42
  38. package/dist/_chunks/{index-Duk1_Wrz.mjs → index-DQO9bNP7.mjs} +45 -42
  39. package/dist/_chunks/pt-21-MAb72.js +277 -0
  40. package/dist/_chunks/pt-zsdTSjba.mjs +277 -0
  41. package/dist/_chunks/{useLicense-BwOlCyhc.js → useLicense-DtvJOszr.js} +1 -1
  42. package/dist/_chunks/{useLicense-Ce8GaxB0.mjs → useLicense-DxbD4Wf8.mjs} +1 -1
  43. package/dist/admin/index.js +1 -1
  44. package/dist/admin/index.mjs +1 -1
  45. package/dist/server/index.js +1 -1
  46. package/dist/server/index.mjs +1 -1
  47. package/package.json +1 -1
  48. package/dist/_chunks/de-BxFx1pwE.js +0 -23
  49. package/dist/_chunks/de-CdO3s01z.mjs +0 -23
  50. package/dist/_chunks/en-CsPpPJL3.mjs +0 -23
  51. package/dist/_chunks/en-RqmpDHdS.js +0 -23
  52. package/dist/_chunks/es-CuLHazN1.js +0 -23
  53. package/dist/_chunks/es-Dkmjhy9c.mjs +0 -23
  54. package/dist/_chunks/fr-BAJp2yhI.js +0 -23
  55. package/dist/_chunks/fr-Bssg_3UF.mjs +0 -23
  56. package/dist/_chunks/pt-BAP9cKs3.js +0 -23
  57. package/dist/_chunks/pt-BVNoNcuY.mjs +0 -23
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const admin = require("@strapi/strapi/admin");
6
+ const styled = require("styled-components");
7
+ const designSystem = require("@strapi/design-system");
8
+ const icons = require("@strapi/icons");
9
+ const index = require("./index-CWcvrfXc.js");
10
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
11
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
12
+ const Container = styled__default.default(designSystem.Box)`
13
+ padding: 32px;
14
+ max-width: 1400px;
15
+ margin: 0 auto;
16
+ `;
17
+ const Header = styled__default.default(designSystem.Box)`
18
+ text-align: center;
19
+ margin-bottom: 48px;
20
+ display: flex;
21
+ flex-direction: column;
22
+ align-items: center;
23
+ gap: 8px;
24
+ `;
25
+ const Title = styled__default.default(designSystem.Typography)`
26
+ font-size: 2.5rem;
27
+ font-weight: 700;
28
+ margin-bottom: 8px;
29
+ background: linear-gradient(135deg, #0EA5E9, #A855F7);
30
+ -webkit-background-clip: text;
31
+ -webkit-text-fill-color: transparent;
32
+ display: block;
33
+ `;
34
+ const Subtitle = styled__default.default(designSystem.Typography)`
35
+ font-size: 1.125rem;
36
+ color: ${(props) => props.theme.colors.neutral600};
37
+ line-height: 1.6;
38
+ display: block;
39
+ `;
40
+ const TierGrid = styled__default.default(designSystem.Flex)`
41
+ gap: 32px;
42
+ margin: 0 auto 48px;
43
+ max-width: 1080px;
44
+ justify-content: center;
45
+ flex-wrap: wrap;
46
+ align-items: stretch;
47
+ `;
48
+ const TierWrapper = styled__default.default(designSystem.Box)`
49
+ flex: 1;
50
+ min-width: 280px;
51
+ max-width: 340px;
52
+ display: flex;
53
+ `;
54
+ const TierCard = styled__default.default(designSystem.Box)`
55
+ background: ${(props) => props.theme.colors.neutral0};
56
+ border-radius: 16px;
57
+ padding: 32px;
58
+ border: 2px solid ${(props) => props.$featured ? "#0EA5E9" : props.theme.colors.neutral200};
59
+ position: relative;
60
+ transition: all 0.3s ease;
61
+ box-shadow: ${(props) => props.$featured ? "0 20px 25px -5px rgba(14, 165, 233, 0.25), 0 8px 10px -6px rgba(14, 165, 233, 0.2)" : "0 10px 15px -3px rgba(15, 23, 42, 0.08), 0 4px 6px -4px rgba(15, 23, 42, 0.05)"};
62
+ display: flex;
63
+ flex-direction: column;
64
+ width: 100%;
65
+
66
+ &:hover {
67
+ transform: translateY(-4px);
68
+ box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.15), 0 8px 10px -6px rgba(15, 23, 42, 0.1);
69
+ }
70
+ `;
71
+ const PopularBadge = styled__default.default(designSystem.Badge)`
72
+ position: absolute;
73
+ top: -12px;
74
+ right: 24px;
75
+ background: linear-gradient(135deg, #0EA5E9, #0284C7);
76
+ color: white;
77
+ padding: 4px 16px;
78
+ font-size: 12px;
79
+ font-weight: 600;
80
+ `;
81
+ const TierIcon = styled__default.default(designSystem.Box)`
82
+ width: 48px;
83
+ height: 48px;
84
+ border-radius: 12px;
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ margin-bottom: 16px;
89
+ background: ${(props) => props.$color};
90
+
91
+ svg {
92
+ width: 28px;
93
+ height: 28px;
94
+ color: white;
95
+ }
96
+ `;
97
+ const TierName = styled__default.default(designSystem.Typography)`
98
+ font-size: 1.5rem;
99
+ font-weight: 700;
100
+ margin-bottom: 8px;
101
+ `;
102
+ const TierPrice = styled__default.default(designSystem.Typography)`
103
+ font-size: 2rem;
104
+ font-weight: 800;
105
+ margin-bottom: 4px;
106
+ `;
107
+ const TierDescription = styled__default.default(designSystem.Typography)`
108
+ color: ${(props) => props.theme.colors.neutral600};
109
+ margin-bottom: 24px;
110
+ `;
111
+ const FeatureList = styled__default.default(designSystem.Box)`
112
+ margin-bottom: 24px;
113
+ flex: 1;
114
+ `;
115
+ const Feature = styled__default.default(designSystem.Flex)`
116
+ gap: 12px;
117
+ margin-bottom: 12px;
118
+ align-items: flex-start;
119
+ `;
120
+ const FeatureIcon = styled__default.default(designSystem.Box)`
121
+ width: 20px;
122
+ height: 20px;
123
+ border-radius: 50%;
124
+ display: flex;
125
+ align-items: center;
126
+ justify-content: center;
127
+ flex-shrink: 0;
128
+ margin-top: 2px;
129
+
130
+ ${(props) => props.$included ? `
131
+ background: #DCFCE7;
132
+ svg { color: #16A34A; }
133
+ ` : `
134
+ background: #FEE2E2;
135
+ svg { color: #DC2626; }
136
+ `}
137
+ `;
138
+ const UpgradeButton = styled__default.default(designSystem.Button)`
139
+ width: 100%;
140
+ height: 48px;
141
+ font-weight: 600;
142
+ font-size: 15px;
143
+ background: ${(props) => props.$gradient};
144
+ border: none;
145
+ color: white;
146
+
147
+ &:hover {
148
+ transform: translateY(-2px);
149
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
150
+ }
151
+ `;
152
+ const CurrentPlanBadge = styled__default.default(designSystem.Badge)`
153
+ width: 100%;
154
+ height: 48px;
155
+ display: flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ background: ${(props) => props.theme.colors.neutral100};
159
+ color: ${(props) => props.theme.colors.neutral600};
160
+ font-weight: 600;
161
+ font-size: 15px;
162
+ `;
163
+ const LimitsBox = styled__default.default(designSystem.Box)`
164
+ background: ${(props) => props.theme.colors.neutral100};
165
+ border-radius: 8px;
166
+ padding: 12px;
167
+ margin-bottom: 20px;
168
+ `;
169
+ const UpgradePage = () => {
170
+ const { get } = admin.useFetchClient();
171
+ const { toggleNotification } = admin.useNotification();
172
+ const [currentTier, setCurrentTier] = react.useState("free");
173
+ const [limits, setLimits] = react.useState(null);
174
+ const [loading, setLoading] = react.useState(true);
175
+ react.useEffect(() => {
176
+ fetchLicenseInfo();
177
+ }, []);
178
+ const fetchLicenseInfo = async () => {
179
+ try {
180
+ const response = await get(`/${index.pluginId}/license/status`);
181
+ const licenseData = response.data || {};
182
+ let tier = "free";
183
+ if (licenseData.data?.features?.advanced) {
184
+ tier = "advanced";
185
+ } else if (licenseData.data?.features?.premium) {
186
+ tier = "premium";
187
+ }
188
+ setCurrentTier(tier);
189
+ setLimits(licenseData.limits);
190
+ setLoading(false);
191
+ } catch (error) {
192
+ console.error("[magic-sessionmanager] Failed to fetch license info:", error);
193
+ setLoading(false);
194
+ }
195
+ };
196
+ const getTierRank = (tierId) => {
197
+ const ranks = {
198
+ "free": 0,
199
+ "premium": 1,
200
+ "advanced": 2
201
+ };
202
+ return ranks[tierId] || 0;
203
+ };
204
+ const getButtonText = (tierId) => {
205
+ const currentRank = getTierRank(currentTier);
206
+ const targetRank = getTierRank(tierId);
207
+ if (currentRank === targetRank) {
208
+ return "Current Plan";
209
+ } else if (targetRank > currentRank) {
210
+ return "Upgrade Now";
211
+ } else {
212
+ return "Downgrade";
213
+ }
214
+ };
215
+ const tiers = [
216
+ {
217
+ id: "free",
218
+ name: "FREE",
219
+ price: "$0",
220
+ period: "forever",
221
+ description: "Perfect for small projects and testing",
222
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Sparkle, {}),
223
+ color: "linear-gradient(135deg, #6B7280, #4B5563)",
224
+ features: [
225
+ { name: "Session Tracking", included: true },
226
+ { name: "Force Logout", included: true },
227
+ { name: "Dashboard Widget", included: true },
228
+ { name: "Device Detection", included: true },
229
+ { name: "Basic Monitoring", included: true },
230
+ { name: "IP Geolocation", included: false },
231
+ { name: "VPN/Proxy Detection", included: false },
232
+ { name: "Threat Analysis", included: false },
233
+ { name: "Auto-blocking", included: false }
234
+ ],
235
+ limits: {
236
+ sessions: "Unlimited",
237
+ support: "Community"
238
+ }
239
+ },
240
+ {
241
+ id: "premium",
242
+ name: "PREMIUM",
243
+ price: "$14.50",
244
+ period: "/month",
245
+ description: "Enhanced security for growing teams",
246
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Lightning, {}),
247
+ color: "linear-gradient(135deg, #8B5CF6, #7C3AED)",
248
+ featured: true,
249
+ features: [
250
+ { name: "Session Tracking", included: true },
251
+ { name: "Force Logout", included: true },
252
+ { name: "Dashboard Widget", included: true },
253
+ { name: "Device Detection", included: true },
254
+ { name: "Basic Monitoring", included: true },
255
+ { name: "IP Geolocation", included: true },
256
+ { name: "VPN/Proxy Detection", included: true },
257
+ { name: "Security Risk Scoring", included: true },
258
+ { name: "Extended Logging", included: true },
259
+ { name: "Priority Support", included: true }
260
+ ],
261
+ limits: {
262
+ sessions: "Unlimited",
263
+ support: "Priority"
264
+ }
265
+ },
266
+ {
267
+ id: "advanced",
268
+ name: "ADVANCED",
269
+ price: "$39.50",
270
+ period: "/month",
271
+ description: "Maximum security for enterprises",
272
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Rocket, {}),
273
+ color: "linear-gradient(135deg, #0EA5E9, #0284C7)",
274
+ features: [
275
+ { name: "Session Tracking", included: true },
276
+ { name: "Force Logout", included: true },
277
+ { name: "Dashboard Widget", included: true },
278
+ { name: "Device Detection", included: true },
279
+ { name: "Basic Monitoring", included: true },
280
+ { name: "IP Geolocation", included: true },
281
+ { name: "VPN/Proxy Detection", included: true },
282
+ { name: "Security Risk Scoring", included: true },
283
+ { name: "Extended Logging", included: true },
284
+ { name: "Threat Analysis", included: true },
285
+ { name: "Auto-blocking", included: true },
286
+ { name: "Email/Webhook Alerts", included: true },
287
+ { name: "Geo-fencing", included: true },
288
+ { name: "Priority + Phone Support", included: true }
289
+ ],
290
+ limits: {
291
+ sessions: "Unlimited",
292
+ support: "Priority + Phone"
293
+ }
294
+ }
295
+ ];
296
+ const handleUpgrade = (tierId) => {
297
+ window.open("https://store.magicdx.dev/", "_blank");
298
+ };
299
+ if (loading) {
300
+ return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: "Loading license information..." }) }) });
301
+ }
302
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
303
+ /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
304
+ /* @__PURE__ */ jsxRuntime.jsx(Title, { variant: "alpha", children: "Choose Your Plan" }),
305
+ /* @__PURE__ */ jsxRuntime.jsx(Subtitle, { variant: "omega", children: "Unlock powerful session management features for your Strapi application" })
306
+ ] }),
307
+ /* @__PURE__ */ jsxRuntime.jsx(TierGrid, { children: tiers.map((tier) => /* @__PURE__ */ jsxRuntime.jsx(TierWrapper, { children: /* @__PURE__ */ jsxRuntime.jsxs(TierCard, { $featured: tier.featured, children: [
308
+ tier.featured && /* @__PURE__ */ jsxRuntime.jsx(PopularBadge, { children: "MOST POPULAR" }),
309
+ /* @__PURE__ */ jsxRuntime.jsx(TierIcon, { $color: tier.color, children: tier.icon }),
310
+ /* @__PURE__ */ jsxRuntime.jsx(TierName, { variant: "beta", children: tier.name }),
311
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "baseline", gap: 1, children: [
312
+ /* @__PURE__ */ jsxRuntime.jsx(TierPrice, { variant: "alpha", children: tier.price }),
313
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", style: { color: "#6B7280" }, children: tier.period })
314
+ ] }),
315
+ /* @__PURE__ */ jsxRuntime.jsx(TierDescription, { variant: "omega", children: tier.description }),
316
+ /* @__PURE__ */ jsxRuntime.jsx(LimitsBox, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
317
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
318
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Sessions:" }),
319
+ " ",
320
+ tier.limits.sessions
321
+ ] }),
322
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
323
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Support:" }),
324
+ " ",
325
+ tier.limits.support
326
+ ] })
327
+ ] }) }),
328
+ /* @__PURE__ */ jsxRuntime.jsx(FeatureList, { children: tier.features.map((feature, index2) => /* @__PURE__ */ jsxRuntime.jsxs(Feature, { children: [
329
+ /* @__PURE__ */ jsxRuntime.jsx(FeatureIcon, { $included: feature.included, children: feature.included ? /* @__PURE__ */ jsxRuntime.jsx(icons.Check, { style: { width: 14, height: 14 } }) : /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, { style: { width: 14, height: 14 } }) }),
330
+ /* @__PURE__ */ jsxRuntime.jsx(
331
+ designSystem.Typography,
332
+ {
333
+ variant: "omega",
334
+ style: {
335
+ fontSize: "14px",
336
+ color: feature.included ? "#374151" : "#9CA3AF",
337
+ textDecoration: feature.included ? "none" : "line-through"
338
+ },
339
+ children: feature.name
340
+ }
341
+ )
342
+ ] }, index2)) }),
343
+ currentTier === tier.id ? /* @__PURE__ */ jsxRuntime.jsx(CurrentPlanBadge, { children: "CURRENT PLAN" }) : /* @__PURE__ */ jsxRuntime.jsx(
344
+ UpgradeButton,
345
+ {
346
+ onClick: () => handleUpgrade(tier.id),
347
+ $gradient: tier.color,
348
+ children: getButtonText(tier.id)
349
+ }
350
+ )
351
+ ] }) }, tier.id)) })
352
+ ] });
353
+ };
354
+ exports.default = UpgradePage;
@@ -0,0 +1,352 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
4
+ import styled from "styled-components";
5
+ import { Flex, Typography, Box, Badge, Button } from "@strapi/design-system";
6
+ import { Check, Cross, Sparkle, Lightning, Rocket } from "@strapi/icons";
7
+ import { a as pluginId } from "./index-DQO9bNP7.mjs";
8
+ const Container = styled(Box)`
9
+ padding: 32px;
10
+ max-width: 1400px;
11
+ margin: 0 auto;
12
+ `;
13
+ const Header = styled(Box)`
14
+ text-align: center;
15
+ margin-bottom: 48px;
16
+ display: flex;
17
+ flex-direction: column;
18
+ align-items: center;
19
+ gap: 8px;
20
+ `;
21
+ const Title = styled(Typography)`
22
+ font-size: 2.5rem;
23
+ font-weight: 700;
24
+ margin-bottom: 8px;
25
+ background: linear-gradient(135deg, #0EA5E9, #A855F7);
26
+ -webkit-background-clip: text;
27
+ -webkit-text-fill-color: transparent;
28
+ display: block;
29
+ `;
30
+ const Subtitle = styled(Typography)`
31
+ font-size: 1.125rem;
32
+ color: ${(props) => props.theme.colors.neutral600};
33
+ line-height: 1.6;
34
+ display: block;
35
+ `;
36
+ const TierGrid = styled(Flex)`
37
+ gap: 32px;
38
+ margin: 0 auto 48px;
39
+ max-width: 1080px;
40
+ justify-content: center;
41
+ flex-wrap: wrap;
42
+ align-items: stretch;
43
+ `;
44
+ const TierWrapper = styled(Box)`
45
+ flex: 1;
46
+ min-width: 280px;
47
+ max-width: 340px;
48
+ display: flex;
49
+ `;
50
+ const TierCard = styled(Box)`
51
+ background: ${(props) => props.theme.colors.neutral0};
52
+ border-radius: 16px;
53
+ padding: 32px;
54
+ border: 2px solid ${(props) => props.$featured ? "#0EA5E9" : props.theme.colors.neutral200};
55
+ position: relative;
56
+ transition: all 0.3s ease;
57
+ box-shadow: ${(props) => props.$featured ? "0 20px 25px -5px rgba(14, 165, 233, 0.25), 0 8px 10px -6px rgba(14, 165, 233, 0.2)" : "0 10px 15px -3px rgba(15, 23, 42, 0.08), 0 4px 6px -4px rgba(15, 23, 42, 0.05)"};
58
+ display: flex;
59
+ flex-direction: column;
60
+ width: 100%;
61
+
62
+ &:hover {
63
+ transform: translateY(-4px);
64
+ box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.15), 0 8px 10px -6px rgba(15, 23, 42, 0.1);
65
+ }
66
+ `;
67
+ const PopularBadge = styled(Badge)`
68
+ position: absolute;
69
+ top: -12px;
70
+ right: 24px;
71
+ background: linear-gradient(135deg, #0EA5E9, #0284C7);
72
+ color: white;
73
+ padding: 4px 16px;
74
+ font-size: 12px;
75
+ font-weight: 600;
76
+ `;
77
+ const TierIcon = styled(Box)`
78
+ width: 48px;
79
+ height: 48px;
80
+ border-radius: 12px;
81
+ display: flex;
82
+ align-items: center;
83
+ justify-content: center;
84
+ margin-bottom: 16px;
85
+ background: ${(props) => props.$color};
86
+
87
+ svg {
88
+ width: 28px;
89
+ height: 28px;
90
+ color: white;
91
+ }
92
+ `;
93
+ const TierName = styled(Typography)`
94
+ font-size: 1.5rem;
95
+ font-weight: 700;
96
+ margin-bottom: 8px;
97
+ `;
98
+ const TierPrice = styled(Typography)`
99
+ font-size: 2rem;
100
+ font-weight: 800;
101
+ margin-bottom: 4px;
102
+ `;
103
+ const TierDescription = styled(Typography)`
104
+ color: ${(props) => props.theme.colors.neutral600};
105
+ margin-bottom: 24px;
106
+ `;
107
+ const FeatureList = styled(Box)`
108
+ margin-bottom: 24px;
109
+ flex: 1;
110
+ `;
111
+ const Feature = styled(Flex)`
112
+ gap: 12px;
113
+ margin-bottom: 12px;
114
+ align-items: flex-start;
115
+ `;
116
+ const FeatureIcon = styled(Box)`
117
+ width: 20px;
118
+ height: 20px;
119
+ border-radius: 50%;
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ flex-shrink: 0;
124
+ margin-top: 2px;
125
+
126
+ ${(props) => props.$included ? `
127
+ background: #DCFCE7;
128
+ svg { color: #16A34A; }
129
+ ` : `
130
+ background: #FEE2E2;
131
+ svg { color: #DC2626; }
132
+ `}
133
+ `;
134
+ const UpgradeButton = styled(Button)`
135
+ width: 100%;
136
+ height: 48px;
137
+ font-weight: 600;
138
+ font-size: 15px;
139
+ background: ${(props) => props.$gradient};
140
+ border: none;
141
+ color: white;
142
+
143
+ &:hover {
144
+ transform: translateY(-2px);
145
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
146
+ }
147
+ `;
148
+ const CurrentPlanBadge = styled(Badge)`
149
+ width: 100%;
150
+ height: 48px;
151
+ display: flex;
152
+ align-items: center;
153
+ justify-content: center;
154
+ background: ${(props) => props.theme.colors.neutral100};
155
+ color: ${(props) => props.theme.colors.neutral600};
156
+ font-weight: 600;
157
+ font-size: 15px;
158
+ `;
159
+ const LimitsBox = styled(Box)`
160
+ background: ${(props) => props.theme.colors.neutral100};
161
+ border-radius: 8px;
162
+ padding: 12px;
163
+ margin-bottom: 20px;
164
+ `;
165
+ const UpgradePage = () => {
166
+ const { get } = useFetchClient();
167
+ const { toggleNotification } = useNotification();
168
+ const [currentTier, setCurrentTier] = useState("free");
169
+ const [limits, setLimits] = useState(null);
170
+ const [loading, setLoading] = useState(true);
171
+ useEffect(() => {
172
+ fetchLicenseInfo();
173
+ }, []);
174
+ const fetchLicenseInfo = async () => {
175
+ try {
176
+ const response = await get(`/${pluginId}/license/status`);
177
+ const licenseData = response.data || {};
178
+ let tier = "free";
179
+ if (licenseData.data?.features?.advanced) {
180
+ tier = "advanced";
181
+ } else if (licenseData.data?.features?.premium) {
182
+ tier = "premium";
183
+ }
184
+ setCurrentTier(tier);
185
+ setLimits(licenseData.limits);
186
+ setLoading(false);
187
+ } catch (error) {
188
+ console.error("[magic-sessionmanager] Failed to fetch license info:", error);
189
+ setLoading(false);
190
+ }
191
+ };
192
+ const getTierRank = (tierId) => {
193
+ const ranks = {
194
+ "free": 0,
195
+ "premium": 1,
196
+ "advanced": 2
197
+ };
198
+ return ranks[tierId] || 0;
199
+ };
200
+ const getButtonText = (tierId) => {
201
+ const currentRank = getTierRank(currentTier);
202
+ const targetRank = getTierRank(tierId);
203
+ if (currentRank === targetRank) {
204
+ return "Current Plan";
205
+ } else if (targetRank > currentRank) {
206
+ return "Upgrade Now";
207
+ } else {
208
+ return "Downgrade";
209
+ }
210
+ };
211
+ const tiers = [
212
+ {
213
+ id: "free",
214
+ name: "FREE",
215
+ price: "$0",
216
+ period: "forever",
217
+ description: "Perfect for small projects and testing",
218
+ icon: /* @__PURE__ */ jsx(Sparkle, {}),
219
+ color: "linear-gradient(135deg, #6B7280, #4B5563)",
220
+ features: [
221
+ { name: "Session Tracking", included: true },
222
+ { name: "Force Logout", included: true },
223
+ { name: "Dashboard Widget", included: true },
224
+ { name: "Device Detection", included: true },
225
+ { name: "Basic Monitoring", included: true },
226
+ { name: "IP Geolocation", included: false },
227
+ { name: "VPN/Proxy Detection", included: false },
228
+ { name: "Threat Analysis", included: false },
229
+ { name: "Auto-blocking", included: false }
230
+ ],
231
+ limits: {
232
+ sessions: "Unlimited",
233
+ support: "Community"
234
+ }
235
+ },
236
+ {
237
+ id: "premium",
238
+ name: "PREMIUM",
239
+ price: "$14.50",
240
+ period: "/month",
241
+ description: "Enhanced security for growing teams",
242
+ icon: /* @__PURE__ */ jsx(Lightning, {}),
243
+ color: "linear-gradient(135deg, #8B5CF6, #7C3AED)",
244
+ featured: true,
245
+ features: [
246
+ { name: "Session Tracking", included: true },
247
+ { name: "Force Logout", included: true },
248
+ { name: "Dashboard Widget", included: true },
249
+ { name: "Device Detection", included: true },
250
+ { name: "Basic Monitoring", included: true },
251
+ { name: "IP Geolocation", included: true },
252
+ { name: "VPN/Proxy Detection", included: true },
253
+ { name: "Security Risk Scoring", included: true },
254
+ { name: "Extended Logging", included: true },
255
+ { name: "Priority Support", included: true }
256
+ ],
257
+ limits: {
258
+ sessions: "Unlimited",
259
+ support: "Priority"
260
+ }
261
+ },
262
+ {
263
+ id: "advanced",
264
+ name: "ADVANCED",
265
+ price: "$39.50",
266
+ period: "/month",
267
+ description: "Maximum security for enterprises",
268
+ icon: /* @__PURE__ */ jsx(Rocket, {}),
269
+ color: "linear-gradient(135deg, #0EA5E9, #0284C7)",
270
+ features: [
271
+ { name: "Session Tracking", included: true },
272
+ { name: "Force Logout", included: true },
273
+ { name: "Dashboard Widget", included: true },
274
+ { name: "Device Detection", included: true },
275
+ { name: "Basic Monitoring", included: true },
276
+ { name: "IP Geolocation", included: true },
277
+ { name: "VPN/Proxy Detection", included: true },
278
+ { name: "Security Risk Scoring", included: true },
279
+ { name: "Extended Logging", included: true },
280
+ { name: "Threat Analysis", included: true },
281
+ { name: "Auto-blocking", included: true },
282
+ { name: "Email/Webhook Alerts", included: true },
283
+ { name: "Geo-fencing", included: true },
284
+ { name: "Priority + Phone Support", included: true }
285
+ ],
286
+ limits: {
287
+ sessions: "Unlimited",
288
+ support: "Priority + Phone"
289
+ }
290
+ }
291
+ ];
292
+ const handleUpgrade = (tierId) => {
293
+ window.open("https://store.magicdx.dev/", "_blank");
294
+ };
295
+ if (loading) {
296
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsx(Typography, { children: "Loading license information..." }) }) });
297
+ }
298
+ return /* @__PURE__ */ jsxs(Container, { children: [
299
+ /* @__PURE__ */ jsxs(Header, { children: [
300
+ /* @__PURE__ */ jsx(Title, { variant: "alpha", children: "Choose Your Plan" }),
301
+ /* @__PURE__ */ jsx(Subtitle, { variant: "omega", children: "Unlock powerful session management features for your Strapi application" })
302
+ ] }),
303
+ /* @__PURE__ */ jsx(TierGrid, { children: tiers.map((tier) => /* @__PURE__ */ jsx(TierWrapper, { children: /* @__PURE__ */ jsxs(TierCard, { $featured: tier.featured, children: [
304
+ tier.featured && /* @__PURE__ */ jsx(PopularBadge, { children: "MOST POPULAR" }),
305
+ /* @__PURE__ */ jsx(TierIcon, { $color: tier.color, children: tier.icon }),
306
+ /* @__PURE__ */ jsx(TierName, { variant: "beta", children: tier.name }),
307
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "baseline", gap: 1, children: [
308
+ /* @__PURE__ */ jsx(TierPrice, { variant: "alpha", children: tier.price }),
309
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", style: { color: "#6B7280" }, children: tier.period })
310
+ ] }),
311
+ /* @__PURE__ */ jsx(TierDescription, { variant: "omega", children: tier.description }),
312
+ /* @__PURE__ */ jsx(LimitsBox, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
313
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
314
+ /* @__PURE__ */ jsx("strong", { children: "Sessions:" }),
315
+ " ",
316
+ tier.limits.sessions
317
+ ] }),
318
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
319
+ /* @__PURE__ */ jsx("strong", { children: "Support:" }),
320
+ " ",
321
+ tier.limits.support
322
+ ] })
323
+ ] }) }),
324
+ /* @__PURE__ */ jsx(FeatureList, { children: tier.features.map((feature, index) => /* @__PURE__ */ jsxs(Feature, { children: [
325
+ /* @__PURE__ */ jsx(FeatureIcon, { $included: feature.included, children: feature.included ? /* @__PURE__ */ jsx(Check, { style: { width: 14, height: 14 } }) : /* @__PURE__ */ jsx(Cross, { style: { width: 14, height: 14 } }) }),
326
+ /* @__PURE__ */ jsx(
327
+ Typography,
328
+ {
329
+ variant: "omega",
330
+ style: {
331
+ fontSize: "14px",
332
+ color: feature.included ? "#374151" : "#9CA3AF",
333
+ textDecoration: feature.included ? "none" : "line-through"
334
+ },
335
+ children: feature.name
336
+ }
337
+ )
338
+ ] }, index)) }),
339
+ currentTier === tier.id ? /* @__PURE__ */ jsx(CurrentPlanBadge, { children: "CURRENT PLAN" }) : /* @__PURE__ */ jsx(
340
+ UpgradeButton,
341
+ {
342
+ onClick: () => handleUpgrade(tier.id),
343
+ $gradient: tier.color,
344
+ children: getButtonText(tier.id)
345
+ }
346
+ )
347
+ ] }) }, tier.id)) })
348
+ ] });
349
+ };
350
+ export {
351
+ UpgradePage as default
352
+ };