@gnar-engine/cli 1.0.0 → 1.0.2

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,44 @@
1
+ const SubscriptionSchedule = ({subscription, onChange, formData}) => {
2
+
3
+ return (
4
+ <div className="card">
5
+ <div className='card-header'>
6
+ <h2>Subscription Schedule</h2>
7
+ </div>
8
+ <div className='card-content'>
9
+ <div className="subscription-schedule-cont">
10
+ <div className="subscription-schedule-body">
11
+ {subscription ? (
12
+ <div>
13
+ <p><strong>Payment Interval:</strong> {subscription.paymentInterval.interval}</p>
14
+ <p><strong>Interval Count:</strong> {subscription.paymentInterval.intervalCount}</p>
15
+ <p><strong>Trial Period:</strong> {subscription.trialPeriodDays || '0'}</p>
16
+ <p><strong>Next Payment Date:</strong>
17
+ <input
18
+ type="text"
19
+ name="billingNextScheduled"
20
+ value={formData.billingNextScheduled || ''}
21
+ onChange={(e) => onChange(e)}
22
+ />
23
+ </p>
24
+
25
+ <p><strong>Retry attempt</strong>
26
+ <input
27
+ type="number"
28
+ name="retryAttempt"
29
+ value={formData.retryAttempt || 0}
30
+ onChange={(e) => onChange(e)}
31
+ />
32
+ </p>
33
+ </div>
34
+ ) : (
35
+ <p>No subscription details available.</p>
36
+ )}
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ export default SubscriptionSchedule;
@@ -0,0 +1,32 @@
1
+ import bin from '../../assets/bin.svg';
2
+ import CustomSelect from '../../ui/customSelect/CustomSelect';
3
+
4
+ const TaxonomyFormRow = ({ item, onChange, remove }) => {
5
+
6
+
7
+ return (
8
+ <div className='form-row'>
9
+ <CustomSelect
10
+ name="taxonomy"
11
+ placeholder="Select taxonomy"
12
+ options="TBC"
13
+ labelKey="taxonomy"
14
+ setSelectedOption="TBC"
15
+ selectedOption="TBC"
16
+ />
17
+ <CustomSelect
18
+ name="value"
19
+ placeholder="Select terms"
20
+ options="TBC"
21
+ labelKey="value"
22
+ setSelectedOption="TBC"
23
+ selectedOption="TBC"
24
+ />
25
+
26
+ <button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
27
+ </div>
28
+ )
29
+ }
30
+
31
+
32
+ export default TaxonomyFormRow;
@@ -0,0 +1,54 @@
1
+ import React, { useState, useEffect } from "react";
2
+ import { useDispatch, useSelector } from "react-redux";
3
+ import { logout } from '../../slices/authSlice';
4
+ import userIcon from '../../assets/user.svg';
5
+
6
+
7
+ const User = () => {
8
+
9
+ const user = useSelector(state => state.auth.authUser);
10
+ const authState = useSelector(state => state.auth);
11
+ const dispatch = useDispatch();
12
+ const [userInitials, setUserInitials] = useState('?');
13
+
14
+ useEffect(() => {
15
+ if (user?.name) {
16
+ const initials = user.name.split(' ').map(name => name.charAt(0)).join('');
17
+ setUserInitials(initials);
18
+ }
19
+ }, [user]);
20
+
21
+ const handleLogout = () => {
22
+ dispatch(logout());
23
+ };
24
+
25
+ useEffect(() => {
26
+
27
+ console.log('Redux auth state:', authState);
28
+
29
+ }, [user]);
30
+
31
+
32
+
33
+ return (
34
+ <div className="user-avatar-container">
35
+ <div className="user-info">
36
+ <div className="userAvatar">
37
+ <span><img src={userIcon} alt="user icon" /></span>
38
+ </div>
39
+
40
+ {user && user.username && (
41
+ <div className="userName">
42
+ <span>{user.username}</span>
43
+ </div>
44
+ )}
45
+
46
+ {user && (
47
+ <a onClick={handleLogout} className="log-out">Log out</a>
48
+ )}
49
+ </div>
50
+ </div>
51
+ );
52
+ }
53
+
54
+ export default User;
@@ -0,0 +1,57 @@
1
+ .user-avatar-container {
2
+ display: flex;
3
+ justify-content: center;
4
+ flex-direction: column;
5
+ align-items: flex-end;
6
+ padding-bottom: 10px;
7
+
8
+ .user-info {
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ justify-content: center;
13
+
14
+ .userAvatar {
15
+ width: 40px;
16
+ height: 40px;
17
+ border-radius: 50%;
18
+ border: 2px solid #37936B;
19
+ background: @green-1;
20
+ display: flex;
21
+ justify-content: center;
22
+ align-items: center;
23
+
24
+ span {
25
+ text-transform: uppercase;
26
+ font-size: 18px;
27
+ font-weight: 400;
28
+ color: @green-1;
29
+
30
+ img {
31
+ width: 30px;
32
+ height: 30px;
33
+ }
34
+ }
35
+ }
36
+
37
+ span {
38
+ color: @green-1;
39
+ font-size: 14px;
40
+ }
41
+
42
+ .log-out {
43
+ color: @dark-1;
44
+ transition-duration: 0.4s;
45
+
46
+ &:hover {
47
+ cursor: pointer;
48
+ opacity: 0.9;
49
+ }
50
+ }
51
+
52
+
53
+
54
+ }
55
+
56
+
57
+ }
@@ -0,0 +1,259 @@
1
+
2
+ import { mainAreasOfMaths } from '../data/data';
3
+
4
+ /**
5
+ * Calculate the total level from the levels
6
+ *
7
+ * @param {array} levels
8
+ * @param {int} startsAt
9
+ */
10
+ export const calcTotalLevel = (levels, startsAt) => {
11
+
12
+ if (!levels || levels.length == 0) {
13
+ levels = [0,0,0,0,0,0];
14
+ }
15
+
16
+ let newTotalLevel = levels.reduce((acc, level, i) => {
17
+ if (startsAt > 0 && i + 1 < startsAt) {
18
+ return acc;
19
+ }
20
+ if (level == '' || level == null) {
21
+ return acc;
22
+ }
23
+ return parseFloat(acc) + parseFloat(level);
24
+ }, 0);
25
+
26
+ if (newTotalLevel > 0 && startsAt) {
27
+ newTotalLevel = newTotalLevel + (startsAt - 1);
28
+ }
29
+
30
+ return newTotalLevel;
31
+ }
32
+
33
+
34
+ /**
35
+ * Calculate assessment areas with intervention
36
+ *
37
+ * @param {object} currentPeriod
38
+ * @param {object} previousPeriod
39
+ * @return {array} assessmentAreas
40
+ */
41
+ export const calcAreasWithIntervention = (currentPeriod, previousPeriod) => {
42
+
43
+ const areas = [];
44
+
45
+ return areas;
46
+ }
47
+
48
+
49
+ /**
50
+ * Calculate the period prior to the current period
51
+ *
52
+ * @param {array} periods
53
+ * @param {object} currentPeriod
54
+ */
55
+ export const calcPreviousPeriod = (periods, currentPeriod) => {
56
+
57
+ let previousPeriod = null;
58
+
59
+ periods.forEach((period, i) => {
60
+ if (period.period_id == currentPeriod.period_id) {
61
+ previousPeriod = periods[i - 1];
62
+ }
63
+ });
64
+
65
+ return previousPeriod;
66
+ }
67
+
68
+
69
+ /**
70
+ * Calculate bundles with intervention
71
+ *
72
+ * @param {object} currentBundleProgress
73
+ * @param {object} previousBundleProgress
74
+ * @return {array} bundles
75
+ */
76
+ export const calcBundlesWithIntervention = (currentBundleProgress, previousBundleProgress) => {
77
+
78
+ const bundles = [];
79
+
80
+ Object.keys(currentBundleProgress).forEach((levelKey, i) => {
81
+ Object.keys(currentBundleProgress[levelKey]).forEach((bundleKey, j) => {
82
+
83
+ let currentPeriodBundle = currentBundleProgress[levelKey][bundleKey];
84
+ let previousPeriodBundle = previousBundleProgress[levelKey][bundleKey];
85
+
86
+ if (currentPeriodBundle.completed == 'complete' && previousPeriodBundle.completed !== 'complete') {
87
+ const levelLabel = levelKey.replace('level-', 'Level ');
88
+ currentPeriodBundle.levelLabel = levelLabel;
89
+ bundles.push(currentPeriodBundle);
90
+ }
91
+ });
92
+ });
93
+
94
+ return bundles;
95
+ }
96
+
97
+
98
+ /**
99
+ * Calculate assessment average score
100
+ *
101
+ * @param {object} assessment
102
+ * @return {float} averageScore
103
+ */
104
+ export const calcAssessmentAverageScore = (assessment, selectedSubject = 'maths_all_areas') => {
105
+
106
+ if (!assessment) {
107
+ return 0;
108
+ }
109
+
110
+ // parse if it's a string
111
+ if (typeof assessment === 'string') {
112
+ assessment = JSON.parse(assessment);
113
+ }
114
+
115
+ let totalScore = 0;
116
+ let totalAreas = 0;
117
+
118
+ Object.keys(assessment).forEach((areaKey) => {
119
+ assessment[areaKey].topics.forEach((topic) => {
120
+
121
+ // skip some areas if it's maths main areas
122
+ if (selectedSubject == 'maths_main_areas') {
123
+ console.log('maths main areas', areaKey);
124
+ if (!mainAreasOfMaths.includes(areaKey)) {
125
+ return;
126
+ }
127
+ }
128
+
129
+ const thisScore = parseFloat(calcTotalLevel(topic.level, topic['starts-at']));
130
+
131
+ if (thisScore) {
132
+ totalAreas++;
133
+ totalScore = totalScore + thisScore;
134
+ }
135
+ });
136
+ });
137
+
138
+ let average = totalScore / totalAreas;
139
+
140
+ // round to 1 decimal place
141
+ average = Math.round(average * 10) / 10;
142
+
143
+ return average;
144
+ }
145
+
146
+ /**
147
+ * Calculate assessment average score
148
+ *
149
+ * @param {object} assessment
150
+ * @return {float} averageScore
151
+ */
152
+ export const calcNumbersAreaAverageScore = (assessment) => {
153
+
154
+ const numberAreaKeys = mainAreasOfMaths;
155
+
156
+ if (!assessment) {
157
+ return 0;
158
+ }
159
+
160
+ // parse if it's a string
161
+ if (typeof assessment === 'string') {
162
+ assessment = JSON.parse(assessment);
163
+ }
164
+
165
+ let totalScore = 0;
166
+ let totalAreas = 0;
167
+
168
+ Object.keys(assessment).forEach((areaKey) => {
169
+ if (!numberAreaKeys.includes(areaKey)) {
170
+ return;
171
+ }
172
+
173
+ assessment[areaKey].topics.forEach((topic) => {
174
+ const thisScore = parseFloat(calcTotalLevel(topic.level, topic['starts-at']));
175
+
176
+ if (thisScore) {
177
+ totalAreas++;
178
+ totalScore = totalScore + thisScore;
179
+ }
180
+ });
181
+ });
182
+
183
+ let average = totalScore / totalAreas;
184
+
185
+ // round to 1 decimal place
186
+ average = Math.round(average * 10) / 10;
187
+
188
+ return average;
189
+ }
190
+
191
+ /**
192
+ * Calculate completeness of academic year intervention for a student
193
+ *
194
+ * @param {array} periods
195
+ * @param {array} selectedPeriods
196
+ * @return {string} completeness (complete, partial, none)
197
+ */
198
+ export const calcAcademicYearInterventionCompleteness = (periods, selectedPeriods) => {
199
+
200
+ let completeness;
201
+ let someWithIntervention = false;
202
+ let someWithoutIntervention = false;
203
+
204
+ // get the academic years in selected periods
205
+ // let selectedAcademicYears = [];
206
+
207
+ // selectedPeriods.forEach(selectedPeriod => {
208
+ // if (!selectedAcademicYears.includes(selectedPeriod.academic_year)) {
209
+ // selectedAcademicYears.push(selectedPeriod.academic_year);
210
+ // }
211
+ // });
212
+
213
+ selectedPeriods.forEach((selectedPeriod) => {
214
+ periods.forEach(period => {
215
+ if (period.period_name == selectedPeriod.period_name && period.calendar_year == selectedPeriod.calendar_year) {
216
+ if (period.has_had_intervention == 1) {
217
+ someWithIntervention = true;
218
+ } else {
219
+ someWithoutIntervention = true;
220
+ }
221
+ }
222
+ });
223
+ });
224
+
225
+ if (someWithIntervention && someWithoutIntervention) {
226
+ completeness = 'partial';
227
+ } else if (someWithIntervention && !someWithoutIntervention) {
228
+ completeness = 'complete';
229
+ } else {
230
+ completeness = 'none';
231
+ }
232
+
233
+ return completeness;
234
+ }
235
+
236
+
237
+ /**
238
+ * Calculate if had some low attendance in selected periods
239
+ *
240
+ * @param {array} periods
241
+ * @param {array} selectedPeriods
242
+ * @return {boolean} hadLowAttendance
243
+ */
244
+ export const calcHadSomeLowAttendance = (periods, selectedPeriods) => {
245
+
246
+ let hadSomeLowAttendance = false;
247
+
248
+ periods.forEach((period) => {
249
+ selectedPeriods.forEach((selectedPeriod) => {
250
+ if (period.period_name == selectedPeriod.period_name && period.academic_year == selectedPeriod.academic_year) {
251
+ if (period.attendance == 'low') {
252
+ hadSomeLowAttendance = true;
253
+ }
254
+ }
255
+ });
256
+ })
257
+
258
+ return hadSomeLowAttendance;
259
+ }
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import ReactDOM from 'react-dom/client';
3
+ import App from './App';
4
+ import { Provider } from 'react-redux';
5
+ import store from './store/configureStore';
6
+
7
+ const root = ReactDOM.createRoot(document.getElementById('root'));
8
+ root.render(
9
+ <React.StrictMode>
10
+ <Provider store={store}>
11
+ <App />
12
+ </Provider>
13
+ </React.StrictMode>
14
+ );
@@ -0,0 +1,50 @@
1
+ import React, {useEffect} from "react";
2
+ import {useLocation, useNavigate} from 'react-router-dom';
3
+
4
+
5
+ const CrudLayout = ({children, view, setView, selectedSingleItemId, setSelectedSingleItemId}) => {
6
+
7
+ const location = useLocation();
8
+ const navigate = useNavigate();
9
+
10
+ useEffect(() => {
11
+ // if there is no current ?view in the url, set it to list
12
+ // if (!location.search) {
13
+ // navigate("?view=list", {replace: true});
14
+ // }
15
+
16
+ if (view === 'list') {
17
+ navigate("?view=list", {replace: false});
18
+ } else if (view === 'single' && selectedSingleItemId) {
19
+ navigate(`?view=single&id=${selectedSingleItemId}`, {replace: false});
20
+ } else if (view === 'single') {
21
+ navigate("?view=single", {replace: false});
22
+ }
23
+ }, [view]);
24
+
25
+ // set view and selected id from url
26
+ useEffect(() => {
27
+ const urlParams = new URLSearchParams(window.location.search);
28
+ const view = urlParams.get('view');
29
+ const id = urlParams.get('id');
30
+
31
+ if (view === 'list') {
32
+ setView('list')
33
+ } else if (view === 'single' && id) {
34
+ setView('single')
35
+ setSelectedSingleItemId(id);
36
+ } else if (view === 'single') {
37
+ setView('single')
38
+ } else {
39
+ setView('list')
40
+ }
41
+ }, [location]);
42
+
43
+ return (
44
+ <>
45
+ {children}
46
+ </>
47
+ )
48
+ }
49
+
50
+ export default CrudLayout;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+
3
+ function LoginLayout({children}) {
4
+
5
+ return (
6
+ <div className="login-layout">
7
+ <div className="left-cont">
8
+ <img src={require('../assets/Logo_Anchord_White_Green.svg').default} alt="Anchord Logo" />
9
+ </div>
10
+ <div className="right-cont">
11
+ {children}
12
+ </div>
13
+ </div>
14
+ );
15
+ }
16
+
17
+ export default LoginLayout;
@@ -0,0 +1,48 @@
1
+ import React, {useEffect} from "react";
2
+ import { useLocation } from "react-router";
3
+ import Sidebar from "../features/sidebar/Sidebar";
4
+ import User from "../features/user/User";
5
+ import { Link } from "react-router-dom";
6
+ import "react-datepicker/dist/react-datepicker.css";
7
+
8
+ const PortalLayout = ({children}) => {
9
+
10
+ const location = useLocation();
11
+
12
+ useEffect(() => {
13
+ console.log(location);
14
+ }, [location]);
15
+
16
+
17
+ return (
18
+ <div className="portal-layout">
19
+
20
+ <div className="header">
21
+ <div className="content-wrap">
22
+ <div className="content">
23
+ </div>
24
+ </div>
25
+ </div>
26
+
27
+ <div className="main">
28
+ <div className="content-wrap">
29
+ <div className="content">
30
+ <Sidebar />
31
+ <div className="main-page">
32
+ <div className="header-details">
33
+ <Link to="/portal/" className="header-logo">
34
+ <img src={require('../assets/Logo_Anchord_Black.svg').default} alt="Gnar Engine" className="header-logo" />
35
+ </Link>
36
+ <User />
37
+ </div>
38
+ {children}
39
+ </div>
40
+ </div>
41
+ </div>
42
+
43
+ </div>
44
+ </div>
45
+ );
46
+ }
47
+
48
+ export default PortalLayout;
@@ -0,0 +1,33 @@
1
+ .login-layout {
2
+ min-height: 100vh;
3
+ background: @dark-grey-1;
4
+ display: flex;
5
+ flex-direction: row;
6
+ position: relative;
7
+
8
+ .left-cont {
9
+ min-width: 50%;
10
+ max-width: 50%;
11
+ min-height: 100%;
12
+ display: flex;
13
+ justify-content: center;
14
+ align-items: center;
15
+
16
+ img {
17
+ max-width: 60%;
18
+ min-width: 60%;
19
+ }
20
+ }
21
+ .right-cont {
22
+ background: @grey-light-1;
23
+ min-height: 100%;
24
+ min-width: 50%;
25
+ max-width: 50%;
26
+ display: flex;
27
+ flex-direction: column;
28
+ justify-content: center;
29
+ flex-wrap: nowrap;
30
+ padding: 50px;
31
+ box-sizing: border-box;
32
+ }
33
+ }
@@ -0,0 +1,67 @@
1
+ .portal-layout {
2
+ min-height: 101vh;
3
+ background: linear-gradient(to right, #E7E7E7 0%, #E7E7E7 49%, #f7f7f7 51%, #f7f7f7 100%);
4
+
5
+ .header {
6
+ background: @dark-grey-1;
7
+ height: 30px;
8
+ padding-top: 20px;
9
+ padding-bottom: 20px;
10
+ box-sizing: border-box;
11
+ display: flex;
12
+ flex-direction: row;
13
+ align-items: center;
14
+
15
+ .content-wrap {
16
+ max-height: 100%;
17
+ }
18
+ .content {
19
+ display: flex;
20
+ flex-direction: row;
21
+ flex-wrap: nowrap;
22
+ justify-content: space-between;
23
+ max-height: 100%;
24
+ align-items: center;
25
+ }
26
+ }
27
+
28
+ .main {
29
+ min-height: calc(100vh - 197px);
30
+ position: relative;
31
+
32
+ .content-wrap,
33
+ .content {
34
+ height: 100%;
35
+ min-height: 100%;
36
+ }
37
+ .content {
38
+ display: flex;
39
+ flex-direction: row;
40
+ flex-wrap: nowrap;
41
+ }
42
+
43
+ .main-page {
44
+ background: #f7f7f7;
45
+ width: 100%;
46
+ height: 100%;
47
+ min-height: calc(100vh - 100px);
48
+ padding: 30px 40px;
49
+
50
+ .header-details {
51
+ display: flex;
52
+ flex-direction: row;
53
+ align-items: center;
54
+ justify-content: space-between;
55
+ padding-bottom: 20px;
56
+ }
57
+
58
+ .header-logo {
59
+ max-height: 100%;
60
+ width: 180px;
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: center;
64
+ }
65
+ }
66
+ }
67
+ }