@gnar-engine/cli 1.0.3 → 1.0.4

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 (160) hide show
  1. package/bootstrap/deploy.localdev.yml +18 -31
  2. package/bootstrap/secrets.localdev.yml +7 -12
  3. package/bootstrap/services/user/Dockerfile +1 -1
  4. package/package.json +1 -1
  5. package/src/config.js +2 -1
  6. package/src/dev/dev.service.js +44 -16
  7. package/src/scaffolder/commands.js +11 -4
  8. package/src/scaffolder/scaffolder.handler.js +228 -55
  9. package/templates/service/Dockerfile.hbs +4 -1
  10. package/templates/service/package.json.hbs +14 -16
  11. package/templates/service/{app.js.hbs → src/app.js.hbs} +8 -4
  12. package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +1 -2
  13. package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs} +11 -18
  14. package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +6 -0
  15. package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
  16. package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
  17. package/bootstrap/services/agent/Dockerfile +0 -23
  18. package/bootstrap/services/agent/notes.md +0 -28
  19. package/bootstrap/services/agent/package.json +0 -16
  20. package/bootstrap/services/agent/src/app.js +0 -52
  21. package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
  22. package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
  23. package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
  24. package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
  25. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
  26. package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
  27. package/bootstrap/services/agent/src/services/agent.service.js +0 -259
  28. package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
  29. package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
  30. package/bootstrap/services/portal/Dockerfile +0 -23
  31. package/bootstrap/services/portal/Dockerfile.remote +0 -40
  32. package/bootstrap/services/portal/README.md +0 -22
  33. package/bootstrap/services/portal/nginx.conf +0 -12
  34. package/bootstrap/services/portal/package.json +0 -59
  35. package/bootstrap/services/portal/public/favicon.ico +0 -0
  36. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  37. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  38. package/bootstrap/services/portal/public/index.html +0 -43
  39. package/bootstrap/services/portal/public/logo192.png +0 -0
  40. package/bootstrap/services/portal/public/logo512.png +0 -0
  41. package/bootstrap/services/portal/public/manifest.json +0 -25
  42. package/bootstrap/services/portal/public/robots.txt +0 -3
  43. package/bootstrap/services/portal/src/App.js +0 -56
  44. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
  45. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
  46. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
  47. package/bootstrap/services/portal/src/assets/activity.svg +0 -3
  48. package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
  49. package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
  50. package/bootstrap/services/portal/src/assets/bin.svg +0 -3
  51. package/bootstrap/services/portal/src/assets/check.svg +0 -3
  52. package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
  53. package/bootstrap/services/portal/src/assets/contact.svg +0 -3
  54. package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
  55. package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
  56. package/bootstrap/services/portal/src/assets/eye.svg +0 -4
  57. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
  58. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
  59. package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
  60. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  61. package/bootstrap/services/portal/src/assets/home.svg +0 -3
  62. package/bootstrap/services/portal/src/assets/link.svg +0 -3
  63. package/bootstrap/services/portal/src/assets/lock.svg +0 -3
  64. package/bootstrap/services/portal/src/assets/package.svg +0 -4
  65. package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
  66. package/bootstrap/services/portal/src/assets/settings.svg +0 -4
  67. package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
  68. package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
  69. package/bootstrap/services/portal/src/assets/user.svg +0 -3
  70. package/bootstrap/services/portal/src/assets/users.svg +0 -3
  71. package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
  72. package/bootstrap/services/portal/src/css/style.css +0 -1007
  73. package/bootstrap/services/portal/src/data/data.js +0 -70
  74. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
  75. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
  76. package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
  77. package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
  78. package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
  79. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
  80. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
  81. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
  82. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
  83. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
  84. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
  85. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
  86. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
  87. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
  88. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
  89. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
  90. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
  91. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
  92. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
  93. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
  94. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
  95. package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
  96. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
  97. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
  98. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
  99. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
  100. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
  101. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
  102. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
  103. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
  104. package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
  105. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
  106. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
  107. package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
  108. package/bootstrap/services/portal/src/features/user/user.less +0 -57
  109. package/bootstrap/services/portal/src/includes/utilities.js +0 -259
  110. package/bootstrap/services/portal/src/index.js +0 -14
  111. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
  112. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
  113. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
  114. package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
  115. package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
  116. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
  117. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
  118. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
  119. package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
  120. package/bootstrap/services/portal/src/pages/login/login.less +0 -10
  121. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
  122. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
  123. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
  124. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
  125. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
  126. package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
  127. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
  128. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
  129. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
  130. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
  131. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
  132. package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
  133. package/bootstrap/services/portal/src/pages/users/users.less +0 -25
  134. package/bootstrap/services/portal/src/slices/authSlice.js +0 -71
  135. package/bootstrap/services/portal/src/store/configureStore.js +0 -12
  136. package/bootstrap/services/portal/src/styles/global.less +0 -159
  137. package/bootstrap/services/portal/src/styles/inputs.less +0 -157
  138. package/bootstrap/services/portal/src/styles/main.less +0 -26
  139. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
  140. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
  141. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
  142. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
  143. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
  144. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
  145. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +0 -63
  146. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +0 -92
  147. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
  148. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
  149. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
  150. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
  151. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
  152. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  153. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
  154. package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
  155. /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
  156. /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
  157. /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
  158. /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
  159. /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
  160. /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
@@ -1,402 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import CustomSelect from '../../ui/customSelect/CustomSelect';
3
- import { userRoles } from '../../data/data';
4
- import gnarEngine from '@gnar-engine/js-client';
5
- import SaveButton from '../../ui/saveButton/SaveButton';
6
- import Eye from '../../assets/eye.svg'
7
- import EyeOff from '../../assets/eye-off.svg'
8
- import arrow from '../../assets/arrow.svg';
9
- import { useSelector } from 'react-redux';
10
-
11
-
12
- const CrudUserSingle = ({selectedUser, setUser, setView, loading, setLoading, refreshSelectedUser, fetchUsers, formatDate, setSelectedSingleItemId}) => {
13
-
14
- const user = useSelector(state => state.auth.authUser);
15
- const [formData, setFormData] = useState({
16
- email: '',
17
- username: '',
18
- role: '',
19
- apiKey: ''
20
- });
21
- const [validationErrors, setValidationErrors] = useState([]);
22
- const [passwordResetSuccess, setPasswordResetSuccess] = useState(false);
23
- const [showPassword, setShowPassword] = useState(false);
24
- const [selectedAction, setSelectedAction] = useState(null);
25
-
26
-
27
- // prepare form data for editing existing user
28
- useEffect(() => {
29
- console.log('user:', selectedUser);
30
- // set form data for updating user
31
- if (selectedUser && selectedUser.id) {
32
- const newFormData = {...selectedUser};
33
- setFormData(newFormData);
34
- }
35
-
36
- // set back to default if no user is selected
37
- else {
38
- setFormData({
39
- email: ''
40
- });
41
- }
42
-
43
- setLoading(null);
44
- }, [selectedUser]);
45
-
46
- // handle form data changes
47
- const handleChange = (e) => {
48
- setValidationErrors([]);
49
-
50
- const { name, value } = e.target;
51
- setFormData(prevData => ({
52
- ...prevData,
53
- [name]: value
54
- }));
55
- };
56
-
57
-
58
- // handle delete user
59
- const handleDelete = async (selectedUser) => {
60
- if (window.confirm('Are you sure you want to delete this user?')) {
61
- try {
62
- setLoading('loading');
63
-
64
- console.log('selectedUser:', selectedUser);
65
-
66
- await gnarEngine.user.delete(selectedUser.id);
67
-
68
- setLoading('success');
69
- setTimeout(() => {
70
- setLoading(null);
71
- }, 3000);
72
-
73
- refreshSelectedUser();
74
- await fetchUsers();
75
- setView('list');
76
-
77
- } catch (error) {
78
-
79
- setLoading('error');
80
- console.error('Error deleting user:', error);
81
- }
82
- } else {
83
- console.log('Deletion canceled');
84
- }
85
- };
86
-
87
- const handleSubmit = async (e) => {
88
- e.preventDefault();
89
- setValidationErrors([]); // Clear any previous validation errors
90
-
91
- // Set loading state to 'loading'
92
- setLoading('loading');
93
-
94
- try {
95
- if (selectedUser) {
96
- // Update existing user
97
- const data = { ...formData };
98
- delete data.created_at;
99
- delete data.updated_at;
100
- delete data.id;
101
-
102
- const updatedUserResponse = await gnarEngine.user.update(selectedUser.id, data);
103
-
104
- setLoading('success');
105
- setTimeout(() => {
106
- setLoading(null);
107
- refreshSelectedUser(updatedUserResponse.user);
108
- }, 3000);
109
-
110
- } else {
111
- // Creating a new user
112
- await gnarEngine.user.createUser(formData);
113
-
114
- setLoading('success');
115
- setTimeout(() => {
116
- setLoading(null);
117
- fetchUsers();
118
- setView('list');
119
-
120
- }, 3000);
121
- }
122
- } catch (error) {
123
- // Collect server-side validation errors, if any
124
- const errors = [];
125
-
126
- if (error.response?.data?.errors) {
127
- Object.keys(error.response.data.errors).forEach((key) => {
128
- errors.push(error.response.data.errors[key]);
129
- });
130
- } else if (error.response?.data?.message) {
131
- errors.push(error.response.data.message);
132
- }
133
-
134
- setValidationErrors(errors); // Set validation errors to be displayed
135
- console.error('Error saving user:', error);
136
-
137
- setLoading('error');
138
- setTimeout(() => {
139
- setLoading(null);
140
- }, 3000);
141
- }
142
- };
143
-
144
- const handleAction = () => {
145
- if (!selectedAction) {
146
- alert("Please select an action first!");
147
- return;
148
- }
149
-
150
- if (selectedAction.id === "delete") {
151
- handleDelete(selectedUser);
152
- } else if (selectedAction.id === "export") {
153
- console.log("Export action triggered");
154
- }
155
- };
156
-
157
-
158
-
159
- const handlePasswordReset = async () => {
160
- if (!selectedUser || !selectedUser.id) {
161
- return;
162
- }
163
-
164
- setPasswordResetSuccess(true); // Show success message
165
- setTimeout(() => {
166
- setPasswordResetSuccess(false); // Hide it after 3 seconds
167
- }, 3000);
168
-
169
- try {
170
- await gnarEngine.sendPasswordReset({ email: selectedUser.email });
171
-
172
- } catch (error) {
173
- const errors = [];
174
-
175
- if (error.response.data.errors) {
176
- Object.keys(error.response.data.errors).forEach((key) => {
177
- errors.push(error.response.data.errors[key]);
178
- });
179
- } else if (error.response.data.message && error.response.data.error) {
180
- errors.push(error.response.data.message);
181
- errors.push(error.response.data.error);
182
- }
183
-
184
- setValidationErrors(errors);
185
- console.error('Error sending password reset:', error);
186
- }
187
- }
188
-
189
- const routeKey = 'manage-users';
190
- const handleMenuBtnClick = () => setView({ isBackToList: true });
191
-
192
- // add event listener to sidebar buttons to change view
193
- useEffect(() => {
194
- const sidebarButtons = document.querySelectorAll('.sidebar a[href^="/portal/' + routeKey + '"]');
195
- sidebarButtons.forEach(button => {
196
- // if it doesn't already have an event listener
197
- if (!button.hasEventListener) {
198
- button.addEventListener('click', handleMenuBtnClick);
199
- }
200
- })
201
-
202
- // Cleanup to prevent memory leaks and double bindings
203
- return () => {
204
- sidebarButtons.forEach(button => {
205
- button.removeEventListener('click', handleMenuBtnClick);
206
- });
207
- };
208
- }, []);
209
-
210
- return (
211
- <div className="single-edit user">
212
- <div className='single-edit-header'>
213
- <div className='single-edit-header-left'>
214
- {selectedUser && selectedUser.id &&
215
- <>
216
- <p><strong>User ID:&nbsp;</strong>{selectedUser.id}</p>
217
- <p><strong>Email:&nbsp;</strong>{selectedUser.email}</p>
218
- <p><strong>Role:&nbsp;</strong>{selectedUser.role}</p>
219
- <p><strong>Date Added:&nbsp;</strong>{formatDate(selectedUser?.createdAt)}</p>
220
- </>
221
- }
222
- </div>
223
- <div className='single-edit-header-right'>
224
- <div className="flex-row-buttons-cont">
225
- <button onClick={() => {
226
- setView('list');
227
- setUser(null);
228
- setSelectedSingleItemId(null);
229
- }} className="secondaryButton">
230
- Back
231
- </button>
232
- <button onClick={() => handleDelete(selectedUser)} className="secondaryButton">Delete</button>
233
- <SaveButton
234
- save={handleSubmit}
235
- loading={loading}
236
- textCreate="Add User"
237
- textCreateLoading="Saving..."
238
- textCreateSuccess="Saved"
239
- textCreateError="Error"
240
- textUpdate="Save"
241
- textUpdateLoading="Updating..."
242
- textUpdateSuccess="Updated"
243
- textUpdateError="Error"
244
- isUpdating={!!selectedUser}
245
- />
246
- </div>
247
- {validationErrors.length > 0 &&
248
- <div className="error-messages">
249
- {validationErrors.map((error, index) => {
250
- return <p key={index}>{error}</p>
251
- })}
252
- </div>
253
- }
254
- </div>
255
-
256
- </div>
257
-
258
- <h2>Details</h2>
259
-
260
- <div className='card account'>
261
- <div className='card-header'>
262
- <h2>Account</h2>
263
- </div>
264
- <div className='card-content'>
265
- <form className='user-form' onSubmit={handleSubmit}>
266
- <div className='form-group'>
267
- <label>Email:</label>
268
- <input
269
- type="text"
270
- name="email"
271
- value={formData.email}
272
- onChange={handleChange}
273
- required
274
- />
275
- </div>
276
-
277
- {selectedUser && selectedUser.id &&
278
- <div className='form-group'>
279
- <label>Username:</label>
280
- <input
281
- type="text"
282
- name="username"
283
- value={formData.username}
284
- onChange={handleChange}
285
- required
286
- />
287
- </div>
288
- }
289
-
290
- {!selectedUser &&
291
- <div>
292
- <label>Password:</label>
293
- <input
294
- type="password"
295
- name="password"
296
- value={formData.password}
297
- onChange={handleChange}
298
- required
299
- />
300
- </div>
301
- }
302
-
303
-
304
- <div className='form-group'>
305
- <label>User Role:</label>
306
- <CustomSelect
307
- name="select-user-role"
308
- placeholder="Select User Role"
309
- options={userRoles}
310
- labelKey="name"
311
- setSelectedOption={(option) => setFormData(prev => ({ ...prev, role: option.role }))}
312
- selectedOption={userRoles.find(role => role.role === formData.role) || null}
313
- required
314
- />
315
- </div>
316
- </form>
317
- {selectedUser && selectedUser.id &&
318
- <div className='form-group'>
319
- <a onClick={() => handlePasswordReset()} className="password-reset-btn">Send password reset</a>
320
- {passwordResetSuccess && <p>Password reset email sent successfully!</p>}
321
- </div>
322
- }
323
- </div>
324
- </div>
325
-
326
- {selectedUser && selectedUser.id &&
327
- <div className='card contacts'>
328
- <div className='card-header'>
329
- <h2>Contacts</h2>
330
- </div>
331
- <div className='card-content'>
332
- <p>Contact details associated with this user.</p>
333
- <form onSubmit={handleSubmit}>
334
- <div className='form-group'>
335
- <label>Type</label>
336
- <input
337
- type="text"
338
- name="email"
339
- value={formData.type}
340
- onChange={handleChange}
341
- required
342
- />
343
- </div>
344
-
345
- <div className='form-group'>
346
- <label>Name</label>
347
- <input
348
- type="text"
349
- name="name"
350
- value={formData.name}
351
- onChange={handleChange}
352
- required
353
- />
354
- </div>
355
- <button className="secondaryButton">View / Edit</button>
356
- </form>
357
- </div>
358
- </div>
359
- }
360
-
361
- {user && user.id && user.role === 'service_admin' || !selectedUser &&
362
- <>
363
- <h2>API Access (Service Admin Only)</h2>
364
- <div className='card api-key'>
365
- <div className='card-header'>
366
- <h2>API Keys</h2>
367
- </div>
368
- <div className='card-content'>
369
- <form onSubmit={handleSubmit}>
370
- <div className='form-group'>
371
- <label>Key</label>
372
- <input
373
- type={showPassword ? "text" : "password"}
374
- name="apiKey"
375
- value={formData.apiKey}
376
- onChange={handleChange}
377
- required
378
- />
379
- <button
380
- type="button"
381
- onClick={() => setShowPassword((prev) => !prev)}
382
- style={{
383
- position: "absolute",
384
- right: "0",
385
- background: "none",
386
- border: "none",
387
- cursor: "pointer"
388
- }}
389
- >
390
- <img src={showPassword ? Eye : EyeOff} alt="Show password" />
391
- </button>
392
- </div>
393
- </form>
394
- </div>
395
- </div>
396
- </>
397
- }
398
- </div>
399
- );
400
- };
401
-
402
- export default CrudUserSingle;
@@ -1,30 +0,0 @@
1
- import bin from '../../assets/bin.svg';
2
- import { useState } from 'react';
3
- import { currencies, taxClasses } from '../../data/data';
4
- import CustomSelect from '../../ui/customSelect/CustomSelect';
5
-
6
- const InventoryFormRow = ({ item, onChange, remove }) => {
7
-
8
-
9
- return (
10
- <div className='form-row'>
11
- <input
12
- type="text"
13
- name='price'
14
- value={item.price}
15
- onChange={(e) => onChange("price", Number(e.target.value))}
16
- />
17
- <input
18
- type="text"
19
- name='salePrice'
20
- value={item.salePrice}
21
- onChange={(e) => onChange("price", Number(e.target.value))}
22
- />
23
-
24
- <button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
25
- </div>
26
- )
27
- }
28
-
29
-
30
- export default InventoryFormRow;
@@ -1,113 +0,0 @@
1
- const LineItems = ({order}) => {
2
-
3
- return (
4
- <div className="card">
5
- <div className='card-header'>
6
- <h2>Line Items & Totals</h2>
7
- </div>
8
- <div className='card-content'>
9
- <div className="line-items-totals-cont">
10
-
11
- {/* Line Items Section */}
12
- <div className="line-items-cont">
13
- <div className="line-items-body">
14
- {order?.lineItems && order.lineItems.length > 0 ? (
15
- <table className="line-items-table">
16
-
17
- {order?.originalSubscriptionOrderId && (
18
- <>
19
- <thead>
20
- <tr>
21
- <th>Product</th>
22
- <th>SKU</th>
23
- <th>Price</th>
24
- <th>Quantity</th>
25
- <th>Discount</th>
26
- <th>Subtotal</th>
27
- </tr>
28
- </thead>
29
- <tbody>
30
- {order.lineItems.map((item, index) => (
31
- <tr key={index}>
32
- <td>{item.sku.replace(/-/g, ' ').toUpperCase()}</td>
33
- <td>{item.sku}</td>
34
- <td>£{item.price.toFixed(2)}</td>
35
- <td>x{item.quantity}</td>
36
- <td>£{'0.00' ||item.discount}</td>
37
- <td>£{(item.quantity * item.price).toFixed(2)}</td>
38
- </tr>
39
- ))}
40
- </tbody>
41
- </>
42
- )}
43
-
44
- {order?.type === 'order' && (
45
- <>
46
- <thead>
47
- <tr>
48
- <th>Product</th>
49
- <th>SKU</th>
50
- <th>Price</th>
51
- <th>Quantity</th>
52
- <th>Type</th>
53
- <th>Subtotal</th>
54
- </tr>
55
- </thead>
56
- <tbody>
57
- {order.lineItems.map((item, index) => (
58
- <tr key={index}>
59
- <td>{item.sku.replace(/-/g, ' ').toUpperCase()}</td>
60
- <td>{item.sku}</td>
61
- <td>£{item.price.price.toFixed(2)}</td>
62
- <td>x{item.quantity}</td>
63
- <td>{item.type}</td>
64
- <td>£{(item.quantity * item.price.price).toFixed(2)}</td>
65
- </tr>
66
- ))}
67
- </tbody>
68
- </>
69
- )}
70
- </table>
71
- ) : (
72
- <p>No line items found.</p>
73
- )}
74
- </div>
75
- </div>
76
-
77
- {/* Order Totals Section */}
78
- <div className="totals-cont">
79
- <div className="totals-body">
80
- <table className="totals-table">
81
- <tbody>
82
- <tr>
83
- <td>Currency:</td>
84
- <td>{order?.currency}</td>
85
- </tr>
86
- <tr>
87
- <td>Items Subtotal:</td>
88
- <td>£{(order?.subTotal ?? order?.subTotal)?.toFixed(2)}</td>
89
- </tr>
90
- <tr>
91
- <td>Shipping:</td>
92
- <td>£{'0.00' || order?.shipping.toFixed(2)}</td>
93
- </tr>
94
- <tr>
95
- <td>Tax:</td>
96
- <td>£{(order?.tax ?? order?.tax)?.toFixed(2)}</td>
97
- </tr>
98
- <tr className="order-total">
99
- <td><strong>Total:</strong></td>
100
- <td><strong>£{order?.total?.toFixed(2)}</strong></td>
101
- </tr>
102
- </tbody>
103
- </table>
104
- </div>
105
- </div>
106
-
107
- </div>
108
- </div>
109
- </div>
110
- );
111
- }
112
-
113
- export default LineItems;
@@ -1,56 +0,0 @@
1
- import React, {useState, useEffect} from "react";
2
- import {useDispatch, useSelector} from "react-redux";
3
- import { login } from "../../slices/authSlice";
4
- import { Link } from "react-router-dom";
5
-
6
- const LoginForm = () => {
7
-
8
- const saltRounds = 12;
9
- const dispatch = useDispatch();
10
- const [username, setUsername] = useState("");
11
- const [password, setPassword] = useState("");
12
- const [loginMessage, setLoginMessage] = useState("");
13
- const {authError} = useSelector(state => state.auth);
14
-
15
- const handleLogin = async (e) => {
16
- e.preventDefault();
17
-
18
- if (username === "" || password === "") {
19
- setLoginMessage("Please enter your email and password");
20
- return;
21
- }
22
- try {
23
- dispatch(login({username, password}));
24
-
25
- } catch (error) {
26
- setLoginMessage("Error logging in: " + error.response?.data?.message || "Unknown error");
27
- console.error('Error logging in:', error);
28
- }
29
- }
30
-
31
- useEffect(() => {
32
- if (authError) {
33
- setLoginMessage(authError);
34
- }
35
- }, [authError])
36
-
37
- return (
38
- <div className="login">
39
- <form className="login-form" onSubmit={handleLogin}>
40
- <div className="input-container">
41
- <input type="text" placeholder="Email address / Username" className="email-input-icon" value={username} onChange={(e) => { setUsername(e.target.value); setLoginMessage(''); }} />
42
- </div>
43
- <div className="input-container">
44
- <input type="password" placeholder="Password" className="password-input-icon" value={password} onChange={(e) => { setPassword(e.target.value); setLoginMessage(''); }}/>
45
- </div>
46
- <div>
47
- <button type="submit">Sign in</button>
48
- <Link to="/login/forgotten-password">password reset</Link>
49
- </div>
50
- <span id="login-message">{loginMessage}</span>
51
- </form>
52
- </div>
53
- );
54
- }
55
-
56
- export default LoginForm;
@@ -1,56 +0,0 @@
1
- .login {
2
- display: flex;
3
- flex-direction: column;
4
- align-items: center;
5
- justify-content: center;
6
-
7
- .login-form {
8
- display: flex;
9
- flex-direction: column;
10
- width: 400px;
11
-
12
- #login-message {
13
- color: @red-1;
14
- min-height: 40px;
15
- }
16
-
17
- button.loading {
18
- opacity: 0.6;
19
- cursor: not-allowed;
20
- }
21
-
22
- a {
23
- text-decoration: none;
24
- color: @green-1;
25
- margin-left: 10px;
26
- }
27
-
28
- .input-container {
29
- position: relative;
30
-
31
- input {
32
- padding-left: 50px;
33
- }
34
-
35
- &::before {
36
- content: '';
37
- position: absolute;
38
- top: 50%;
39
- left: 18px;
40
- transform: translateY(-50%);
41
- width: 20px;
42
- height: 20px;
43
- background-size: contain;
44
- background-repeat: no-repeat;
45
- }
46
-
47
- &:nth-child(1)::before {
48
- background-image: url('../assets/user-black.svg');
49
- }
50
-
51
- &:nth-child(2)::before {
52
- background-image: url('../assets/lock.svg');
53
- }
54
- }
55
- }
56
- }
@@ -1,18 +0,0 @@
1
- import bin from '../../assets/bin.svg';
2
-
3
- const Notes = ({ item, onChange, remove }) => {
4
- return (
5
- <div className="note-item">
6
- <div className="note-item-body">
7
- <textarea
8
- value={item.note || ''}
9
- onChange={(e) => onChange({ note: e.target.value })}
10
- placeholder="Add a note..."
11
- />
12
- </div>
13
- <button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
14
- </div>
15
- );
16
- };
17
-
18
- export default Notes;