@gnar-engine/cli 1.0.0 → 1.0.1

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 (230) hide show
  1. package/assets/gnar-engine-logo-white.svg +9 -0
  2. package/bootstrap/deploy.localdev.yml +51 -0
  3. package/bootstrap/secrets.localdev.yml +27 -0
  4. package/bootstrap/services/agent/Dockerfile +23 -0
  5. package/bootstrap/services/agent/notes.md +28 -0
  6. package/bootstrap/services/agent/package.json +16 -0
  7. package/bootstrap/services/agent/src/app.js +52 -0
  8. package/bootstrap/services/agent/src/commands/agent.handler.js +104 -0
  9. package/bootstrap/services/agent/src/config.js +52 -0
  10. package/bootstrap/services/agent/src/controllers/http.controller.js +44 -0
  11. package/bootstrap/services/agent/src/controllers/message.controller.js +51 -0
  12. package/bootstrap/services/agent/src/db/migrations/01-init.js +50 -0
  13. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +36 -0
  14. package/bootstrap/services/agent/src/policies/agent.policy.js +13 -0
  15. package/bootstrap/services/agent/src/schema/Agent.schema.js +17 -0
  16. package/bootstrap/services/agent/src/services/agent.service.js +259 -0
  17. package/bootstrap/services/agent/src/services/chatgpt.service.js +46 -0
  18. package/bootstrap/services/agent/src/services/manifest.service.js +21 -0
  19. package/bootstrap/services/control/Dockerfile +23 -0
  20. package/bootstrap/services/control/Dockerfile.prod +37 -0
  21. package/bootstrap/services/control/README.md +25 -0
  22. package/bootstrap/services/control/package.json +16 -0
  23. package/bootstrap/services/control/src/app.js +45 -0
  24. package/bootstrap/services/control/src/commands/control.handler.js +231 -0
  25. package/bootstrap/services/control/src/commands/service.handler.js +81 -0
  26. package/bootstrap/services/control/src/commands/task.handler.js +247 -0
  27. package/bootstrap/services/control/src/config.js +55 -0
  28. package/bootstrap/services/control/src/controllers/http.controller.js +228 -0
  29. package/bootstrap/services/control/src/controllers/message.controller.js +40 -0
  30. package/bootstrap/services/control/src/db/migrations/01-init.js +50 -0
  31. package/bootstrap/services/control/src/db/migrations/02-control-service-init.js +60 -0
  32. package/bootstrap/services/control/src/db/migrations/03-alter-tasks.js +29 -0
  33. package/bootstrap/services/control/src/policies/task.policy.js +53 -0
  34. package/bootstrap/services/control/src/schema/control.schema.js +42 -0
  35. package/bootstrap/services/control/src/services/registry.service.js +83 -0
  36. package/bootstrap/services/control/src/services/reset.service.js +28 -0
  37. package/bootstrap/services/control/src/services/task.service.js +153 -0
  38. package/bootstrap/services/control/src/tests/control.test.js +50 -0
  39. package/bootstrap/services/notification/Dockerfile +23 -0
  40. package/bootstrap/services/notification/Dockerfile.prod +37 -0
  41. package/bootstrap/services/notification/README.md +3 -0
  42. package/bootstrap/services/notification/package.json +34 -0
  43. package/bootstrap/services/notification/src/app.js +51 -0
  44. package/bootstrap/services/notification/src/commands/command-bus.js +20 -0
  45. package/bootstrap/services/notification/src/commands/handlers/control.handler.js +18 -0
  46. package/bootstrap/services/notification/src/commands/handlers/notification.handler.js +157 -0
  47. package/bootstrap/services/notification/src/config.js +15 -0
  48. package/bootstrap/services/notification/src/controllers/message.controller.js +82 -0
  49. package/bootstrap/services/notification/src/services/logger.service.js +16 -0
  50. package/bootstrap/services/notification/src/services/ses.service.js +23 -0
  51. package/bootstrap/services/notification/src/templates/admin-order-recieved.hbs +136 -0
  52. package/bootstrap/services/notification/src/templates/admin-subscription-failed.hbs +87 -0
  53. package/bootstrap/services/notification/src/templates/customer-order-recieved.hbs +132 -0
  54. package/bootstrap/services/notification/src/templates/customer-subscription-failed.hbs +77 -0
  55. package/bootstrap/services/notification/src/tests/notification.test.js +0 -0
  56. package/bootstrap/services/portal/Dockerfile +23 -0
  57. package/bootstrap/services/portal/Dockerfile.remote +40 -0
  58. package/bootstrap/services/portal/README.md +22 -0
  59. package/bootstrap/services/portal/nginx.conf +12 -0
  60. package/bootstrap/services/portal/package.json +59 -0
  61. package/bootstrap/services/portal/public/favicon.ico +0 -0
  62. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  63. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  64. package/bootstrap/services/portal/public/index.html +43 -0
  65. package/bootstrap/services/portal/public/logo192.png +0 -0
  66. package/bootstrap/services/portal/public/logo512.png +0 -0
  67. package/bootstrap/services/portal/public/manifest.json +25 -0
  68. package/bootstrap/services/portal/public/robots.txt +3 -0
  69. package/bootstrap/services/portal/src/App.js +56 -0
  70. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +1 -0
  71. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +1 -0
  72. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +1 -0
  73. package/bootstrap/services/portal/src/assets/activity.svg +3 -0
  74. package/bootstrap/services/portal/src/assets/arrow.svg +3 -0
  75. package/bootstrap/services/portal/src/assets/bin-white.svg +3 -0
  76. package/bootstrap/services/portal/src/assets/bin.svg +3 -0
  77. package/bootstrap/services/portal/src/assets/check.svg +3 -0
  78. package/bootstrap/services/portal/src/assets/chevron.svg +3 -0
  79. package/bootstrap/services/portal/src/assets/contact.svg +3 -0
  80. package/bootstrap/services/portal/src/assets/dots-vertical.svg +5 -0
  81. package/bootstrap/services/portal/src/assets/eye-off.svg +3 -0
  82. package/bootstrap/services/portal/src/assets/eye.svg +4 -0
  83. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +47 -0
  84. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +47 -0
  85. package/bootstrap/services/portal/src/assets/gnar_engine.svg +3 -0
  86. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  87. package/bootstrap/services/portal/src/assets/home.svg +3 -0
  88. package/bootstrap/services/portal/src/assets/link.svg +3 -0
  89. package/bootstrap/services/portal/src/assets/lock.svg +3 -0
  90. package/bootstrap/services/portal/src/assets/package.svg +4 -0
  91. package/bootstrap/services/portal/src/assets/raffle.svg +3 -0
  92. package/bootstrap/services/portal/src/assets/settings.svg +4 -0
  93. package/bootstrap/services/portal/src/assets/shopping-bag.svg +3 -0
  94. package/bootstrap/services/portal/src/assets/user-black.svg +3 -0
  95. package/bootstrap/services/portal/src/assets/user.svg +3 -0
  96. package/bootstrap/services/portal/src/assets/users.svg +3 -0
  97. package/bootstrap/services/portal/src/assets/wallet.svg +3 -0
  98. package/bootstrap/services/portal/src/css/style.css +1007 -0
  99. package/bootstrap/services/portal/src/data/data.js +70 -0
  100. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +32 -0
  101. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +160 -0
  102. package/bootstrap/services/portal/src/features/crud/crudEdit.less +230 -0
  103. package/bootstrap/services/portal/src/features/crud/crudList.less +134 -0
  104. package/bootstrap/services/portal/src/features/crud/crudPage.less +31 -0
  105. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +108 -0
  106. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +243 -0
  107. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +109 -0
  108. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +315 -0
  109. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +104 -0
  110. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +388 -0
  111. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +104 -0
  112. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +208 -0
  113. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +110 -0
  114. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +261 -0
  115. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +107 -0
  116. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +402 -0
  117. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +30 -0
  118. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +113 -0
  119. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +56 -0
  120. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +56 -0
  121. package/bootstrap/services/portal/src/features/notes/Notes.jsx +18 -0
  122. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +96 -0
  123. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +74 -0
  124. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +102 -0
  125. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +24 -0
  126. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +99 -0
  127. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +46 -0
  128. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +64 -0
  129. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +49 -0
  130. package/bootstrap/services/portal/src/features/skus/Skus.jsx +109 -0
  131. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +44 -0
  132. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +32 -0
  133. package/bootstrap/services/portal/src/features/user/User.jsx +54 -0
  134. package/bootstrap/services/portal/src/features/user/user.less +57 -0
  135. package/bootstrap/services/portal/src/includes/utilities.js +259 -0
  136. package/bootstrap/services/portal/src/index.js +14 -0
  137. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +50 -0
  138. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +17 -0
  139. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +48 -0
  140. package/bootstrap/services/portal/src/layouts/loginLayout.less +33 -0
  141. package/bootstrap/services/portal/src/layouts/portalLayout.less +67 -0
  142. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +199 -0
  143. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +17 -0
  144. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +10 -0
  145. package/bootstrap/services/portal/src/pages/login/Login.jsx +15 -0
  146. package/bootstrap/services/portal/src/pages/login/login.less +10 -0
  147. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +199 -0
  148. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +15 -0
  149. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +15 -0
  150. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +10 -0
  151. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +43 -0
  152. package/bootstrap/services/portal/src/pages/products/Products.jsx +212 -0
  153. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +124 -0
  154. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +186 -0
  155. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +10 -0
  156. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +10 -0
  157. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +199 -0
  158. package/bootstrap/services/portal/src/pages/users/Users.jsx +193 -0
  159. package/bootstrap/services/portal/src/pages/users/users.less +25 -0
  160. package/bootstrap/services/portal/src/slices/authSlice.js +71 -0
  161. package/bootstrap/services/portal/src/store/configureStore.js +12 -0
  162. package/bootstrap/services/portal/src/styles/global.less +159 -0
  163. package/bootstrap/services/portal/src/styles/inputs.less +157 -0
  164. package/bootstrap/services/portal/src/styles/main.less +26 -0
  165. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +97 -0
  166. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +23 -0
  167. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +17 -0
  168. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +42 -0
  169. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +63 -0
  170. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +63 -0
  171. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +63 -0
  172. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +92 -0
  173. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +19 -0
  174. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +12 -0
  175. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +23 -0
  176. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +29 -0
  177. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +69 -0
  178. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  179. package/bootstrap/services/rabbit-mq/Dockerfile.prod +9 -0
  180. package/bootstrap/services/user/Dockerfile +23 -0
  181. package/bootstrap/services/user/Dockerfile.prod +37 -0
  182. package/bootstrap/services/user/README.md +8 -0
  183. package/bootstrap/services/user/package.json +16 -0
  184. package/bootstrap/services/user/src/app.js +45 -0
  185. package/bootstrap/services/user/src/commands/session.handler.js +23 -0
  186. package/bootstrap/services/user/src/commands/user.handler.js +286 -0
  187. package/bootstrap/services/user/src/config.js +73 -0
  188. package/bootstrap/services/user/src/controllers/http.controller.js +156 -0
  189. package/bootstrap/services/user/src/controllers/message.controller.js +51 -0
  190. package/bootstrap/services/user/src/db/migrations/01-init.js +50 -0
  191. package/bootstrap/services/user/src/db/migrations/02-user-service-init.js +63 -0
  192. package/bootstrap/services/user/src/db/migrations/03-unauth-sessions.js +43 -0
  193. package/bootstrap/services/user/src/db/seeders/development/01-root-user.js +29 -0
  194. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +27 -0
  195. package/bootstrap/services/user/src/db/seeders/production/01-root-user.js +29 -0
  196. package/bootstrap/services/user/src/policies/user.policy.js +81 -0
  197. package/bootstrap/services/user/src/schema/user.schema.js +69 -0
  198. package/bootstrap/services/user/src/services/authentication.service.js +127 -0
  199. package/bootstrap/services/user/src/services/session.service.js +58 -0
  200. package/bootstrap/services/user/src/services/user.service.js +130 -0
  201. package/bootstrap/services/user/src/tests/user.test.js +126 -0
  202. package/package.json +3 -7
  203. package/src/agent/agent.client.js +28 -0
  204. package/src/agent/commands.js +48 -0
  205. package/src/cli.js +30 -0
  206. package/src/config.js +8 -0
  207. package/src/control/commands.js +156 -0
  208. package/src/control/control.client.js +127 -0
  209. package/src/dev/commands.js +71 -0
  210. package/src/dev/dev.service.js +320 -0
  211. package/src/engine/infra.js +142 -0
  212. package/src/helpers/helpers.js +63 -0
  213. package/src/profiles/command.js +170 -0
  214. package/src/profiles/profiles.client.js +101 -0
  215. package/src/scaffolder/commands.js +123 -0
  216. package/src/scaffolder/scaffolder.handler.js +252 -0
  217. package/src/services/client.js +174 -0
  218. package/templates/service/Dockerfile.hbs +20 -0
  219. package/templates/service/app.js.hbs +38 -0
  220. package/templates/service/commands/{{serviceName}}.handler.js.hbs +97 -0
  221. package/templates/service/config.js.hbs +48 -0
  222. package/templates/service/controllers/http.controller.js.hbs +87 -0
  223. package/templates/service/controllers/message.controller.js.hbs +51 -0
  224. package/templates/service/db/migrations/01-init.js.hbs +50 -0
  225. package/templates/service/db/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +23 -0
  226. package/templates/service/package.json.hbs +18 -0
  227. package/templates/service/policies/{{serviceName}}.policy.js.hbs +49 -0
  228. package/templates/service/schema/{{serviceName}}.schema.js.hbs +14 -0
  229. package/templates/service/services/{{serviceName}}.service.js.hbs +32 -0
  230. package/dist/cli.js +0 -18
@@ -0,0 +1,212 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import CrudLayout from "../../layouts/CrudLayout";
3
+ import CrudProductList from '../../features/crudProducts/CrudProductList';
4
+ import CrudProductSingle from '../../features/crudProducts/CrudProductSingle';
5
+ import gnarEngine from "@gnar-engine/js-client";
6
+ import CustomSelect from "../../ui/customSelect/CustomSelect";
7
+ import arrow from '../../assets/arrow.svg';
8
+
9
+
10
+ const Products = () => {
11
+
12
+ const [view, setView] = useState("list");
13
+ const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
14
+ const [selectedProduct, setProduct] = useState(null);
15
+ const [loading, setLoading] = useState(false);
16
+ const [selectedAction, setSelectedAction] = useState(null);
17
+ const [selectedProductIds, setSelectedProductIds] = useState(new Set());
18
+ const [products, setProducts] = useState([]);
19
+ const [message, setMessage] = useState('');
20
+ const [currentPage, setCurrentPage] = useState(1);
21
+
22
+ const fetchProducts = async () => {
23
+ try {
24
+ // Fetch users from gnarEngine SDK
25
+ const data = await gnarEngine.products.getMany();
26
+
27
+ console.log('data:', data);
28
+
29
+ // Map response data to expected structure
30
+ const productsList = data.products.map(product => ({
31
+ id: product._id,
32
+ image: product.image,
33
+ name: product.name,
34
+ sku: product.skus.map(sku => sku.sku).join(', '),
35
+ categories: product.categories.join(', '),
36
+ createdAt: formatDate(product.createdAt),
37
+ }));
38
+
39
+ setProducts(productsList);
40
+ setMessage(productsList.length > 0 ? '' : 'No products found');
41
+ } catch (error) {
42
+ console.error('Error fetching products:', error);
43
+ setMessage('Error fetching products');
44
+ setProducts([]);
45
+ }
46
+ }
47
+
48
+ useEffect(() => {
49
+ fetchProducts();
50
+ }, []);
51
+
52
+ const formatDate = (isoString) => {
53
+ if (!isoString) return "N/A";
54
+
55
+ const date = new Date(isoString);
56
+ if (isNaN(date.getTime())) return "N/A"; // Checks if the date is invalid
57
+
58
+ return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} at ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
59
+ };
60
+
61
+
62
+ const handleAddNew = () => {
63
+ setView("single");
64
+ setSelectedSingleItemId(null);
65
+ setProduct(null);
66
+ }
67
+
68
+ const handleImport = () => {
69
+ console.log('import');
70
+ }
71
+
72
+ const handleExport = () => {
73
+ console.log('export');
74
+ }
75
+
76
+ const refreshSelectedProduct = () => {
77
+ if (!selectedSingleItemId) {
78
+ return;
79
+ }
80
+ (async () => {
81
+ try {
82
+ const data = await gnarEngine.products.getProduct(selectedSingleItemId);
83
+ setProduct(data.product);
84
+ } catch (error) {
85
+ console.error('Error fetching product:', error);
86
+ }
87
+ })();
88
+ }
89
+
90
+ useEffect(() => {
91
+ (async () => {
92
+ if (!selectedSingleItemId) {
93
+ return;
94
+ }
95
+ try {
96
+ // fetch product data
97
+ const data = await gnarEngine.products.getProduct(selectedSingleItemId);
98
+ console.log('single product data:', data);
99
+ setProduct(data.product);
100
+
101
+ } catch (error) {
102
+ console.error('Error fetching product:', error);
103
+ }
104
+ })();
105
+ }, [selectedSingleItemId]);
106
+
107
+ const handleAction = () => {
108
+ if (!selectedAction) {
109
+ alert("Please select an action first!");
110
+ return;
111
+ }
112
+
113
+ if (selectedAction.id === "delete") {
114
+ handleDelete();
115
+ } else if (selectedAction.id === "export") {
116
+ console.log("Export action triggered");
117
+ }
118
+ };
119
+
120
+ const handleDelete = () => {
121
+ if (selectedProductIds.size === 0) {
122
+ alert("Please select a product to delete first!");
123
+ return;
124
+ }
125
+ if (!window.confirm(`Are you sure you want to delete ${selectedProductIds.size} product(s)?`)) {
126
+ return;
127
+ }
128
+ (async () => {
129
+ try {
130
+ for (const productId of selectedProductIds) {
131
+ await gnarEngine.products.delete(productId);
132
+ }
133
+ setSelectedProductIds(new Set());
134
+ setSelectedAction(null);
135
+ await fetchProducts();
136
+ } catch (error) {
137
+ console.error('Error deleting product:', error);
138
+ }
139
+ })();
140
+ };
141
+
142
+ return (
143
+ <CrudLayout
144
+ view={view}
145
+ setView={setView}
146
+ selectedSingleItemId={selectedSingleItemId}
147
+ setSelectedSingleItemId={setSelectedSingleItemId}
148
+ >
149
+ <div className="crud-page">
150
+
151
+ {view === "list" ? (
152
+ <div className="crud-list-cont">
153
+ <div className="crud-list-controls">
154
+ <div className="controls-left-col">
155
+ <button onClick={handleAddNew} className="add-new">Add new</button>
156
+ {/* <button onClick={handleImport} className="add-new">Import</button> */}
157
+ {/* <button onClick={handleExport} className="add-new">Export</button> */}
158
+ </div>
159
+ <div className="controls-right-col">
160
+ <CustomSelect
161
+ name="filter-products"
162
+ placeholder="filter by"
163
+ options={[
164
+ { id: "all", name: "All" }
165
+ ]}
166
+ labelKey="name"
167
+ setSelectedOption={() => {}}
168
+ selectedOption={null}
169
+ />
170
+ <CustomSelect
171
+ name="action"
172
+ placeholder="action"
173
+ options={[
174
+ { id: "delete", name: "Delete" },
175
+ // { id: "export", name: "Export" }
176
+ ]}
177
+ labelKey="name"
178
+ setSelectedOption={setSelectedAction}
179
+ selectedOption={selectedAction}
180
+ />
181
+ <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
182
+ </div>
183
+ </div>
184
+ <CrudProductList
185
+ setSelectedSingleItemId={setSelectedSingleItemId}
186
+ setView={() => setView('single')}
187
+ selectedProductIds={selectedProductIds}
188
+ setSelectedProductIds={setSelectedProductIds}
189
+ products={products}
190
+ message={message}
191
+ />
192
+ </div>
193
+ ) : (
194
+ <CrudProductSingle
195
+ loading={loading}
196
+ setLoading={setLoading}
197
+ product={selectedProduct}
198
+ setView={() => setView('list')}
199
+ refreshSelectedProduct={refreshSelectedProduct}
200
+ setProduct={setProduct}
201
+ fetchProducts={fetchProducts}
202
+ handleDelete={handleDelete}
203
+ setSelectedSingleItemId={setSelectedSingleItemId}
204
+ formatDate={formatDate}
205
+ />
206
+ )}
207
+ </div>
208
+ </CrudLayout>
209
+ );
210
+ }
211
+
212
+ export default Products;
@@ -0,0 +1,124 @@
1
+ import { useEffect, useState } from "react";
2
+ import RaffleEntriesList from "../../features/raffleEntriesList/RaffleEntriesList";
3
+ import CustomSelect from "../../ui/customSelect/CustomSelect";
4
+ import gnarEngine from "@gnar-engine/js-client";
5
+ import arrow from '../../assets/arrow.svg';
6
+
7
+
8
+ const RaffleEntries = () => {
9
+ const [raffleEntries, setRaffleEntries] = useState([]);
10
+ const [raffles, setRaffles] = useState([]);
11
+ const [message, setMessage] = useState('Please select a raffle to see entries');
12
+ const [selectedRaffle, setSelectedRaffle] = useState(null);
13
+ const [selectedEntryIds, setSelectedEntryIds] = useState(new Set());
14
+ const [selectedAction, setSelectedAction] = useState(null);
15
+
16
+
17
+ const fetchRaffles = async () => {
18
+ try {
19
+ const data = await gnarEngine.raffles.getRaffles();
20
+ console.log('raffles:', data);
21
+
22
+ setRaffles(data.raffle);
23
+ } catch (error) {
24
+ console.error('Error fetching raffles:', error);
25
+ setRaffles([]);
26
+ }
27
+ }
28
+
29
+ const fetchRaffleEntries = async (raffleId) => {
30
+ if (!raffleId) return;
31
+
32
+ try {
33
+ const data = await gnarEngine.raffles.getRaffleEntries(raffleId);
34
+ console.log('raffle entries:', data);
35
+
36
+ setRaffleEntries(data.entries);
37
+ setMessage(data.entries.length > 0 ? '' : 'No entries found for this raffle');
38
+ } catch (error) {
39
+ console.error('Error fetching raffle entries:', error);
40
+ setRaffleEntries([]);
41
+ }
42
+ }
43
+
44
+ useEffect(() => {
45
+ fetchRaffles();
46
+ }, []);
47
+
48
+ useEffect(() => {
49
+ if (selectedRaffle?.id) {
50
+ fetchRaffleEntries(selectedRaffle.id);
51
+ }
52
+ }, [selectedRaffle]);
53
+
54
+ const handleAction = async () => {
55
+ if (!selectedAction) {
56
+ alert("Please select an action first!");
57
+ return;
58
+ }
59
+
60
+ if (selectedAction.id === "export") {
61
+ console.log("Export action triggered");
62
+ }
63
+
64
+ if (selectedAction.id === "generate-list") {
65
+ console.log("Generate list action triggered");
66
+
67
+ if (!selectedRaffle?.id) {
68
+ alert("Please select a raffle first!");
69
+ return;
70
+ }
71
+
72
+ try {
73
+ await gnarEngine.raffles.generateList(selectedRaffle.id)
74
+ } catch (error) {
75
+ console.error("Error generating raffle list:", error);
76
+ alert("Failed to generate raffle list");
77
+ }
78
+ }
79
+ };
80
+
81
+
82
+ return (
83
+ <div className="crud-page">
84
+ <div className="crud-list-cont">
85
+ <div className="crud-list-controls">
86
+ <div className="controls-left-col">
87
+ <CustomSelect
88
+ name="raffle"
89
+ labelKey="name"
90
+ options={raffles}
91
+ setSelectedOption={setSelectedRaffle}
92
+ selectedOption={selectedRaffle}
93
+ placeholder="Select a raffle"
94
+ />
95
+ </div>
96
+ <div className="controls-right-col">
97
+ <CustomSelect
98
+ name="action"
99
+ placeholder="action"
100
+ options={[
101
+ { id: "export", name: "Export" },
102
+ { id: "generate-list", name: "Generate List" }
103
+ ]}
104
+ labelKey="name"
105
+ setSelectedOption={setSelectedAction}
106
+ selectedOption={selectedAction}
107
+ />
108
+ <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
109
+ </div>
110
+ </div>
111
+
112
+ <RaffleEntriesList
113
+ raffleEntries={raffleEntries}
114
+ setRaffleEntries={setRaffleEntries}
115
+ selectedEntryIds={selectedEntryIds}
116
+ setSelectedEntryIds={setSelectedEntryIds}
117
+ message={message}
118
+ />
119
+ </div>
120
+ </div>
121
+ );
122
+ }
123
+
124
+ export default RaffleEntries;
@@ -0,0 +1,186 @@
1
+ import gnarEngine from "@gnar-engine/js-client";
2
+ import { useEffect, useState } from "react";
3
+ import CrudLayout from "../../layouts/CrudLayout";
4
+ import CustomSelect from "../../ui/customSelect/CustomSelect";
5
+ import CrudRafflesList from "../../features/crudRaffles/CrudRafflesList";
6
+ import CrudRafflesSingle from "../../features/crudRaffles/CrudRafflesSingle";
7
+ import arrow from '../../assets/arrow.svg';
8
+
9
+
10
+ const Raffles = () => {
11
+ const [view, setView] = useState("list");
12
+ const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
13
+ const [raffles, setRaffles] = useState([]);
14
+ const [selectedRaffle, setRaffle] = useState(null);
15
+ const [loading, setLoading] = useState(false);
16
+ const [selectedAction, setSelectedAction] = useState(null);
17
+ const [selectedRaffleIds, setSelectedRaffleIds] = useState(new Set());
18
+ const [message, setMessage] = useState('');
19
+ const [currentPage, setCurrentPage] = useState(1);
20
+
21
+
22
+ const fetchRaffles = async () => {
23
+ try {
24
+ const data = await gnarEngine.raffles.getRaffles();
25
+ console.log('raffles:', data);
26
+
27
+ const rafflesList = data.raffle.map(raffle => ({
28
+ id: raffle.id,
29
+ name: raffle.name,
30
+ description: raffle.description,
31
+ prizeDescription: raffle.prizeDescription,
32
+ created_at: formatDate(raffle.created_at),
33
+ }));
34
+
35
+ setRaffles(rafflesList);
36
+ setMessage(rafflesList.length > 0 ? '' : 'No raffles found');
37
+
38
+ } catch (error) {
39
+ console.error('Error fetching raffles:', error);
40
+ setRaffles([]);
41
+ }
42
+ }
43
+
44
+ useEffect(() => {
45
+ fetchRaffles();
46
+ }, []);
47
+
48
+ const formatDate = (isoString) => {
49
+ if (!isoString) return "N/A";
50
+
51
+ const date = new Date(isoString);
52
+ if (isNaN(date.getTime())) return "N/A"; // Checks if the date is invalid
53
+
54
+ return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} at ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
55
+ };
56
+
57
+
58
+ const handleAddNew = () => {
59
+ setView("single");
60
+ setSelectedSingleItemId(null);
61
+ setRaffle(null);
62
+ }
63
+
64
+ const refreshSelectedRaffle = () => {
65
+ if (!selectedSingleItemId) {
66
+ return;
67
+ }
68
+ (async () => {
69
+ try {
70
+ const data = await gnarEngine.raffles.getRaffle(selectedSingleItemId);
71
+ setRaffle(data.raffle);
72
+ } catch (error) {
73
+ console.error('Error fetching raffles:', error);
74
+ }
75
+ })();
76
+ }
77
+
78
+ useEffect(() => {
79
+ (async () => {
80
+ if (!selectedSingleItemId) {
81
+ return;
82
+ }
83
+ try {
84
+ // fetch contact data
85
+ const data = await gnarEngine.raffles.getRaffle(selectedSingleItemId);
86
+ setRaffle(data.raffle);
87
+
88
+ } catch (error) {
89
+ console.error('Error fetching raffle:', error);
90
+ }
91
+ })();
92
+ }, [selectedSingleItemId]);
93
+
94
+ const handleAction = () => {
95
+ if (!selectedAction) {
96
+ alert("Please select an action first!");
97
+ return;
98
+ }
99
+
100
+ if (selectedAction.id === "delete") {
101
+ handleDelete();
102
+ } else if (selectedAction.id === "export") {
103
+ console.log("Export action triggered");
104
+ }
105
+ };
106
+
107
+ const handleDelete = () => {
108
+ if (selectedRaffleIds.size === 0) {
109
+ alert("Please select a raffle to delete first!");
110
+ return;
111
+ }
112
+ if (!window.confirm(`Are you sure you want to delete ${selectedRaffleIds.size} raffle(s)?`)) {
113
+ return;
114
+ }
115
+ (async () => {
116
+ try {
117
+ for (const raffleId of selectedRaffleIds) {
118
+ await gnarEngine.raffles.deleteRaffle(raffleId);
119
+ }
120
+ setSelectedRaffleIds(new Set());
121
+ setSelectedAction(null);
122
+ await fetchRaffles();
123
+ } catch (error) {
124
+ console.error('Error deleting raffle:', error);
125
+ }
126
+ })();
127
+ };
128
+
129
+ return (
130
+ <CrudLayout
131
+ view={view}
132
+ setView={setView}
133
+ selectedSingleItemId={selectedSingleItemId}
134
+ setSelectedSingleItemId={setSelectedSingleItemId}
135
+ >
136
+ <div className="crud-page">
137
+
138
+ {view === "list" ? (
139
+ <div className="crud-list-cont">
140
+ <div className="crud-list-controls">
141
+ <div className="controls-left-col">
142
+ <button onClick={handleAddNew} className="add-new">Add new</button>
143
+ </div>
144
+ <div className="controls-right-col">
145
+ <CustomSelect
146
+ name="action"
147
+ placeholder="action"
148
+ options={[
149
+ { id: "delete", name: "Delete" },
150
+ // { id: "export", name: "Export" }
151
+ ]}
152
+ labelKey="name"
153
+ setSelectedOption={setSelectedAction}
154
+ selectedOption={selectedAction}
155
+ />
156
+ <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
157
+ </div>
158
+ </div>
159
+ <CrudRafflesList
160
+ setSelectedSingleItemId={setSelectedSingleItemId}
161
+ setView={() => setView('single')}
162
+ selectedRaffleIds={selectedRaffleIds}
163
+ setSelectedRaffleIds={setSelectedRaffleIds}
164
+ raffles={raffles}
165
+ message={message}
166
+ />
167
+ </div>
168
+ ) : (
169
+ <CrudRafflesSingle
170
+ loading={loading}
171
+ setLoading={setLoading}
172
+ raffle={selectedRaffle}
173
+ setView={() => setView('list')}
174
+ refreshSelectedRaffle={refreshSelectedRaffle}
175
+ setRaffle={setRaffle}
176
+ fetchRaffles={fetchRaffles}
177
+ formatDate={formatDate}
178
+ setSelectedSingleItemId={setSelectedSingleItemId}
179
+ />
180
+ )}
181
+ </div>
182
+ </CrudLayout>
183
+ );
184
+ }
185
+
186
+ export default Raffles;
@@ -0,0 +1,10 @@
1
+ const Reports = () => {
2
+
3
+ return (
4
+ <div>
5
+ <h1>Reports Page</h1>
6
+ </div>
7
+ );
8
+ }
9
+
10
+ export default Reports;
@@ -0,0 +1,10 @@
1
+ const Settings = () => {
2
+
3
+ return (
4
+ <div>
5
+ <h1>Settings Page</h1>
6
+ </div>
7
+ );
8
+ }
9
+
10
+ export default Settings;