@reeboot/strapi-payment-plugin 0.0.0

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