@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,199 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import CrudLayout from "../../layouts/CrudLayout";
3
+ import gnarEngine from "@gnar-engine/js-client";
4
+ import CustomSelect from "../../ui/customSelect/CustomSelect";
5
+ import arrow from '../../assets/arrow.svg';
6
+ import CrudContactSingle from "../../features/crudContact/CrudContactSingle";
7
+ import CrudContactList from "../../features/crudContact/CrudContactList";
8
+
9
+ const Contacts = () => {
10
+
11
+ const [view, setView] = useState(null);
12
+ const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
13
+ const [selectedContact, setContact] = useState(null);
14
+ const [loading, setLoading] = useState(false);
15
+ const [selectedAction, setSelectedAction] = useState(null);
16
+ const [selectedContactIds, setSelectedContactIds] = useState(new Set());
17
+ const [contacts, setContacts] = useState([]);
18
+ const [message, setMessage] = useState('');
19
+ const [currentPage, setCurrentPage] = useState(1);
20
+
21
+ const fetchContacts = async () => {
22
+ try {
23
+ const data = await gnarEngine.contacts.getMany();
24
+ console.log('data:', data);
25
+
26
+ const contactsList = data.contacts.map(contact => ({
27
+ id: contact._id,
28
+ firstName: contact.firstName,
29
+ lastName: contact.lastName,
30
+ email: contact.email,
31
+ phone: contact.phone,
32
+ dateOfBirth: contact.dateOfBirth,
33
+ createdAt: formatDate(contact.createdAt),
34
+ }));
35
+
36
+ setContacts(contactsList);
37
+ setMessage(contactsList.length > 0 ? '' : 'No contacts found');
38
+ } catch (error) {
39
+ console.error('Error fetching contacts:', error);
40
+ setContacts([]);
41
+ }
42
+ };
43
+
44
+ useEffect(() => {
45
+ fetchContacts();
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
+ setContact(null);
62
+ }
63
+
64
+ const refreshSelectedContact = () => {
65
+ if (!selectedSingleItemId) {
66
+ return;
67
+ }
68
+ (async () => {
69
+ try {
70
+ const data = await gnarEngine.contacts.getContact(selectedSingleItemId);
71
+ setContact(data.contact);
72
+ } catch (error) {
73
+ console.error('Error fetching contact:', 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.contacts.getContact(selectedSingleItemId);
86
+ setContact(data.contact);
87
+
88
+ } catch (error) {
89
+ console.error('Error fetching contact:', 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 (selectedContactIds.size === 0) {
109
+ alert("Please select a contact to delete first!");
110
+ return;
111
+ }
112
+ if (!window.confirm(`Are you sure you want to delete ${selectedContactIds.size} contact(s)?`)) {
113
+ return;
114
+ }
115
+ (async () => {
116
+ try {
117
+ for (const contactId of selectedContactIds) {
118
+ await gnarEngine.contacts.delete(contactId);
119
+ }
120
+ setSelectedContactIds(new Set());
121
+ setSelectedAction(null);
122
+ await fetchContacts();
123
+ } catch (error) {
124
+ console.error('Error deleting contact:', error);
125
+ }
126
+ })();
127
+ };
128
+
129
+
130
+ return (
131
+ <CrudLayout
132
+ view={view}
133
+ setView={setView}
134
+ selectedSingleItemId={selectedSingleItemId}
135
+ setSelectedSingleItemId={setSelectedSingleItemId}
136
+ >
137
+ <div className="crud-page">
138
+
139
+ {view === "list" ? (
140
+ <div className="crud-list-cont">
141
+ <div className="crud-list-controls">
142
+ <div className="controls-left-col">
143
+ <button onClick={handleAddNew} className="add-new">Add new</button>
144
+ </div>
145
+ <div className="controls-right-col">
146
+ <CustomSelect
147
+ name="filter-contacts"
148
+ placeholder="filter by"
149
+ options={[
150
+ { id: "all", name: "All" },
151
+ { id: "admin", name: "Admin" },
152
+ { id: "contact", name: "User" }
153
+ ]}
154
+ labelKey="name"
155
+ setSelectedOption={() => {}}
156
+ selectedOption={null}
157
+ />
158
+ <CustomSelect
159
+ name="action"
160
+ placeholder="action"
161
+ options={[
162
+ { id: "delete", name: "Delete" },
163
+ // { id: "export", name: "Export" }
164
+ ]}
165
+ labelKey="name"
166
+ setSelectedOption={setSelectedAction}
167
+ selectedOption={selectedAction}
168
+ />
169
+ <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
170
+ </div>
171
+ </div>
172
+ <CrudContactList
173
+ setSelectedSingleItemId={setSelectedSingleItemId}
174
+ setView={() => setView('single')}
175
+ selectedContactIds={selectedContactIds}
176
+ setSelectedContactIds={setSelectedContactIds}
177
+ contacts={contacts}
178
+ message={message}
179
+ />
180
+ </div>
181
+ ) : (
182
+ <CrudContactSingle
183
+ loading={loading}
184
+ setLoading={setLoading}
185
+ contact={selectedContact}
186
+ setView={() => setView('list')}
187
+ refreshSelectedContact={refreshSelectedContact}
188
+ setContact={setContact}
189
+ fetchContacts={fetchContacts}
190
+ formatDate={formatDate}
191
+ setSelectedSingleItemId={setSelectedSingleItemId}
192
+ />
193
+ )}
194
+ </div>
195
+ </CrudLayout>
196
+ );
197
+ }
198
+
199
+ export default Contacts;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+
3
+ const Dashboard = () => {
4
+
5
+ return (
6
+ <div className="dashboard">
7
+ <h1>Dashboard</h1>
8
+
9
+ <div className="separator"></div>
10
+
11
+ <p>Please use the relevant links within the side bar to view, update and track your data.</p>
12
+
13
+ </div>
14
+ );
15
+ }
16
+
17
+ export default Dashboard;
@@ -0,0 +1,10 @@
1
+ const Integrations = () => {
2
+
3
+ return (
4
+ <div>
5
+ <h1>Integrations Page</h1>
6
+ </div>
7
+ );
8
+ }
9
+
10
+ export default Integrations;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import LoginLayout from "../../layouts/LoginLayout";
3
+ import LoginForm from "../../features/loginForm/LoginForm";
4
+
5
+ const LoginPage = () => {
6
+ return (
7
+ <LoginLayout>
8
+
9
+ <LoginForm />
10
+
11
+ </LoginLayout>
12
+ );
13
+ }
14
+
15
+ export default LoginPage;
@@ -0,0 +1,10 @@
1
+ .login-layout {
2
+
3
+ h1 {
4
+ margin-bottom: 10px;
5
+ }
6
+ h2 {
7
+ margin-top: 0px;
8
+ margin-bottom: 10px;
9
+ }
10
+ }
@@ -0,0 +1,199 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import CrudLayout from "../../layouts/CrudLayout";
3
+ import gnarEngine from "@gnar-engine/js-client";
4
+ import CustomSelect from "../../ui/customSelect/CustomSelect";
5
+ import arrow from '../../assets/arrow.svg';
6
+ import CrudOrderList from "../../features/crudOrder/CrudOrderList";
7
+ import CrudOrderSingle from "../../features/crudOrder/CrudOrderSingle";
8
+
9
+ const Orders = () => {
10
+
11
+ const [view, setView] = useState("list");
12
+ const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
13
+ const [selectedOrder, setOrder] = useState(null);
14
+ const [loading, setLoading] = useState(false);
15
+ const [selectedAction, setSelectedAction] = useState(null);
16
+ const [selectedOrderIds, setSelectedOrderIds] = useState(new Set());
17
+ const [orders, setOrders] = useState([]);
18
+ const [message, setMessage] = useState('');
19
+ const [currentPage, setCurrentPage] = useState(1);
20
+
21
+ const fetchOrders = async () => {
22
+ try {
23
+ const data = await gnarEngine.order.getOrders();
24
+ console.log('data:', data);
25
+
26
+ const ordersList = data.orders.map(order => ({
27
+ id: order._id,
28
+ type: order.type,
29
+ firstName: order.billingAddress.firstName,
30
+ lastName: order.billingAddress.lastName,
31
+ date: new Date(order.createdAt).toLocaleDateString(),
32
+ status: order.status,
33
+ total: '£' + order.total?.toFixed(2),
34
+ createdAt: formatDate(order.createdAt),
35
+ }));
36
+
37
+ setOrders(ordersList);
38
+ setMessage(ordersList.length > 0 ? '' : 'No orders found');
39
+ } catch (error) {
40
+ console.error('Error fetching orders:', error);
41
+ setOrders([]);
42
+ }
43
+ }
44
+
45
+ useEffect(() => {
46
+ fetchOrders();
47
+ }, []);
48
+
49
+ const formatDate = (isoString) => {
50
+ if (!isoString) return "N/A";
51
+
52
+ const date = new Date(isoString);
53
+ if (isNaN(date.getTime())) return "N/A"; // Checks if the date is invalid
54
+
55
+ 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')}`;
56
+ };
57
+
58
+
59
+ const handleAddNew = () => {
60
+ setView("single");
61
+ setSelectedSingleItemId(null);
62
+ setOrder(null);
63
+ }
64
+
65
+ const refreshSelectedOrder = () => {
66
+ if (!selectedSingleItemId) {
67
+ return;
68
+ }
69
+ (async () => {
70
+ try {
71
+ const data = await gnarEngine.order.getOrder(selectedSingleItemId);
72
+ setOrder(data.order);
73
+ } catch (error) {
74
+ console.error('Error fetching orders:', error);
75
+ }
76
+ })();
77
+ }
78
+
79
+ useEffect(() => {
80
+ (async () => {
81
+ if (!selectedSingleItemId) {
82
+ return;
83
+ }
84
+ try {
85
+ // fetch contact data
86
+ const data = await gnarEngine.order.getOrder(selectedSingleItemId);
87
+ setOrder(data.order);
88
+
89
+ } catch (error) {
90
+ console.error('Error fetching order:', error);
91
+ }
92
+ })();
93
+ }, [selectedSingleItemId]);
94
+
95
+ const handleAction = () => {
96
+ if (!selectedAction) {
97
+ alert("Please select an action first!");
98
+ return;
99
+ }
100
+
101
+ if (selectedAction.id === "delete") {
102
+ handleDelete();
103
+ } else if (selectedAction.id === "export") {
104
+ console.log("Export action triggered");
105
+ }
106
+ };
107
+
108
+ const handleDelete = () => {
109
+ if (selectedOrderIds.size === 0) {
110
+ alert("Please select an order to delete first!");
111
+ return;
112
+ }
113
+ if (!window.confirm(`Are you sure you want to delete ${selectedOrderIds.size} order(s)?`)) {
114
+ return;
115
+ }
116
+ (async () => {
117
+ try {
118
+ for (const orderId of selectedOrderIds) {
119
+ await gnarEngine.order.deleteOrder(orderId);
120
+ }
121
+ setSelectedOrderIds(new Set());
122
+ setSelectedAction(null);
123
+ await fetchOrders();
124
+ } catch (error) {
125
+ console.error('Error deleting order:', error);
126
+ }
127
+ })();
128
+ };
129
+
130
+ return (
131
+ <CrudLayout
132
+ view={view}
133
+ setView={setView}
134
+ selectedSingleItemId={selectedSingleItemId}
135
+ setSelectedSingleItemId={setSelectedSingleItemId}
136
+ >
137
+ <div className="crud-page">
138
+
139
+ {view === "list" ? (
140
+ <div className="crud-list-cont">
141
+ <div className="crud-list-controls">
142
+ <div className="controls-left-col">
143
+ <button onClick={handleAddNew} className="add-new">Add new</button>
144
+ </div>
145
+ <div className="controls-right-col">
146
+ <CustomSelect
147
+ name="filter-contacts"
148
+ placeholder="filter by"
149
+ options={[
150
+ { id: "all", name: "All" },
151
+ { id: "admin", name: "Admin" },
152
+ { id: "contact", name: "User" }
153
+ ]}
154
+ labelKey="name"
155
+ setSelectedOption={() => {}}
156
+ selectedOption={null}
157
+ />
158
+ <CustomSelect
159
+ name="action"
160
+ placeholder="action"
161
+ options={[
162
+ { id: "delete", name: "Delete" },
163
+ // { id: "export", name: "Export" }
164
+ ]}
165
+ labelKey="name"
166
+ setSelectedOption={setSelectedAction}
167
+ selectedOption={selectedAction}
168
+ />
169
+ <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
170
+ </div>
171
+ </div>
172
+ <CrudOrderList
173
+ setSelectedSingleItemId={setSelectedSingleItemId}
174
+ setView={() => setView('single')}
175
+ selectedOrderIds={selectedOrderIds}
176
+ setSelectedOrderIds={setSelectedOrderIds}
177
+ orders={orders}
178
+ message={message}
179
+ />
180
+ </div>
181
+ ) : (
182
+ <CrudOrderSingle
183
+ loading={loading}
184
+ setLoading={setLoading}
185
+ order={selectedOrder}
186
+ setView={() => setView('list')}
187
+ refreshSelectedOrder={refreshSelectedOrder}
188
+ setOrder={setOrder}
189
+ fetchOrders={fetchOrders}
190
+ formatDate={formatDate}
191
+ setSelectedSingleItemId={setSelectedSingleItemId}
192
+ />
193
+ )}
194
+ </div>
195
+ </CrudLayout>
196
+ );
197
+ }
198
+
199
+ export default Orders;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import LoginLayout from "../../layouts/LoginLayout";
3
+ import PasswordResetForm from "../../features/passwordReset/PasswordResetForm";
4
+
5
+ const PasswordResetPage = () => {
6
+ return (
7
+ <LoginLayout>
8
+
9
+ <PasswordResetForm />
10
+
11
+ </LoginLayout>
12
+ );
13
+ }
14
+
15
+ export default PasswordResetPage;
@@ -0,0 +1,15 @@
1
+ import React from "react";
2
+ import LoginLayout from "../../layouts/LoginLayout";
3
+ import PasswordResetRequestForm from "../../features/passwordReset/PasswordResetRequestForm";
4
+
5
+ const PasswordResetRequestPage = () => {
6
+ return (
7
+ <LoginLayout>
8
+
9
+ <PasswordResetRequestForm />
10
+
11
+ </LoginLayout>
12
+ );
13
+ }
14
+
15
+ export default PasswordResetRequestPage;
@@ -0,0 +1,10 @@
1
+ const Payments = () => {
2
+
3
+ return (
4
+ <div>
5
+ <h1>Payments Page</h1>
6
+ </div>
7
+ );
8
+ }
9
+
10
+ export default Payments;
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import { Routes, Route, Outlet } from 'react-router-dom';
3
+ import PortalLayout from "../../layouts/PortalLayout";
4
+ import Dashboard from "../dashboard/Dashboard";
5
+ import Products from "../products/Products";
6
+ import Reports from "../reports/Reports";
7
+ import Orders from "../orders/Orders";
8
+ import Integrations from "../integrations/Integrations";
9
+ import Contacts from "../contacts/Contacts";
10
+ import Payments from "../payments/Payments";
11
+ import Settings from "../settings/Settings";
12
+ import Users from "../users/Users";
13
+ import Subscriptions from "../subscriptions/Subscriptions";
14
+ import RaffleEntries from "../raffleEntries/RaffleEntries";
15
+ import Raffles from "../raffles/Raffles";
16
+
17
+
18
+ const Portal = () => {
19
+
20
+ return (
21
+ <PortalLayout>
22
+
23
+ <Routes>
24
+ <Route path="/" element={<Dashboard />} />
25
+ <Route path="/products" element={<Products />} />
26
+ <Route path="/orders" element={<Orders />} />
27
+ <Route path="/subscriptions" element={<Subscriptions />} />
28
+ <Route path="/integrations" element={<Integrations />} />
29
+ <Route path="/raffles" element={<Raffles />} />
30
+ <Route path="/raffle-entries" element={<RaffleEntries />} />
31
+ <Route path="/contacts" element={<Contacts />} />
32
+ <Route path="/payments" element={<Payments />} />
33
+ <Route path="/users" element={<Users />} />
34
+ <Route path="/reports" element={<Reports />} />
35
+ <Route path="/settings" element={<Settings />} />
36
+ </Routes>
37
+
38
+ <Outlet />
39
+ </PortalLayout>
40
+ );
41
+ }
42
+
43
+ export default Portal;