@reeboot/strapi-payment-plugin 0.0.1 → 0.0.3

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 (84) hide show
  1. package/README.md +378 -119
  2. package/dist/_chunks/Analytics-DSJqY9ng.mjs +355 -0
  3. package/dist/_chunks/Analytics-nBSdLT2v.js +355 -0
  4. package/dist/_chunks/App-B83DZ9NG.js +70 -0
  5. package/dist/_chunks/App-BUSTbkyy.mjs +68 -0
  6. package/dist/_chunks/Customers-BpFzfglV.js +273 -0
  7. package/dist/_chunks/Customers-C6FH7-zG.mjs +273 -0
  8. package/dist/_chunks/Dashboard-CNMTzSyc.js +180 -0
  9. package/dist/_chunks/Dashboard-Dbwl0ZBo.mjs +180 -0
  10. package/dist/_chunks/Orders-CBkT2YfP.mjs +308 -0
  11. package/dist/_chunks/Orders-OG-pwV-B.js +308 -0
  12. package/dist/_chunks/Payments-BLen1P9N.js +489 -0
  13. package/dist/_chunks/Payments-DSDJ-HWm.mjs +489 -0
  14. package/dist/_chunks/Settings-Dq1xy32B.js +357 -0
  15. package/dist/_chunks/Settings-jmGslDsB.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-BqqrpI6D.js +66 -0
  19. package/dist/_chunks/index-DS_PYNkf.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/admin/src/pluginId.d.ts +1 -1
  36. package/dist/server/index.js +1770 -992
  37. package/dist/server/index.mjs +1773 -995
  38. package/dist/server/src/bootstrap.d.ts +5 -11
  39. package/dist/server/src/config/index.d.ts +0 -10
  40. package/dist/server/src/content-types/customer/index.d.ts +69 -0
  41. package/dist/server/src/content-types/index.d.ts +123 -39
  42. package/dist/server/src/content-types/{product.d.ts → order/index.d.ts} +26 -19
  43. package/dist/server/src/content-types/{subscription.d.ts → payment/index.d.ts} +30 -21
  44. package/dist/server/src/controllers/controller.d.ts +5 -12
  45. package/dist/server/src/controllers/index.d.ts +29 -34
  46. package/dist/server/src/controllers/stripe.d.ts +104 -0
  47. package/dist/server/src/index.d.ts +179 -139
  48. package/dist/server/src/middlewares/index.d.ts +19 -1
  49. package/dist/server/src/policies/index.d.ts +3 -1
  50. package/dist/server/src/routes/{admin-routes.d.ts → admin/index.d.ts} +4 -4
  51. package/dist/server/src/routes/content-api/index.d.ts +21 -0
  52. package/dist/server/src/routes/index.d.ts +11 -16
  53. package/dist/server/src/services/index.d.ts +2 -38
  54. package/dist/server/src/services/{stripeDriver.d.ts → stripe.d.ts} +52 -59
  55. package/dist/server/src/types/index.d.ts +179 -0
  56. package/package.json +20 -25
  57. package/dist/_chunks/App-DD7GyuRr.mjs +0 -1424
  58. package/dist/_chunks/App-KZVBFRwo.js +0 -1424
  59. package/dist/_chunks/en-B4KWt_jN.js +0 -4
  60. package/dist/_chunks/en-Byx4XI2L.mjs +0 -4
  61. package/dist/admin/src/components/Header.d.ts +0 -2
  62. package/dist/admin/src/components/NavigationMenu.d.ts +0 -2
  63. package/dist/admin/src/components/Sidebar.d.ts +0 -2
  64. package/dist/admin/src/components/TransactionDetailsModal.d.ts +0 -18
  65. package/dist/admin/src/components/TransactionList.d.ts +0 -18
  66. package/dist/admin/src/pages/ConfigurationPage.d.ts +0 -2
  67. package/dist/admin/src/pages/DashboardPage.d.ts +0 -2
  68. package/dist/admin/src/pages/ProductsPage.d.ts +0 -2
  69. package/dist/admin/src/pages/SubscriptionsPage.d.ts +0 -2
  70. package/dist/admin/src/pages/TransactionsPage.d.ts +0 -2
  71. package/dist/server/src/controllers/product.d.ts +0 -18
  72. package/dist/server/src/controllers/subscription.d.ts +0 -16
  73. package/dist/server/src/controllers/webhook.d.ts +0 -10
  74. package/dist/server/src/routes/content-api.d.ts +0 -12
  75. package/dist/server/src/routes/product.d.ts +0 -2
  76. package/dist/server/src/routes/refund-routes.d.ts +0 -13
  77. package/dist/server/src/routes/subscription.d.ts +0 -5
  78. package/dist/server/src/routes/webhook.d.ts +0 -15
  79. package/dist/server/src/services/paypalDriver.d.ts +0 -47
  80. package/dist/server/src/services/product.d.ts +0 -7
  81. package/dist/server/src/services/service.d.ts +0 -26
  82. package/dist/server/src/services/subscription.d.ts +0 -9
  83. package/dist/server/src/services/sync.d.ts +0 -13
  84. package/jest.config.js +0 -13
@@ -1,1424 +0,0 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { Page } from "@strapi/strapi/admin";
3
- import { NavLink, Routes, Route, Navigate } from "react-router-dom";
4
- import { useState, useEffect } from "react";
5
- import { Main, Box, Typography, Grid, Flex, TextInput, Button, Table, Thead, Tr, Th, Tbody, Td, SingleSelect, Modal, Alert, SingleSelectOption, Textarea } from "@strapi/design-system";
6
- import { Formik, Form, Field } from "formik";
7
- const ConfigurationPage = () => {
8
- const [stripeSecretKey, setStripeSecretKey] = useState("");
9
- const [stripePublishableKey, setStripePublishableKey] = useState("");
10
- const [stripeWebhookSecret, setStripeWebhookSecret] = useState("");
11
- const [paypalClientId, setPaypalClientId] = useState("");
12
- const [paypalClientSecret, setPaypalClientSecret] = useState("");
13
- const [paypalWebhookId, setPaypalWebhookId] = useState("");
14
- const [returnURL, setReturnURL] = useState(`${window.location.origin}/strapi-payment-plugin/webhook/stripe`);
15
- const [configStatus, setConfigStatus] = useState({
16
- stripe: false,
17
- paypal: false
18
- });
19
- useEffect(() => {
20
- const fetchConfigStatus = async () => {
21
- try {
22
- const response = await fetch("/strapi-payment-plugin/config-status");
23
- if (response.ok) {
24
- const data = await response.json();
25
- setConfigStatus(data);
26
- }
27
- } catch (error) {
28
- console.error("Failed to fetch config status:", error);
29
- }
30
- };
31
- fetchConfigStatus();
32
- }, []);
33
- const handleSave = async () => {
34
- const response = await fetch("/strapi-payment-plugin/config", {
35
- method: "POST",
36
- headers: {
37
- "Content-Type": "application/json"
38
- },
39
- body: JSON.stringify({
40
- stripe: {
41
- secretKey: stripeSecretKey,
42
- publishableKey: stripePublishableKey,
43
- webhookSecret: stripeWebhookSecret
44
- },
45
- paypal: {
46
- clientId: paypalClientId,
47
- clientSecret: paypalClientSecret,
48
- webhookId: paypalWebhookId
49
- }
50
- })
51
- });
52
- if (response.ok) {
53
- alert("Configuration saved successfully");
54
- } else {
55
- alert("Failed to save configuration");
56
- }
57
- };
58
- async function onclickTest() {
59
- try {
60
- const returnUrl = returnURL;
61
- const response = await fetch("/strapi-payment-plugin/test-payment", {
62
- method: "POST",
63
- headers: {
64
- "Content-Type": "application/json"
65
- },
66
- body: JSON.stringify({
67
- amount: 1e3,
68
- // $10.00
69
- currency: "usd",
70
- paymentMethod: "pm_card_visa",
71
- // Test card
72
- returnUrl
73
- })
74
- });
75
- if (response.ok) {
76
- const result = await response.json();
77
- alert(`Payment successful!
78
- Payment ID: ${result.paymentId}
79
- Return URL: ${returnUrl}`);
80
- } else {
81
- const error = await response.json();
82
- alert(`Payment failed:
83
- ${error.message}`);
84
- }
85
- } catch (err) {
86
- if (err instanceof Error) {
87
- alert(`Error testing payment:
88
- ${err.message}`);
89
- } else {
90
- alert("An unknown error occurred while testing payment");
91
- }
92
- }
93
- }
94
- async function onclickTestWithRedirect() {
95
- try {
96
- const returnUrl = returnURL;
97
- const response = await fetch("/strapi-payment-plugin/test-payment-with-redirect", {
98
- method: "POST",
99
- headers: {
100
- "Content-Type": "application/json"
101
- },
102
- body: JSON.stringify({
103
- productId: "price_1Rryf5FYBY9tFLhrxZRaCvC8"
104
- // Example product ID
105
- })
106
- });
107
- if (response.ok) {
108
- const result = await response.json();
109
- if (result.paymentLink) {
110
- window.location.href = result.paymentLink;
111
- } else {
112
- alert(`Payment successful!
113
- Payment ID: ${result.paymentId}`);
114
- }
115
- } else {
116
- const error = await response.json();
117
- alert(`Payment failed:
118
- ${error.message}`);
119
- }
120
- } catch (err) {
121
- if (err instanceof Error) {
122
- alert(`Error testing payment:
123
- ${err.message}`);
124
- } else {
125
- alert("An unknown error occurred while testing payment");
126
- }
127
- }
128
- }
129
- return /* @__PURE__ */ jsxs(Main, { children: [
130
- /* @__PURE__ */ jsx(Main, { title: "Payment Plugin Configuration" }),
131
- /* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsxs(Box, { padding: 6, background: "neutral0", children: [
132
- /* @__PURE__ */ jsx(
133
- Typography,
134
- {
135
- variant: "alpha",
136
- as: "h1",
137
- textColor: "primary600",
138
- style: { marginBottom: "2rem" },
139
- children: "Payment Configuration"
140
- }
141
- ),
142
- /* @__PURE__ */ jsxs(
143
- Box,
144
- {
145
- padding: 4,
146
- background: "neutral100",
147
- borderRadius: "4px",
148
- border: "1px solid #e0e0e0",
149
- style: { marginBottom: "2rem" },
150
- children: [
151
- /* @__PURE__ */ jsx(
152
- Typography,
153
- {
154
- variant: "beta",
155
- as: "h2",
156
- textColor: "neutral800",
157
- style: { marginBottom: "1rem" },
158
- children: "Payment Configuration"
159
- }
160
- ),
161
- /* @__PURE__ */ jsxs(Grid.Root, { gap: 6, style: { marginBottom: "2rem" }, children: [
162
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
163
- /* @__PURE__ */ jsx(Typography, { variant: "gamma", as: "h3", textColor: "neutral800", children: "Stripe Status  " }),
164
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", children: [
165
- /* @__PURE__ */ jsx(
166
- "div",
167
- {
168
- style: {
169
- width: "10px",
170
- height: "10px",
171
- borderRadius: "50%",
172
- backgroundColor: configStatus.stripe ? "green" : "red",
173
- marginRight: "8px"
174
- }
175
- }
176
- ),
177
- /* @__PURE__ */ jsx(
178
- Typography,
179
- {
180
- variant: "pi",
181
- fontWeight: "bold",
182
- textColor: configStatus.stripe ? "success600" : "danger600",
183
- children: configStatus.stripe ? "Connected" : "Not Connected"
184
- }
185
- )
186
- ] })
187
- ] }) }),
188
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", children: [
189
- /* @__PURE__ */ jsx(Typography, { variant: "gamma", as: "h3", textColor: "neutral800", children: "PayPal Status  " }),
190
- /* @__PURE__ */ jsxs(Flex, { alignItems: "center", children: [
191
- /* @__PURE__ */ jsx(
192
- "div",
193
- {
194
- style: {
195
- width: "10px",
196
- height: "10px",
197
- borderRadius: "50%",
198
- backgroundColor: configStatus.paypal ? "green" : "red",
199
- marginRight: "8px"
200
- }
201
- }
202
- ),
203
- /* @__PURE__ */ jsx(
204
- Typography,
205
- {
206
- variant: "pi",
207
- fontWeight: "bold",
208
- textColor: configStatus.paypal ? "success600" : "danger600",
209
- children: configStatus.paypal ? "Connected" : "Not Connected"
210
- }
211
- )
212
- ] })
213
- ] }) })
214
- ] }),
215
- /* @__PURE__ */ jsxs(Grid.Root, { gap: 6, children: [
216
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(
217
- Box,
218
- {
219
- padding: 6,
220
- background: "neutral0",
221
- borderRadius: "4px",
222
- border: "1px solid #e0e0e0",
223
- style: { marginBottom: "1rem", width: "100%" },
224
- children: [
225
- /* @__PURE__ */ jsx(
226
- Typography,
227
- {
228
- variant: "gamma",
229
- as: "h3",
230
- textColor: "neutral800",
231
- style: { marginBottom: "1rem" },
232
- children: "Stripe Configuration"
233
- }
234
- ),
235
- /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 8, alignItems: "initial", children: [
236
- /* @__PURE__ */ jsx(
237
- TextInput,
238
- {
239
- placeholder: "Secret Key",
240
- name: "stripeSecretKey",
241
- value: stripeSecretKey,
242
- onChange: (e) => setStripeSecretKey(e.target.value),
243
- type: "password",
244
- disabled: configStatus.stripe,
245
- style: {
246
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
247
- },
248
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
249
- }
250
- ),
251
- /* @__PURE__ */ jsx(
252
- TextInput,
253
- {
254
- placeholder: "Publishable Key",
255
- name: "stripePublishableKey",
256
- value: stripePublishableKey,
257
- onChange: (e) => setStripePublishableKey(e.target.value),
258
- disabled: configStatus.stripe,
259
- style: {
260
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
261
- },
262
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
263
- }
264
- ),
265
- /* @__PURE__ */ jsx(
266
- TextInput,
267
- {
268
- placeholder: "Webhook Secret",
269
- name: "stripeWebhookSecret",
270
- value: stripeWebhookSecret,
271
- onChange: (e) => setStripeWebhookSecret(e.target.value),
272
- type: "password",
273
- disabled: configStatus.stripe,
274
- style: {
275
- border: configStatus.stripe ? "2px solid #4CAF50" : ""
276
- },
277
- hint: configStatus.stripe ? "This value is controlled by environment variables" : ""
278
- }
279
- )
280
- ] })
281
- ]
282
- }
283
- ) }),
284
- /* @__PURE__ */ jsx(Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxs(
285
- Box,
286
- {
287
- padding: 6,
288
- background: "neutral0",
289
- borderRadius: "4px",
290
- border: "1px solid #e0e0e0",
291
- style: { marginBottom: "1rem", width: "100%" },
292
- children: [
293
- /* @__PURE__ */ jsx(
294
- Typography,
295
- {
296
- variant: "gamma",
297
- as: "h3",
298
- textColor: "neutral800",
299
- style: { marginBottom: "1rem" },
300
- children: "PayPal Configuration (not implemented for now)"
301
- }
302
- ),
303
- /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 8, alignItems: "initial", children: [
304
- /* @__PURE__ */ jsx(
305
- TextInput,
306
- {
307
- placeholder: "Client ID",
308
- name: "paypalClientId",
309
- value: paypalClientId,
310
- onChange: (e) => setPaypalClientId(e.target.value),
311
- disabled: true,
312
- style: {
313
- border: configStatus.paypal ? "2px solid #4CAF50" : "",
314
- width: "100%"
315
- },
316
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
317
- }
318
- ),
319
- /* @__PURE__ */ jsx(
320
- TextInput,
321
- {
322
- placeholder: "Client Secret",
323
- name: "paypalClientSecret",
324
- value: paypalClientSecret,
325
- onChange: (e) => setPaypalClientSecret(e.target.value),
326
- type: "password",
327
- disabled: true,
328
- style: {
329
- border: configStatus.paypal ? "2px solid #4CAF50" : ""
330
- },
331
- width: "80%",
332
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
333
- }
334
- ),
335
- /* @__PURE__ */ jsx(
336
- TextInput,
337
- {
338
- placeholder: "Webhook ID",
339
- name: "paypalWebhookId",
340
- value: paypalWebhookId,
341
- onChange: (e) => setPaypalWebhookId(e.target.value),
342
- disabled: true,
343
- style: {
344
- border: configStatus.paypal ? "2px solid #4CAF50" : ""
345
- },
346
- hint: configStatus.paypal ? "This value is controlled by environment variables" : ""
347
- }
348
- )
349
- ] })
350
- ]
351
- }
352
- ) })
353
- ] }),
354
- /* @__PURE__ */ jsx(Button, { onClick: handleSave, style: { marginTop: "1rem" }, children: "Save Configuration" })
355
- ]
356
- }
357
- ),
358
- /* @__PURE__ */ jsxs(
359
- Box,
360
- {
361
- padding: 4,
362
- background: "neutral100",
363
- borderRadius: "4px",
364
- border: "1px solid #e0e0e0",
365
- style: { marginTop: "2rem" },
366
- children: [
367
- /* @__PURE__ */ jsx(
368
- Typography,
369
- {
370
- variant: "beta",
371
- as: "h2",
372
- textColor: "neutral800",
373
- style: { marginBottom: "1rem" },
374
- children: "Stripe Payment Testing"
375
- }
376
- ),
377
- /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", style: { marginBottom: "1rem" }, children: "Test Stripe payment generation and handling" }),
378
- /* @__PURE__ */ jsx(Box, { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsx(
379
- TextInput,
380
- {
381
- placeholder: "Return URL (e.g., https://example.com/return)",
382
- name: "returnUrl",
383
- id: "returnUrl",
384
- style: { marginBottom: "1rem", width: "100%" },
385
- value: returnURL,
386
- onChange: (e) => setReturnURL(e.target.value),
387
- defaultValue: `${window.location.origin}/strapi-payment-plugin/webhook/stripe`
388
- }
389
- ) }),
390
- /* @__PURE__ */ jsx(
391
- Button,
392
- {
393
- onClick: onclickTest,
394
- style: { marginBottom: "1rem" },
395
- children: "Test Stripe Payment"
396
- }
397
- ),
398
- /* @__PURE__ */ jsx(
399
- Button,
400
- {
401
- onClick: onclickTestWithRedirect,
402
- style: { marginBottom: "1rem", marginLeft: "1rem" },
403
- children: "Test Stripe Payment with Redirect"
404
- }
405
- )
406
- ]
407
- }
408
- )
409
- ] }) })
410
- ] });
411
- };
412
- const TransactionList = ({ transactions, onViewDetails, onStatusUpdate }) => {
413
- return /* @__PURE__ */ jsxs(Table, { style: { fontSize: "14px" }, children: [
414
- /* @__PURE__ */ jsx(Thead, { children: /* @__PURE__ */ jsxs(Tr, { children: [
415
- /* @__PURE__ */ jsx(Th, { children: "ID" }),
416
- /* @__PURE__ */ jsx(Th, { children: "Amount" }),
417
- /* @__PURE__ */ jsx(Th, { children: "Currency" }),
418
- /* @__PURE__ */ jsx(Th, { children: "Status" }),
419
- /* @__PURE__ */ jsx(Th, { children: "Date" }),
420
- /* @__PURE__ */ jsx(Th, { children: "Customer" }),
421
- /* @__PURE__ */ jsx(Th, { children: "Gateway" }),
422
- /* @__PURE__ */ jsx(Th, { children: "Actions" })
423
- ] }) }),
424
- /* @__PURE__ */ jsx(Tbody, { children: transactions.map((transaction) => /* @__PURE__ */ jsxs(Tr, { children: [
425
- /* @__PURE__ */ jsx(Td, { children: transaction.id }),
426
- /* @__PURE__ */ jsxs(Td, { children: [
427
- "$",
428
- transaction.amount.toFixed(2)
429
- ] }),
430
- /* @__PURE__ */ jsx(Td, { children: transaction.currency }),
431
- /* @__PURE__ */ jsx(Td, { children: onStatusUpdate ? /* @__PURE__ */ jsxs(
432
- SingleSelect,
433
- {
434
- value: transaction.status,
435
- onChange: (e) => onStatusUpdate(transaction.id, e.target.value),
436
- style: { minWidth: "120px" },
437
- children: [
438
- /* @__PURE__ */ jsx("option", { value: "pending", children: "Pending" }),
439
- /* @__PURE__ */ jsx("option", { value: "completed", children: "Completed" }),
440
- /* @__PURE__ */ jsx("option", { value: "failed", children: "Failed" }),
441
- /* @__PURE__ */ jsx("option", { value: "refunded", children: "Refunded" })
442
- ]
443
- }
444
- ) : transaction.status }),
445
- /* @__PURE__ */ jsx(Td, { children: new Date(transaction.date).toLocaleDateString() }),
446
- /* @__PURE__ */ jsx(Td, { children: transaction.customer }),
447
- /* @__PURE__ */ jsx(Td, { children: transaction.gateway }),
448
- /* @__PURE__ */ jsx(Td, { children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "S", onClick: () => onViewDetails(transaction), children: "View" }) })
449
- ] }, transaction.id)) })
450
- ] });
451
- };
452
- const TransactionDetailsModal = ({
453
- isOpen,
454
- onClose,
455
- transaction,
456
- onRefund
457
- }) => {
458
- if (!transaction) return null;
459
- return /* @__PURE__ */ jsx(Modal.Root, { open: isOpen, onClose, children: /* @__PURE__ */ jsxs(Modal.Content, { onClick: onClose, children: [
460
- /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: "Transaction Details" }) }),
461
- /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsxs(Box, { padding: 4, children: [
462
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: "Details" }),
463
- /* @__PURE__ */ jsx(Box, { style: { marginTop: "1rem" }, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, children: [
464
- /* @__PURE__ */ jsxs(Typography, { children: [
465
- /* @__PURE__ */ jsx("strong", { children: "Amount:" }),
466
- " $",
467
- transaction.amount.toFixed(2),
468
- " ",
469
- transaction.currency
470
- ] }),
471
- /* @__PURE__ */ jsxs(Typography, { children: [
472
- /* @__PURE__ */ jsx("strong", { children: "Status:" }),
473
- " ",
474
- transaction.status
475
- ] }),
476
- /* @__PURE__ */ jsxs(Typography, { children: [
477
- /* @__PURE__ */ jsx("strong", { children: "Date:" }),
478
- " ",
479
- new Date(transaction.date).toLocaleString()
480
- ] }),
481
- /* @__PURE__ */ jsxs(Typography, { children: [
482
- /* @__PURE__ */ jsx("strong", { children: "Customer:" }),
483
- " ",
484
- transaction.customer
485
- ] }),
486
- /* @__PURE__ */ jsxs(Typography, { children: [
487
- /* @__PURE__ */ jsx("strong", { children: "Payment Method:" }),
488
- " ",
489
- transaction.paymentMethod
490
- ] }),
491
- /* @__PURE__ */ jsxs(Typography, { children: [
492
- /* @__PURE__ */ jsx("strong", { children: "Gateway:" }),
493
- " ",
494
- transaction.gateway
495
- ] })
496
- ] }) }),
497
- /* @__PURE__ */ jsxs(Flex, { style: { marginTop: "2rem", gap: "1rem" }, children: [
498
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: onClose, children: "Close" }),
499
- transaction.status === "completed" && transaction.gateway !== "paypal" && /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: onRefund, style: { marginLeft: "auto" }, children: "Refund" })
500
- ] })
501
- ] }) })
502
- ] }) });
503
- };
504
- const TransactionsPage = () => {
505
- const [searchTerm, setSearchTerm] = useState("");
506
- const [filter, setFilter] = useState("all");
507
- const [transactions, setTransactions] = useState([]);
508
- const [loading, setLoading] = useState(false);
509
- const [error, setError] = useState(null);
510
- const [selectedTransaction, setSelectedTransaction] = useState(null);
511
- const [isModalOpen, setIsModalOpen] = useState(false);
512
- const handleSearch = (e) => {
513
- setSearchTerm(e.target.value);
514
- };
515
- const handleFilterChange = (value) => {
516
- setFilter(value);
517
- };
518
- const fetchTransactions = async () => {
519
- setLoading(true);
520
- setError(null);
521
- try {
522
- const response = await fetch("/strapi-payment-plugin/transactions?gateway=all&status=all");
523
- if (!response.ok) {
524
- throw new Error("Failed to fetch transactions");
525
- }
526
- const data = await response.json();
527
- setTransactions(data.data);
528
- } catch (err) {
529
- if (err instanceof Error) {
530
- setError(err.message);
531
- } else {
532
- setError("An unknown error occurred");
533
- }
534
- } finally {
535
- setLoading(false);
536
- }
537
- };
538
- useEffect(() => {
539
- fetchTransactions();
540
- }, []);
541
- const filteredTransactions = transactions.filter((transaction) => {
542
- const matchesSearch = [
543
- transaction.id,
544
- transaction.customer,
545
- transaction.amount.toString()
546
- ].some(
547
- (field) => field.toLowerCase().includes(searchTerm.toLowerCase())
548
- );
549
- const matchesFilter = filter === "all" || transaction.status === filter;
550
- return matchesSearch && matchesFilter;
551
- });
552
- const handleViewDetails = (transaction) => {
553
- setSelectedTransaction(transaction);
554
- setIsModalOpen(true);
555
- };
556
- const handleRefund = async () => {
557
- if (!selectedTransaction) return;
558
- try {
559
- const response = await fetch("/strapi-payment-plugin/refund", {
560
- method: "POST",
561
- headers: {
562
- "Content-Type": "application/json"
563
- },
564
- body: JSON.stringify({
565
- gateway: selectedTransaction.gateway,
566
- transactionId: selectedTransaction.id,
567
- amount: selectedTransaction.amount
568
- })
569
- });
570
- if (!response.ok) {
571
- throw new Error("Failed to process refund");
572
- }
573
- const result = await response.json();
574
- if (result.success) {
575
- setTransactions(transactions.map(
576
- (t) => t.id === selectedTransaction.id ? { ...t, status: "refunded" } : t
577
- ));
578
- setIsModalOpen(false);
579
- } else {
580
- throw new Error(result.message || "Refund failed");
581
- }
582
- } catch (err) {
583
- if (err instanceof Error) {
584
- setError(err.message);
585
- } else {
586
- setError("An unknown error occurred");
587
- }
588
- }
589
- };
590
- return /* @__PURE__ */ jsxs(Main, { children: [
591
- /* @__PURE__ */ jsx(Main, { title: "Transactions" }),
592
- /* @__PURE__ */ jsxs(Box, { padding: 6, background: "neutral0", children: [
593
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Transactions" }),
594
- error && /* @__PURE__ */ jsx(Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
595
- /* @__PURE__ */ jsxs(
596
- Box,
597
- {
598
- padding: 4,
599
- background: "neutral100",
600
- borderRadius: "4px",
601
- border: "1px solid #e0e0e0",
602
- children: [
603
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", style: { marginBottom: "1rem" }, children: "Transaction List" }),
604
- /* @__PURE__ */ jsxs("div", { style: { marginBottom: "1rem", display: "flex", gap: "1rem", alignItems: "center", flexWrap: "wrap" }, children: [
605
- /* @__PURE__ */ jsx(
606
- TextInput,
607
- {
608
- label: "Search Transactions",
609
- value: searchTerm,
610
- onChange: handleSearch,
611
- placeholder: "Search by ID, email, or amount",
612
- style: { flex: 1, minWidth: "200px" }
613
- }
614
- ),
615
- /* @__PURE__ */ jsxs(SingleSelect, { value: filter, onChange: handleFilterChange, style: { minWidth: "150px" }, children: [
616
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "all", children: "All Transactions" }),
617
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "completed", children: "Successful" }),
618
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "failed", children: "Failed" }),
619
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "pending", children: "Pending" }),
620
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "refunded", children: "Refunded" })
621
- ] })
622
- ] }),
623
- /* @__PURE__ */ jsxs("div", { children: [
624
- loading && /* @__PURE__ */ jsx("p", { children: "Loading transactions..." }),
625
- !loading && /* @__PURE__ */ jsx(Fragment, { children: filteredTransactions.length > 0 ? /* @__PURE__ */ jsx(
626
- TransactionList,
627
- {
628
- transactions: filteredTransactions,
629
- onViewDetails: handleViewDetails
630
- }
631
- ) : /* @__PURE__ */ jsx("p", { children: "No transactions found" }) })
632
- ] })
633
- ]
634
- }
635
- )
636
- ] }),
637
- /* @__PURE__ */ jsx(
638
- TransactionDetailsModal,
639
- {
640
- isOpen: isModalOpen,
641
- onClose: () => setIsModalOpen(false),
642
- transaction: selectedTransaction,
643
- onRefund: handleRefund
644
- }
645
- )
646
- ] });
647
- };
648
- const DashboardPage = () => {
649
- const [transactions, setTransactions] = useState([]);
650
- const [loading, setLoading] = useState(false);
651
- const [error, setError] = useState(null);
652
- const [stats, setStats] = useState({
653
- totalRevenue: 0,
654
- totalTransactions: 0,
655
- successRate: 0
656
- });
657
- const fetchData = async () => {
658
- setLoading(true);
659
- setError(null);
660
- try {
661
- const response = await fetch("/strapi-payment-plugin/transactions?gateway=all&status=all");
662
- if (!response.ok) {
663
- throw new Error("Failed to fetch transactions");
664
- }
665
- const data = await response.json();
666
- setTransactions(data.data.slice(0, 5));
667
- const totalAmount = data.data.reduce((sum, t) => sum + t.amount, 0);
668
- const successCount = data.data.filter((t) => t.status === "completed").length;
669
- const successRate = data.data.length > 0 ? successCount / data.data.length * 100 : 0;
670
- setStats({
671
- totalRevenue: totalAmount,
672
- totalTransactions: data.data.length,
673
- successRate
674
- });
675
- } catch (err) {
676
- if (err instanceof Error) {
677
- setError(err.message);
678
- } else {
679
- setError("An unknown error occurred");
680
- }
681
- } finally {
682
- setLoading(false);
683
- }
684
- };
685
- useEffect(() => {
686
- fetchData();
687
- }, []);
688
- return /* @__PURE__ */ jsxs(Main, { children: [
689
- /* @__PURE__ */ jsx(Main, { title: "Payment Dashboard" }),
690
- /* @__PURE__ */ jsxs(Box, { padding: 6, background: "neutral0", children: [
691
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Payment Dashboard" }),
692
- /* @__PURE__ */ jsxs(
693
- Box,
694
- {
695
- padding: 4,
696
- background: "neutral100",
697
- borderRadius: "4px",
698
- border: "1px solid #e0e0e0",
699
- style: { marginBottom: "2rem" },
700
- children: [
701
- /* @__PURE__ */ jsx(
702
- Typography,
703
- {
704
- variant: "beta",
705
- as: "h2",
706
- textColor: "neutral800",
707
- style: { marginBottom: "1rem" },
708
- children: "Payment Statistics"
709
- }
710
- ),
711
- loading && /* @__PURE__ */ jsx("p", { children: "Loading statistics..." }),
712
- error && /* @__PURE__ */ jsx("p", { style: { color: "red" }, children: error }),
713
- !loading && !error && /* @__PURE__ */ jsxs(Grid.Root, { gap: 4, children: [
714
- /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsx(
715
- Box,
716
- {
717
- padding: 4,
718
- background: "neutral0",
719
- borderRadius: "4px",
720
- border: "1px solid #e0e0e0",
721
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", direction: "column", children: [
722
- /* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Revenues" }),
723
- /* @__PURE__ */ jsxs(Typography, { variant: "alpha", textColor: "primary600", children: [
724
- "$",
725
- stats.totalRevenue.toFixed(2)
726
- ] })
727
- ] })
728
- }
729
- ) }),
730
- /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsx(
731
- Box,
732
- {
733
- padding: 4,
734
- background: "neutral0",
735
- borderRadius: "4px",
736
- border: "1px solid #e0e0e0",
737
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", direction: "column", children: [
738
- /* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral800", children: "Total Transactions" }),
739
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", textColor: "primary600", children: stats.totalTransactions })
740
- ] })
741
- }
742
- ) }),
743
- /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsx(
744
- Box,
745
- {
746
- padding: 4,
747
- background: "neutral0",
748
- borderRadius: "4px",
749
- border: "1px solid #e0e0e0",
750
- children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", alignItems: "center", direction: "column", children: [
751
- /* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral800", children: "Successful Payments" }),
752
- /* @__PURE__ */ jsxs(Typography, { variant: "alpha", textColor: "primary600", children: [
753
- stats.successRate.toFixed(2),
754
- "%"
755
- ] })
756
- ] })
757
- }
758
- ) })
759
- ] })
760
- ]
761
- }
762
- ),
763
- /* @__PURE__ */ jsxs(Box, { padding: 4, background: "neutral100", borderRadius: "4px", border: "1px solid #e0e0e0", children: [
764
- /* @__PURE__ */ jsx(
765
- Typography,
766
- {
767
- variant: "beta",
768
- as: "h2",
769
- textColor: "neutral800",
770
- style: { marginBottom: "1rem" },
771
- children: "Recent Transactions"
772
- }
773
- ),
774
- loading && /* @__PURE__ */ jsx("p", { children: "Loading transactions..." }),
775
- error && /* @__PURE__ */ jsx("p", { style: { color: "red" }, children: error }),
776
- !loading && !error && /* @__PURE__ */ jsx(Fragment, { children: transactions.length > 0 ? /* @__PURE__ */ jsx(TransactionList, { transactions, onViewDetails: () => {
777
- } }) : /* @__PURE__ */ jsx("p", { children: "No recent transactions" }) })
778
- ] })
779
- ] })
780
- ] });
781
- };
782
- const ProductsPage = () => {
783
- const [products, setProducts] = useState([]);
784
- const [stripeProducts, setStripeProducts] = useState([]);
785
- const [loading, setLoading] = useState(false);
786
- const [error, setError] = useState(null);
787
- const [isModalOpen, setIsModalOpen] = useState(false);
788
- const [currentProduct, setCurrentProduct] = useState(null);
789
- const fetchProducts = async () => {
790
- setLoading(true);
791
- setError(null);
792
- try {
793
- const response = await fetch("/strapi-payment-plugin/products");
794
- if (!response.ok) {
795
- throw new Error("Failed to fetch products");
796
- }
797
- const data = await response.json();
798
- setProducts(data);
799
- } catch (err) {
800
- if (err instanceof Error) {
801
- setError(err.message);
802
- } else {
803
- setError("An unknown error occurred");
804
- }
805
- } finally {
806
- setLoading(false);
807
- }
808
- };
809
- const fetchStripeProducts = async () => {
810
- setLoading(true);
811
- setError(null);
812
- try {
813
- const response = await fetch("/strapi-payment-plugin/products/stripeProducts");
814
- if (!response.ok) {
815
- throw new Error("Failed to fetch Stripe products");
816
- }
817
- const data = await response.json();
818
- console.log("Stripe Products:", data);
819
- setStripeProducts(data);
820
- } catch (err) {
821
- if (err instanceof Error) {
822
- setError(err.message);
823
- } else {
824
- setError("An unknown error occurred");
825
- }
826
- } finally {
827
- setLoading(false);
828
- }
829
- };
830
- useEffect(() => {
831
- fetchProducts();
832
- fetchStripeProducts();
833
- }, []);
834
- const handleCreate = () => {
835
- setCurrentProduct({
836
- documentId: "",
837
- id: 0,
838
- name: "",
839
- description: "",
840
- price: 0,
841
- currency: "USD",
842
- isSubscription: false,
843
- subscriptionInterval: "month"
844
- });
845
- setIsModalOpen(true);
846
- };
847
- const handleEdit = (product) => {
848
- location.href = `/admin/content-manager/collection-types/plugin::strapi-payment-plugin.product/${product.documentId}`;
849
- };
850
- const handleDelete = async (id) => {
851
- if (confirm("Are you sure you want to delete this product?")) {
852
- try {
853
- const response = await fetch(`/strapi-payment-plugin/products/${id}`, {
854
- method: "DELETE"
855
- });
856
- if (!response.ok) {
857
- throw new Error("Failed to delete product");
858
- }
859
- fetchProducts();
860
- } catch (err) {
861
- if (err instanceof Error) {
862
- setError(err.message);
863
- } else {
864
- setError("An unknown error occurred");
865
- }
866
- }
867
- }
868
- };
869
- const handleSync = async (id) => {
870
- try {
871
- const response = await fetch(`/strapi-payment-plugin/products/${id}/sync`, {
872
- method: "POST"
873
- });
874
- if (!response.ok) {
875
- throw new Error("Failed to sync product");
876
- }
877
- const result = await response.json();
878
- alert(result.message);
879
- fetchProducts();
880
- } catch (err) {
881
- if (err instanceof Error) {
882
- setError(err.message);
883
- } else {
884
- setError("An unknown error occurred");
885
- }
886
- }
887
- };
888
- const handleImport = async (stripeProductId) => {
889
- try {
890
- const response = await fetch("/strapi-payment-plugin/products/import", {
891
- method: "POST",
892
- headers: {
893
- "Content-Type": "application/json"
894
- },
895
- body: JSON.stringify({ stripeProductId })
896
- });
897
- if (!response.ok) {
898
- throw new Error("Failed to import product");
899
- }
900
- const result = await response.json();
901
- alert(result.message);
902
- fetchProducts();
903
- fetchStripeProducts();
904
- } catch (err) {
905
- if (err instanceof Error) {
906
- setError(err.message);
907
- } else {
908
- setError("An unknown error occurred");
909
- }
910
- }
911
- };
912
- const handleSubmit = async (values) => {
913
- if (!currentProduct) return;
914
- try {
915
- const method = currentProduct.id ? "PUT" : "POST";
916
- const url = currentProduct.id ? `/strapi-payment-plugin/products/${currentProduct.id}` : "/strapi-payment-plugin/products";
917
- const response = await fetch(url, {
918
- method,
919
- headers: {
920
- "Content-Type": "application/json"
921
- },
922
- body: JSON.stringify({ data: values })
923
- });
924
- if (!response.ok) {
925
- throw new Error(`Failed to ${currentProduct.id ? "update" : "create"} product`);
926
- }
927
- setIsModalOpen(false);
928
- fetchProducts();
929
- } catch (err) {
930
- if (err instanceof Error) {
931
- setError(err.message);
932
- } else {
933
- setError("An unknown error occurred");
934
- }
935
- }
936
- };
937
- return /* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsxs(Box, { padding: 6, background: "neutral0", children: [
938
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Products" }),
939
- error && /* @__PURE__ */ jsx(Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
940
- loading && /* @__PURE__ */ jsx("p", { children: "Loading products..." }),
941
- /* @__PURE__ */ jsxs(Modal.Root, { open: isModalOpen, onOpenChange: setIsModalOpen, children: [
942
- /* @__PURE__ */ jsx(Modal.Trigger, { children: /* @__PURE__ */ jsx(Button, { onClick: handleCreate, children: "Create product" }) }),
943
- /* @__PURE__ */ jsxs(Modal.Content, { children: [
944
- /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: currentProduct ? currentProduct.id ? "Edit Product" : "Create Product" : "Product" }) }),
945
- /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(
946
- Formik,
947
- {
948
- initialValues: {
949
- documentId: currentProduct?.documentId || "",
950
- id: currentProduct?.id || 0,
951
- name: currentProduct?.name || "",
952
- description: currentProduct?.description || "",
953
- price: currentProduct?.price || 0,
954
- currency: currentProduct?.currency || "USD",
955
- isSubscription: currentProduct?.isSubscription || false,
956
- subscriptionInterval: currentProduct?.subscriptionInterval || "month"
957
- },
958
- onSubmit: handleSubmit,
959
- children: ({ values, handleChange, setFieldValue }) => /* @__PURE__ */ jsx(Form, { children: /* @__PURE__ */ jsxs(Flex, { justifyContent: "space-between", direction: "column", gap: 4, col: 12, children: [
960
- /* @__PURE__ */ jsx(
961
- TextInput,
962
- {
963
- label: "Name",
964
- name: "name",
965
- placeHolder: "Product Name",
966
- value: values.name,
967
- onChange: handleChange,
968
- required: true
969
- }
970
- ),
971
- /* @__PURE__ */ jsx(
972
- Textarea,
973
- {
974
- label: "Description",
975
- name: "description",
976
- placeholder: "Product Description",
977
- value: values.description,
978
- onChange: handleChange
979
- }
980
- ),
981
- /* @__PURE__ */ jsx(
982
- TextInput,
983
- {
984
- label: "Price",
985
- name: "price",
986
- type: "number",
987
- placeholder: "Product Price",
988
- value: values.price,
989
- onChange: handleChange,
990
- required: true
991
- }
992
- ),
993
- /* @__PURE__ */ jsxs(
994
- SingleSelect,
995
- {
996
- label: "Currency",
997
- name: "currency",
998
- placeholder: "Select Currency",
999
- value: values.currency,
1000
- onChange: handleChange,
1001
- children: [
1002
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "USD", children: "USD" }),
1003
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "EUR", children: "EUR" }),
1004
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "GBP", children: "GBP" })
1005
- ]
1006
- }
1007
- ),
1008
- /* @__PURE__ */ jsx(Box, { style: { marginTop: "1rem" }, children: /* @__PURE__ */ jsxs(Typography, { variant: "pi", textColor: "neutral800", children: [
1009
- /* @__PURE__ */ jsx(
1010
- Field,
1011
- {
1012
- type: "checkbox",
1013
- name: "isSubscription",
1014
- checked: values.isSubscription,
1015
- onChange: () => setFieldValue("isSubscription", !values.isSubscription)
1016
- }
1017
- ),
1018
- " Is Subscription"
1019
- ] }) }),
1020
- values.isSubscription && /* @__PURE__ */ jsxs(
1021
- SingleSelect,
1022
- {
1023
- label: "Subscription Interval",
1024
- name: "subscriptionInterval",
1025
- value: values.subscriptionInterval,
1026
- onChange: handleChange,
1027
- children: [
1028
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "day", children: "Day" }),
1029
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "week", children: "Week" }),
1030
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "month", children: "Month" }),
1031
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "year", children: "Year" })
1032
- ]
1033
- }
1034
- ),
1035
- /* @__PURE__ */ jsx(Button, { type: "submit", style: { marginTop: "1rem" }, children: currentProduct?.id ? "Update" : "Create" })
1036
- ] }) })
1037
- }
1038
- ) })
1039
- ] })
1040
- ] }),
1041
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "primary600", style: { margin: "2rem 0 1rem" }, children: "Local Products" }),
1042
- /* @__PURE__ */ jsx(Grid.Root, { gap: 4, children: products.map((product) => /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxs(
1043
- Box,
1044
- {
1045
- padding: 4,
1046
- background: "neutral100",
1047
- borderRadius: "4px",
1048
- border: "1px solid #e0e0e0",
1049
- children: [
1050
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: product.name }),
1051
- /* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
1052
- product.price,
1053
- " ",
1054
- product.currency,
1055
- " ",
1056
- product.isSubscription ? `/ ${product.subscriptionInterval}` : ""
1057
- ] }),
1058
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", style: { marginTop: "1rem" }, children: product.description }),
1059
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", style: { marginTop: "1rem" }, children: product.stripeProductId ? "✅ Synced with Stripe" : "⚠️ Not synced with Stripe" }),
1060
- /* @__PURE__ */ jsxs(Flex, { style: { marginTop: "1rem", gap: "1rem" }, children: [
1061
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => handleEdit(product), children: "Edit" }),
1062
- /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: () => handleDelete(product.id), children: "Delete" }),
1063
- /* @__PURE__ */ jsx(Button, { onClick: () => handleSync(product.id), children: product.stripeProductId ? "Sync" : "Create in Stripe" })
1064
- ] })
1065
- ]
1066
- },
1067
- product.id
1068
- ) }, product.id)) }),
1069
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "primary600", style: { margin: "2rem 0 1rem" }, children: "Stripe Products (Available for Import)" }),
1070
- /* @__PURE__ */ jsx(Grid.Root, { gap: 4, children: stripeProducts.filter(
1071
- (product) => !products.some((localProduct) => localProduct.stripeProductId === product.id)
1072
- ).map((product) => /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxs(
1073
- Box,
1074
- {
1075
- padding: 4,
1076
- background: "neutral100",
1077
- borderRadius: "4px",
1078
- border: "1px solid #e0e0e0",
1079
- children: [
1080
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: product.name }),
1081
- /* @__PURE__ */ jsxs(Typography, { textColor: "red", children: [
1082
- product?.default_price?.unit_amount / 100,
1083
- " ",
1084
- product?.default_price?.currency
1085
- ] }),
1086
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", style: { marginTop: "1rem" }, children: product.description }),
1087
- /* @__PURE__ */ jsx(Flex, { style: { marginTop: "1rem", gap: "1rem" }, children: /* @__PURE__ */ jsx(Button, { onClick: () => handleImport(product.id), children: "Import from Stripe" }) })
1088
- ]
1089
- },
1090
- product.id
1091
- ) }, product.id)) })
1092
- ] }) });
1093
- };
1094
- const SubscriptionsPage = () => {
1095
- const [subscriptions, setSubscriptions] = useState([]);
1096
- const [products, setProducts] = useState([]);
1097
- const [loading, setLoading] = useState(false);
1098
- const [error, setError] = useState(null);
1099
- const [isModalOpen, setIsModalOpen] = useState(false);
1100
- const [currentSubscription, setCurrentSubscription] = useState(null);
1101
- const fetchSubscriptions = async () => {
1102
- setLoading(true);
1103
- setError(null);
1104
- try {
1105
- const response = await fetch("/strapi-payment-plugin/subscriptions");
1106
- if (!response.ok) {
1107
- throw new Error("Failed to fetch subscriptions");
1108
- }
1109
- const data = await response.json();
1110
- setSubscriptions(data);
1111
- } catch (err) {
1112
- if (err instanceof Error) {
1113
- setError(err.message);
1114
- } else {
1115
- setError("An unknown error occurred");
1116
- }
1117
- } finally {
1118
- setLoading(false);
1119
- }
1120
- };
1121
- const fetchProducts = async () => {
1122
- try {
1123
- const response = await fetch("/strapi-payment-plugin/products");
1124
- if (!response.ok) {
1125
- throw new Error("Failed to fetch products");
1126
- }
1127
- const data = await response.json();
1128
- setProducts(data);
1129
- } catch (err) {
1130
- console.error("Failed to fetch products:", err);
1131
- }
1132
- };
1133
- useEffect(() => {
1134
- fetchSubscriptions();
1135
- fetchProducts();
1136
- }, []);
1137
- const handleEdit = (subscription) => {
1138
- setCurrentSubscription(subscription);
1139
- setIsModalOpen(true);
1140
- };
1141
- const handleDelete = async (id) => {
1142
- if (confirm("Are you sure you want to delete this subscription?")) {
1143
- try {
1144
- const response = await fetch(`/strapi-payment-plugin/subscriptions/${id}`, {
1145
- method: "DELETE"
1146
- });
1147
- if (!response.ok) {
1148
- throw new Error("Failed to delete subscription");
1149
- }
1150
- fetchSubscriptions();
1151
- } catch (err) {
1152
- if (err instanceof Error) {
1153
- setError(err.message);
1154
- } else {
1155
- setError("An unknown error occurred");
1156
- }
1157
- }
1158
- }
1159
- };
1160
- const handleSubmit = async (values) => {
1161
- if (!currentSubscription) return;
1162
- try {
1163
- const method = currentSubscription.id ? "PUT" : "POST";
1164
- const url = currentSubscription.id ? `/strapi-payment-plugin/subscriptions/${currentSubscription.id}` : "/strapi-payment-plugin/subscriptions";
1165
- const response = await fetch(url, {
1166
- method,
1167
- headers: {
1168
- "Content-Type": "application/json"
1169
- },
1170
- body: JSON.stringify({ data: values })
1171
- });
1172
- if (!response.ok) {
1173
- throw new Error(`Failed to ${currentSubscription.id ? "update" : "create"} subscription`);
1174
- }
1175
- setIsModalOpen(false);
1176
- fetchSubscriptions();
1177
- } catch (err) {
1178
- if (err instanceof Error) {
1179
- setError(err.message);
1180
- } else {
1181
- setError("An unknown error occurred");
1182
- }
1183
- }
1184
- };
1185
- const handleSync = async (id) => {
1186
- try {
1187
- const response = await fetch(`/strapi-payment-plugin/subscriptions/${id}/sync`, {
1188
- method: "POST"
1189
- });
1190
- if (!response.ok) {
1191
- throw new Error("Failed to sync subscription");
1192
- }
1193
- const result = await response.json();
1194
- alert(result.message);
1195
- fetchSubscriptions();
1196
- } catch (err) {
1197
- if (err instanceof Error) {
1198
- setError(err.message);
1199
- } else {
1200
- setError("An unknown error occurred");
1201
- }
1202
- }
1203
- };
1204
- return /* @__PURE__ */ jsx(Main, { children: /* @__PURE__ */ jsxs(Box, { padding: 6, background: "neutral0", children: [
1205
- /* @__PURE__ */ jsx(Typography, { variant: "alpha", as: "h1", textColor: "primary600", style: { marginBottom: "2rem" }, children: "Subscriptions" }),
1206
- error && /* @__PURE__ */ jsx(Alert, { variant: "danger", style: { marginBottom: "1rem" }, children: error }),
1207
- loading && /* @__PURE__ */ jsx("p", { children: "Loading subscriptions..." }),
1208
- /* @__PURE__ */ jsxs(Modal.Root, { children: [
1209
- /* @__PURE__ */ jsx(Modal.Trigger, { children: /* @__PURE__ */ jsx(Button, { children: "Create subscription" }) }),
1210
- /* @__PURE__ */ jsxs(Modal.Content, { children: [
1211
- /* @__PURE__ */ jsx(Modal.Header, { children: /* @__PURE__ */ jsx(Modal.Title, { children: currentSubscription ? currentSubscription.id ? "Edit Subscription" : "Create Subscription" : "Subscription" }) }),
1212
- /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(Box, { padding: 4, children: /* @__PURE__ */ jsx(
1213
- Formik,
1214
- {
1215
- initialValues: {
1216
- id: currentSubscription?.id || 0,
1217
- product: currentSubscription?.product || { documentId: "", name: "", description: "", id: 0 },
1218
- user: currentSubscription?.user || { id: 0, email: "" },
1219
- status: currentSubscription?.status || "active",
1220
- startDate: currentSubscription?.startDate || (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
1221
- endDate: currentSubscription?.endDate || ""
1222
- },
1223
- onSubmit: handleSubmit,
1224
- children: ({ values, handleChange, setFieldValue }) => /* @__PURE__ */ jsx(Form, { children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, children: [
1225
- /* @__PURE__ */ jsxs(
1226
- SingleSelect,
1227
- {
1228
- placeholder: "Product",
1229
- name: "product.documentId",
1230
- value: values.product.documentId || "",
1231
- onChange: (selectedDocumentId) => {
1232
- setFieldValue("product", products.find((product) => product.documentId === selectedDocumentId));
1233
- setFieldValue("product.documentId", selectedDocumentId);
1234
- },
1235
- required: true,
1236
- children: [
1237
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "", children: "Select a product" }),
1238
- products.map((product) => /* @__PURE__ */ jsx(SingleSelectOption, { value: product.documentId, children: product.name }, product.id))
1239
- ]
1240
- }
1241
- ),
1242
- /* @__PURE__ */ jsx(
1243
- TextInput,
1244
- {
1245
- placeholder: "User Email",
1246
- name: "user.email",
1247
- value: values.user.email,
1248
- onChange: handleChange,
1249
- required: true
1250
- }
1251
- ),
1252
- /* @__PURE__ */ jsxs(
1253
- SingleSelect,
1254
- {
1255
- placeholder: "Status",
1256
- name: "status",
1257
- value: values.status,
1258
- onChange: (selectedStatus) => {
1259
- setFieldValue("status", selectedStatus);
1260
- },
1261
- children: [
1262
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "active", children: "Active" }),
1263
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "canceled", children: "Canceled" }),
1264
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "past_due", children: "Past Due" }),
1265
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "unpaid", children: "Unpaid" }),
1266
- /* @__PURE__ */ jsx(SingleSelectOption, { value: "trialing", children: "Trialing" })
1267
- ]
1268
- }
1269
- ),
1270
- /* @__PURE__ */ jsx(
1271
- TextInput,
1272
- {
1273
- placeholder: "Start Date",
1274
- name: "startDate",
1275
- type: "date",
1276
- value: values.startDate,
1277
- onChange: handleChange,
1278
- required: true
1279
- }
1280
- ),
1281
- /* @__PURE__ */ jsx(
1282
- TextInput,
1283
- {
1284
- placeholder: "End Date",
1285
- name: "endDate",
1286
- type: "date",
1287
- value: values.endDate,
1288
- onChange: handleChange
1289
- }
1290
- ),
1291
- /* @__PURE__ */ jsx(Button, { type: "submit", style: { marginTop: "1rem" }, children: currentSubscription?.id ? "Update" : "Create" })
1292
- ] }) })
1293
- }
1294
- ) }) })
1295
- ] })
1296
- ] }),
1297
- /* @__PURE__ */ jsx(Grid.Root, { gap: 4, children: subscriptions.map((subscription) => /* @__PURE__ */ jsx(Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxs(
1298
- Box,
1299
- {
1300
- padding: 4,
1301
- background: "neutral100",
1302
- borderRadius: "4px",
1303
- border: "1px solid #e0e0e0",
1304
- children: [
1305
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h2", textColor: "neutral800", children: subscription.product.name }),
1306
- /* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
1307
- "User: ",
1308
- subscription.user.email
1309
- ] }),
1310
- /* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
1311
- "Status: ",
1312
- subscription.status
1313
- ] }),
1314
- /* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
1315
- "Start Date: ",
1316
- subscription.startDate
1317
- ] }),
1318
- subscription.endDate && /* @__PURE__ */ jsxs(Typography, { textColor: "neutral600", children: [
1319
- "End Date: ",
1320
- subscription.endDate
1321
- ] }),
1322
- /* @__PURE__ */ jsx(Typography, { textColor: "neutral600", style: { marginTop: "1rem" }, children: subscription.stripeSubscriptionId ? "✅ Synced with Stripe" : "⚠️ Not synced with Stripe" }),
1323
- /* @__PURE__ */ jsxs(Flex, { style: { marginTop: "1rem", gap: "1rem" }, children: [
1324
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => handleEdit(subscription), children: "Edit" }),
1325
- /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: () => handleDelete(subscription.id), children: "Delete" }),
1326
- /* @__PURE__ */ jsx(Button, { onClick: () => handleSync(subscription.id), children: subscription.stripeSubscriptionId ? "Sync" : "Create in Stripe" })
1327
- ] })
1328
- ]
1329
- },
1330
- subscription.id
1331
- ) }, subscription.id)) })
1332
- ] }) });
1333
- };
1334
- const NavigationMenu = () => {
1335
- return /* @__PURE__ */ jsxs(
1336
- Box,
1337
- {
1338
- background: "neutral100",
1339
- padding: 4,
1340
- width: "200px",
1341
- height: "100vh",
1342
- position: "fixed",
1343
- top: 0,
1344
- left: 100,
1345
- children: [
1346
- /* @__PURE__ */ jsx(Typography, { variant: "beta", as: "h1", style: { marginBottom: "2rem" }, children: "Payment Plugin" }),
1347
- /* @__PURE__ */ jsx("nav", { children: /* @__PURE__ */ jsxs("ul", { style: { listStyle: "none", padding: 0, fontSize: "14px" }, children: [
1348
- /* @__PURE__ */ jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsx(
1349
- NavLink,
1350
- {
1351
- to: "/plugins/strapi-payment-plugin/dashboard",
1352
- style: ({ isActive }) => ({
1353
- color: isActive ? "#7b79ff" : "inherit",
1354
- textDecoration: "none"
1355
- }),
1356
- children: "Dashboard"
1357
- }
1358
- ) }),
1359
- /* @__PURE__ */ jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsx(
1360
- NavLink,
1361
- {
1362
- to: "/plugins/strapi-payment-plugin/transactions",
1363
- style: ({ isActive }) => ({
1364
- color: isActive ? "#7b79ff" : "inherit",
1365
- textDecoration: "none"
1366
- }),
1367
- children: "Transactions"
1368
- }
1369
- ) }),
1370
- /* @__PURE__ */ jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsx(
1371
- NavLink,
1372
- {
1373
- to: "/plugins/strapi-payment-plugin/products",
1374
- style: ({ isActive }) => ({
1375
- color: isActive ? "#7b79ff" : "inherit",
1376
- textDecoration: "none"
1377
- }),
1378
- children: "Products"
1379
- }
1380
- ) }),
1381
- /* @__PURE__ */ jsx("li", { style: { marginBottom: "1rem" }, children: /* @__PURE__ */ jsx(
1382
- NavLink,
1383
- {
1384
- to: "/plugins/strapi-payment-plugin/subscriptions",
1385
- style: ({ isActive }) => ({
1386
- color: isActive ? "#7b79ff" : "inherit",
1387
- textDecoration: "none"
1388
- }),
1389
- children: "Subscriptions"
1390
- }
1391
- ) }),
1392
- /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1393
- NavLink,
1394
- {
1395
- to: "/plugins/strapi-payment-plugin/configuration",
1396
- style: ({ isActive }) => ({
1397
- color: isActive ? "#7b79ff" : "inherit",
1398
- textDecoration: "none"
1399
- }),
1400
- children: "Configuration"
1401
- }
1402
- ) })
1403
- ] }) })
1404
- ]
1405
- }
1406
- );
1407
- };
1408
- const App = () => {
1409
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex" }, children: [
1410
- /* @__PURE__ */ jsx(NavigationMenu, {}),
1411
- /* @__PURE__ */ jsx("div", { style: { marginLeft: "200px", flex: 1 }, children: /* @__PURE__ */ jsxs(Routes, { children: [
1412
- /* @__PURE__ */ jsx(Route, { index: true, element: /* @__PURE__ */ jsx(Navigate, { to: "dashboard" }) }),
1413
- /* @__PURE__ */ jsx(Route, { path: "/dashboard", element: /* @__PURE__ */ jsx(DashboardPage, {}) }),
1414
- /* @__PURE__ */ jsx(Route, { path: "/transactions", element: /* @__PURE__ */ jsx(TransactionsPage, {}) }),
1415
- /* @__PURE__ */ jsx(Route, { path: "/products", element: /* @__PURE__ */ jsx(ProductsPage, {}) }),
1416
- /* @__PURE__ */ jsx(Route, { path: "/subscriptions", element: /* @__PURE__ */ jsx(SubscriptionsPage, {}) }),
1417
- /* @__PURE__ */ jsx(Route, { path: "/configuration", element: /* @__PURE__ */ jsx(ConfigurationPage, {}) }),
1418
- /* @__PURE__ */ jsx(Route, { path: "*", element: /* @__PURE__ */ jsx(Page.Error, {}) })
1419
- ] }) })
1420
- ] });
1421
- };
1422
- export {
1423
- App
1424
- };