@gnar-engine/cli 1.0.2 → 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 (161) 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/install.sh +32 -0
  5. package/package.json +1 -1
  6. package/src/config.js +2 -1
  7. package/src/dev/dev.service.js +44 -16
  8. package/src/scaffolder/commands.js +11 -4
  9. package/src/scaffolder/scaffolder.handler.js +228 -55
  10. package/templates/service/Dockerfile.hbs +4 -1
  11. package/templates/service/package.json.hbs +14 -16
  12. package/templates/service/{app.js.hbs → src/app.js.hbs} +8 -4
  13. package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +1 -2
  14. package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs} +11 -18
  15. package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +6 -0
  16. package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
  17. package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
  18. package/bootstrap/services/agent/Dockerfile +0 -23
  19. package/bootstrap/services/agent/notes.md +0 -28
  20. package/bootstrap/services/agent/package.json +0 -16
  21. package/bootstrap/services/agent/src/app.js +0 -52
  22. package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
  23. package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
  24. package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
  25. package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
  26. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
  27. package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
  28. package/bootstrap/services/agent/src/services/agent.service.js +0 -259
  29. package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
  30. package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
  31. package/bootstrap/services/portal/Dockerfile +0 -23
  32. package/bootstrap/services/portal/Dockerfile.remote +0 -40
  33. package/bootstrap/services/portal/README.md +0 -22
  34. package/bootstrap/services/portal/nginx.conf +0 -12
  35. package/bootstrap/services/portal/package.json +0 -59
  36. package/bootstrap/services/portal/public/favicon.ico +0 -0
  37. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  38. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  39. package/bootstrap/services/portal/public/index.html +0 -43
  40. package/bootstrap/services/portal/public/logo192.png +0 -0
  41. package/bootstrap/services/portal/public/logo512.png +0 -0
  42. package/bootstrap/services/portal/public/manifest.json +0 -25
  43. package/bootstrap/services/portal/public/robots.txt +0 -3
  44. package/bootstrap/services/portal/src/App.js +0 -56
  45. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
  46. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
  47. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
  48. package/bootstrap/services/portal/src/assets/activity.svg +0 -3
  49. package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
  50. package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
  51. package/bootstrap/services/portal/src/assets/bin.svg +0 -3
  52. package/bootstrap/services/portal/src/assets/check.svg +0 -3
  53. package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
  54. package/bootstrap/services/portal/src/assets/contact.svg +0 -3
  55. package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
  56. package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
  57. package/bootstrap/services/portal/src/assets/eye.svg +0 -4
  58. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
  59. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
  60. package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
  61. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  62. package/bootstrap/services/portal/src/assets/home.svg +0 -3
  63. package/bootstrap/services/portal/src/assets/link.svg +0 -3
  64. package/bootstrap/services/portal/src/assets/lock.svg +0 -3
  65. package/bootstrap/services/portal/src/assets/package.svg +0 -4
  66. package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
  67. package/bootstrap/services/portal/src/assets/settings.svg +0 -4
  68. package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
  69. package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
  70. package/bootstrap/services/portal/src/assets/user.svg +0 -3
  71. package/bootstrap/services/portal/src/assets/users.svg +0 -3
  72. package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
  73. package/bootstrap/services/portal/src/css/style.css +0 -1007
  74. package/bootstrap/services/portal/src/data/data.js +0 -70
  75. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
  76. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
  77. package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
  78. package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
  79. package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
  80. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
  81. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
  82. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
  83. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
  84. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
  85. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
  86. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
  87. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
  88. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
  89. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
  90. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
  91. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
  92. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
  93. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
  94. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
  95. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
  96. package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
  97. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
  98. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
  99. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
  100. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
  101. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
  102. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
  103. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
  104. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
  105. package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
  106. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
  107. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
  108. package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
  109. package/bootstrap/services/portal/src/features/user/user.less +0 -57
  110. package/bootstrap/services/portal/src/includes/utilities.js +0 -259
  111. package/bootstrap/services/portal/src/index.js +0 -14
  112. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
  113. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
  114. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
  115. package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
  116. package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
  117. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
  118. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
  119. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
  120. package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
  121. package/bootstrap/services/portal/src/pages/login/login.less +0 -10
  122. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
  123. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
  124. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
  125. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
  126. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
  127. package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
  128. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
  129. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
  130. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
  131. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
  132. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
  133. package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
  134. package/bootstrap/services/portal/src/pages/users/users.less +0 -25
  135. package/bootstrap/services/portal/src/slices/authSlice.js +0 -71
  136. package/bootstrap/services/portal/src/store/configureStore.js +0 -12
  137. package/bootstrap/services/portal/src/styles/global.less +0 -159
  138. package/bootstrap/services/portal/src/styles/inputs.less +0 -157
  139. package/bootstrap/services/portal/src/styles/main.less +0 -26
  140. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
  141. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
  142. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
  143. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
  144. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
  145. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
  146. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +0 -63
  147. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +0 -92
  148. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
  149. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
  150. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
  151. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
  152. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
  153. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  154. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
  155. package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
  156. /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
  157. /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
  158. /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
  159. /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
  160. /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
  161. /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
@@ -1,208 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import gnarEngine from '@gnar-engine/js-client';
3
- import SaveButton from "../../ui/saveButton/SaveButton";
4
- import Repeater from "../../ui/repeater/Repeater";
5
- import { raffleStatuses } from "../../data/data";
6
- import bin from '../../assets/bin.svg';
7
- import RaffleProductFormRow from "../raffleProductFormRow/RaffleProductFormRow";
8
- import CustomSelect from "../../ui/customSelect/CustomSelect";
9
-
10
-
11
- const CrudRafflesSingle = ({ loading, setLoading, raffle, setView, refreshSelectedRaffle, setRaffle, formatDate, setSelectedSingleItemId, fetchRaffles }) => {
12
- const initialForm = {
13
- name: '',
14
- status: { id: 'draft', status: 'Draft' }, // default to draft status
15
- description: '',
16
- prizeDescription: '',
17
- raffleProducts: [
18
- { productSku: '', type: '', numEntries: '' }
19
- ]
20
- };
21
-
22
- const [formData, setFormData] = useState(initialForm);
23
- const [validationErrors, setValidationErrors] = useState([]);
24
-
25
- // when raffle prop changes, populate form
26
- useEffect(() => {
27
- const raffleStatus = raffleStatuses.find(status => status.id === (raffle?.status || 'draft'));
28
-
29
- if (raffle && raffle.id) {
30
- setFormData({
31
- name: raffle.name || '',
32
- status: raffleStatus,
33
- description: raffle.description || '',
34
- prizeDescription: raffle.prize_description || '',
35
- raffleProducts: raffle.raffleProducts?.map(p => ({
36
- productSku: p.product_sku || '',
37
- numEntries: p.num_entries?.toString() || '',
38
- type: p.type || 'one-time'
39
- })) || [{ productSku: '', numEntries: '', type: 'one-time' }]
40
- });
41
- } else {
42
- setFormData(initialForm);
43
- }
44
- }, [raffle]);
45
-
46
-
47
- // handle change for text/textarea inputs
48
- const handleFieldChange = (field, value) => {
49
- setFormData({ ...formData, [field]: value });
50
- };
51
-
52
- const handleSubmit = async (e) => {
53
- e.preventDefault();
54
- setLoading('loading');
55
- setValidationErrors([]);
56
-
57
- // prepare payload: convert numEntries to number
58
- const payload = {
59
- name: formData.name,
60
- status: formData.status.id,
61
- description: formData.description,
62
- prizeDescription: formData.prizeDescription,
63
- raffleProducts: formData.raffleProducts.map(p => ({
64
- productSku: p.productSku,
65
- type: p.type,
66
- numEntries: Number(p.numEntries) || 1,
67
- }))
68
- };
69
-
70
-
71
- try {
72
- let response;
73
- if (raffle && raffle.id) {
74
- response = await gnarEngine.raffles.updateRaffle(raffle.id, payload);
75
- } else {
76
- response = await gnarEngine.raffles.createRaffle([payload]);
77
- }
78
-
79
- if (response.error) {
80
- setValidationErrors(response.error);
81
- setLoading('error');
82
- } else {
83
- setLoading('success');
84
- setTimeout(() => {
85
- setLoading(null)
86
- }, 3000);
87
-
88
- if (raffle && raffle.id) {
89
- refreshSelectedRaffle();
90
- } else {
91
- setRaffle(response.raffle);
92
- refreshSelectedRaffle();
93
- await fetchRaffles();
94
- setView('list');
95
- }
96
- }
97
- } catch (error) {
98
- console.error('Error saving raffle:', error);
99
- setValidationErrors(['Error saving raffle']);
100
- setLoading('error');
101
- setTimeout(() => setLoading(null), 3000);
102
- }
103
- };
104
-
105
- const handleDelete = async () => {
106
- if (!raffle?.id)
107
- return;
108
- if (window.confirm('Are you sure you want to delete this raffle?')) {
109
- try {
110
- setLoading('loading');
111
- await gnarEngine.raffles.deleteRaffle(raffle.id);
112
- setLoading('success');
113
- setTimeout(() => {
114
- setLoading(null);
115
- }, 3000);
116
-
117
- refreshSelectedRaffle();
118
- await fetchRaffles();
119
- setView('list');
120
- } catch (error) {
121
- console.error('Error deleting raffle:', error);
122
- setLoading('error');
123
- }
124
- }
125
- };
126
-
127
- return (
128
- <div className="single-edit raffle">
129
- {validationErrors.length > 0 && (
130
- <div className="error-messages">
131
- {validationErrors.map((err, i) => <p key={i}>{err}</p>)}
132
- </div>
133
- )}
134
-
135
- <div className="single-edit-header">
136
- <div className="single-edit-header-left">
137
- <p><strong>{raffle?.id ? `Raffle# ${raffle.id}` : 'Add New Raffle'}</strong></p>
138
- {raffle?.createdAt && <p>Date Added: {formatDate(raffle.createdAt)}</p>}
139
- </div>
140
- <div className="single-edit-header-right flex-row-buttons-cont">
141
- <button type="button" onClick={() => { setView('list'); setRaffle(null); setSelectedSingleItemId(null); }} className="secondaryButton">Back</button>
142
- {raffle?.id && <button type="button" onClick={handleDelete} className="secondaryButton">Delete</button>}
143
- </div>
144
- </div>
145
-
146
- <form onSubmit={handleSubmit} className="form-body">
147
- <div className="form-group">
148
- <label>Name</label>
149
- <input type="text" value={formData.name} onChange={e => handleFieldChange('name', e.target.value)} />
150
- </div>
151
-
152
- <CustomSelect
153
- name="status"
154
- placeholder="Status"
155
- options={raffleStatuses}
156
- labelKey="status"
157
- setSelectedOption={selectedItem => handleFieldChange('status', selectedItem)}
158
- selectedOption={formData.status}
159
- />
160
-
161
- <div className="form-group">
162
- <label>Description</label>
163
- <textarea value={formData.description} onChange={e => handleFieldChange('description', e.target.value)} />
164
- </div>
165
-
166
- <div className="form-group">
167
- <label>Prize Description</label>
168
- <textarea value={formData.prizeDescription} onChange={e => handleFieldChange('prizeDescription', e.target.value)} />
169
- </div>
170
-
171
- </form>
172
-
173
- <Repeater
174
- items={formData.raffleProducts}
175
- setItems={(newItems) => setFormData({ ...formData, raffleProducts: newItems })}
176
- defaultItem={{ productSku: '', type: '', numEntries: 1 }}
177
- buttonText="Add Product"
178
- renderRow={(item, index, updateItem, remove) => (
179
- <RaffleProductFormRow
180
- key={index}
181
- item={item}
182
- onChange={(field, value) => updateItem({ ...item, [field]: value })}
183
- remove={remove}
184
- />
185
- )}
186
- />
187
-
188
-
189
- <div className="form-actions">
190
- <SaveButton
191
- save={handleSubmit}
192
- loading={loading}
193
- textCreate="Add Raffle"
194
- textCreateLoading="Saving..."
195
- textCreateSuccess="Saved"
196
- textCreateError="Error"
197
- textUpdate="Save"
198
- textUpdateLoading="Updating..."
199
- textUpdateSuccess="Updated"
200
- textUpdateError="Error"
201
- isUpdating={!!raffle?.id}
202
- />
203
- </div>
204
- </div>
205
- );
206
- };
207
-
208
- export default CrudRafflesSingle;
@@ -1,110 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import gnarEngine from '@gnar-engine/js-client';
3
- import CustomCheckbox from '../../ui/customCheckbox/CustomCheckbox';
4
-
5
- const CrudSubscriptionList = ({ setSelectedSingleItemId, setView, selectedSubscriptionIds, setSelectedSubscriptionIds, subscriptions, message}) => {
6
-
7
- const allSelected = subscriptions.length > 0 && selectedSubscriptionIds.size === subscriptions.length;
8
-
9
- const toggleContactSelection = (subscriptionId) => {
10
- setSelectedSubscriptionIds(prev => {
11
- const newSet = new Set(prev);
12
- if (newSet.has(subscriptionId)) {
13
- newSet.delete(subscriptionId);
14
- } else {
15
- newSet.add(subscriptionId);
16
- }
17
- return newSet;
18
- });
19
- };
20
-
21
-
22
- const toggleSelectAll = () => {
23
- if (allSelected) {
24
- setSelectedSubscriptionIds(new Set());
25
- } else {
26
- setSelectedSubscriptionIds(new Set(subscriptions.map(subscription => subscription.id)));
27
- }
28
- };
29
-
30
-
31
- const handleEditClick = (product) => {
32
- setSelectedSingleItemId(product.id);
33
- setView('single');
34
- };
35
-
36
- const columns = [
37
- { columnLabel: 'Subscription', dataKey: 'id' },
38
- { columnLabel: 'First Name', dataKey: 'firstName' },
39
- { columnLabel: 'Last Name', dataKey: 'lastName' },
40
- { columnLabel: 'Date', dataKey: 'createdAt' },
41
- { columnLabel: 'Status', dataKey: 'status' },
42
- { columnLabel: 'Total', dataKey: 'total' },
43
- { columnLabel: 'Date added', dataKey: 'createdAt' },
44
- ];
45
-
46
-
47
- return (
48
- <div className="">
49
- <div className='pagination-labels-cont'>
50
- <div className='pagination-count'>
51
- Showing {subscriptions.length} of {subscriptions.length} subscription{subscriptions.length !== 1 ? 's' : ''}
52
- </div>
53
- <div className="pagination-count">
54
- {selectedSubscriptionIds.size} of {subscriptions.length} subscription{subscriptions.length !== 1 ? 's' : ''} selected
55
- </div>
56
- </div>
57
- <div className='crud-list'>
58
- <table className='custom-table'>
59
- <thead>
60
- <tr>
61
- <th className="checkbox">
62
- <CustomCheckbox
63
- name="selectAll"
64
- checked={allSelected}
65
- setChecked={toggleSelectAll}
66
- />
67
- </th>
68
- {columns.map(column => (
69
- <th key={column.columnLabel}>{column.columnLabel}</th>
70
- ))}
71
- </tr>
72
- </thead>
73
-
74
- <tbody>
75
- {message ? (
76
- <tr>
77
- <td colSpan={columns.length + 1}>{message}</td>
78
- </tr>
79
- ) : (
80
- subscriptions.length > 0 ? (
81
- subscriptions.map(order => (
82
- <tr key={order.id} onClick={() => handleEditClick(order)}>
83
- <td>
84
- <CustomCheckbox
85
- name={`checkbox-${order.id}`}
86
- checked={selectedSubscriptionIds.has(order.id)}
87
- setChecked={() => toggleContactSelection(order.id)}
88
- />
89
- </td>
90
- {columns.map(column => (
91
- <td key={column.dataKey}>{order[column.dataKey]}</td>
92
- ))}
93
- </tr>
94
- ))
95
- ) : (
96
- <tr>
97
- <td colSpan={columns.length + 1}>No orders found</td>
98
- </tr>
99
- )
100
- )}
101
- </tbody>
102
- </table>
103
- </div>
104
- </div>
105
-
106
- );
107
-
108
- };
109
-
110
- export default CrudSubscriptionList;
@@ -1,261 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import gnarEngine from '@gnar-engine/js-client';
3
- import SaveButton from "../../ui/saveButton/SaveButton";
4
- import Repeater from "../../ui/repeater/Repeater";
5
- import Notes from "../notes/Notes";
6
- import CustomSelect from "../../ui/customSelect/CustomSelect";
7
- import { orderTypes, subscriptionStatuses } from '../../data/data';
8
- import { Link } from "react-router-dom";
9
- import BillingShipping from "../billingShipping/BillingShipping";
10
- import SubscriptionSchedule from "../subscriptionSchedule/SubscriptionSchedule";
11
- import LineItems from "../lineItems/LineItems";
12
-
13
-
14
- const CrudSubscriptionSingle = ({ loading, setLoading, subscription, setView, refreshSelectedSubscription, setSubscription, fetchSubscriptions, setSelectedSingleItemId, formatDate }) => {
15
-
16
- const [formData, setFormData] = useState({});
17
- const [validationErrors, setValidationErrors] = useState([]);
18
- const [orderType, setOrderType] = useState(null);
19
- const [orderStatus, setOrderStatus] = useState(null);
20
-
21
- useEffect(() => {
22
- if (subscription && subscription._id) {
23
- setFormData({
24
- ...subscription,
25
- });
26
-
27
- // set order type
28
- const existingOrderType = orderTypes.find(type => type.id === subscription.type);
29
- setOrderType(existingOrderType);
30
-
31
- // set order status
32
- const existingSubscriptionStatus = subscriptionStatuses.find(status => status.id === subscription.status);
33
- setOrderStatus(existingSubscriptionStatus);
34
-
35
- } else {
36
- setFormData({
37
- ...formData,
38
- userId: '',
39
- notes: [],
40
- type: null,
41
- status: null,
42
- billingAddress: {
43
- firstName: '',
44
- lastName: '',
45
- addressLine1: '',
46
- addressLine2: '',
47
- city: '',
48
- postcode: '',
49
- email: '',
50
- phone: '',
51
- },
52
- shippingAddress: {
53
- firstName: '',
54
- lastName: '',
55
- addressLine1: '',
56
- addressLine2: '',
57
- city: '',
58
- postcode: '',
59
- },
60
- lineItems: [],
61
- currency: 'GBP',
62
- subTotal: 0,
63
- shipping: 0,
64
- tax: 0,
65
- total: 0,
66
- });
67
- }
68
- }, [subscription]);
69
-
70
-
71
- const handleSubmit = async (e) => {
72
- e.preventDefault();
73
- setLoading('loading');
74
- setValidationErrors([]);
75
-
76
- try {
77
-
78
- // parse ints
79
- formData.retryAttempt = parseInt(formData.retryAttempt) || 0;
80
-
81
- if (subscription) {
82
- const response = await gnarEngine.subscription.updateSubscription(subscription._id, formData);
83
- console.log('response:', response);
84
-
85
- setLoading('success');
86
- setTimeout(() => {
87
- setLoading(null);
88
- fetchSubscriptions();
89
- refreshSelectedSubscription();
90
- }, 3000);
91
-
92
- refreshSelectedSubscription();
93
- } else {
94
-
95
- const response = await gnarEngine.subscription.createSubscription([formData]);
96
- console.log('response:', response);
97
-
98
- if (response.error) {
99
- setValidationErrors(response.error);
100
- } else {
101
- setSubscription(response.subscription);
102
- refreshSelectedSubscription();
103
- setView('list');
104
- }
105
- }
106
- }
107
- catch (error) {
108
- console.error('Error updating subscription:', error);
109
- setValidationErrors(['Error updating subscription']);
110
- setTimeout(() => {
111
- setLoading(null);
112
- }, 3000);
113
- }
114
-
115
-
116
- }
117
-
118
- // handle delete user
119
- const handleDelete = async () => {
120
- if (window.confirm('Are you sure you want to delete this subscription?')) {
121
- try {
122
- setLoading('loading');
123
-
124
- await gnarEngine.subscription.deleteSubscription(subscription._id);
125
-
126
- setLoading('success');
127
- setTimeout(() => {
128
- setLoading(null);
129
- }, 3000);
130
-
131
- refreshSelectedSubscription();
132
- setView('list');
133
-
134
- } catch (error) {
135
-
136
- setLoading('error');
137
- console.error('Error deleting subscription:', subscription);
138
- }
139
- } else {
140
- console.log('Deletion canceled');
141
- }
142
- };
143
-
144
- // check order being passed in
145
- useEffect(() => {
146
- console.log('subscription:', subscription);
147
- }, [subscription]);
148
-
149
-
150
- const handleStatusChange = (selectedOption) => {
151
- setOrderStatus(selectedOption);
152
- setFormData({
153
- ...formData,
154
- status: selectedOption.id,
155
- });
156
- }
157
-
158
-
159
- return (
160
-
161
- <div className="single-edit subscriptions">
162
- {validationErrors.length > 0 &&
163
- <div className="error-messages">
164
- {validationErrors.map((error, index) => {
165
- return <p key={index}>{error}</p>
166
- })}
167
- </div>
168
- }
169
-
170
- <div className='single-edit-header'>
171
- <div className='single-edit-header-left'>
172
- <p><strong>{subscription ? 'Subscription ID# ' + subscription._id : 'Add New Subscription'}</strong></p>
173
- <p>Date Added: {formatDate(subscription?.createdAt)}</p>
174
- <label htmlFor="orderStatus">Order Status</label>
175
- <CustomSelect
176
- name="status"
177
- labelKey="status"
178
- placeholder="Select subscription status"
179
- options={subscriptionStatuses}
180
- setSelectedOption={handleStatusChange}
181
- selectedOption={orderStatus}
182
- />
183
- <div className="input-cont flex-row flex-row-end">
184
- <div>
185
- <label htmlFor="userId">User ID</label>
186
- <input
187
- type="text"
188
- name="userId"
189
- placeholder="User ID"
190
- value={formData.userId}
191
- onChange={(e) => setFormData({ ...formData, userId: e.target.value })}
192
- />
193
- </div>
194
- <Link to={`/portal/users?view=single&id=${subscription?.userId}`}>
195
- <button className="mainButton">View / Edit</button>
196
- </Link>
197
- </div>
198
-
199
- </div>
200
- <div className='single-edit-header-right'>
201
- <div className="flex-row-buttons-cont">
202
- <button onClick={() => {
203
- setView('list');
204
- setSubscription(null);
205
- setSelectedSingleItemId(null);
206
- }} className="secondaryButton">
207
- Back
208
- </button>
209
- <button onClick={handleDelete} className="secondaryButton">Delete</button>
210
- <SaveButton
211
- save={handleSubmit}
212
- loading={loading}
213
- textCreate="Add Subscription"
214
- textCreateLoading="Saving..."
215
- textCreateSuccess="Saved"
216
- textCreateError="Error"
217
- textUpdate="Save"
218
- textUpdateLoading="Updating..."
219
- textUpdateSuccess="Updated"
220
- textUpdateError="Error"
221
- isUpdating={!!subscription}
222
- />
223
- </div>
224
- </div>
225
- </div>
226
-
227
- <BillingShipping
228
- order={subscription}
229
- />
230
-
231
- <SubscriptionSchedule
232
- subscription={subscription}
233
- formData={formData}
234
- onChange={(e) => setFormData({ ...formData, [e.target.name]: e.target.value })}
235
- />
236
-
237
- <LineItems
238
- order={subscription}
239
- />
240
-
241
- <div className="card">
242
- <div className='card-header'>
243
- <h2>Orders</h2>
244
- </div>
245
- <div className='card-content'>
246
- <div className="subscription-details-cont">
247
- <p><strong>Parent Order ID:</strong> {subscription?.originalSubscriptionOrderId}</p>
248
- <Link to={`/portal/orders?view=single&id=${subscription?.originalSubscriptionOrderId}`}>
249
- <button className="secondaryButton">View / Edit</button>
250
- </Link>
251
- </div>
252
- </div>
253
- </div>
254
-
255
- </div>
256
-
257
- );
258
-
259
- };
260
-
261
- export default CrudSubscriptionSingle;
@@ -1,107 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import gnarEngine from '@gnar-engine/js-client';
3
- import dotsVertical from '../../assets/dots-vertical.svg';
4
- import CustomCheckbox from '../../ui/customCheckbox/CustomCheckbox';
5
-
6
- const CrudUserList = ({ setSelectedSingleItemId, setView, selectedUserIds, setSelectedUserIds, users, message }) => {
7
-
8
- const allSelected = users.length > 0 && selectedUserIds.size === users.length;
9
-
10
- const handleEditClick = (user) => {
11
- setSelectedSingleItemId(user.id);
12
- setView('single');
13
- };
14
-
15
- const toggleUserSelection = (userId) => {
16
- setSelectedUserIds(prev => {
17
- const newSet = new Set(prev);
18
- if (newSet.has(userId)) {
19
- newSet.delete(userId);
20
- } else {
21
- newSet.add(userId);
22
- }
23
- return newSet;
24
- });
25
- };
26
-
27
-
28
- const toggleSelectAll = () => {
29
- if (allSelected) {
30
- setSelectedUserIds(new Set());
31
- } else {
32
- setSelectedUserIds(new Set(users.map(user => user.id)));
33
- }
34
- };
35
-
36
-
37
- const columns = [
38
- { columnLabel: 'ID', dataKey: 'id' },
39
- { columnLabel: 'Username', dataKey: 'username' },
40
- { columnLabel: 'Email', dataKey: 'email' },
41
- { columnLabel: 'User Role', dataKey: 'userRole' },
42
- { columnLabel: 'Date Added', dataKey: 'createdAt' }
43
- ];
44
-
45
- return (
46
- <div className="">
47
- <div className='pagination-labels-cont'>
48
- <div className='pagination-count'>
49
- Showing {users.length} of {users.length} user{users.length !== 1 ? 's' : ''}
50
- </div>
51
- <div className="pagination-count">
52
- {selectedUserIds.size} of {users.length} user{users.length !== 1 ? 's' : ''} selected
53
- </div>
54
- </div>
55
-
56
- <div className='crud-list'>
57
- <table className='custom-table'>
58
- <thead>
59
- <tr>
60
- <th className="checkbox">
61
- <CustomCheckbox
62
- name="select-all"
63
- checked={allSelected}
64
- setChecked={toggleSelectAll}
65
- />
66
- </th>
67
- {columns.map(column => (
68
- <th key={column.columnLabel}>{column.columnLabel}</th>
69
- ))}
70
- </tr>
71
- </thead>
72
-
73
- <tbody>
74
- {message ? (
75
- <tr>
76
- <td colSpan={columns.length + 1}>{message}</td>
77
- </tr>
78
- ) : (
79
- users.length > 0 ? (
80
- users.map(user => (
81
- <tr key={user.id} onClick={() => handleEditClick(user)}>
82
- <td onClick={(e) => e.stopPropagation()}>
83
- <CustomCheckbox
84
- name={`checkbox-${user.id}`}
85
- checked={selectedUserIds.has(user.id)}
86
- setChecked={() => toggleUserSelection(user.id)}
87
- />
88
- </td>
89
- {columns.map(column => (
90
- <td key={column.dataKey}>{user[column.dataKey]}</td>
91
- ))}
92
- </tr>
93
- ))
94
- ) : (
95
- <tr>
96
- <td colSpan={columns.length + 1}>No users found</td>
97
- </tr>
98
- )
99
- )}
100
- </tbody>
101
- </table>
102
- </div>
103
- </div>
104
- );
105
- };
106
-
107
- export default CrudUserList;