@reeboot/strapi-payment-plugin 0.0.0 → 0.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 (81) hide show
  1. package/README.md +398 -66
  2. package/dist/_chunks/Analytics-C2GKvPDX.js +355 -0
  3. package/dist/_chunks/Analytics-Chydh3dg.mjs +355 -0
  4. package/dist/_chunks/App-BCbEuN6h.mjs +68 -0
  5. package/dist/_chunks/App-E2k2mo5p.js +70 -0
  6. package/dist/_chunks/Customers-B8BlQ1BO.mjs +273 -0
  7. package/dist/_chunks/Customers-D0O5ET5C.js +273 -0
  8. package/dist/_chunks/Dashboard-CuqclLak.js +180 -0
  9. package/dist/_chunks/Dashboard-D8-ifJqB.mjs +180 -0
  10. package/dist/_chunks/Orders-5WGSzPGo.js +308 -0
  11. package/dist/_chunks/Orders-ClJJaQrX.mjs +308 -0
  12. package/dist/_chunks/Payments-CIMyOC3n.js +489 -0
  13. package/dist/_chunks/Payments-CRnRBf48.mjs +489 -0
  14. package/dist/_chunks/Settings-BXMLePI_.js +357 -0
  15. package/dist/_chunks/Settings-TeAvV4RH.mjs +357 -0
  16. package/dist/_chunks/en-BJocyOVu.mjs +240 -0
  17. package/dist/_chunks/en-BkVAf_R4.js +240 -0
  18. package/dist/_chunks/index-BTk7a2T5.js +66 -0
  19. package/dist/_chunks/index-Bz8V_5zH.mjs +67 -0
  20. package/dist/admin/index.js +2 -63
  21. package/dist/admin/index.mjs +2 -63
  22. package/dist/admin/src/components/AnalyticsChart.d.ts +19 -0
  23. package/dist/admin/src/components/CustomerList.d.ts +21 -0
  24. package/dist/admin/src/components/OrderList.d.ts +27 -0
  25. package/dist/admin/src/components/PaymentCard.d.ts +39 -0
  26. package/dist/admin/src/components/PaymentList.d.ts +19 -0
  27. package/dist/admin/src/components/RefundModal.d.ts +15 -0
  28. package/dist/admin/src/pages/Analytics.d.ts +2 -0
  29. package/dist/admin/src/pages/Customers.d.ts +2 -0
  30. package/dist/admin/src/pages/Dashboard.d.ts +2 -0
  31. package/dist/admin/src/pages/HomePage.d.ts +1 -1
  32. package/dist/admin/src/pages/Orders.d.ts +2 -0
  33. package/dist/admin/src/pages/Payments.d.ts +2 -0
  34. package/dist/admin/src/pages/Settings.d.ts +2 -0
  35. package/dist/server/index.js +1827 -7101
  36. package/dist/server/index.mjs +1826 -7100
  37. package/dist/server/src/config/index.d.ts +2 -10
  38. package/dist/server/src/content-types/customer/index.d.ts +69 -0
  39. package/dist/server/src/content-types/index.d.ts +207 -1
  40. package/dist/server/src/content-types/order/index.d.ts +70 -0
  41. package/dist/server/src/content-types/payment/index.d.ts +69 -0
  42. package/dist/server/src/controllers/controller.d.ts +6 -9
  43. package/dist/server/src/controllers/index.d.ts +30 -35
  44. package/dist/server/src/controllers/stripe.d.ts +104 -0
  45. package/dist/server/src/index.d.ts +262 -110
  46. package/dist/server/src/middlewares/index.d.ts +19 -1
  47. package/dist/server/src/policies/index.d.ts +3 -1
  48. package/dist/server/src/routes/{admin-routes.d.ts → admin/index.d.ts} +4 -4
  49. package/dist/server/src/routes/content-api/index.d.ts +21 -0
  50. package/dist/server/src/routes/index.d.ts +10 -26
  51. package/dist/server/src/services/index.d.ts +2 -37
  52. package/dist/server/src/services/{stripeDriver.d.ts → stripe.d.ts} +52 -28
  53. package/dist/server/src/types/index.d.ts +179 -0
  54. package/package.json +20 -24
  55. package/dist/_chunks/App-BGle38NN.js +0 -1149
  56. package/dist/_chunks/App-DoUUpjp-.mjs +0 -1149
  57. package/dist/_chunks/en-B4KWt_jN.js +0 -4
  58. package/dist/_chunks/en-Byx4XI2L.mjs +0 -4
  59. package/dist/admin/src/components/Header.d.ts +0 -2
  60. package/dist/admin/src/components/NavigationMenu.d.ts +0 -2
  61. package/dist/admin/src/components/Sidebar.d.ts +0 -2
  62. package/dist/admin/src/components/TransactionDetailsModal.d.ts +0 -18
  63. package/dist/admin/src/components/TransactionList.d.ts +0 -18
  64. package/dist/admin/src/pages/ConfigurationPage.d.ts +0 -2
  65. package/dist/admin/src/pages/DashboardPage.d.ts +0 -2
  66. package/dist/admin/src/pages/ProductsPage.d.ts +0 -2
  67. package/dist/admin/src/pages/SubscriptionsPage.d.ts +0 -2
  68. package/dist/admin/src/pages/TransactionsPage.d.ts +0 -2
  69. package/dist/server/controllers/product.d.ts +0 -12
  70. package/dist/server/controllers/subscription.d.ts +0 -12
  71. package/dist/server/services/product.d.ts +0 -7
  72. package/dist/server/services/subscription.d.ts +0 -7
  73. package/dist/server/src/controllers/productController.d.ts +0 -9
  74. package/dist/server/src/controllers/subscriptionController.d.ts +0 -9
  75. package/dist/server/src/routes/content-api.d.ts +0 -12
  76. package/dist/server/src/routes/product-routes.d.ts +0 -13
  77. package/dist/server/src/routes/refund-routes.d.ts +0 -13
  78. package/dist/server/src/routes/subscription-routes.d.ts +0 -13
  79. package/dist/server/src/services/paypalDriver.d.ts +0 -7
  80. package/dist/server/src/services/service.d.ts +0 -33
  81. package/jest.config.js +0 -13
@@ -1,1149 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const jsxRuntime = require("react/jsx-runtime");
4
- const admin = require("@strapi/strapi/admin");
5
- const reactRouterDom = require("react-router-dom");
6
- const react = require("react");
7
- const designSystem = require("@strapi/design-system");
8
- const formik = require("formik");
9
- const HomePage = () => {
10
- const [transactions, setTransactions] = react.useState([]);
11
- const [loading, setLoading] = react.useState(false);
12
- const [error, setError] = react.useState(null);
13
- const [stats, setStats] = react.useState({
14
- totalRevenue: 0,
15
- totalTransactions: 0,
16
- successRate: 0
17
- });
18
- const [searchTerm, setSearchTerm] = react.useState("");
19
- const [filter, setFilter] = react.useState("all");
20
- const fetchData = async () => {
21
- setLoading(true);
22
- setError(null);
23
- try {
24
- const response = await fetch("/payment-plugin/transactions");
25
- if (!response.ok) {
26
- throw new Error("Failed to fetch transactions");
27
- }
28
- const data = await response.json();
29
- setTransactions(data.data);
30
- const totalAmount = data.data.reduce(
31
- (sum, t) => sum + t.amount,
32
- 0
33
- );
34
- const successCount = data.data.filter(
35
- (t) => t.status === "completed"
36
- ).length;
37
- const successRate = data.data.length > 0 ? successCount / data.data.length * 100 : 0;
38
- setStats({
39
- totalRevenue: totalAmount,
40
- totalTransactions: data.data.length,
41
- successRate
42
- });
43
- } catch (err) {
44
- if (err instanceof Error) {
45
- setError(err.message);
46
- } else {
47
- setError("An unknown error occurred");
48
- }
49
- } finally {
50
- setLoading(false);
51
- }
52
- };
53
- react.useEffect(() => {
54
- fetchData();
55
- }, []);
56
- const handleSearch = (e) => {
57
- setSearchTerm(e.target.value);
58
- };
59
- const handleFilterChange = (e) => {
60
- setFilter(e.target.value);
61
- };
62
- const filteredTransactions = transactions.filter((transaction) => {
63
- const matchesSearch = [
64
- transaction.id,
65
- transaction.customer,
66
- transaction.amount.toString()
67
- ].some(
68
- (field) => field.toLowerCase().includes(searchTerm.toLowerCase())
69
- );
70
- const matchesFilter = filter === "all" || transaction.status === filter;
71
- return matchesSearch && matchesFilter;
72
- });
73
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
74
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Payment Plugin Home" }),
75
- /* @__PURE__ */ jsxRuntime.jsxs(
76
- designSystem.Box,
77
- {
78
- padding: 4,
79
- background: "neutral100",
80
- borderRadius: "4px",
81
- border: "1px solid #e0e0e0",
82
- style: { marginBottom: "2rem" },
83
- children: [
84
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Payment Statistics" }),
85
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading statistics..." }),
86
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "red" }, children: error }),
87
- !loading && !error && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, children: [
88
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
89
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Revenue" }),
90
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: [
91
- "$",
92
- stats.totalRevenue.toFixed(2)
93
- ] })
94
- ] }) }),
95
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
96
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Transactions" }),
97
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: stats.totalTransactions })
98
- ] }) }),
99
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
100
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Successful Payments" }),
101
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: [
102
- stats.successRate.toFixed(2),
103
- "%"
104
- ] })
105
- ] }) })
106
- ] })
107
- ]
108
- }
109
- ),
110
- /* @__PURE__ */ jsxRuntime.jsxs(
111
- designSystem.Box,
112
- {
113
- padding: 4,
114
- background: "neutral100",
115
- borderRadius: "4px",
116
- border: "1px solid #e0e0e0",
117
- children: [
118
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Transactions" }),
119
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "1rem", display: "flex", gap: "1rem", alignItems: "center", flexWrap: "wrap" }, children: [
120
- /* @__PURE__ */ jsxRuntime.jsx(
121
- designSystem.TextInput,
122
- {
123
- label: "Search Transactions",
124
- value: searchTerm,
125
- onChange: handleSearch,
126
- placeholder: "Search by ID, email, or amount",
127
- style: { flex: 1, minWidth: "200px" }
128
- }
129
- ),
130
- /* @__PURE__ */ jsxRuntime.jsxs("select", { value: filter, onChange: handleFilterChange, style: { minWidth: "150px" }, children: [
131
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Transactions" }),
132
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "completed", children: "Successful" }),
133
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "failed", children: "Failed" }),
134
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" })
135
- ] })
136
- ] }),
137
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { overflowX: "auto" }, children: [
138
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading transactions..." }),
139
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "red" }, children: error }),
140
- !loading && !error && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filteredTransactions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { children: [
141
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
142
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "ID" }),
143
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Amount" }),
144
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Currency" }),
145
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Status" }),
146
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Date" }),
147
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Customer" })
148
- ] }) }),
149
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: filteredTransactions.map((transaction) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
150
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.id }),
151
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { children: [
152
- "$",
153
- transaction.amount.toFixed(2)
154
- ] }),
155
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.currency }),
156
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.status }),
157
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: new Date(transaction.date).toLocaleDateString() }),
158
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.customer })
159
- ] }, transaction.id)) })
160
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No transactions found" }) })
161
- ] })
162
- ]
163
- }
164
- )
165
- ] });
166
- };
167
- const ConfigurationPage = () => {
168
- const [stripeSecretKey, setStripeSecretKey] = react.useState("");
169
- const [stripePublishableKey, setStripePublishableKey] = react.useState("");
170
- const [stripeWebhookSecret, setStripeWebhookSecret] = react.useState("");
171
- const [paypalClientId, setPaypalClientId] = react.useState("");
172
- const [paypalClientSecret, setPaypalClientSecret] = react.useState("");
173
- const [paypalWebhookId, setPaypalWebhookId] = react.useState("");
174
- const [configStatus, setConfigStatus] = react.useState({
175
- stripe: false,
176
- paypal: false
177
- });
178
- react.useEffect(() => {
179
- const fetchConfigStatus = async () => {
180
- try {
181
- const response = await fetch("/payment-plugin/config-status");
182
- if (response.ok) {
183
- const data = await response.json();
184
- setConfigStatus(data);
185
- }
186
- } catch (error) {
187
- console.error("Failed to fetch config status:", error);
188
- }
189
- };
190
- fetchConfigStatus();
191
- }, []);
192
- const handleSave = async () => {
193
- const response = await fetch("/payment-plugin/config", {
194
- method: "POST",
195
- headers: {
196
- "Content-Type": "application/json"
197
- },
198
- body: JSON.stringify({
199
- stripe: {
200
- secretKey: stripeSecretKey,
201
- publishableKey: stripePublishableKey,
202
- webhookSecret: stripeWebhookSecret
203
- },
204
- paypal: {
205
- clientId: paypalClientId,
206
- clientSecret: paypalClientSecret,
207
- webhookId: paypalWebhookId
208
- }
209
- })
210
- });
211
- if (response.ok) {
212
- alert("Configuration saved successfully");
213
- } else {
214
- alert("Failed to save configuration");
215
- }
216
- };
217
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
218
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { title: "Payment Plugin Configuration" }),
219
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
220
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Payment Configuration" }),
221
- /* @__PURE__ */ jsxRuntime.jsxs(
222
- designSystem.Box,
223
- {
224
- padding: 4,
225
- background: "neutral100",
226
- borderRadius: "4px",
227
- border: "1px solid #e0e0e0",
228
- style: { marginBottom: "2rem" },
229
- children: [
230
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Payment Configuration" }),
231
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, style: { marginBottom: "2rem" }, children: [
232
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
233
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "gamma", as: "h3", textColor: "neutral800", children: "Stripe Status  " }),
234
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", children: [
235
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
236
- width: "10px",
237
- height: "10px",
238
- borderRadius: "50%",
239
- backgroundColor: configStatus.stripe ? "green" : "red",
240
- marginRight: "8px"
241
- } }),
242
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: configStatus.stripe ? "success600" : "danger600", children: configStatus.stripe ? "Connected" : "Not Connected" })
243
- ] })
244
- ] }) }),
245
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { justifyContent: "space-between", alignItems: "center", children: [
246
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "gamma", as: "h3", textColor: "neutral800", children: "PayPal Status  " }),
247
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { alignItems: "center", children: [
248
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
249
- width: "10px",
250
- height: "10px",
251
- borderRadius: "50%",
252
- backgroundColor: configStatus.paypal ? "green" : "red",
253
- marginRight: "8px"
254
- } }),
255
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", fontWeight: "bold", textColor: configStatus.paypal ? "success600" : "danger600", children: configStatus.paypal ? "Connected" : "Not Connected" })
256
- ] })
257
- ] }) })
258
- ] }),
259
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 6, children: [
260
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(
261
- designSystem.Box,
262
- {
263
- padding: 6,
264
- background: "neutral0",
265
- borderRadius: "4px",
266
- border: "1px solid #e0e0e0",
267
- style: { marginBottom: "1rem", width: "100%" },
268
- children: [
269
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "gamma", as: "h3", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Stripe Configuration" }),
270
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 8, alignItems: "initial", children: [
271
- /* @__PURE__ */ jsxRuntime.jsx(
272
- designSystem.TextInput,
273
- {
274
- placeholder: "Secret Key",
275
- name: "stripeSecretKey",
276
- value: stripeSecretKey,
277
- onChange: (e) => setStripeSecretKey(e.target.value),
278
- type: "password",
279
- disabled: configStatus.stripe,
280
- style: {
281
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
282
- },
283
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
284
- }
285
- ),
286
- /* @__PURE__ */ jsxRuntime.jsx(
287
- designSystem.TextInput,
288
- {
289
- placeholder: "Publishable Key",
290
- name: "stripePublishableKey",
291
- value: stripePublishableKey,
292
- onChange: (e) => setStripePublishableKey(e.target.value),
293
- disabled: configStatus.stripe,
294
- style: {
295
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
296
- },
297
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
298
- }
299
- ),
300
- /* @__PURE__ */ jsxRuntime.jsx(
301
- designSystem.TextInput,
302
- {
303
- placeholder: "Webhook Secret",
304
- name: "stripeWebhookSecret",
305
- value: stripeWebhookSecret,
306
- onChange: (e) => setStripeWebhookSecret(e.target.value),
307
- type: "password",
308
- disabled: configStatus.stripe,
309
- style: {
310
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
311
- },
312
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
313
- }
314
- )
315
- ] })
316
- ]
317
- }
318
- ) }),
319
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(
320
- designSystem.Box,
321
- {
322
- padding: 6,
323
- background: "neutral0",
324
- borderRadius: "4px",
325
- border: "1px solid #e0e0e0",
326
- style: { marginBottom: "1rem", width: "100%" },
327
- children: [
328
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "gamma", as: "h3", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "PayPal Configuration" }),
329
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 8, alignItems: "initial", children: [
330
- /* @__PURE__ */ jsxRuntime.jsx(
331
- designSystem.TextInput,
332
- {
333
- placeholder: "Client ID",
334
- name: "paypalClientId",
335
- value: paypalClientId,
336
- onChange: (e) => setPaypalClientId(e.target.value),
337
- disabled: configStatus.paypal,
338
- style: {
339
- border: configStatus.paypal ? "2px solid #4CAF50" : "",
340
- width: "100%"
341
- },
342
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
343
- }
344
- ),
345
- /* @__PURE__ */ jsxRuntime.jsx(
346
- designSystem.TextInput,
347
- {
348
- placeholder: "Client Secret",
349
- name: "paypalClientSecret",
350
- value: paypalClientSecret,
351
- onChange: (e) => setPaypalClientSecret(e.target.value),
352
- type: "password",
353
- disabled: configStatus.paypal,
354
- style: {
355
- border: configStatus.paypal ? "2px solid #4CAF50" : ""
356
- },
357
- width: "80%",
358
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
359
- }
360
- ),
361
- /* @__PURE__ */ jsxRuntime.jsx(
362
- designSystem.TextInput,
363
- {
364
- placeholder: "Webhook ID",
365
- name: "paypalWebhookId",
366
- value: paypalWebhookId,
367
- onChange: (e) => setPaypalWebhookId(e.target.value),
368
- disabled: configStatus.paypal,
369
- style: {
370
- border: configStatus.paypal ? "2px solid #4CAF50" : ""
371
- },
372
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
373
- }
374
- )
375
- ] })
376
- ]
377
- }
378
- ) })
379
- ] }),
380
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: handleSave, style: { marginTop: "1rem" }, children: "Save Configuration" })
381
- ]
382
- }
383
- )
384
- ] }) })
385
- ] });
386
- };
387
- const TransactionList = ({ transactions, onViewDetails, onStatusUpdate }) => {
388
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { children: [
389
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
390
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "ID" }),
391
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Amount" }),
392
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Currency" }),
393
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Status" }),
394
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Date" }),
395
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Customer" }),
396
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: "Actions" })
397
- ] }) }),
398
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: transactions.map((transaction) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
399
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.id }),
400
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Td, { children: [
401
- "$",
402
- transaction.amount.toFixed(2)
403
- ] }),
404
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.currency }),
405
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: onStatusUpdate ? /* @__PURE__ */ jsxRuntime.jsxs(
406
- designSystem.SingleSelect,
407
- {
408
- value: transaction.status,
409
- onChange: (e) => onStatusUpdate(transaction.id, e.target.value),
410
- style: { minWidth: "120px" },
411
- children: [
412
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pending", children: "Pending" }),
413
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "completed", children: "Completed" }),
414
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "failed", children: "Failed" }),
415
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "refunded", children: "Refunded" })
416
- ]
417
- }
418
- ) : transaction.status }),
419
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: new Date(transaction.date).toLocaleDateString() }),
420
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: transaction.customer }),
421
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", size: "S", onClick: () => onViewDetails(transaction), children: "View" }) })
422
- ] }, transaction.id)) })
423
- ] });
424
- };
425
- const TransactionDetailsModal = ({
426
- isOpen,
427
- onClose,
428
- transaction,
429
- onRefund
430
- }) => {
431
- if (!transaction) return null;
432
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Root, { open: isOpen, onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { onClick: onClose, children: [
433
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: "Transaction Details" }) }),
434
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, children: [
435
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: "Details" }),
436
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { style: { marginTop: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 2, children: [
437
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
438
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Amount:" }),
439
- " $",
440
- transaction.amount.toFixed(2),
441
- " ",
442
- transaction.currency
443
- ] }),
444
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
445
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Status:" }),
446
- " ",
447
- transaction.status
448
- ] }),
449
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
450
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Date:" }),
451
- " ",
452
- new Date(transaction.date).toLocaleString()
453
- ] }),
454
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
455
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Customer:" }),
456
- " ",
457
- transaction.customer
458
- ] }),
459
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
460
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Payment Method:" }),
461
- " ",
462
- transaction.paymentMethod
463
- ] }),
464
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
465
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Gateway:" }),
466
- " ",
467
- transaction.gateway
468
- ] })
469
- ] }) }),
470
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { style: { marginTop: "2rem", gap: "1rem" }, children: [
471
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", onClick: onClose, children: "Close" }),
472
- transaction.status === "completed" && transaction.gateway !== "paypal" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger", onClick: onRefund, style: { marginLeft: "auto" }, children: "Refund" })
473
- ] })
474
- ] }) })
475
- ] }) });
476
- };
477
- const TransactionsPage = () => {
478
- const [searchTerm, setSearchTerm] = react.useState("");
479
- const [filter, setFilter] = react.useState("all");
480
- const [transactions, setTransactions] = react.useState([]);
481
- const [loading, setLoading] = react.useState(false);
482
- const [error, setError] = react.useState(null);
483
- const [selectedTransaction, setSelectedTransaction] = react.useState(null);
484
- const [isModalOpen, setIsModalOpen] = react.useState(false);
485
- const handleSearch = (e) => {
486
- setSearchTerm(e.target.value);
487
- };
488
- const handleFilterChange = (value) => {
489
- setFilter(value);
490
- };
491
- const fetchTransactions = async () => {
492
- setLoading(true);
493
- setError(null);
494
- try {
495
- const response = await fetch("/payment-plugin/transactions");
496
- if (!response.ok) {
497
- throw new Error("Failed to fetch transactions");
498
- }
499
- const data = await response.json();
500
- setTransactions(data.data);
501
- } catch (err) {
502
- if (err instanceof Error) {
503
- setError(err.message);
504
- } else {
505
- setError("An unknown error occurred");
506
- }
507
- } finally {
508
- setLoading(false);
509
- }
510
- };
511
- react.useEffect(() => {
512
- fetchTransactions();
513
- }, []);
514
- const filteredTransactions = transactions.filter((transaction) => {
515
- const matchesSearch = [
516
- transaction.id,
517
- transaction.customer,
518
- transaction.amount.toString()
519
- ].some(
520
- (field) => field.toLowerCase().includes(searchTerm.toLowerCase())
521
- );
522
- const matchesFilter = filter === "all" || transaction.status === filter;
523
- return matchesSearch && matchesFilter;
524
- });
525
- const handleViewDetails = (transaction) => {
526
- setSelectedTransaction(transaction);
527
- setIsModalOpen(true);
528
- };
529
- const handleRefund = async () => {
530
- if (!selectedTransaction) return;
531
- try {
532
- const response = await fetch("/payment-plugin/refund", {
533
- method: "POST",
534
- headers: {
535
- "Content-Type": "application/json"
536
- },
537
- body: JSON.stringify({
538
- gateway: selectedTransaction.gateway,
539
- transactionId: selectedTransaction.id,
540
- amount: selectedTransaction.amount
541
- })
542
- });
543
- if (!response.ok) {
544
- throw new Error("Failed to process refund");
545
- }
546
- const result = await response.json();
547
- if (result.success) {
548
- setTransactions(transactions.map(
549
- (t) => t.id === selectedTransaction.id ? { ...t, status: "refunded" } : t
550
- ));
551
- setIsModalOpen(false);
552
- } else {
553
- throw new Error(result.message || "Refund failed");
554
- }
555
- } catch (err) {
556
- if (err instanceof Error) {
557
- setError(err.message);
558
- } else {
559
- setError("An unknown error occurred");
560
- }
561
- }
562
- };
563
- const handleStatusUpdate = async (transactionId, newStatus) => {
564
- try {
565
- setTransactions(transactions.map(
566
- (t) => t.id === transactionId ? { ...t, status: newStatus } : t
567
- ));
568
- } catch (err) {
569
- if (err instanceof Error) {
570
- setError(err.message);
571
- } else {
572
- setError("An unknown error occurred");
573
- }
574
- }
575
- };
576
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
577
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { title: "Transactions" }),
578
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
579
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Transactions" }),
580
- error && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
581
- /* @__PURE__ */ jsxRuntime.jsxs(
582
- designSystem.Box,
583
- {
584
- padding: 4,
585
- background: "neutral100",
586
- borderRadius: "4px",
587
- border: "1px solid #e0e0e0",
588
- children: [
589
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Transaction List" }),
590
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: "1rem", display: "flex", gap: "1rem", alignItems: "center", flexWrap: "wrap" }, children: [
591
- /* @__PURE__ */ jsxRuntime.jsx(
592
- designSystem.TextInput,
593
- {
594
- label: "Search Transactions",
595
- value: searchTerm,
596
- onChange: handleSearch,
597
- placeholder: "Search by ID, email, or amount",
598
- style: { flex: 1, minWidth: "200px" }
599
- }
600
- ),
601
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.SingleSelect, { value: filter, onChange: handleFilterChange, style: { minWidth: "150px" }, children: [
602
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "all", children: "All Transactions" }),
603
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "completed", children: "Successful" }),
604
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "failed", children: "Failed" }),
605
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "pending", children: "Pending" }),
606
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "refunded", children: "Refunded" })
607
- ] })
608
- ] }),
609
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
610
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading transactions..." }),
611
- !loading && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: filteredTransactions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
612
- TransactionList,
613
- {
614
- transactions: filteredTransactions,
615
- onViewDetails: handleViewDetails,
616
- onStatusUpdate: handleStatusUpdate
617
- }
618
- ) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No transactions found" }) })
619
- ] })
620
- ]
621
- }
622
- )
623
- ] }),
624
- /* @__PURE__ */ jsxRuntime.jsx(
625
- TransactionDetailsModal,
626
- {
627
- isOpen: isModalOpen,
628
- onClose: () => setIsModalOpen(false),
629
- transaction: selectedTransaction,
630
- onRefund: handleRefund
631
- }
632
- )
633
- ] });
634
- };
635
- const DashboardPage = () => {
636
- const [transactions, setTransactions] = react.useState([]);
637
- const [loading, setLoading] = react.useState(false);
638
- const [error, setError] = react.useState(null);
639
- const [stats, setStats] = react.useState({
640
- totalRevenue: 0,
641
- totalTransactions: 0,
642
- successRate: 0
643
- });
644
- const fetchData = async () => {
645
- setLoading(true);
646
- setError(null);
647
- try {
648
- const response = await fetch("/payment-plugin/transactions");
649
- if (!response.ok) {
650
- throw new Error("Failed to fetch transactions");
651
- }
652
- const data = await response.json();
653
- setTransactions(data.data.slice(0, 5));
654
- const totalAmount = data.data.reduce(
655
- (sum, t) => sum + t.amount,
656
- 0
657
- );
658
- const successCount = data.data.filter(
659
- (t) => t.status === "completed"
660
- ).length;
661
- const successRate = data.data.length > 0 ? successCount / data.data.length * 100 : 0;
662
- setStats({
663
- totalRevenue: totalAmount,
664
- totalTransactions: data.data.length,
665
- successRate
666
- });
667
- } catch (err) {
668
- if (err instanceof Error) {
669
- setError(err.message);
670
- } else {
671
- setError("An unknown error occurred");
672
- }
673
- } finally {
674
- setLoading(false);
675
- }
676
- };
677
- react.useEffect(() => {
678
- fetchData();
679
- }, []);
680
- return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Main, { children: [
681
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { title: "Payment Dashboard" }),
682
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
683
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Payment Dashboard" }),
684
- /* @__PURE__ */ jsxRuntime.jsxs(
685
- designSystem.Box,
686
- {
687
- padding: 4,
688
- background: "neutral100",
689
- borderRadius: "4px",
690
- border: "1px solid #e0e0e0",
691
- style: { marginBottom: "2rem" },
692
- children: [
693
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Payment Statistics" }),
694
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading statistics..." }),
695
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "red" }, children: error }),
696
- !loading && !error && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, children: [
697
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
698
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Revenue" }),
699
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: [
700
- "$",
701
- stats.totalRevenue.toFixed(2)
702
- ] })
703
- ] }) }),
704
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
705
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Transactions" }),
706
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: stats.totalTransactions })
707
- ] }) }),
708
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 4, background: "neutral0", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
709
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral800", children: "Successful Payments" }),
710
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "alpha", textColor: "primary600", children: [
711
- stats.successRate.toFixed(2),
712
- "%"
713
- ] })
714
- ] }) })
715
- ] })
716
- ]
717
- }
718
- ),
719
- /* @__PURE__ */ jsxRuntime.jsxs(
720
- designSystem.Box,
721
- {
722
- padding: 4,
723
- background: "neutral100",
724
- borderRadius: "4px",
725
- border: "1px solid #e0e0e0",
726
- children: [
727
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Recent Transactions" }),
728
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading transactions..." }),
729
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "red" }, children: error }),
730
- !loading && !error && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: transactions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(TransactionList, { transactions, onViewDetails: () => {
731
- } }) : /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No recent transactions" }) })
732
- ]
733
- }
734
- )
735
- ] })
736
- ] });
737
- };
738
- const ProductsPage = () => {
739
- const [products, setProducts] = react.useState([]);
740
- const [loading, setLoading] = react.useState(false);
741
- const [error, setError] = react.useState(null);
742
- const [isModalOpen, setIsModalOpen] = react.useState(false);
743
- const [currentProduct, setCurrentProduct] = react.useState(null);
744
- const fetchProducts = async () => {
745
- setLoading(true);
746
- setError(null);
747
- try {
748
- const response = await fetch("/payment-plugin/products");
749
- if (!response.ok) {
750
- throw new Error("Failed to fetch products");
751
- }
752
- const data = await response.json();
753
- setProducts(data);
754
- } catch (err) {
755
- if (err instanceof Error) {
756
- setError(err.message);
757
- } else {
758
- setError("An unknown error occurred");
759
- }
760
- } finally {
761
- setLoading(false);
762
- }
763
- };
764
- react.useEffect(() => {
765
- fetchProducts();
766
- }, []);
767
- const handleEdit = (product) => {
768
- setCurrentProduct(product);
769
- setIsModalOpen(true);
770
- };
771
- const handleDelete = async (id) => {
772
- if (confirm("Are you sure you want to delete this product?")) {
773
- try {
774
- const response = await fetch(`/payment-plugin/products/${id}`, {
775
- method: "DELETE"
776
- });
777
- if (!response.ok) {
778
- throw new Error("Failed to delete product");
779
- }
780
- fetchProducts();
781
- } catch (err) {
782
- if (err instanceof Error) {
783
- setError(err.message);
784
- } else {
785
- setError("An unknown error occurred");
786
- }
787
- }
788
- }
789
- };
790
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
791
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Products" }),
792
- error && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
793
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading products..." }),
794
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Root, { children: [
795
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { children: "Create product" }) }),
796
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
797
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Header, { children: [
798
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: currentProduct ? currentProduct.id ? "Edit Product" : "Create Product" : "Product" }),
799
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.CloseButton, {})
800
- ] }),
801
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, {})
802
- ] })
803
- ] }),
804
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: products.map((product) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(
805
- designSystem.Box,
806
- {
807
- padding: 4,
808
- background: "neutral100",
809
- borderRadius: "4px",
810
- border: "1px solid #e0e0e0",
811
- children: [
812
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: product.name }),
813
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
814
- product.price,
815
- " ",
816
- product.currency,
817
- " ",
818
- product.isSubscription ? `/ ${product.subscriptionInterval}` : ""
819
- ] }),
820
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral600", style: { marginTop: "1rem" }, children: product.description }),
821
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { style: { marginTop: "1rem", gap: "1rem" }, children: [
822
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", onClick: () => handleEdit(product), children: "Edit" }),
823
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger", onClick: () => handleDelete(product.id), children: "Delete" })
824
- ] })
825
- ]
826
- },
827
- product.id
828
- ) }, product.id)) })
829
- ] }) });
830
- };
831
- const SubscriptionsPage = () => {
832
- const [subscriptions, setSubscriptions] = react.useState([]);
833
- const [products, setProducts] = react.useState([]);
834
- const [loading, setLoading] = react.useState(false);
835
- const [error, setError] = react.useState(null);
836
- const [isModalOpen, setIsModalOpen] = react.useState(false);
837
- const [currentSubscription, setCurrentSubscription] = react.useState(null);
838
- const fetchSubscriptions = async () => {
839
- setLoading(true);
840
- setError(null);
841
- try {
842
- const response = await fetch("/payment-plugin/subscriptions");
843
- if (!response.ok) {
844
- throw new Error("Failed to fetch subscriptions");
845
- }
846
- const data = await response.json();
847
- setSubscriptions(data);
848
- } catch (err) {
849
- if (err instanceof Error) {
850
- setError(err.message);
851
- } else {
852
- setError("An unknown error occurred");
853
- }
854
- } finally {
855
- setLoading(false);
856
- }
857
- };
858
- const fetchProducts = async () => {
859
- try {
860
- const response = await fetch("/payment-plugin/products");
861
- if (!response.ok) {
862
- throw new Error("Failed to fetch products");
863
- }
864
- const data = await response.json();
865
- setProducts(data);
866
- } catch (err) {
867
- console.error("Failed to fetch products:", err);
868
- }
869
- };
870
- react.useEffect(() => {
871
- fetchSubscriptions();
872
- fetchProducts();
873
- }, []);
874
- const handleEdit = (subscription) => {
875
- setCurrentSubscription(subscription);
876
- setIsModalOpen(true);
877
- };
878
- const handleDelete = async (id) => {
879
- if (confirm("Are you sure you want to delete this subscription?")) {
880
- try {
881
- const response = await fetch(`/payment-plugin/subscriptions/${id}`, {
882
- method: "DELETE"
883
- });
884
- if (!response.ok) {
885
- throw new Error("Failed to delete subscription");
886
- }
887
- fetchSubscriptions();
888
- } catch (err) {
889
- if (err instanceof Error) {
890
- setError(err.message);
891
- } else {
892
- setError("An unknown error occurred");
893
- }
894
- }
895
- }
896
- };
897
- const handleSubmit = async (values) => {
898
- if (!currentSubscription) return;
899
- try {
900
- const method = currentSubscription.id ? "PUT" : "POST";
901
- const url = currentSubscription.id ? `/payment-plugin/subscriptions/${currentSubscription.id}` : "/payment-plugin/subscriptions";
902
- const response = await fetch(url, {
903
- method,
904
- headers: {
905
- "Content-Type": "application/json"
906
- },
907
- body: JSON.stringify({ data: values })
908
- });
909
- if (!response.ok) {
910
- throw new Error(`Failed to ${currentSubscription.id ? "update" : "create"} subscription`);
911
- }
912
- setIsModalOpen(false);
913
- fetchSubscriptions();
914
- } catch (err) {
915
- if (err instanceof Error) {
916
- setError(err.message);
917
- } else {
918
- setError("An unknown error occurred");
919
- }
920
- }
921
- };
922
- return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Main, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 6, background: "neutral0", children: [
923
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Subscriptions" }),
924
- error && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
925
- loading && /* @__PURE__ */ jsxRuntime.jsx("p", { children: "Loading subscriptions..." }),
926
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Root, { children: [
927
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { children: "Create subscription" }) }),
928
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { children: [
929
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Title, { children: currentSubscription ? currentSubscription.id ? "Edit Subscription" : "Create Subscription" : "Subscription" }) }),
930
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
931
- formik.Formik,
932
- {
933
- initialValues: {
934
- id: currentSubscription?.id || 0,
935
- product: currentSubscription?.product || { id: 0, name: "" },
936
- user: currentSubscription?.user || { id: 0, email: "" },
937
- status: currentSubscription?.status || "active",
938
- startDate: currentSubscription?.startDate || (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
939
- endDate: currentSubscription?.endDate || ""
940
- },
941
- onSubmit: handleSubmit,
942
- children: ({ values, handleChange, setFieldValue }) => /* @__PURE__ */ jsxRuntime.jsx(formik.Form, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, children: [
943
- /* @__PURE__ */ jsxRuntime.jsxs(
944
- designSystem.SingleSelect,
945
- {
946
- placeholder: "Product",
947
- name: "product.id",
948
- value: values.product.id || "",
949
- onChange: (e) => {
950
- const selectedProduct = products.find(
951
- (p) => p.id === parseInt(e.target.value)
952
- );
953
- setFieldValue("product", selectedProduct || { id: 0, name: "" });
954
- },
955
- required: true,
956
- children: [
957
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select a product" }),
958
- products.map((product) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: product.id, children: product.name }, product.id))
959
- ]
960
- }
961
- ),
962
- /* @__PURE__ */ jsxRuntime.jsx(
963
- designSystem.TextInput,
964
- {
965
- placeholder: "User Email",
966
- name: "user.email",
967
- value: values.user.email,
968
- onChange: handleChange,
969
- required: true
970
- }
971
- ),
972
- /* @__PURE__ */ jsxRuntime.jsxs(
973
- designSystem.SingleSelect,
974
- {
975
- placeholder: "Status",
976
- name: "status",
977
- value: values.status,
978
- onChange: handleChange,
979
- children: [
980
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "active", children: "Active" }),
981
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "canceled", children: "Canceled" }),
982
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "past_due", children: "Past Due" }),
983
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "unpaid", children: "Unpaid" }),
984
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "trialing", children: "Trialing" })
985
- ]
986
- }
987
- ),
988
- /* @__PURE__ */ jsxRuntime.jsx(
989
- designSystem.TextInput,
990
- {
991
- placeholder: "Start Date",
992
- name: "startDate",
993
- type: "date",
994
- value: values.startDate,
995
- onChange: handleChange,
996
- required: true
997
- }
998
- ),
999
- /* @__PURE__ */ jsxRuntime.jsx(
1000
- designSystem.TextInput,
1001
- {
1002
- placeholder: "End Date",
1003
- name: "endDate",
1004
- type: "date",
1005
- value: values.endDate,
1006
- onChange: handleChange
1007
- }
1008
- ),
1009
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", style: { marginTop: "1rem" }, children: currentSubscription?.id ? "Update" : "Create" })
1010
- ] }) })
1011
- }
1012
- ) }) })
1013
- ] })
1014
- ] }),
1015
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: subscriptions.map((subscription) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(
1016
- designSystem.Box,
1017
- {
1018
- padding: 4,
1019
- background: "neutral100",
1020
- borderRadius: "4px",
1021
- border: "1px solid #e0e0e0",
1022
- children: [
1023
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: subscription.product.name }),
1024
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
1025
- "User: ",
1026
- subscription.user.email
1027
- ] }),
1028
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
1029
- "Status: ",
1030
- subscription.status
1031
- ] }),
1032
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
1033
- "Start Date: ",
1034
- subscription.startDate
1035
- ] }),
1036
- subscription.endDate && /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral600", children: [
1037
- "End Date: ",
1038
- subscription.endDate
1039
- ] }),
1040
- /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { style: { marginTop: "1rem", gap: "1rem" }, children: [
1041
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", onClick: () => handleEdit(subscription), children: "Edit" }),
1042
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "danger", onClick: () => handleDelete(subscription.id), children: "Delete" })
1043
- ] })
1044
- ]
1045
- },
1046
- subscription.id
1047
- ) }, subscription.id)) })
1048
- ] }) });
1049
- };
1050
- const NavigationMenu = () => {
1051
- return /* @__PURE__ */ jsxRuntime.jsxs(
1052
- designSystem.Box,
1053
- {
1054
- background: "neutral100",
1055
- padding: 4,
1056
- width: "200px",
1057
- height: "100vh",
1058
- position: "fixed",
1059
- top: 0,
1060
- left: 100,
1061
- children: [
1062
- /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", as: "h1", style: { marginBottom: "2rem" }, children: "Payment Plugin" }),
1063
- /* @__PURE__ */ jsxRuntime.jsx("nav", { children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { style: { listStyle: "none", padding: 0, fontSize: "14px" }, children: [
1064
- /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1065
- reactRouterDom.NavLink,
1066
- {
1067
- to: "/plugins/payment-plugin/",
1068
- style: ({ isActive }) => ({
1069
- color: isActive ? "#7b79ff" : "inherit",
1070
- textDecoration: "none"
1071
- }),
1072
- children: "Home"
1073
- }
1074
- ) }),
1075
- /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1076
- reactRouterDom.NavLink,
1077
- {
1078
- to: "/plugins/payment-plugin/dashboard",
1079
- style: ({ isActive }) => ({
1080
- color: isActive ? "#7b79ff" : "inherit",
1081
- textDecoration: "none"
1082
- }),
1083
- children: "Dashboard"
1084
- }
1085
- ) }),
1086
- /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1087
- reactRouterDom.NavLink,
1088
- {
1089
- to: "/plugins/payment-plugin/transactions",
1090
- style: ({ isActive }) => ({
1091
- color: isActive ? "#7b79ff" : "inherit",
1092
- textDecoration: "none"
1093
- }),
1094
- children: "Transactions"
1095
- }
1096
- ) }),
1097
- /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1098
- reactRouterDom.NavLink,
1099
- {
1100
- to: "/plugins/payment-plugin/products",
1101
- style: ({ isActive }) => ({
1102
- color: isActive ? "#7b79ff" : "inherit",
1103
- textDecoration: "none"
1104
- }),
1105
- children: "Products"
1106
- }
1107
- ) }),
1108
- /* @__PURE__ */ jsxRuntime.jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1109
- reactRouterDom.NavLink,
1110
- {
1111
- to: "/plugins/payment-plugin/subscriptions",
1112
- style: ({ isActive }) => ({
1113
- color: isActive ? "#7b79ff" : "inherit",
1114
- textDecoration: "none"
1115
- }),
1116
- children: "Subscriptions"
1117
- }
1118
- ) }),
1119
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
1120
- reactRouterDom.NavLink,
1121
- {
1122
- to: "/plugins/payment-plugin/configuration",
1123
- style: ({ isActive }) => ({
1124
- color: isActive ? "#7b79ff" : "inherit",
1125
- textDecoration: "none"
1126
- }),
1127
- children: "Configuration"
1128
- }
1129
- ) })
1130
- ] }) })
1131
- ]
1132
- }
1133
- );
1134
- };
1135
- const App = () => {
1136
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex" }, children: [
1137
- /* @__PURE__ */ jsxRuntime.jsx(NavigationMenu, {}),
1138
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginLeft: "200px", flex: 1 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
1139
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }),
1140
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/dashboard", element: /* @__PURE__ */ jsxRuntime.jsx(DashboardPage, {}) }),
1141
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/transactions", element: /* @__PURE__ */ jsxRuntime.jsx(TransactionsPage, {}) }),
1142
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/products", element: /* @__PURE__ */ jsxRuntime.jsx(ProductsPage, {}) }),
1143
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/subscriptions", element: /* @__PURE__ */ jsxRuntime.jsx(SubscriptionsPage, {}) }),
1144
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "/configuration", element: /* @__PURE__ */ jsxRuntime.jsx(ConfigurationPage, {}) }),
1145
- /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
1146
- ] }) })
1147
- ] });
1148
- };
1149
- exports.App = App;