strapi-plugin-magic-mark 3.0.0 → 3.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 (51) hide show
  1. package/README.md +1 -1
  2. package/dist/_chunks/{App-C5UU0yUr.js → App-B6x0aSMN.js} +97 -55
  3. package/dist/_chunks/{App-Dt-v39BQ.mjs → App-BCliVBSB.mjs} +98 -56
  4. package/dist/_chunks/UpgradePage-Bm0SkuCi.js +353 -0
  5. package/dist/_chunks/UpgradePage-GoocQ4av.mjs +351 -0
  6. package/dist/_chunks/de-Cs9dd3Mr.js +138 -0
  7. package/dist/_chunks/de-DOVki5VS.mjs +138 -0
  8. package/dist/_chunks/en-CE3r46Y2.js +138 -0
  9. package/dist/_chunks/en-Cf5-O03L.mjs +138 -0
  10. package/dist/_chunks/es-Ba6JcPIm.mjs +138 -0
  11. package/dist/_chunks/es-D4AOyJYJ.js +138 -0
  12. package/dist/_chunks/fr-CWSfoA8i.js +138 -0
  13. package/dist/_chunks/fr-CrMBXR3c.mjs +138 -0
  14. package/dist/_chunks/{index-B-Cc7QNW.mjs → index-B_EiWnCU.mjs} +13 -4
  15. package/dist/_chunks/index-D5-84IjV.js +3365 -0
  16. package/dist/_chunks/{index-B11QBtag.js → index-DA7Jswi4.js} +12 -3
  17. package/dist/_chunks/index-DdTUt6EH.mjs +3361 -0
  18. package/dist/_chunks/pt-BXxZ1Zym.mjs +138 -0
  19. package/dist/_chunks/pt-DW_6r_mP.js +138 -0
  20. package/dist/admin/index.js +1 -1
  21. package/dist/admin/index.mjs +1 -1
  22. package/dist/admin/src/components/QueryBuilder.d.ts +12 -1
  23. package/dist/admin/src/components/RelationFieldSelector.d.ts +24 -0
  24. package/dist/admin/src/components/SimpleAdvancedFilterModal.d.ts +2 -0
  25. package/dist/admin/src/components/UpgradePrompt.d.ts +22 -0
  26. package/dist/admin/src/hooks/useFeatureGate.d.ts +88 -0
  27. package/dist/admin/src/hooks/useRelationSchema.d.ts +27 -0
  28. package/dist/admin/src/pages/UpgradePage.d.ts +6 -0
  29. package/dist/admin/src/utils/queryGenerator.d.ts +4 -0
  30. package/dist/admin/src/utils/queryToStructure.d.ts +8 -1
  31. package/dist/admin/src/utils/theme.d.ts +95 -0
  32. package/dist/server/index.js +212 -9
  33. package/dist/server/index.mjs +212 -9
  34. package/dist/server/src/controllers/index.d.ts +1 -0
  35. package/dist/server/src/controllers/license.d.ts +4 -0
  36. package/dist/server/src/index.d.ts +24 -1
  37. package/dist/server/src/services/index.d.ts +23 -1
  38. package/dist/server/src/services/license-guard.d.ts +48 -2
  39. package/package.json +1 -1
  40. package/dist/_chunks/de-Bag-366k.mjs +0 -49
  41. package/dist/_chunks/de-Dic_hhjg.js +0 -49
  42. package/dist/_chunks/en-C5BvHqNo.js +0 -54
  43. package/dist/_chunks/en-zokEerzt.mjs +0 -54
  44. package/dist/_chunks/es-BlSQpU1z.js +0 -54
  45. package/dist/_chunks/es-Br1ucP3h.mjs +0 -54
  46. package/dist/_chunks/fr-BHciYPYG.js +0 -54
  47. package/dist/_chunks/fr-Dzo3kt_q.mjs +0 -54
  48. package/dist/_chunks/index-BAmZV8aX.mjs +0 -2020
  49. package/dist/_chunks/index-RuDV4dTy.js +0 -2024
  50. package/dist/_chunks/pt-DQoGyzyD.mjs +0 -54
  51. package/dist/_chunks/pt-Dawo5aUA.js +0 -54
@@ -0,0 +1,353 @@
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 reactIntl = require("react-intl");
6
+ const admin = require("@strapi/strapi/admin");
7
+ const styled = require("styled-components");
8
+ const designSystem = require("@strapi/design-system");
9
+ const icons = require("@strapi/icons");
10
+ const index = require("./index-D5-84IjV.js");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ const styled__default = /* @__PURE__ */ _interopDefault(styled);
13
+ const Container = styled__default.default(designSystem.Box)`
14
+ padding: 32px;
15
+ max-width: 1400px;
16
+ margin: 0 auto;
17
+ `;
18
+ const Header = styled__default.default(designSystem.Box)`
19
+ text-align: center;
20
+ margin-bottom: 48px;
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: center;
24
+ gap: 8px;
25
+ `;
26
+ const Title = styled__default.default(designSystem.Typography)`
27
+ font-size: 2.5rem;
28
+ font-weight: 700;
29
+ margin-bottom: 8px;
30
+ background: linear-gradient(135deg, #0EA5E9, #A855F7);
31
+ -webkit-background-clip: text;
32
+ -webkit-text-fill-color: transparent;
33
+ display: block;
34
+ `;
35
+ const Subtitle = styled__default.default(designSystem.Typography)`
36
+ font-size: 1.125rem;
37
+ color: ${(props) => props.theme.colors.neutral600};
38
+ line-height: 1.6;
39
+ display: block;
40
+ `;
41
+ const TierGrid = styled__default.default(designSystem.Flex)`
42
+ gap: 32px;
43
+ margin: 0 auto 48px;
44
+ max-width: 1080px;
45
+ justify-content: center;
46
+ flex-wrap: wrap;
47
+ align-items: stretch;
48
+ `;
49
+ const TierWrapper = styled__default.default(designSystem.Box)`
50
+ flex: 1;
51
+ min-width: 280px;
52
+ max-width: 340px;
53
+ display: flex;
54
+ `;
55
+ const TierCard = styled__default.default(designSystem.Box)`
56
+ background: ${(props) => props.theme.colors.neutral0};
57
+ border-radius: 16px;
58
+ padding: 32px;
59
+ border: 2px solid ${(props) => props.$featured ? "#0EA5E9" : props.theme.colors.neutral200};
60
+ position: relative;
61
+ transition: all 0.3s ease;
62
+ 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)"};
63
+ display: flex;
64
+ flex-direction: column;
65
+ width: 100%;
66
+
67
+ &:hover {
68
+ transform: translateY(-4px);
69
+ box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.15), 0 8px 10px -6px rgba(15, 23, 42, 0.1);
70
+ }
71
+ `;
72
+ const PopularBadge = styled__default.default(designSystem.Badge)`
73
+ position: absolute;
74
+ top: -12px;
75
+ right: 24px;
76
+ background: linear-gradient(135deg, #0EA5E9, #0284C7);
77
+ color: white;
78
+ padding: 4px 16px;
79
+ font-size: 12px;
80
+ font-weight: 600;
81
+ `;
82
+ const TierIcon = styled__default.default(designSystem.Box)`
83
+ width: 48px;
84
+ height: 48px;
85
+ border-radius: 12px;
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ margin-bottom: 16px;
90
+ background: ${(props) => props.$color};
91
+
92
+ svg {
93
+ width: 28px;
94
+ height: 28px;
95
+ color: white;
96
+ }
97
+ `;
98
+ const TierName = styled__default.default(designSystem.Typography)`
99
+ font-size: 1.5rem;
100
+ font-weight: 700;
101
+ margin-bottom: 8px;
102
+ `;
103
+ const TierPrice = styled__default.default(designSystem.Typography)`
104
+ font-size: 2rem;
105
+ font-weight: 800;
106
+ margin-bottom: 4px;
107
+ `;
108
+ const TierDescription = styled__default.default(designSystem.Typography)`
109
+ color: ${(props) => props.theme.colors.neutral600};
110
+ margin-bottom: 24px;
111
+ `;
112
+ const FeatureList = styled__default.default(designSystem.Box)`
113
+ margin-bottom: 24px;
114
+ flex: 1;
115
+ `;
116
+ const Feature = styled__default.default(designSystem.Flex)`
117
+ gap: 12px;
118
+ margin-bottom: 12px;
119
+ align-items: flex-start;
120
+ `;
121
+ const FeatureIcon = styled__default.default(designSystem.Box)`
122
+ width: 20px;
123
+ height: 20px;
124
+ border-radius: 50%;
125
+ display: flex;
126
+ align-items: center;
127
+ justify-content: center;
128
+ flex-shrink: 0;
129
+ margin-top: 2px;
130
+
131
+ ${(props) => props.$included ? `
132
+ background: #DCFCE7;
133
+ svg { color: #16A34A; }
134
+ ` : `
135
+ background: #FEE2E2;
136
+ svg { color: #DC2626; }
137
+ `}
138
+ `;
139
+ const UpgradeButton = styled__default.default(designSystem.Button)`
140
+ width: 100%;
141
+ height: 48px;
142
+ font-weight: 600;
143
+ font-size: 15px;
144
+ background: ${(props) => props.$gradient};
145
+ border: none;
146
+ color: white;
147
+
148
+ &:hover {
149
+ transform: translateY(-2px);
150
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
151
+ }
152
+ `;
153
+ const CurrentPlanBadge = styled__default.default(designSystem.Badge)`
154
+ width: 100%;
155
+ height: 48px;
156
+ display: flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ background: ${(props) => props.theme.colors.neutral100};
160
+ color: ${(props) => props.theme.colors.neutral600};
161
+ font-weight: 600;
162
+ font-size: 15px;
163
+ `;
164
+ const LimitsBox = styled__default.default(designSystem.Box)`
165
+ background: ${(props) => props.theme.colors.neutral100};
166
+ border-radius: 8px;
167
+ padding: 12px;
168
+ margin-bottom: 20px;
169
+ `;
170
+ const UpgradePage = () => {
171
+ const { formatMessage } = reactIntl.useIntl();
172
+ const { get } = admin.useFetchClient();
173
+ const { toggleNotification } = admin.useNotification();
174
+ const [currentTier, setCurrentTier] = React.useState("free");
175
+ const [limits, setLimits] = React.useState(null);
176
+ const [loading, setLoading] = React.useState(true);
177
+ React.useEffect(() => {
178
+ fetchLicenseInfo();
179
+ }, []);
180
+ const fetchLicenseInfo = async () => {
181
+ try {
182
+ const response = await get("/magic-mark/license/status");
183
+ const licenseData = response.data || {};
184
+ let tier = "free";
185
+ if (licenseData.data?.features?.advanced) {
186
+ tier = "advanced";
187
+ } else if (licenseData.data?.features?.premium) {
188
+ tier = "premium";
189
+ }
190
+ setCurrentTier(tier);
191
+ setLimits(licenseData.limits);
192
+ setLoading(false);
193
+ } catch (error) {
194
+ console.error("[magic-mark] Failed to fetch license info:", error);
195
+ setLoading(false);
196
+ }
197
+ };
198
+ const getTierRank = (tierId) => {
199
+ const ranks = {
200
+ "free": 0,
201
+ "premium": 1,
202
+ "advanced": 2
203
+ };
204
+ return ranks[tierId] || 0;
205
+ };
206
+ const getButtonText = (tierId) => {
207
+ const currentRank = getTierRank(currentTier);
208
+ const targetRank = getTierRank(tierId);
209
+ if (currentRank === targetRank) {
210
+ return formatMessage({ id: `${index.pluginId}.upgradePage.currentPlan`, defaultMessage: "Current Plan" });
211
+ } else if (targetRank > currentRank) {
212
+ return formatMessage({ id: `${index.pluginId}.upgrade.upgradeNow`, defaultMessage: "Upgrade Now" });
213
+ } else {
214
+ return formatMessage({ id: `${index.pluginId}.upgradePage.downgrade`, defaultMessage: "Downgrade" });
215
+ }
216
+ };
217
+ const tiers = [
218
+ {
219
+ id: "free",
220
+ name: "FREE",
221
+ price: "$0",
222
+ period: "forever",
223
+ description: "Perfect for small projects and testing",
224
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Sparkle, {}),
225
+ color: "linear-gradient(135deg, #6B7280, #4B5563)",
226
+ features: [
227
+ { name: "10 Bookmarks", included: true },
228
+ { name: "Advanced Filters", included: true },
229
+ { name: "Role Sharing", included: true },
230
+ { name: "Drag & Drop", included: true },
231
+ { name: "Quick Access", included: true },
232
+ { name: "Query History", included: false },
233
+ { name: "Export Bookmarks", included: false },
234
+ { name: "Analytics", included: false },
235
+ { name: "Bulk Operations", included: false }
236
+ ],
237
+ limits: {
238
+ bookmarks: "10",
239
+ support: "Community"
240
+ }
241
+ },
242
+ {
243
+ id: "premium",
244
+ name: "PREMIUM",
245
+ price: "$14.50",
246
+ period: "/month",
247
+ description: "Enhanced features for growing teams",
248
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Lightning, {}),
249
+ color: "linear-gradient(135deg, #8B5CF6, #7C3AED)",
250
+ featured: true,
251
+ features: [
252
+ { name: "50 Bookmarks", included: true },
253
+ { name: "Advanced Filters", included: true },
254
+ { name: "Role Sharing", included: true },
255
+ { name: "Drag & Drop", included: true },
256
+ { name: "Quick Access", included: true },
257
+ { name: "Query History", included: true },
258
+ { name: "Export Bookmarks", included: true },
259
+ { name: "Priority Support", included: true },
260
+ { name: "Analytics", included: false },
261
+ { name: "Bulk Operations", included: false }
262
+ ],
263
+ limits: {
264
+ bookmarks: "50",
265
+ support: "Priority"
266
+ }
267
+ },
268
+ {
269
+ id: "advanced",
270
+ name: "ADVANCED",
271
+ price: "$39.50",
272
+ period: "/month",
273
+ description: "Maximum features for power users",
274
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Rocket, {}),
275
+ color: "linear-gradient(135deg, #0EA5E9, #0284C7)",
276
+ features: [
277
+ { name: "Unlimited Bookmarks", included: true },
278
+ { name: "Advanced Filters", included: true },
279
+ { name: "Role Sharing", included: true },
280
+ { name: "Drag & Drop", included: true },
281
+ { name: "Quick Access", included: true },
282
+ { name: "Query History", included: true },
283
+ { name: "Export Bookmarks", included: true },
284
+ { name: "Analytics Dashboard", included: true },
285
+ { name: "Bulk Operations", included: true },
286
+ { name: "Custom Integrations", included: true },
287
+ { name: "Priority + Phone Support", included: true }
288
+ ],
289
+ limits: {
290
+ bookmarks: "Unlimited",
291
+ support: "Priority + Phone"
292
+ }
293
+ }
294
+ ];
295
+ const handleUpgrade = (tierId) => {
296
+ window.open("https://store.magicdx.dev/", "_blank");
297
+ };
298
+ if (loading) {
299
+ 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: formatMessage({ id: `${index.pluginId}.upgradePage.loading`, defaultMessage: "Loading license information..." }) }) }) });
300
+ }
301
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
302
+ /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
303
+ /* @__PURE__ */ jsxRuntime.jsx(Title, { variant: "alpha", children: formatMessage({ id: `${index.pluginId}.upgradePage.title`, defaultMessage: "Choose Your Plan" }) }),
304
+ /* @__PURE__ */ jsxRuntime.jsx(Subtitle, { variant: "omega", children: formatMessage({ id: `${index.pluginId}.upgradePage.subtitle`, defaultMessage: "Unlock powerful bookmarking features for your Strapi application" }) })
305
+ ] }),
306
+ /* @__PURE__ */ jsxRuntime.jsx(TierGrid, { children: tiers.map((tier) => /* @__PURE__ */ jsxRuntime.jsx(TierWrapper, { children: /* @__PURE__ */ jsxRuntime.jsxs(TierCard, { $featured: tier.featured, children: [
307
+ tier.featured && /* @__PURE__ */ jsxRuntime.jsx(PopularBadge, { children: formatMessage({ id: `${index.pluginId}.upgradePage.mostPopular`, defaultMessage: "MOST POPULAR" }) }),
308
+ /* @__PURE__ */ jsxRuntime.jsx(TierIcon, { $color: tier.color, children: tier.icon }),
309
+ /* @__PURE__ */ jsxRuntime.jsx(TierName, { variant: "beta", children: tier.name }),
310
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "baseline", gap: 1, children: [
311
+ /* @__PURE__ */ jsxRuntime.jsx(TierPrice, { variant: "alpha", children: tier.price }),
312
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", style: { color: "#6B7280" }, children: tier.period })
313
+ ] }),
314
+ /* @__PURE__ */ jsxRuntime.jsx(TierDescription, { variant: "omega", children: tier.description }),
315
+ /* @__PURE__ */ jsxRuntime.jsx(LimitsBox, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
316
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
317
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatMessage({ id: `${index.pluginId}.upgradePage.bookmarks`, defaultMessage: "Bookmarks:" }) }),
318
+ " ",
319
+ tier.limits.bookmarks
320
+ ] }),
321
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
322
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatMessage({ id: `${index.pluginId}.upgradePage.support`, defaultMessage: "Support:" }) }),
323
+ " ",
324
+ tier.limits.support
325
+ ] })
326
+ ] }) }),
327
+ /* @__PURE__ */ jsxRuntime.jsx(FeatureList, { children: tier.features.map((feature, index2) => /* @__PURE__ */ jsxRuntime.jsxs(Feature, { children: [
328
+ /* @__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 } }) }),
329
+ /* @__PURE__ */ jsxRuntime.jsx(
330
+ designSystem.Typography,
331
+ {
332
+ variant: "omega",
333
+ style: {
334
+ fontSize: "14px",
335
+ color: feature.included ? "#374151" : "#9CA3AF",
336
+ textDecoration: feature.included ? "none" : "line-through"
337
+ },
338
+ children: feature.name
339
+ }
340
+ )
341
+ ] }, index2)) }),
342
+ currentTier === tier.id ? /* @__PURE__ */ jsxRuntime.jsx(CurrentPlanBadge, { children: formatMessage({ id: `${index.pluginId}.upgradePage.currentPlan`, defaultMessage: "CURRENT PLAN" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
343
+ UpgradeButton,
344
+ {
345
+ onClick: () => handleUpgrade(tier.id),
346
+ $gradient: tier.color,
347
+ children: getButtonText(tier.id)
348
+ }
349
+ )
350
+ ] }) }, tier.id)) })
351
+ ] });
352
+ };
353
+ exports.default = UpgradePage;
@@ -0,0 +1,351 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from "react";
3
+ import { useIntl } from "react-intl";
4
+ import { useFetchClient, useNotification } from "@strapi/strapi/admin";
5
+ import styled from "styled-components";
6
+ import { Flex, Typography, Box, Badge, Button } from "@strapi/design-system";
7
+ import { Check, Cross, Sparkle, Lightning, Rocket } from "@strapi/icons";
8
+ import { p as pluginId } from "./index-DdTUt6EH.mjs";
9
+ const Container = styled(Box)`
10
+ padding: 32px;
11
+ max-width: 1400px;
12
+ margin: 0 auto;
13
+ `;
14
+ const Header = styled(Box)`
15
+ text-align: center;
16
+ margin-bottom: 48px;
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: center;
20
+ gap: 8px;
21
+ `;
22
+ const Title = styled(Typography)`
23
+ font-size: 2.5rem;
24
+ font-weight: 700;
25
+ margin-bottom: 8px;
26
+ background: linear-gradient(135deg, #0EA5E9, #A855F7);
27
+ -webkit-background-clip: text;
28
+ -webkit-text-fill-color: transparent;
29
+ display: block;
30
+ `;
31
+ const Subtitle = styled(Typography)`
32
+ font-size: 1.125rem;
33
+ color: ${(props) => props.theme.colors.neutral600};
34
+ line-height: 1.6;
35
+ display: block;
36
+ `;
37
+ const TierGrid = styled(Flex)`
38
+ gap: 32px;
39
+ margin: 0 auto 48px;
40
+ max-width: 1080px;
41
+ justify-content: center;
42
+ flex-wrap: wrap;
43
+ align-items: stretch;
44
+ `;
45
+ const TierWrapper = styled(Box)`
46
+ flex: 1;
47
+ min-width: 280px;
48
+ max-width: 340px;
49
+ display: flex;
50
+ `;
51
+ const TierCard = styled(Box)`
52
+ background: ${(props) => props.theme.colors.neutral0};
53
+ border-radius: 16px;
54
+ padding: 32px;
55
+ border: 2px solid ${(props) => props.$featured ? "#0EA5E9" : props.theme.colors.neutral200};
56
+ position: relative;
57
+ transition: all 0.3s ease;
58
+ 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)"};
59
+ display: flex;
60
+ flex-direction: column;
61
+ width: 100%;
62
+
63
+ &:hover {
64
+ transform: translateY(-4px);
65
+ box-shadow: 0 20px 25px -5px rgba(15, 23, 42, 0.15), 0 8px 10px -6px rgba(15, 23, 42, 0.1);
66
+ }
67
+ `;
68
+ const PopularBadge = styled(Badge)`
69
+ position: absolute;
70
+ top: -12px;
71
+ right: 24px;
72
+ background: linear-gradient(135deg, #0EA5E9, #0284C7);
73
+ color: white;
74
+ padding: 4px 16px;
75
+ font-size: 12px;
76
+ font-weight: 600;
77
+ `;
78
+ const TierIcon = styled(Box)`
79
+ width: 48px;
80
+ height: 48px;
81
+ border-radius: 12px;
82
+ display: flex;
83
+ align-items: center;
84
+ justify-content: center;
85
+ margin-bottom: 16px;
86
+ background: ${(props) => props.$color};
87
+
88
+ svg {
89
+ width: 28px;
90
+ height: 28px;
91
+ color: white;
92
+ }
93
+ `;
94
+ const TierName = styled(Typography)`
95
+ font-size: 1.5rem;
96
+ font-weight: 700;
97
+ margin-bottom: 8px;
98
+ `;
99
+ const TierPrice = styled(Typography)`
100
+ font-size: 2rem;
101
+ font-weight: 800;
102
+ margin-bottom: 4px;
103
+ `;
104
+ const TierDescription = styled(Typography)`
105
+ color: ${(props) => props.theme.colors.neutral600};
106
+ margin-bottom: 24px;
107
+ `;
108
+ const FeatureList = styled(Box)`
109
+ margin-bottom: 24px;
110
+ flex: 1;
111
+ `;
112
+ const Feature = styled(Flex)`
113
+ gap: 12px;
114
+ margin-bottom: 12px;
115
+ align-items: flex-start;
116
+ `;
117
+ const FeatureIcon = styled(Box)`
118
+ width: 20px;
119
+ height: 20px;
120
+ border-radius: 50%;
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ flex-shrink: 0;
125
+ margin-top: 2px;
126
+
127
+ ${(props) => props.$included ? `
128
+ background: #DCFCE7;
129
+ svg { color: #16A34A; }
130
+ ` : `
131
+ background: #FEE2E2;
132
+ svg { color: #DC2626; }
133
+ `}
134
+ `;
135
+ const UpgradeButton = styled(Button)`
136
+ width: 100%;
137
+ height: 48px;
138
+ font-weight: 600;
139
+ font-size: 15px;
140
+ background: ${(props) => props.$gradient};
141
+ border: none;
142
+ color: white;
143
+
144
+ &:hover {
145
+ transform: translateY(-2px);
146
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
147
+ }
148
+ `;
149
+ const CurrentPlanBadge = styled(Badge)`
150
+ width: 100%;
151
+ height: 48px;
152
+ display: flex;
153
+ align-items: center;
154
+ justify-content: center;
155
+ background: ${(props) => props.theme.colors.neutral100};
156
+ color: ${(props) => props.theme.colors.neutral600};
157
+ font-weight: 600;
158
+ font-size: 15px;
159
+ `;
160
+ const LimitsBox = styled(Box)`
161
+ background: ${(props) => props.theme.colors.neutral100};
162
+ border-radius: 8px;
163
+ padding: 12px;
164
+ margin-bottom: 20px;
165
+ `;
166
+ const UpgradePage = () => {
167
+ const { formatMessage } = useIntl();
168
+ const { get } = useFetchClient();
169
+ const { toggleNotification } = useNotification();
170
+ const [currentTier, setCurrentTier] = useState("free");
171
+ const [limits, setLimits] = useState(null);
172
+ const [loading, setLoading] = useState(true);
173
+ useEffect(() => {
174
+ fetchLicenseInfo();
175
+ }, []);
176
+ const fetchLicenseInfo = async () => {
177
+ try {
178
+ const response = await get("/magic-mark/license/status");
179
+ const licenseData = response.data || {};
180
+ let tier = "free";
181
+ if (licenseData.data?.features?.advanced) {
182
+ tier = "advanced";
183
+ } else if (licenseData.data?.features?.premium) {
184
+ tier = "premium";
185
+ }
186
+ setCurrentTier(tier);
187
+ setLimits(licenseData.limits);
188
+ setLoading(false);
189
+ } catch (error) {
190
+ console.error("[magic-mark] Failed to fetch license info:", error);
191
+ setLoading(false);
192
+ }
193
+ };
194
+ const getTierRank = (tierId) => {
195
+ const ranks = {
196
+ "free": 0,
197
+ "premium": 1,
198
+ "advanced": 2
199
+ };
200
+ return ranks[tierId] || 0;
201
+ };
202
+ const getButtonText = (tierId) => {
203
+ const currentRank = getTierRank(currentTier);
204
+ const targetRank = getTierRank(tierId);
205
+ if (currentRank === targetRank) {
206
+ return formatMessage({ id: `${pluginId}.upgradePage.currentPlan`, defaultMessage: "Current Plan" });
207
+ } else if (targetRank > currentRank) {
208
+ return formatMessage({ id: `${pluginId}.upgrade.upgradeNow`, defaultMessage: "Upgrade Now" });
209
+ } else {
210
+ return formatMessage({ id: `${pluginId}.upgradePage.downgrade`, defaultMessage: "Downgrade" });
211
+ }
212
+ };
213
+ const tiers = [
214
+ {
215
+ id: "free",
216
+ name: "FREE",
217
+ price: "$0",
218
+ period: "forever",
219
+ description: "Perfect for small projects and testing",
220
+ icon: /* @__PURE__ */ jsx(Sparkle, {}),
221
+ color: "linear-gradient(135deg, #6B7280, #4B5563)",
222
+ features: [
223
+ { name: "10 Bookmarks", included: true },
224
+ { name: "Advanced Filters", included: true },
225
+ { name: "Role Sharing", included: true },
226
+ { name: "Drag & Drop", included: true },
227
+ { name: "Quick Access", included: true },
228
+ { name: "Query History", included: false },
229
+ { name: "Export Bookmarks", included: false },
230
+ { name: "Analytics", included: false },
231
+ { name: "Bulk Operations", included: false }
232
+ ],
233
+ limits: {
234
+ bookmarks: "10",
235
+ support: "Community"
236
+ }
237
+ },
238
+ {
239
+ id: "premium",
240
+ name: "PREMIUM",
241
+ price: "$14.50",
242
+ period: "/month",
243
+ description: "Enhanced features for growing teams",
244
+ icon: /* @__PURE__ */ jsx(Lightning, {}),
245
+ color: "linear-gradient(135deg, #8B5CF6, #7C3AED)",
246
+ featured: true,
247
+ features: [
248
+ { name: "50 Bookmarks", included: true },
249
+ { name: "Advanced Filters", included: true },
250
+ { name: "Role Sharing", included: true },
251
+ { name: "Drag & Drop", included: true },
252
+ { name: "Quick Access", included: true },
253
+ { name: "Query History", included: true },
254
+ { name: "Export Bookmarks", included: true },
255
+ { name: "Priority Support", included: true },
256
+ { name: "Analytics", included: false },
257
+ { name: "Bulk Operations", included: false }
258
+ ],
259
+ limits: {
260
+ bookmarks: "50",
261
+ support: "Priority"
262
+ }
263
+ },
264
+ {
265
+ id: "advanced",
266
+ name: "ADVANCED",
267
+ price: "$39.50",
268
+ period: "/month",
269
+ description: "Maximum features for power users",
270
+ icon: /* @__PURE__ */ jsx(Rocket, {}),
271
+ color: "linear-gradient(135deg, #0EA5E9, #0284C7)",
272
+ features: [
273
+ { name: "Unlimited Bookmarks", included: true },
274
+ { name: "Advanced Filters", included: true },
275
+ { name: "Role Sharing", included: true },
276
+ { name: "Drag & Drop", included: true },
277
+ { name: "Quick Access", included: true },
278
+ { name: "Query History", included: true },
279
+ { name: "Export Bookmarks", included: true },
280
+ { name: "Analytics Dashboard", included: true },
281
+ { name: "Bulk Operations", included: true },
282
+ { name: "Custom Integrations", included: true },
283
+ { name: "Priority + Phone Support", included: true }
284
+ ],
285
+ limits: {
286
+ bookmarks: "Unlimited",
287
+ support: "Priority + Phone"
288
+ }
289
+ }
290
+ ];
291
+ const handleUpgrade = (tierId) => {
292
+ window.open("https://store.magicdx.dev/", "_blank");
293
+ };
294
+ if (loading) {
295
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsx(Flex, { justifyContent: "center", alignItems: "center", style: { minHeight: "400px" }, children: /* @__PURE__ */ jsx(Typography, { children: formatMessage({ id: `${pluginId}.upgradePage.loading`, defaultMessage: "Loading license information..." }) }) }) });
296
+ }
297
+ return /* @__PURE__ */ jsxs(Container, { children: [
298
+ /* @__PURE__ */ jsxs(Header, { children: [
299
+ /* @__PURE__ */ jsx(Title, { variant: "alpha", children: formatMessage({ id: `${pluginId}.upgradePage.title`, defaultMessage: "Choose Your Plan" }) }),
300
+ /* @__PURE__ */ jsx(Subtitle, { variant: "omega", children: formatMessage({ id: `${pluginId}.upgradePage.subtitle`, defaultMessage: "Unlock powerful bookmarking features for your Strapi application" }) })
301
+ ] }),
302
+ /* @__PURE__ */ jsx(TierGrid, { children: tiers.map((tier) => /* @__PURE__ */ jsx(TierWrapper, { children: /* @__PURE__ */ jsxs(TierCard, { $featured: tier.featured, children: [
303
+ tier.featured && /* @__PURE__ */ jsx(PopularBadge, { children: formatMessage({ id: `${pluginId}.upgradePage.mostPopular`, defaultMessage: "MOST POPULAR" }) }),
304
+ /* @__PURE__ */ jsx(TierIcon, { $color: tier.color, children: tier.icon }),
305
+ /* @__PURE__ */ jsx(TierName, { variant: "beta", children: tier.name }),
306
+ /* @__PURE__ */ jsxs(Flex, { alignItems: "baseline", gap: 1, children: [
307
+ /* @__PURE__ */ jsx(TierPrice, { variant: "alpha", children: tier.price }),
308
+ /* @__PURE__ */ jsx(Typography, { variant: "omega", style: { color: "#6B7280" }, children: tier.period })
309
+ ] }),
310
+ /* @__PURE__ */ jsx(TierDescription, { variant: "omega", children: tier.description }),
311
+ /* @__PURE__ */ jsx(LimitsBox, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
312
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
313
+ /* @__PURE__ */ jsx("strong", { children: formatMessage({ id: `${pluginId}.upgradePage.bookmarks`, defaultMessage: "Bookmarks:" }) }),
314
+ " ",
315
+ tier.limits.bookmarks
316
+ ] }),
317
+ /* @__PURE__ */ jsxs(Typography, { variant: "pi", style: { fontSize: "13px" }, children: [
318
+ /* @__PURE__ */ jsx("strong", { children: formatMessage({ id: `${pluginId}.upgradePage.support`, defaultMessage: "Support:" }) }),
319
+ " ",
320
+ tier.limits.support
321
+ ] })
322
+ ] }) }),
323
+ /* @__PURE__ */ jsx(FeatureList, { children: tier.features.map((feature, index) => /* @__PURE__ */ jsxs(Feature, { children: [
324
+ /* @__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 } }) }),
325
+ /* @__PURE__ */ jsx(
326
+ Typography,
327
+ {
328
+ variant: "omega",
329
+ style: {
330
+ fontSize: "14px",
331
+ color: feature.included ? "#374151" : "#9CA3AF",
332
+ textDecoration: feature.included ? "none" : "line-through"
333
+ },
334
+ children: feature.name
335
+ }
336
+ )
337
+ ] }, index)) }),
338
+ currentTier === tier.id ? /* @__PURE__ */ jsx(CurrentPlanBadge, { children: formatMessage({ id: `${pluginId}.upgradePage.currentPlan`, defaultMessage: "CURRENT PLAN" }) }) : /* @__PURE__ */ jsx(
339
+ UpgradeButton,
340
+ {
341
+ onClick: () => handleUpgrade(tier.id),
342
+ $gradient: tier.color,
343
+ children: getButtonText(tier.id)
344
+ }
345
+ )
346
+ ] }) }, tier.id)) })
347
+ ] });
348
+ };
349
+ export {
350
+ UpgradePage as default
351
+ };