@coorpacademy/app-review 0.1.3 → 0.1.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 (266) hide show
  1. package/es/actions/data/skills.d.ts +13 -0
  2. package/es/actions/data/skills.js +10 -0
  3. package/es/actions/data/slides.d.ts +54 -0
  4. package/es/actions/{slides.js → data/slides.js} +5 -0
  5. package/es/actions/index.d.ts +19 -5
  6. package/es/actions/ui/finished-slides.d.ts +10 -0
  7. package/es/actions/{finished-slides.js → ui/finished-slides.js} +1 -0
  8. package/es/actions/ui/is-fetching.d.ts +10 -0
  9. package/es/actions/ui/is-fetching.js +6 -0
  10. package/{lib/actions → es/actions/ui}/navigation.d.ts +2 -2
  11. package/es/actions/ui/review-status.d.ts +7 -0
  12. package/{lib/actions → es/actions/ui}/step-items.d.ts +17 -1
  13. package/es/actions/{step-items.js → ui/step-items.js} +5 -0
  14. package/es/common/index.d.ts +1 -1
  15. package/es/common/index.js +1 -1
  16. package/es/configure-store.d.ts +34 -4
  17. package/es/configure-store.js +1 -2
  18. package/es/fixtures/qcm-slide.js +7 -3
  19. package/es/fixtures/temp-fixture.d.ts +1 -1
  20. package/es/index.js +54 -36
  21. package/es/index.test.js +1 -1
  22. package/es/middlewares/on-start-app.d.ts +2 -3
  23. package/es/middlewares/on-start-app.js +18 -17
  24. package/es/reducers/data/index.d.ts +7 -0
  25. package/es/reducers/data/index.js +11 -0
  26. package/es/reducers/data/progression.d.ts +14 -0
  27. package/es/reducers/data/progression.js +78 -0
  28. package/es/reducers/data/skills.d.ts +6 -0
  29. package/es/reducers/{courses.js → data/skills.js} +3 -4
  30. package/es/reducers/data/slides.d.ts +8 -0
  31. package/es/reducers/{slides.js → data/slides.js} +4 -3
  32. package/es/reducers/data/token.d.ts +5 -0
  33. package/es/reducers/data/token.js +15 -0
  34. package/es/reducers/index.d.ts +11 -8
  35. package/es/reducers/index.js +3 -16
  36. package/es/reducers/ui/finished-slides.d.ts +8 -0
  37. package/es/reducers/{finished-slides.js → ui/finished-slides.js} +9 -6
  38. package/es/reducers/ui/index.d.ts +7 -0
  39. package/es/reducers/ui/index.js +11 -0
  40. package/es/reducers/ui/navigation.d.ts +5 -0
  41. package/es/reducers/{navigation.js → ui/navigation.js} +4 -7
  42. package/es/reducers/ui/review-status.d.ts +5 -0
  43. package/es/reducers/{review-status.js → ui/review-status.js} +3 -2
  44. package/es/reducers/ui/step-items.d.ts +14 -0
  45. package/es/reducers/{step-items.js → ui/step-items.js} +7 -7
  46. package/es/services/fetch-skills.d.ts +8 -0
  47. package/es/services/fetch-skills.js +23 -0
  48. package/es/services/fetch-skills.mock.d.ts +3 -0
  49. package/es/services/fetch-skills.mock.js +17 -0
  50. package/es/services/fetch-skills.test.js +22 -0
  51. package/es/services/tools/fetch-responses.d.ts +7 -0
  52. package/es/services/tools/fetch.mocks.d.ts +8 -0
  53. package/es/services/{fetch.mocks.js → tools/fetch.mocks.js} +1 -0
  54. package/es/types/common.d.ts +12 -0
  55. package/es/types/skills.d.ts +7 -0
  56. package/es/types/slides.d.ts +3 -21
  57. package/es/types/views/skills.d.ts +24 -0
  58. package/{lib/types/views.d.ts → es/types/views/slides.d.ts} +7 -11
  59. package/lib/actions/data/skills.d.ts +13 -0
  60. package/lib/actions/data/skills.js +10 -0
  61. package/lib/actions/data/slides.d.ts +54 -0
  62. package/lib/actions/{slides.js → data/slides.js} +5 -0
  63. package/lib/actions/index.d.ts +19 -5
  64. package/lib/actions/ui/finished-slides.d.ts +10 -0
  65. package/lib/actions/{finished-slides.js → ui/finished-slides.js} +1 -0
  66. package/lib/actions/ui/is-fetching.d.ts +10 -0
  67. package/lib/actions/ui/is-fetching.js +6 -0
  68. package/{es/actions → lib/actions/ui}/navigation.d.ts +2 -2
  69. package/lib/actions/ui/review-status.d.ts +7 -0
  70. package/{es/actions → lib/actions/ui}/step-items.d.ts +17 -1
  71. package/lib/actions/{step-items.js → ui/step-items.js} +5 -0
  72. package/lib/common/index.d.ts +1 -1
  73. package/lib/common/index.js +1 -1
  74. package/lib/configure-store.d.ts +34 -4
  75. package/lib/configure-store.js +1 -2
  76. package/lib/fixtures/qcm-slide.js +7 -3
  77. package/lib/fixtures/temp-fixture.d.ts +1 -1
  78. package/lib/index.js +57 -37
  79. package/lib/index.test.js +1 -1
  80. package/lib/middlewares/on-start-app.d.ts +2 -3
  81. package/lib/middlewares/on-start-app.js +18 -17
  82. package/lib/reducers/data/index.d.ts +7 -0
  83. package/lib/reducers/data/index.js +11 -0
  84. package/lib/reducers/data/progression.d.ts +14 -0
  85. package/lib/reducers/data/progression.js +79 -0
  86. package/lib/reducers/data/skills.d.ts +6 -0
  87. package/lib/reducers/data/skills.js +15 -0
  88. package/lib/reducers/data/slides.d.ts +8 -0
  89. package/lib/reducers/{slides.js → data/slides.js} +4 -3
  90. package/lib/reducers/data/token.d.ts +5 -0
  91. package/lib/reducers/data/token.js +16 -0
  92. package/lib/reducers/index.d.ts +11 -8
  93. package/lib/reducers/index.js +3 -16
  94. package/lib/reducers/ui/finished-slides.d.ts +8 -0
  95. package/lib/reducers/{finished-slides.js → ui/finished-slides.js} +9 -6
  96. package/lib/reducers/ui/index.d.ts +7 -0
  97. package/lib/reducers/ui/index.js +11 -0
  98. package/lib/reducers/ui/navigation.d.ts +5 -0
  99. package/lib/reducers/{courses.js → ui/navigation.js} +9 -3
  100. package/lib/reducers/ui/review-status.d.ts +5 -0
  101. package/lib/reducers/{review-status.js → ui/review-status.js} +3 -2
  102. package/lib/reducers/ui/step-items.d.ts +14 -0
  103. package/lib/reducers/{step-items.js → ui/step-items.js} +7 -7
  104. package/lib/services/fetch-skills.d.ts +8 -0
  105. package/lib/services/{fetch-demo.js → fetch-skills.js} +28 -35
  106. package/lib/services/fetch-skills.mock.d.ts +3 -0
  107. package/lib/services/fetch-skills.mock.js +17 -0
  108. package/lib/services/{fetch-demo.test.js → fetch-skills.test.js} +31 -12
  109. package/lib/services/tools/fetch-responses.d.ts +7 -0
  110. package/lib/services/tools/fetch.mocks.d.ts +8 -0
  111. package/lib/services/{fetch.mocks.js → tools/fetch.mocks.js} +1 -0
  112. package/lib/types/common.d.ts +12 -0
  113. package/lib/types/skills.d.ts +7 -0
  114. package/lib/types/slides.d.ts +3 -21
  115. package/lib/types/views/skills.d.ts +24 -0
  116. package/{es/types/views.d.ts → lib/types/views/slides.d.ts} +7 -11
  117. package/package.json +3 -3
  118. package/src/actions/data/skills.ts +24 -0
  119. package/src/actions/data/slides.ts +89 -0
  120. package/src/actions/index.ts +27 -5
  121. package/src/actions/{finished-slides.ts → ui/finished-slides.ts} +5 -5
  122. package/src/actions/ui/is-fetching.ts +19 -0
  123. package/src/actions/{navigation.ts → ui/navigation.ts} +2 -2
  124. package/src/actions/{review-status.ts → ui/review-status.ts} +4 -4
  125. package/src/actions/{step-items.ts → ui/step-items.ts} +22 -4
  126. package/src/common/index.ts +2 -2
  127. package/src/configure-store.ts +40 -8
  128. package/src/fixtures/qcm-slide.ts +7 -3
  129. package/src/fixtures/temp-fixture.ts +1 -1
  130. package/src/index.test.tsx +1 -1
  131. package/src/index.tsx +69 -44
  132. package/src/middlewares/on-start-app.ts +23 -26
  133. package/src/reducers/data/index.ts +13 -0
  134. package/src/reducers/data/progression.ts +106 -0
  135. package/src/reducers/data/skills.ts +21 -0
  136. package/src/reducers/{slides.ts → data/slides.ts} +24 -21
  137. package/src/reducers/{review-status.ts → data/token.ts} +8 -6
  138. package/src/reducers/index.ts +3 -17
  139. package/src/reducers/{finished-slides.ts → ui/finished-slides.ts} +24 -14
  140. package/src/reducers/ui/index.ts +13 -0
  141. package/src/reducers/ui/navigation.ts +36 -0
  142. package/src/reducers/ui/review-status.ts +26 -0
  143. package/src/reducers/{step-items.ts → ui/step-items.ts} +34 -21
  144. package/src/services/fetch-skills.mock.ts +21 -0
  145. package/src/services/fetch-skills.test.ts +32 -0
  146. package/src/services/fetch-skills.ts +40 -0
  147. package/src/services/{fetch-responses.ts → tools/fetch-responses.ts} +3 -16
  148. package/src/services/{fetch.mocks.ts → tools/fetch.mocks.ts} +10 -10
  149. package/src/types/common.ts +15 -0
  150. package/src/types/globals.d.ts +2 -0
  151. package/src/types/skills.ts +8 -0
  152. package/src/types/slides.ts +3 -26
  153. package/src/types/views/skills.ts +27 -0
  154. package/src/types/{views.tsx → views/slides.ts} +7 -11
  155. package/es/actions/courses.d.ts +0 -6
  156. package/es/actions/courses.js +0 -5
  157. package/es/actions/data/is-fetching.d.ts +0 -5
  158. package/es/actions/data/is-fetching.js +0 -4
  159. package/es/actions/data/validate-slide.d.ts +0 -5
  160. package/es/actions/data/validate-slide.js +0 -6
  161. package/es/actions/finished-slides.d.ts +0 -7
  162. package/es/actions/review-status.d.ts +0 -7
  163. package/es/actions/slides.d.ts +0 -20
  164. package/es/reducers/courses.d.ts +0 -5
  165. package/es/reducers/data.d.ts +0 -7
  166. package/es/reducers/data.js +0 -76
  167. package/es/reducers/finished-slides.d.ts +0 -6
  168. package/es/reducers/navigation.d.ts +0 -8
  169. package/es/reducers/review-status.d.ts +0 -5
  170. package/es/reducers/slides.d.ts +0 -6
  171. package/es/reducers/step-items.d.ts +0 -6
  172. package/es/reducers/token.d.ts +0 -5
  173. package/es/reducers/token.js +0 -8
  174. package/es/services/fetch-demo.d.ts +0 -11
  175. package/es/services/fetch-demo.js +0 -26
  176. package/es/services/fetch-demo.test.js +0 -12
  177. package/es/services/fetch-responses.d.ts +0 -19
  178. package/es/services/fetch.mocks.d.ts +0 -9
  179. package/es/types/data/index.d.ts +0 -14
  180. package/es/types/dispatchers.d.ts +0 -17
  181. package/es/types/finished-slides.d.ts +0 -9
  182. package/es/types/review-status.d.ts +0 -1
  183. package/es/types/states.d.ts +0 -6
  184. package/es/types/step-items.d.ts +0 -26
  185. package/es/types/step-items.js +0 -5
  186. package/es/types/store-state.d.ts +0 -12
  187. package/es/types/utils.d.ts +0 -3
  188. package/es/types/views.js +0 -1
  189. package/lib/actions/courses.d.ts +0 -6
  190. package/lib/actions/courses.js +0 -5
  191. package/lib/actions/data/is-fetching.d.ts +0 -5
  192. package/lib/actions/data/is-fetching.js +0 -4
  193. package/lib/actions/data/validate-slide.d.ts +0 -5
  194. package/lib/actions/data/validate-slide.js +0 -6
  195. package/lib/actions/finished-slides.d.ts +0 -7
  196. package/lib/actions/review-status.d.ts +0 -7
  197. package/lib/actions/slides.d.ts +0 -20
  198. package/lib/reducers/courses.d.ts +0 -5
  199. package/lib/reducers/data.d.ts +0 -7
  200. package/lib/reducers/data.js +0 -77
  201. package/lib/reducers/finished-slides.d.ts +0 -6
  202. package/lib/reducers/navigation.d.ts +0 -8
  203. package/lib/reducers/navigation.js +0 -36
  204. package/lib/reducers/review-status.d.ts +0 -5
  205. package/lib/reducers/slides.d.ts +0 -6
  206. package/lib/reducers/step-items.d.ts +0 -6
  207. package/lib/reducers/token.d.ts +0 -5
  208. package/lib/reducers/token.js +0 -8
  209. package/lib/services/fetch-demo.d.ts +0 -11
  210. package/lib/services/fetch-demo.test.d.ts +0 -1
  211. package/lib/services/fetch-responses.d.ts +0 -19
  212. package/lib/services/fetch.mocks.d.ts +0 -9
  213. package/lib/types/data/index.d.ts +0 -14
  214. package/lib/types/data/index.js +0 -1
  215. package/lib/types/dispatchers.d.ts +0 -17
  216. package/lib/types/dispatchers.js +0 -1
  217. package/lib/types/finished-slides.d.ts +0 -9
  218. package/lib/types/finished-slides.js +0 -1
  219. package/lib/types/review-status.d.ts +0 -1
  220. package/lib/types/review-status.js +0 -1
  221. package/lib/types/states.d.ts +0 -6
  222. package/lib/types/states.js +0 -1
  223. package/lib/types/step-items.d.ts +0 -26
  224. package/lib/types/step-items.js +0 -5
  225. package/lib/types/store-state.d.ts +0 -12
  226. package/lib/types/store-state.js +0 -1
  227. package/lib/types/utils.d.ts +0 -3
  228. package/lib/types/utils.js +0 -1
  229. package/lib/types/views.js +0 -1
  230. package/src/actions/courses.ts +0 -11
  231. package/src/actions/data/is-fetching.ts +0 -12
  232. package/src/actions/data/validate-slide.ts +0 -15
  233. package/src/actions/slides.ts +0 -45
  234. package/src/reducers/courses.ts +0 -23
  235. package/src/reducers/data.ts +0 -88
  236. package/src/reducers/navigation.ts +0 -36
  237. package/src/reducers/token.ts +0 -17
  238. package/src/services/fetch-demo.test.ts +0 -16
  239. package/src/services/fetch-demo.ts +0 -57
  240. package/src/types/data/index.ts +0 -16
  241. package/src/types/dispatchers.ts +0 -18
  242. package/src/types/finished-slides.ts +0 -9
  243. package/src/types/review-status.ts +0 -1
  244. package/src/types/states.ts +0 -6
  245. package/src/types/step-items.ts +0 -31
  246. package/src/types/store-state.ts +0 -20
  247. package/src/types/utils.ts +0 -4
  248. /package/es/actions/{token.d.ts → data/token.d.ts} +0 -0
  249. /package/es/actions/{token.js → data/token.js} +0 -0
  250. /package/es/actions/{navigation.js → ui/navigation.js} +0 -0
  251. /package/es/actions/{review-status.js → ui/review-status.js} +0 -0
  252. /package/es/services/{fetch-demo.test.d.ts → fetch-skills.test.d.ts} +0 -0
  253. /package/es/services/{fetch-responses.js → tools/fetch-responses.js} +0 -0
  254. /package/es/types/{data/index.js → skills.js} +0 -0
  255. /package/es/types/{dispatchers.js → views/skills.js} +0 -0
  256. /package/es/types/{finished-slides.js → views/slides.js} +0 -0
  257. /package/lib/actions/{token.d.ts → data/token.d.ts} +0 -0
  258. /package/lib/actions/{token.js → data/token.js} +0 -0
  259. /package/lib/actions/{navigation.js → ui/navigation.js} +0 -0
  260. /package/lib/actions/{review-status.js → ui/review-status.js} +0 -0
  261. /package/{es/types/review-status.js → lib/services/fetch-skills.test.d.ts} +0 -0
  262. /package/lib/services/{fetch-responses.js → tools/fetch-responses.js} +0 -0
  263. /package/{es/types/states.js → lib/types/skills.js} +0 -0
  264. /package/{es/types/store-state.js → lib/types/views/skills.js} +0 -0
  265. /package/{es/types/utils.js → lib/types/views/slides.js} +0 -0
  266. /package/src/actions/{token.ts → data/token.ts} +0 -0
@@ -0,0 +1,106 @@
1
+ import {getOr, noop} from 'lodash/fp';
2
+ import {ValidateSlide, VALIDATE_SLIDE} from '../../actions/data/slides';
3
+ import {AnswerUI} from '../../types/slides';
4
+
5
+ // -----------------------------------------------------------------------------
6
+
7
+ export type ProgressionState = {
8
+ // virtual field
9
+ slideNumber: number;
10
+ isCorrect?: boolean;
11
+ // pass down the successExitNode if all slides are finished, not before
12
+ exitNode?: 'successExitNode' | 'failExitNode';
13
+ // TODO: create another action, to retrieve the next slide
14
+ // nextSlide should be renamed as nextContent when this new action is created
15
+ // ex: nextContent: {ref: "sli_E1n2i2sBo", type: "slide"}
16
+ // the middleware should trigger a nextSlide request once the result is
17
+ // received && update the state accordingly
18
+ nextSlide?: {
19
+ questionText?: string;
20
+ answerUI?: AnswerUI;
21
+ };
22
+ } | null;
23
+
24
+ // -----------------------------------------------------------------------------
25
+
26
+ export const initialState: ProgressionState = null;
27
+
28
+ // -----------------------------------------------------------------------------
29
+
30
+ const reducer = (
31
+ // eslint-disable-next-line default-param-last
32
+ state: ProgressionState = initialState,
33
+ action: ValidateSlide
34
+ ): ProgressionState => {
35
+ switch (action.type) {
36
+ case VALIDATE_SLIDE: {
37
+ const previousSlideNumber: number = getOr(-1, 'slideNumber', state);
38
+ // hard coded for now
39
+ return {
40
+ // virtual field
41
+ slideNumber: previousSlideNumber + 1,
42
+ isCorrect: true,
43
+ // exitNode
44
+ // TODO: create another action, to retrieve the next slide
45
+ // nextSlide should be corrected to nextContent, when this new action is created
46
+ // ex: nextContent: {ref: "sli_E1n2i2sBo", type: "slide"}
47
+ // the middleware should trigger a next content request once the result is
48
+ // received && update the state accordingly,
49
+ //
50
+ nextSlide: {
51
+ questionText: 'Test',
52
+ answerUI: {
53
+ model: {
54
+ answers: [
55
+ {
56
+ title: 'There is no need for a password',
57
+ // TODO: onClick of each answer should use a dispatcher to
58
+ // update selected answers (in order to use them on validation)
59
+ // in each retrieval, the answers of answerUI need to be augmented
60
+ // for the onClick prop to achieve this.
61
+ onClick: noop,
62
+ selected: false,
63
+ help: 'help'
64
+ },
65
+ {
66
+ title: 'Lorem ipsum',
67
+ onClick: noop,
68
+ selected: false,
69
+ help: 'help'
70
+ },
71
+ {
72
+ title: 'Lorem',
73
+ onClick: noop,
74
+ selected: true,
75
+ order: 1,
76
+ help: 'help'
77
+ },
78
+ {
79
+ title: 'You need to have a password',
80
+ onClick: noop,
81
+ selected: false,
82
+ help: 'help'
83
+ },
84
+ {
85
+ title: 'Pouet',
86
+ onClick: noop,
87
+ selected: true,
88
+ order: 0,
89
+ help: 'help'
90
+ }
91
+ ],
92
+ type: 'qcmDrag'
93
+ },
94
+ help: 'Help text will appear here'
95
+ }
96
+ }
97
+ };
98
+ }
99
+ default:
100
+ return state;
101
+ }
102
+ };
103
+
104
+ // -----------------------------------------------------------------------------
105
+
106
+ export default reducer;
@@ -0,0 +1,21 @@
1
+ import {ReceivedSkills, RECEIVED_SKILLS} from '../../actions/data/skills';
2
+ import {Skills} from '../../types/skills';
3
+
4
+ export type SkillsState = Skills;
5
+ export const initialState: SkillsState = [];
6
+
7
+ // -----------------------------------------------------------------------------
8
+
9
+ // eslint-disable-next-line default-param-last
10
+ const reducer = (state: SkillsState = initialState, action: ReceivedSkills): SkillsState => {
11
+ switch (action.type) {
12
+ case RECEIVED_SKILLS:
13
+ return action.payload;
14
+ default:
15
+ return state;
16
+ }
17
+ };
18
+
19
+ // -----------------------------------------------------------------------------
20
+
21
+ export default reducer;
@@ -1,24 +1,27 @@
1
1
  import map from 'lodash/fp/map';
2
2
  import {
3
+ OnNextPayload,
4
+ Slide,
3
5
  SlidesAction,
4
6
  STORE_FIRST_SLIDE,
5
7
  UPDATE_SLIDES_ON_NEXT,
6
- UPDATE_SLIDES_ON_VALIDATION
7
- } from '../actions/slides';
8
- import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../common';
9
- import {
10
- Slide,
11
- Slides,
12
- UpdateSlidesOnNextPayload,
13
- UpdateSlidesOnValidationPayload
14
- } from '../types/slides';
8
+ UPDATE_SLIDES_ON_VALIDATION,
9
+ ValidationPayload
10
+ } from '../../actions/data/slides';
11
+ import {Slide as SlideFromAPI} from '../../types/slides';
12
+ import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../../common';
15
13
 
16
14
  // -----------------------------------------------------------------------------
17
15
 
18
- export type State = Slides;
16
+ export type SlidesState = {
17
+ slideNumbers: number[];
18
+ [key: number]: Slide;
19
+ };
20
+
21
+ // -----------------------------------------------------------------------------
19
22
 
20
- const getInitialState = (): State => {
21
- const state: State = {
23
+ const getInitialState = (): SlidesState => {
24
+ const state: SlidesState = {
22
25
  slideNumbers
23
26
  };
24
27
  // eslint-disable-next-line fp/no-loops
@@ -28,12 +31,12 @@ const getInitialState = (): State => {
28
31
  return state;
29
32
  };
30
33
 
31
- export const initialState: State = getInitialState();
34
+ export const initialState: SlidesState = getInitialState();
32
35
 
33
36
  // -----------------------------------------------------------------------------
34
37
 
35
- const setFirstSlide = (state, slide: Slide): State => {
36
- const _state: State = {
38
+ const setFirstSlide = (state: SlidesState, slide: SlideFromAPI): SlidesState => {
39
+ const _state: SlidesState = {
37
40
  slideNumbers
38
41
  };
39
42
  // eslint-disable-next-line lodash-fp/no-unused-result
@@ -49,9 +52,9 @@ const setFirstSlide = (state, slide: Slide): State => {
49
52
 
50
53
  // ||-------> Handles the updates of a given slide on validation,
51
54
  // & then updates de remaining slides if this given change should impact their content
52
- const stateUpdateOnValidation = (state: State, payload: UpdateSlidesOnValidationPayload): State => {
55
+ const stateUpdateOnValidation = (state: SlidesState, payload: ValidationPayload): SlidesState => {
53
56
  const {slideNumber, newSlideContent, numberOfFinishedSlides, nextSlide} = payload;
54
- const _state: State = {
57
+ const _state: SlidesState = {
55
58
  slideNumbers
56
59
  };
57
60
 
@@ -66,7 +69,7 @@ const stateUpdateOnValidation = (state: State, payload: UpdateSlidesOnValidation
66
69
  ...previousValue,
67
70
  nextSlide,
68
71
  position: newSlideContent.position,
69
- validationResult: newSlideContent.validationResult
72
+ isCorrect: newSlideContent.isCorrect
70
73
  };
71
74
  } else _state[slideNumber] = {...previousValue, ...newSlideContent};
72
75
  } else {
@@ -81,9 +84,9 @@ const stateUpdateOnValidation = (state: State, payload: UpdateSlidesOnValidation
81
84
 
82
85
  // ||-------> Handles the updates of a given slide on correction popin's next click,
83
86
  // & then updates de remaining slides (updates position to trigger animations)
84
- const stateUpdateOnNext = (state: State, payload: UpdateSlidesOnNextPayload): State => {
87
+ const stateUpdateOnNext = (state: SlidesState, payload: OnNextPayload): SlidesState => {
85
88
  const {slideNumber, newSlideContent, numberOfFinishedSlides} = payload;
86
- const _state: State = {
89
+ const _state: SlidesState = {
87
90
  slideNumbers
88
91
  };
89
92
 
@@ -115,7 +118,7 @@ const stateUpdateOnNext = (state: State, payload: UpdateSlidesOnNextPayload): St
115
118
  // -----------------------------------------------------------------------------
116
119
 
117
120
  // eslint-disable-next-line default-param-last
118
- const reducer = (state: State = initialState, action: SlidesAction): State => {
121
+ const reducer = (state: SlidesState = initialState, action: SlidesAction): SlidesState => {
119
122
  switch (action.type) {
120
123
  case STORE_FIRST_SLIDE: {
121
124
  return setFirstSlide(state, action.payload);
@@ -1,18 +1,20 @@
1
- import {UpdateReviewStatus, UPDATE_REVIEW_STATUS} from '../actions/review-status';
1
+ import {StoreToken, STORE_TOKEN} from '../../actions/data/token';
2
2
 
3
3
  // -----------------------------------------------------------------------------
4
4
 
5
- export type State = 'finished' | 'ongoing';
6
- export const initialState: State = 'ongoing';
5
+ export type TokenState = string | null;
6
+
7
+ // -----------------------------------------------------------------------------
8
+
9
+ export const initialState: TokenState = null;
7
10
 
8
11
  // -----------------------------------------------------------------------------
9
12
 
10
13
  // eslint-disable-next-line default-param-last
11
- const reducer = (state: State = initialState, action: UpdateReviewStatus): State => {
14
+ const reducer = (state: TokenState = initialState, action: StoreToken): TokenState => {
12
15
  switch (action.type) {
13
- case UPDATE_REVIEW_STATUS: {
16
+ case STORE_TOKEN:
14
17
  return action.payload;
15
- }
16
18
  default:
17
19
  return state;
18
20
  }
@@ -1,23 +1,9 @@
1
1
  import {combineReducers} from 'redux';
2
2
 
3
3
  import data from './data';
4
- import courses from './courses';
5
- import finishedSlides from './finished-slides';
6
- import navigation from './navigation';
7
- import reviewStatus from './review-status';
8
- import slides from './slides';
9
- import stepItems from './step-items';
10
-
11
- const ui = combineReducers({
12
- courses,
13
- finishedSlides,
14
- navigation,
15
- reviewStatus,
16
- slides,
17
- stepItems
18
- });
4
+ import ui from './ui';
19
5
 
20
6
  export default combineReducers({
21
- ui,
22
- data
7
+ data,
8
+ ui
23
9
  });
@@ -1,7 +1,21 @@
1
1
  import forEach from 'lodash/fp/forEach';
2
- import {UpdateFinishedSlides, UPDATE_FINISHED_SLIDES} from '../actions/finished-slides';
3
- import {slideNumbers} from '../common';
4
- import {FinishedSlides} from '../types/finished-slides';
2
+ import {UpdateFinishedSlides, UPDATE_FINISHED_SLIDES} from '../../actions/ui/finished-slides';
3
+ import {slideNumbers} from '../../common';
4
+
5
+ // -----------------------------------------------------------------------------
6
+ // Stores only successful slides
7
+ export type FinishedSlidesState = {
8
+ slideNumbers: number[];
9
+ [key: number]: true;
10
+ };
11
+
12
+ // -----------------------------------------------------------------------------
13
+
14
+ export const initialState: FinishedSlidesState = {
15
+ slideNumbers
16
+ };
17
+
18
+ // -----------------------------------------------------------------------------
5
19
 
6
20
  const _forEach: <T>(
7
21
  iteratee: (value: T[keyof T], index: number) => void,
@@ -13,24 +27,20 @@ const _forEach: <T>(
13
27
 
14
28
  // -----------------------------------------------------------------------------
15
29
 
16
- export type State = FinishedSlides;
17
- export const initialState: State = {
18
- slideNumbers
19
- };
20
-
21
- // -----------------------------------------------------------------------------
22
-
23
- // eslint-disable-next-line default-param-last
24
- const reducer = (state: State = initialState, action: UpdateFinishedSlides): State => {
30
+ const reducer = (
31
+ // eslint-disable-next-line default-param-last
32
+ state: FinishedSlidesState = initialState,
33
+ action: UpdateFinishedSlides
34
+ ): FinishedSlidesState => {
25
35
  switch (action.type) {
26
36
  case UPDATE_FINISHED_SLIDES: {
27
37
  const {slideNumbers: _slideNumbers, ...rest} = state;
28
38
  const {slideNumber, value} = action.payload;
29
- const _state: State = {
39
+ const _state: FinishedSlidesState = {
30
40
  slideNumbers: _slideNumbers
31
41
  };
32
42
 
33
- _forEach<Omit<State, 'slideNumbers'>>((finishedSlide, index) => {
43
+ _forEach<Omit<FinishedSlidesState, 'slideNumbers'>>((finishedSlide, index) => {
34
44
  const previousValue = finishedSlide;
35
45
  _state[index] = previousValue;
36
46
  }, rest);
@@ -0,0 +1,13 @@
1
+ import {combineReducers} from 'redux';
2
+
3
+ import finishedSlides from './finished-slides';
4
+ import navigation from './navigation';
5
+ import reviewStatus from './review-status';
6
+ import stepItems from './step-items';
7
+
8
+ export default combineReducers({
9
+ finishedSlides,
10
+ navigation,
11
+ reviewStatus,
12
+ stepItems
13
+ });
@@ -0,0 +1,36 @@
1
+ import {
2
+ type NavigateTo,
3
+ type NavigateBack,
4
+ NAVIGATE_BACK,
5
+ NAVIGATE_TO
6
+ } from '../../actions/ui/navigation';
7
+
8
+ // -----------------------------------------------------------------------------
9
+
10
+ export type NavigationState = Array<'skills' | 'onboarding' | 'slides'>;
11
+ export const initialState: NavigationState = [];
12
+
13
+ // -----------------------------------------------------------------------------
14
+
15
+ const reducer = (
16
+ // eslint-disable-next-line default-param-last
17
+ state: NavigationState = initialState,
18
+ action: NavigateTo | NavigateBack
19
+ ): NavigationState => {
20
+ switch (action.type) {
21
+ case NAVIGATE_TO: {
22
+ return [...state, action.payload];
23
+ }
24
+ case NAVIGATE_BACK: {
25
+ const newState = [...state];
26
+ newState.pop();
27
+ return newState;
28
+ }
29
+ default:
30
+ return state;
31
+ }
32
+ };
33
+
34
+ // -----------------------------------------------------------------------------
35
+
36
+ export default reducer;
@@ -0,0 +1,26 @@
1
+ import {UpdateReviewStatus, UPDATE_REVIEW_STATUS} from '../../actions/ui/review-status';
2
+
3
+ // -----------------------------------------------------------------------------
4
+
5
+ export type ReviewStatusState = 'finished' | 'ongoing';
6
+ export const initialState: ReviewStatusState = 'ongoing';
7
+
8
+ // -----------------------------------------------------------------------------
9
+
10
+ const reducer = (
11
+ // eslint-disable-next-line default-param-last
12
+ state: ReviewStatusState = initialState,
13
+ action: UpdateReviewStatus
14
+ ): ReviewStatusState => {
15
+ switch (action.type) {
16
+ case UPDATE_REVIEW_STATUS: {
17
+ return action.payload;
18
+ }
19
+ default:
20
+ return state;
21
+ }
22
+ };
23
+
24
+ // -----------------------------------------------------------------------------
25
+
26
+ export default reducer;
@@ -1,22 +1,35 @@
1
- import isNil from 'lodash/fp/isNil';
2
1
  import get from 'lodash/fp/get';
3
2
  import has from 'lodash/fp/has';
4
3
  import map from 'lodash/fp/map';
5
4
  import {
5
+ IconValue,
6
6
  StepItemsAction,
7
7
  UPDATE_STEP_ITEMS_ON_NEXT,
8
8
  UPDATE_STEP_ITEMS_ON_VALIDATION
9
- } from '../actions/step-items';
10
- import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../common';
11
- import {SlideNumber} from '../types/slides';
12
- import {FinishedSlides} from '../types/finished-slides';
13
- import {StepItem, StepItems} from '../types/step-items';
9
+ } from '../../actions/ui/step-items';
10
+ import {HIGHEST_INDEX, slideNumbers, TOTAL_SLIDES_STACK} from '../../common';
11
+ import {FinishedSlidesState} from './finished-slides';
14
12
 
15
13
  // -----------------------------------------------------------------------------
16
14
 
17
- export type State = StepItems;
15
+ type StepItem = {
16
+ current: boolean;
17
+ icon: IconValue;
18
+ value: string;
19
+ };
20
+
21
+ export type StepItems = {
22
+ slideNumbers: number[];
23
+ [key: number]: StepItem;
24
+ };
25
+
26
+ // -----------------------------------------------------------------------------
27
+
28
+ export type StepItemsState = StepItems;
29
+
30
+ // -----------------------------------------------------------------------------
18
31
 
19
- const getInitialState = (): State => {
32
+ const getInitialState = (): StepItemsState => {
20
33
  const state: StepItems = {
21
34
  slideNumbers
22
35
  };
@@ -24,12 +37,12 @@ const getInitialState = (): State => {
24
37
  // eslint-disable-next-line fp/no-loops
25
38
  for (let index = 0; index < TOTAL_SLIDES_STACK; index++) {
26
39
  const current = index === 0;
27
- state[index] = {current, value: `${index + 1}`, icon: null};
40
+ state[index] = {current, value: `${index + 1}`, icon: 'no-answer'};
28
41
  }
29
42
  return state;
30
43
  };
31
44
 
32
- export const initialState: State = getInitialState();
45
+ export const initialState: StepItemsState = getInitialState();
33
46
 
34
47
  // -----------------------------------------------------------------------------
35
48
 
@@ -42,15 +55,15 @@ const getNextIndex = (currentIndex: number): number =>
42
55
  // they have to be skipped)
43
56
  const calculateNextStepIndex = (
44
57
  currentStepNumber: number,
45
- finishedSlides: FinishedSlides,
46
- lastVisitedIndex: number | null = null
58
+ finishedSlides: FinishedSlidesState,
59
+ lastVisitedIndex = -1
47
60
  ): number => {
48
61
  // only one slide remaining, the step should stay on the same number
49
62
  if (lastVisitedIndex === currentStepNumber) {
50
63
  return currentStepNumber;
51
64
  }
52
65
 
53
- const indexToVisit = getNextIndex(isNil(lastVisitedIndex) ? currentStepNumber : lastVisitedIndex);
66
+ const indexToVisit = getNextIndex(lastVisitedIndex === -1 ? currentStepNumber : lastVisitedIndex);
54
67
 
55
68
  // if the index is already included in the correctly answered (finished) slides, then we proceed to check for the next one
56
69
  return has(indexToVisit, finishedSlides)
@@ -60,15 +73,15 @@ const calculateNextStepIndex = (
60
73
 
61
74
  type StepItemToUpdateProps =
62
75
  | Pick<StepItem, 'icon'>
63
- | (Pick<StepItem, 'current'> & {nextIndex: SlideNumber});
76
+ | (Pick<StepItem, 'current'> & {nextIndex: number});
64
77
 
65
78
  const recalculateStepItemsState = (
66
- state: State,
67
- stepNumber,
79
+ state: StepItemsState,
80
+ stepNumber: number,
68
81
  stepItemToUpdateProps: StepItemToUpdateProps
69
- ): State => {
70
- const nextIndex: number | null = get('nextIndex', stepItemToUpdateProps);
71
- const _state: State = {
82
+ ): StepItemsState => {
83
+ const nextIndex: number = get('nextIndex', stepItemToUpdateProps);
84
+ const _state: StepItemsState = {
72
85
  slideNumbers
73
86
  };
74
87
 
@@ -91,7 +104,7 @@ const recalculateStepItemsState = (
91
104
  // -----------------------------------------------------------------------------
92
105
 
93
106
  // eslint-disable-next-line default-param-last
94
- const reducer = (state: State = initialState, action: StepItemsAction): State => {
107
+ const reducer = (state: StepItemsState = initialState, action: StepItemsAction): StepItemsState => {
95
108
  switch (action.type) {
96
109
  case UPDATE_STEP_ITEMS_ON_VALIDATION: {
97
110
  const {stepNumber, icon} = action.payload;
@@ -99,7 +112,7 @@ const reducer = (state: State = initialState, action: StepItemsAction): State =>
99
112
  }
100
113
  case UPDATE_STEP_ITEMS_ON_NEXT: {
101
114
  const {stepNumber, finishedSlides, current} = action.payload;
102
- const nextIndex = !current ? calculateNextStepIndex(stepNumber, finishedSlides) : null;
115
+ const nextIndex = !current ? calculateNextStepIndex(stepNumber, finishedSlides) : -1;
103
116
  return recalculateStepItemsState(state, stepNumber, {current, nextIndex});
104
117
  }
105
118
  default:
@@ -0,0 +1,21 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import {Skills} from '../types/skills';
3
+ import {okJSONResponse} from './tools/fetch.mocks';
4
+
5
+ const result: Skills = [
6
+ {
7
+ skillRef: '_skill-ref',
8
+ slidesToReview: 2,
9
+ name: 'skill-test',
10
+ custom: false
11
+ },
12
+ {
13
+ skillRef: '_skill-ref-2',
14
+ slidesToReview: 2,
15
+ name: 'skill-test-2',
16
+ custom: true
17
+ }
18
+ ];
19
+
20
+ const mockFetchSkills: typeof crossFetch = okJSONResponse(result);
21
+ export default mockFetchSkills;
@@ -0,0 +1,32 @@
1
+ import test from 'ava';
2
+ import {Skills} from '../types/skills';
3
+ import {fetchSkills} from './fetch-skills';
4
+ import {okJSONResponse, token} from './tools/fetch.mocks';
5
+
6
+ test('should fetch skills with success', async t => {
7
+ const result: Skills = [
8
+ {
9
+ slidesToReview: 1,
10
+ name: 'skill-test',
11
+ custom: false,
12
+ skillRef: '_skill-ref'
13
+ }
14
+ ];
15
+
16
+ const mockedFetchSkills = fetchSkills(okJSONResponse(result));
17
+ const skills = await mockedFetchSkills(token);
18
+
19
+ t.deepEqual(result, skills);
20
+ });
21
+
22
+ test('should reject bad token', async t => {
23
+ const badToken = 'token is not a jwt';
24
+ const mockedFetchSkills = fetchSkills(okJSONResponse([]));
25
+
26
+ const error = await t.throwsAsync(() => mockedFetchSkills(badToken));
27
+
28
+ t.is(
29
+ error?.message,
30
+ "Invalid token specified: Cannot read properties of undefined (reading 'replace')"
31
+ );
32
+ });
@@ -0,0 +1,40 @@
1
+ import crossFetch from 'cross-fetch';
2
+ import decode from 'jwt-decode';
3
+
4
+ import {JWT} from '../types/common';
5
+ import {Skills} from '../types/skills';
6
+ import {toJSON} from './tools/fetch-responses';
7
+ import mockFetchSkills from './fetch-skills.mock';
8
+
9
+ // -----------------------------------------------------------------------------
10
+
11
+ type FetchSkills = (token: string) => Promise<Skills>;
12
+ type CreateFetchSkills = (fetch: typeof crossFetch) => FetchSkills;
13
+ type CreateDefaultFetchSkills = () => FetchSkills;
14
+
15
+ // -----------------------------------------------------------------------------
16
+
17
+ const fetchSkills: CreateFetchSkills = fetch => async token => {
18
+ const {user: userId, host}: JWT = decode(token);
19
+ const response = await fetch(`${host}/api/v2/skills/review/user/${userId}`, {
20
+ headers: {authorization: token}
21
+ });
22
+
23
+ const skills = (await toJSON(response)) as Skills;
24
+ return skills;
25
+ };
26
+
27
+ // -----------------------------------------------------------------------------
28
+
29
+ const createFetchSkills: CreateDefaultFetchSkills = () => {
30
+ if (process.env.SERVICES !== 'mocks') {
31
+ return fetchSkills(crossFetch);
32
+ }
33
+
34
+ return fetchSkills(mockFetchSkills);
35
+ };
36
+
37
+ // -----------------------------------------------------------------------------
38
+
39
+ export {fetchSkills};
40
+ export default createFetchSkills();
@@ -1,16 +1,3 @@
1
- export type _Response = {
2
- ok: boolean;
3
- status: number;
4
- statusText: string;
5
- json: () => Promise<unknown>;
6
- text: () => Promise<string>;
7
- };
8
-
9
- export type Fetch = (
10
- url?: string,
11
- options?: {headers: {authorization: string}}
12
- ) => Promise<_Response>;
13
-
14
1
  export class ResponseError extends Error {
15
2
  public statusCode: number;
16
3
 
@@ -21,7 +8,7 @@ export class ResponseError extends Error {
21
8
  }
22
9
  }
23
10
 
24
- export const toJSON = async (response: _Response): Promise<unknown> => {
11
+ export const toJSON = async (response: Response): Promise<unknown> => {
25
12
  if (!response.ok) {
26
13
  const body = await response.text();
27
14
  throw new ResponseError(response.status, response.statusText, body);
@@ -34,7 +21,7 @@ export const toJSON = async (response: _Response): Promise<unknown> => {
34
21
  }
35
22
  };
36
23
 
37
- export const toText = async (response: _Response): Promise<string> => {
24
+ export const toText = async (response: Response): Promise<string> => {
38
25
  const body = await response.text();
39
26
 
40
27
  if (!response.ok) {
@@ -44,7 +31,7 @@ export const toText = async (response: _Response): Promise<string> => {
44
31
  return body;
45
32
  };
46
33
 
47
- export const toVoid = async (response: _Response): Promise<void> => {
34
+ export const toVoid = async (response: Response): Promise<void> => {
48
35
  if (!response.ok) {
49
36
  const body = await response.text();
50
37
  throw new ResponseError(response.status, response.statusText, body);