@coorpacademy/app-review 0.0.21-alpha.4 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. package/es/actions/courses.d.ts +2 -3
  2. package/es/actions/data/is-fetching.d.ts +5 -0
  3. package/es/actions/data/is-fetching.js +4 -0
  4. package/es/actions/data/validate-slide.d.ts +5 -0
  5. package/es/actions/data/validate-slide.js +6 -0
  6. package/es/actions/finished-slides.d.ts +7 -0
  7. package/es/actions/finished-slides.js +7 -0
  8. package/es/actions/index.d.ts +2 -5
  9. package/es/actions/index.js +1 -3
  10. package/es/actions/navigation.d.ts +5 -6
  11. package/es/actions/review-status.d.ts +7 -0
  12. package/es/actions/review-status.js +7 -0
  13. package/es/actions/slides.d.ts +20 -0
  14. package/es/actions/slides.js +17 -0
  15. package/es/actions/step-items.d.ts +14 -0
  16. package/es/actions/step-items.js +12 -0
  17. package/es/actions/token.d.ts +0 -1
  18. package/es/common/index.d.ts +8 -0
  19. package/es/common/index.js +8 -0
  20. package/es/configure-store.d.ts +3 -12
  21. package/es/configure-store.js +5 -7
  22. package/es/fixtures/qcm-slide.d.ts +2 -0
  23. package/es/fixtures/qcm-slide.js +29 -0
  24. package/es/fixtures/temp-fixture.d.ts +3 -0
  25. package/es/fixtures/temp-fixture.js +84 -0
  26. package/es/helpers/css-register.d.ts +1 -0
  27. package/es/helpers/css-register.js +2 -0
  28. package/es/index.d.ts +5 -12
  29. package/es/index.js +62 -14
  30. package/es/index.test.d.ts +1 -0
  31. package/es/index.test.js +52 -0
  32. package/es/middlewares/on-start-app.d.ts +1 -2
  33. package/es/middlewares/on-start-app.js +20 -9
  34. package/es/reducers/courses.d.ts +2 -3
  35. package/es/reducers/courses.js +2 -1
  36. package/es/reducers/data.d.ts +7 -0
  37. package/es/reducers/data.js +76 -0
  38. package/es/reducers/finished-slides.d.ts +6 -0
  39. package/es/reducers/finished-slides.js +32 -0
  40. package/es/reducers/index.d.ts +11 -6
  41. package/es/reducers/index.js +14 -4
  42. package/es/reducers/navigation.d.ts +4 -3
  43. package/es/reducers/navigation.js +4 -1
  44. package/es/reducers/review-status.d.ts +5 -0
  45. package/es/reducers/review-status.js +15 -0
  46. package/es/reducers/slides.d.ts +6 -0
  47. package/es/reducers/slides.js +112 -0
  48. package/es/reducers/step-items.d.ts +6 -0
  49. package/es/reducers/step-items.js +75 -0
  50. package/es/reducers/token.d.ts +5 -7
  51. package/es/reducers/token.js +4 -12
  52. package/es/services/fetch-demo.d.ts +0 -1
  53. package/es/services/fetch-demo.test.d.ts +0 -1
  54. package/es/services/fetch-responses.d.ts +6 -7
  55. package/es/services/fetch-responses.js +2 -2
  56. package/es/services/fetch.mocks.d.ts +3 -4
  57. package/es/services/fetch.mocks.js +3 -3
  58. package/es/types/common.d.ts +7 -0
  59. package/es/types/common.js +1 -0
  60. package/es/types/data/index.d.ts +14 -0
  61. package/es/types/data/index.js +1 -0
  62. package/es/types/dispatchers.d.ts +17 -0
  63. package/es/types/dispatchers.js +1 -0
  64. package/es/types/finished-slides.d.ts +9 -0
  65. package/es/types/finished-slides.js +1 -0
  66. package/es/types/review-status.d.ts +1 -0
  67. package/es/types/review-status.js +1 -0
  68. package/es/types/slides.d.ts +87 -0
  69. package/es/types/slides.js +1 -0
  70. package/es/types/states.d.ts +6 -0
  71. package/es/types/states.js +1 -0
  72. package/es/types/step-items.d.ts +26 -0
  73. package/es/types/step-items.js +5 -0
  74. package/es/types/store-state.d.ts +12 -0
  75. package/es/types/store-state.js +1 -0
  76. package/es/types/utils.d.ts +3 -0
  77. package/es/types/utils.js +1 -0
  78. package/es/types/views.d.ts +64 -0
  79. package/es/types/views.js +1 -0
  80. package/lib/actions/courses.d.ts +2 -3
  81. package/lib/actions/data/is-fetching.d.ts +5 -0
  82. package/lib/actions/data/is-fetching.js +4 -0
  83. package/lib/actions/data/validate-slide.d.ts +5 -0
  84. package/lib/actions/data/validate-slide.js +6 -0
  85. package/lib/actions/finished-slides.d.ts +7 -0
  86. package/lib/actions/finished-slides.js +7 -0
  87. package/lib/actions/index.d.ts +2 -5
  88. package/lib/actions/index.js +1 -3
  89. package/lib/actions/navigation.d.ts +5 -6
  90. package/lib/actions/review-status.d.ts +7 -0
  91. package/lib/actions/review-status.js +7 -0
  92. package/lib/actions/slides.d.ts +20 -0
  93. package/lib/actions/slides.js +17 -0
  94. package/lib/actions/step-items.d.ts +14 -0
  95. package/lib/actions/step-items.js +12 -0
  96. package/lib/actions/token.d.ts +0 -1
  97. package/lib/common/index.d.ts +8 -0
  98. package/lib/common/index.js +8 -0
  99. package/lib/configure-store.d.ts +3 -12
  100. package/lib/configure-store.js +10 -59
  101. package/lib/fixtures/qcm-slide.d.ts +2 -0
  102. package/lib/fixtures/qcm-slide.js +29 -0
  103. package/lib/fixtures/temp-fixture.d.ts +3 -0
  104. package/lib/fixtures/temp-fixture.js +84 -0
  105. package/lib/helpers/css-register.d.ts +1 -0
  106. package/lib/helpers/css-register.js +2 -0
  107. package/lib/index.d.ts +5 -12
  108. package/lib/index.js +71 -34
  109. package/lib/index.test.d.ts +1 -0
  110. package/lib/index.test.js +160 -0
  111. package/lib/middlewares/on-start-app.d.ts +1 -2
  112. package/lib/middlewares/on-start-app.js +29 -16
  113. package/lib/reducers/courses.d.ts +2 -3
  114. package/lib/reducers/courses.js +2 -1
  115. package/lib/reducers/data.d.ts +7 -0
  116. package/lib/reducers/data.js +77 -0
  117. package/lib/reducers/finished-slides.d.ts +6 -0
  118. package/lib/reducers/finished-slides.js +44 -0
  119. package/lib/reducers/index.d.ts +11 -6
  120. package/lib/reducers/index.js +14 -4
  121. package/lib/reducers/navigation.d.ts +4 -3
  122. package/lib/reducers/navigation.js +6 -1
  123. package/lib/reducers/review-status.d.ts +5 -0
  124. package/lib/reducers/review-status.js +16 -0
  125. package/lib/reducers/slides.d.ts +6 -0
  126. package/lib/reducers/slides.js +119 -0
  127. package/lib/reducers/step-items.d.ts +6 -0
  128. package/lib/reducers/step-items.js +87 -0
  129. package/lib/reducers/token.d.ts +5 -7
  130. package/lib/reducers/token.js +4 -13
  131. package/lib/services/fetch-demo.d.ts +0 -1
  132. package/lib/services/fetch-demo.js +25 -23
  133. package/lib/services/fetch-demo.test.d.ts +0 -1
  134. package/lib/services/fetch-responses.d.ts +6 -7
  135. package/lib/services/fetch-responses.js +2 -2
  136. package/lib/services/fetch.mocks.d.ts +3 -4
  137. package/lib/services/fetch.mocks.js +28 -16
  138. package/lib/types/common.d.ts +7 -0
  139. package/lib/types/common.js +1 -0
  140. package/lib/types/data/index.d.ts +14 -0
  141. package/lib/types/data/index.js +1 -0
  142. package/lib/types/dispatchers.d.ts +17 -0
  143. package/lib/types/dispatchers.js +1 -0
  144. package/lib/types/finished-slides.d.ts +9 -0
  145. package/lib/types/finished-slides.js +1 -0
  146. package/lib/types/review-status.d.ts +1 -0
  147. package/lib/types/review-status.js +1 -0
  148. package/lib/types/slides.d.ts +87 -0
  149. package/lib/types/slides.js +1 -0
  150. package/lib/types/states.d.ts +6 -0
  151. package/lib/types/states.js +1 -0
  152. package/lib/types/step-items.d.ts +26 -0
  153. package/lib/types/step-items.js +5 -0
  154. package/lib/types/store-state.d.ts +12 -0
  155. package/lib/types/store-state.js +1 -0
  156. package/lib/types/utils.d.ts +3 -0
  157. package/lib/types/utils.js +1 -0
  158. package/lib/types/views.d.ts +64 -0
  159. package/lib/types/views.js +1 -0
  160. package/package.json +21 -7
  161. package/src/actions/courses.ts +2 -2
  162. package/src/actions/data/is-fetching.ts +12 -0
  163. package/src/actions/data/validate-slide.ts +15 -0
  164. package/src/actions/finished-slides.ts +21 -0
  165. package/src/actions/index.ts +8 -5
  166. package/src/actions/navigation.ts +6 -5
  167. package/src/actions/review-status.ts +19 -0
  168. package/src/actions/slides.ts +45 -0
  169. package/src/actions/step-items.ts +39 -0
  170. package/src/common/index.ts +14 -0
  171. package/src/configure-store.ts +14 -22
  172. package/src/fixtures/qcm-slide.ts +31 -0
  173. package/src/fixtures/temp-fixture.ts +94 -0
  174. package/src/helpers/css-modules-require-hook.d.ts +4 -0
  175. package/src/helpers/css-register.ts +3 -0
  176. package/src/index.test.tsx +82 -0
  177. package/src/index.tsx +75 -22
  178. package/src/middlewares/on-start-app.ts +35 -20
  179. package/src/reducers/courses.ts +3 -2
  180. package/src/reducers/data.ts +88 -0
  181. package/src/reducers/finished-slides.ts +48 -0
  182. package/src/reducers/index.ts +14 -4
  183. package/src/reducers/navigation.ts +7 -3
  184. package/src/reducers/review-status.ts +23 -0
  185. package/src/reducers/slides.ts +136 -0
  186. package/src/reducers/step-items.ts +112 -0
  187. package/src/reducers/token.ts +6 -15
  188. package/src/services/fetch-demo.ts +17 -15
  189. package/src/services/fetch-responses.ts +7 -7
  190. package/src/services/fetch.mocks.ts +29 -14
  191. package/src/types/common.ts +8 -0
  192. package/src/types/data/index.ts +16 -0
  193. package/src/types/dispatchers.ts +18 -0
  194. package/src/types/finished-slides.ts +9 -0
  195. package/src/types/globals.d.ts +6 -0
  196. package/src/types/review-status.ts +1 -0
  197. package/src/types/slides.ts +107 -0
  198. package/src/types/states.ts +6 -0
  199. package/src/types/step-items.ts +31 -0
  200. package/src/types/store-state.ts +20 -0
  201. package/src/types/utils.ts +4 -0
  202. package/src/types/views.tsx +69 -0
  203. package/es/actions/courses.d.ts.map +0 -1
  204. package/es/actions/index.d.ts.map +0 -1
  205. package/es/actions/navigation.d.ts.map +0 -1
  206. package/es/actions/token.d.ts.map +0 -1
  207. package/es/components/__tmp-backup-vues-mobile/revision-home.d.ts +0 -10
  208. package/es/components/__tmp-backup-vues-mobile/revision-home.d.ts.map +0 -1
  209. package/es/components/__tmp-backup-vues-mobile/revision-home.js +0 -83
  210. package/es/components/__tmp-backup-vues-mobile/revision-home.stories.d.ts +0 -1
  211. package/es/components/__tmp-backup-vues-mobile/revision-home.stories.d.ts.map +0 -1
  212. package/es/components/__tmp-backup-vues-mobile/revision-home.stories.js +0 -14
  213. package/es/components/__tmp-backup-vues-mobile/revision-onboarding.d.ts +0 -4
  214. package/es/components/__tmp-backup-vues-mobile/revision-onboarding.d.ts.map +0 -1
  215. package/es/components/__tmp-backup-vues-mobile/revision-onboarding.js +0 -57
  216. package/es/components/__tmp-backup-vues-mobile/revision-quizzer.d.ts +0 -19
  217. package/es/components/__tmp-backup-vues-mobile/revision-quizzer.d.ts.map +0 -1
  218. package/es/components/__tmp-backup-vues-mobile/revision-quizzer.js +0 -120
  219. package/es/configure-store.d.ts.map +0 -1
  220. package/es/index.d.ts.map +0 -1
  221. package/es/middlewares/on-start-app.d.ts.map +0 -1
  222. package/es/reducers/courses.d.ts.map +0 -1
  223. package/es/reducers/index.d.ts.map +0 -1
  224. package/es/reducers/navigation.d.ts.map +0 -1
  225. package/es/reducers/token.d.ts.map +0 -1
  226. package/es/services/fetch-demo.d.ts.map +0 -1
  227. package/es/services/fetch-demo.test.d.ts.map +0 -1
  228. package/es/services/fetch-responses.d.ts.map +0 -1
  229. package/es/services/fetch.mocks.d.ts.map +0 -1
  230. package/lib/actions/courses.d.ts.map +0 -1
  231. package/lib/actions/index.d.ts.map +0 -1
  232. package/lib/actions/navigation.d.ts.map +0 -1
  233. package/lib/actions/token.d.ts.map +0 -1
  234. package/lib/components/__tmp-backup-vues-mobile/revision-home.d.ts +0 -10
  235. package/lib/components/__tmp-backup-vues-mobile/revision-home.d.ts.map +0 -1
  236. package/lib/components/__tmp-backup-vues-mobile/revision-home.js +0 -98
  237. package/lib/components/__tmp-backup-vues-mobile/revision-home.stories.d.ts +0 -1
  238. package/lib/components/__tmp-backup-vues-mobile/revision-home.stories.d.ts.map +0 -1
  239. package/lib/components/__tmp-backup-vues-mobile/revision-home.stories.js +0 -14
  240. package/lib/components/__tmp-backup-vues-mobile/revision-onboarding.d.ts +0 -4
  241. package/lib/components/__tmp-backup-vues-mobile/revision-onboarding.d.ts.map +0 -1
  242. package/lib/components/__tmp-backup-vues-mobile/revision-onboarding.js +0 -60
  243. package/lib/components/__tmp-backup-vues-mobile/revision-quizzer.d.ts +0 -19
  244. package/lib/components/__tmp-backup-vues-mobile/revision-quizzer.d.ts.map +0 -1
  245. package/lib/components/__tmp-backup-vues-mobile/revision-quizzer.js +0 -128
  246. package/lib/configure-store.d.ts.map +0 -1
  247. package/lib/index.d.ts.map +0 -1
  248. package/lib/middlewares/on-start-app.d.ts.map +0 -1
  249. package/lib/reducers/courses.d.ts.map +0 -1
  250. package/lib/reducers/index.d.ts.map +0 -1
  251. package/lib/reducers/navigation.d.ts.map +0 -1
  252. package/lib/reducers/token.d.ts.map +0 -1
  253. package/lib/services/fetch-demo.d.ts.map +0 -1
  254. package/lib/services/fetch-demo.test.d.ts.map +0 -1
  255. package/lib/services/fetch-responses.d.ts.map +0 -1
  256. package/lib/services/fetch.mocks.d.ts.map +0 -1
  257. package/src/components/__tmp-backup-vues-mobile/revision-home.stories.tsx +0 -16
  258. package/src/components/__tmp-backup-vues-mobile/revision-home.tsx +0 -125
  259. package/src/components/__tmp-backup-vues-mobile/revision-onboarding.tsx +0 -84
  260. package/src/components/__tmp-backup-vues-mobile/revision-quizzer.tsx +0 -176
@@ -0,0 +1,94 @@
1
+ /* eslint-disable no-console */
2
+ import {SlidesViewProps} from '../types/views';
3
+
4
+ export const correctionPopinProps: SlidesViewProps['correctionPopinProps'] = {
5
+ klf: {
6
+ label: 'Key learning factor',
7
+ tooltip: 'Some tooltip info.',
8
+ onClick: () => {
9
+ console.log('klf onClick');
10
+ }
11
+ },
12
+ information: {
13
+ label: 'Key learning factor',
14
+ message: 'info msg'
15
+ },
16
+ next: {
17
+ label: 'Next',
18
+ ariaLabel: 'Next'
19
+ },
20
+ successLabel: 'CORRECT ANSWER',
21
+ failureLabel: 'WRONG ANSWER'
22
+ };
23
+
24
+ const confettiAnimationProps = {
25
+ 'aria-label': 'aria lottie',
26
+ 'data-name': 'default-lottie',
27
+ className: undefined,
28
+ animationSrc: 'https://static-staging.coorpacademy.com/animations/review/confetti.json',
29
+ loop: undefined,
30
+ autoplay: true,
31
+ rendererSettings: {
32
+ hideOnTransparent: false,
33
+ animationClassName: ''
34
+ },
35
+ ie11ImageBackup:
36
+ 'https://static-staging.coorpacademy.com/animations/review/conffeti_congrats.svg',
37
+ animationControl: undefined
38
+ };
39
+
40
+ const starAnimationProps = {
41
+ 'aria-label': 'Review Card Congrats Container',
42
+ 'data-name': 'card-star',
43
+ animationLottie: {
44
+ 'aria-label': 'aria lottie',
45
+ 'data-name': 'default-lottie',
46
+ animationSrc: 'https://static-staging.coorpacademy.com/animations/review/star.json',
47
+ ie11ImageBackup:
48
+ 'https://static-staging.coorpacademy.com/animations/review/stars_icon_congrats.svg'
49
+ },
50
+ iconAriaLabel: 'Image without information',
51
+ cardType: 'card-star',
52
+ reviewCardTitle: 'You have won',
53
+ reviewCardValue: '100',
54
+ timerAnimation: 200
55
+ };
56
+
57
+ const rankAnimationProps = {
58
+ 'aria-label': 'Review Card Congrats Container',
59
+ 'data-name': 'card-rank',
60
+ animationLottie: {
61
+ 'aria-label': 'aria lottie',
62
+ 'data-name': 'default-lottie',
63
+ animationSrc: 'https://static-staging.coorpacademy.com/animations/review/rank.json',
64
+ ie11ImageBackup:
65
+ 'https://static-staging.coorpacademy.com/animations/review/rank_icon_congrats.svg'
66
+ },
67
+ cardType: 'card-rank',
68
+ iconAriaLabel: 'Image without information',
69
+ reviewCardTitle: 'You are now',
70
+ reviewCardValue: '14',
71
+ rankSuffix: 'th',
72
+ timerAnimation: 200
73
+ };
74
+
75
+ export const congratsProps: SlidesViewProps['congratsProps'] = {
76
+ 'aria-label': 'Review Congratulations',
77
+ 'data-name': 'review-congrats',
78
+ animationLottie: confettiAnimationProps,
79
+ title: 'Congratulations!',
80
+ cardCongratsStar: starAnimationProps,
81
+ cardCongratsRank: rankAnimationProps,
82
+ buttonRevising: {
83
+ 'aria-label': 'Continue revising button',
84
+ label: 'Continue revising',
85
+ onClick: () => console.log('Continue revising'),
86
+ type: 'tertiary'
87
+ },
88
+ buttonRevisingSkill: {
89
+ label: 'Revise another skill',
90
+ 'aria-label': 'Revise another skill button',
91
+ onClick: () => console.log('Revise another skill'),
92
+ type: 'primary'
93
+ }
94
+ };
@@ -0,0 +1,4 @@
1
+ declare module '@coorpacademy/css-modules-require-hook' {
2
+ export const cssRegister: () => void;
3
+ export default cssRegister;
4
+ }
@@ -0,0 +1,3 @@
1
+ import cssRegister from '@coorpacademy/css-modules-require-hook';
2
+
3
+ cssRegister();
@@ -0,0 +1,82 @@
1
+ import browserEnv from 'browser-env';
2
+ import test from 'ava';
3
+ import type {ExecutionContext} from 'ava';
4
+ import React from 'react';
5
+ import {render, fireEvent, act} from '@testing-library/react';
6
+ import {slide} from './fixtures/qcm-slide';
7
+ import type {AppOptions} from './types/common';
8
+ import AppReview from '.';
9
+
10
+ browserEnv({pretendToBeVisual: true});
11
+
12
+ const elementExists = (foundElements: NodeListOf<Element>): Element =>
13
+ foundElements && foundElements[0];
14
+
15
+ const sleep = (msToSleep: number): Promise<void> =>
16
+ new Promise(resolve => {
17
+ setTimeout(resolve, msToSleep);
18
+ });
19
+
20
+ const waitForChanges = async (msToWait = 3000): Promise<void> => {
21
+ await act(async () => {
22
+ await sleep(msToWait); // wait *just* a little longer than the timeout in the component
23
+ });
24
+ };
25
+
26
+ const LIMIT = 5;
27
+
28
+ const clickAllSlides = async (
29
+ t: ExecutionContext<unknown>,
30
+ container: HTMLElement,
31
+ accumulator = 0
32
+ ): Promise<void> => {
33
+ if (accumulator === LIMIT) return;
34
+
35
+ // last one needs to wait for more calculations && components updates
36
+ if (accumulator === 4)
37
+ await act(async () => {
38
+ await sleep(1000);
39
+ });
40
+
41
+ const validateButton = container.querySelectorAll(
42
+ `[data-name="slide-validate-button-${accumulator}"]`
43
+ );
44
+ t.truthy(elementExists(validateButton));
45
+
46
+ await act(async () => {
47
+ await fireEvent.click(validateButton[0]);
48
+ });
49
+
50
+ const nextButton = container.querySelectorAll(
51
+ `[data-name="next-question-button-${accumulator}"]`
52
+ );
53
+ t.truthy(elementExists(nextButton));
54
+
55
+ await act(async () => {
56
+ await fireEvent.click(nextButton[0]);
57
+ });
58
+
59
+ await clickAllSlides(t, container, accumulator + 1);
60
+ };
61
+
62
+ const appOptions: AppOptions = {
63
+ token: process.env.API_TEST_TOKEN || '',
64
+ slide
65
+ };
66
+
67
+ test('should validate all the slides (all correct scenario)', async t => {
68
+ t.plan(13);
69
+ const {container} = render(<AppReview options={appOptions} key={0} />);
70
+ await waitForChanges(1000);
71
+
72
+ const wrapper = container.querySelector('[data-name="slides-revision-container"]');
73
+ t.truthy(wrapper);
74
+
75
+ const stackedSlidesContainer = wrapper.querySelector('[data-name="stacked-slides-container"]');
76
+
77
+ t.truthy(stackedSlidesContainer);
78
+
79
+ await clickAllSlides(t, container);
80
+
81
+ t.pass();
82
+ });
package/src/index.tsx CHANGED
@@ -1,36 +1,94 @@
1
1
  import React, {useEffect, useState} from 'react';
2
2
  import {connect, Provider} from 'react-redux';
3
- import AppReviewRootView from '@coorpacademy/components/es/template/app-review/root-view/root-view';
3
+ import AppReviewTemplate from '@coorpacademy/components/es/template/app-review';
4
4
 
5
5
  import configureStore from './configure-store';
6
6
  import {navigateTo, navigateBack, startApp} from './actions/navigation';
7
+ import {updateSlidesOnNext, updateSlidesOnValidation} from './actions/slides';
7
8
  import {getCurrentViewName} from './reducers/navigation';
9
+ import type {SlidesViewStaticProps} from './types/views';
10
+ import type {AppOptions} from './types/common';
11
+ import type {StoreState} from './types/store-state';
12
+ import {congratsProps, correctionPopinProps} from './fixtures/temp-fixture';
13
+ import {updateFinishedSlides} from './actions/finished-slides';
14
+ import {updateReviewStatus} from './actions/review-status';
15
+ import {updateStepItemsOnValidation, updateStepItemsOnNext} from './actions/step-items';
16
+ import type {Dispatchers} from './types/dispatchers';
17
+ import {validateSlide} from './actions/data/validate-slide';
8
18
 
9
19
  // -----------------------------------------------------------------------------
10
20
 
11
- const mapStateToProps = (state, ownProps) => {
12
- return {...ownProps, viewName: getCurrentViewName(state)};
21
+ type StaticProps = {
22
+ viewName: 'home' | 'onboarding' | 'slides';
23
+ slides: SlidesViewStaticProps;
13
24
  };
14
25
 
15
- const mapDispatchToProps = {navigateTo, navigateBack};
16
- const App = connect(mapStateToProps, mapDispatchToProps)(AppReviewRootView);
26
+ // -----------------------------------------------------------------------------
27
+
28
+ const mapDispatchToProps: Dispatchers = {
29
+ navigateTo,
30
+ navigateBack,
31
+ validateSlide,
32
+ updateSlidesOnValidation,
33
+ updateSlidesOnNext,
34
+ updateReviewStatus,
35
+ updateStepItemsOnValidation,
36
+ updateStepItemsOnNext,
37
+ updateFinishedSlides
38
+ };
39
+
40
+ const mapStateToProps = (state: StoreState): StaticProps => {
41
+ return {
42
+ viewName: getCurrentViewName(state),
43
+ slides: {
44
+ headerProps: {
45
+ mode: '__revision_mode',
46
+ skillName: '__agility',
47
+ onQuitClick: (): void => {
48
+ // eslint-disable-next-line no-console
49
+ console.log('onQuitClick');
50
+ },
51
+ 'aria-label': 'aria-header-wrapper',
52
+ closeButtonAriaLabel: 'aria-close-button'
53
+ },
54
+ slides: state.ui.slides,
55
+ validate: {
56
+ label: '__validate'
57
+ },
58
+ finishedSlides: state.ui.finishedSlides,
59
+ stepItems: state.ui.stepItems,
60
+ reviewStatus: state.ui.reviewStatus,
61
+ correctionPopinProps,
62
+ congratsProps,
63
+ slideValidationResult: state.data.slideValidationResult
64
+ }
65
+ };
66
+ };
67
+
68
+ // Props = StaticProps && Dispatchers
69
+
70
+ const App = connect(mapStateToProps, mapDispatchToProps)(AppReviewTemplate);
17
71
 
18
72
  // -----------------------------------------------------------------------------
19
73
 
20
- const AppRevision = ({options}: Props) => {
74
+ const AppReview = ({options}: {options: AppOptions}): JSX.Element => {
21
75
  const [store, setStore] = useState(null);
76
+ const [appStarted, setAppStarted] = useState(false);
22
77
 
23
78
  useEffect(() => {
24
- const _configure = async () => {
25
- const store = await configureStore();
79
+ if (store) {
26
80
  store.dispatch(startApp(options));
27
- setStore(store);
28
- };
29
-
30
- _configure();
31
- }, []);
81
+ setAppStarted(true);
82
+ } else {
83
+ const _configure = async (): Promise<void> => {
84
+ const _store = await configureStore();
85
+ setStore(_store);
86
+ };
87
+ _configure();
88
+ }
89
+ }, [options, store]);
32
90
 
33
- if (!store) return null;
91
+ if (!store || !appStarted) return null;
34
92
 
35
93
  return (
36
94
  <Provider store={store}>
@@ -42,17 +100,12 @@ const AppRevision = ({options}: Props) => {
42
100
  // -----------------------------------------------------------------------------
43
101
 
44
102
  declare global {
103
+ // eslint-disable-next-line no-shadow
45
104
  interface Window {
46
105
  __REDUX_DEVTOOLS_EXTENSION__?: boolean;
47
106
  }
48
107
  }
49
108
 
50
- type Props = {options: AppOptions};
51
-
52
- export type AppOptions = {
53
- token: string;
54
- theme?: any;
55
- translations?: any;
56
- };
109
+ // -----------------------------------------------------------------------------
57
110
 
58
- export default AppRevision;
111
+ export default AppReview;
@@ -1,30 +1,45 @@
1
- import fetch from 'cross-fetch';
2
1
  import type {Middleware} from 'redux';
3
2
  import {Dispatch} from 'redux';
4
3
 
5
- import {Action, receivedCourse, START_APP, storeToken} from '../actions';
6
- import {StoreState} from '../configure-store';
7
- import fetchCourse from '../services/fetch-demo';
4
+ import {Action} from '../actions';
5
+ // import fetchCourse from '../services/fetch-demo';
6
+ import {VIEWS} from '../common';
7
+ import {navigateTo, START_APP, ViewPath} from '../actions/navigation';
8
+ import {storeToken} from '../actions/token';
9
+ import {storeFirstSlide} from '../actions/slides';
10
+ // import {receivedCourse} from '../actions/courses';
11
+ import {StoreState} from '../types/store-state';
8
12
 
9
- const onStartApp: Middleware<{}, StoreState, Dispatch<Action>> = ({dispatch}) => next => (
10
- action: Action
11
- ) => {
12
- if (action.type === START_APP) {
13
- const {token} = action.payload;
14
- dispatch(storeToken(token));
13
+ const onStartApp: Middleware<{}, StoreState, Dispatch<Action>> =
14
+ ({dispatch}) =>
15
+ next =>
16
+ (action: Action) => {
17
+ if (action.type === START_APP) {
18
+ // eslint-disable-next-line no-warning-comments
19
+ // TODO: fetchProgression + fetchSlide à partir de la progression passée dans les options de l'app
20
+ const {slide} = action.payload;
21
+ if (slide) {
22
+ const {token} = action.payload;
23
+ dispatch(storeToken(token));
24
+ dispatch(storeFirstSlide(slide));
25
+ }
15
26
 
16
- // --------------
17
- // demo service
27
+ const initialView: ViewPath = slide ? VIEWS.slides : VIEWS.onboarding;
18
28
 
19
- const language = 'fr';
20
- const universalRef = 'dis_xxx15';
29
+ dispatch(navigateTo(initialView));
21
30
 
22
- fetchCourse(token, language, universalRef).then(course => {
23
- dispatch(receivedCourse(course));
24
- });
25
- }
31
+ // --------------
32
+ // demo service
26
33
 
27
- return next(action);
28
- };
34
+ // const language = 'fr';
35
+ // const universalRef = 'dis_xxx15';
36
+
37
+ // fetchCourse(token, language, universalRef).then(course => {
38
+ // dispatch(receivedCourse(course));
39
+ // });
40
+ }
41
+
42
+ return next(action);
43
+ };
29
44
 
30
45
  export default onStartApp;
@@ -1,12 +1,13 @@
1
- import {ReceivedCourse, RECEIVED_COURSE} from '../actions';
1
+ import {ReceivedCourse, RECEIVED_COURSE} from '../actions/courses';
2
2
 
3
3
  // -----------------------------------------------------------------------------
4
4
 
5
- export type State = Array<any>;
5
+ export type State = Array<unknown>;
6
6
  export const initialState: State = [];
7
7
 
8
8
  // -----------------------------------------------------------------------------
9
9
 
10
+ // eslint-disable-next-line default-param-last
10
11
  const reducer = (state: State = initialState, action: ReceivedCourse): State => {
11
12
  switch (action.type) {
12
13
  case RECEIVED_COURSE: {
@@ -0,0 +1,88 @@
1
+ import getOr from 'lodash/fp/getOr';
2
+ import noop from 'lodash/fp/noop';
3
+ import set from 'lodash/fp/set';
4
+ import {StoreToken, STORE_TOKEN} from '../actions/token';
5
+ import {IsFetching, IS_FETCHING_TRUE} from '../actions/data/is-fetching';
6
+ import {ValidateSlide, VALIDATE_SLIDE} from '../actions/data/validate-slide';
7
+ import {DataState} from '../types/data';
8
+ import {setToken} from './token';
9
+
10
+ const defaultState = {
11
+ isFetching: true,
12
+ slideValidationResult: null,
13
+ token: null
14
+ };
15
+
16
+ type ApiActions = IsFetching | ValidateSlide | StoreToken;
17
+
18
+ // eslint-disable-next-line default-param-last
19
+ const data = (state: DataState = defaultState, action: ApiActions): DataState => {
20
+ switch (action.type) {
21
+ case STORE_TOKEN: {
22
+ return setToken(action.payload, state);
23
+ }
24
+ case VALIDATE_SLIDE: {
25
+ const previousSlideNumber: number = getOr(-1, 'slideValidationResult.slideNumber', state);
26
+ // hard coded for now
27
+ return set(
28
+ 'slideValidationResult',
29
+ {
30
+ slideNumber: previousSlideNumber + 1,
31
+ result: 'success',
32
+ // exitNode
33
+ nextSlide: {
34
+ questionText: 'Test',
35
+ answerUI: {
36
+ model: {
37
+ answers: [
38
+ {
39
+ title: 'There is no need for a password',
40
+ onClick: noop,
41
+ selected: false
42
+ },
43
+ {
44
+ title: 'Lorem ipsum',
45
+ onClick: noop,
46
+ selected: false
47
+ },
48
+ {
49
+ title: 'Lorem',
50
+ onClick: noop,
51
+ selected: true,
52
+ order: 1
53
+ },
54
+ {
55
+ title: 'You need to have a password',
56
+ onClick: noop,
57
+ selected: false
58
+ },
59
+ {
60
+ title: 'Pouet',
61
+ onClick: noop,
62
+ selected: true,
63
+ order: 0
64
+ }
65
+ ],
66
+ type: 'qcmDrag'
67
+ },
68
+ help: 'Help text will appear here'
69
+ }
70
+ }
71
+ },
72
+ state
73
+ );
74
+ }
75
+ case IS_FETCHING_TRUE: {
76
+ return set('isFetching', true, state);
77
+ }
78
+
79
+ // case VALIDATE_SLIDE_FAILURE: {
80
+ // return set('entities.isFetching', false, state);
81
+ // }
82
+
83
+ default:
84
+ return state;
85
+ }
86
+ };
87
+
88
+ export default data;
@@ -0,0 +1,48 @@
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';
5
+
6
+ const _forEach: <T>(
7
+ iteratee: (value: T[keyof T], index: number) => void,
8
+ collection: T
9
+ // @ts-expect-error to remove lodash's forEach iteratee args number cap
10
+ ) => void = forEach.convert({
11
+ cap: false
12
+ });
13
+
14
+ // -----------------------------------------------------------------------------
15
+
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 => {
25
+ switch (action.type) {
26
+ case UPDATE_FINISHED_SLIDES: {
27
+ const {slideNumbers: _slideNumbers, ...rest} = state;
28
+ const {slideNumber, value} = action.payload;
29
+ const _state: State = {
30
+ slideNumbers: _slideNumbers
31
+ };
32
+
33
+ _forEach<Omit<State, 'slideNumbers'>>((finishedSlide, index) => {
34
+ const previousValue = finishedSlide;
35
+ _state[index] = previousValue;
36
+ }, rest);
37
+
38
+ _state[slideNumber] = value;
39
+ return _state;
40
+ }
41
+ default:
42
+ return state;
43
+ }
44
+ };
45
+
46
+ // -----------------------------------------------------------------------------
47
+
48
+ export default reducer;
@@ -1,13 +1,23 @@
1
1
  import {combineReducers} from 'redux';
2
2
 
3
+ import data from './data';
3
4
  import courses from './courses';
5
+ import finishedSlides from './finished-slides';
4
6
  import navigation from './navigation';
5
- import token from './token';
7
+ import reviewStatus from './review-status';
8
+ import slides from './slides';
9
+ import stepItems from './step-items';
6
10
 
7
- const rootReducer = combineReducers({
11
+ const ui = combineReducers({
8
12
  courses,
13
+ finishedSlides,
9
14
  navigation,
10
- token
15
+ reviewStatus,
16
+ slides,
17
+ stepItems
11
18
  });
12
19
 
13
- export default rootReducer;
20
+ export default combineReducers({
21
+ ui,
22
+ data
23
+ });
@@ -1,13 +1,16 @@
1
- import {NAVIGATE_BACK, NAVIGATE_TO} from '../actions/navigation';
1
+ import {NAVIGATE_BACK, NAVIGATE_TO, ViewPath} from '../actions/navigation';
2
2
  import type {NavigateTo, NavigateBack} from '../actions/navigation';
3
+ import {StoreState} from '../types/store-state';
4
+ import {NavigationState as State} from '../types/states';
3
5
 
4
6
  // -----------------------------------------------------------------------------
5
7
 
6
- export type State = Array<string>;
8
+ // export type State = Array<string>;
7
9
  export const initialState: State = ['home'];
8
10
 
9
11
  // -----------------------------------------------------------------------------
10
12
 
13
+ // eslint-disable-next-line default-param-last
11
14
  const reducer = (state: State = initialState, action: NavigateTo | NavigateBack): State => {
12
15
  switch (action.type) {
13
16
  case NAVIGATE_TO: {
@@ -25,7 +28,8 @@ const reducer = (state: State = initialState, action: NavigateTo | NavigateBack)
25
28
 
26
29
  // -----------------------------------------------------------------------------
27
30
 
28
- export const getCurrentViewName = appState => appState.navigation[appState.navigation.length - 1];
31
+ export const getCurrentViewName = (appState: StoreState): ViewPath =>
32
+ appState.ui.navigation[appState.ui.navigation.length - 1];
29
33
 
30
34
  // -----------------------------------------------------------------------------
31
35
 
@@ -0,0 +1,23 @@
1
+ import {UpdateReviewStatus, UPDATE_REVIEW_STATUS} from '../actions/review-status';
2
+
3
+ // -----------------------------------------------------------------------------
4
+
5
+ export type State = 'finished' | 'ongoing';
6
+ export const initialState: State = 'ongoing';
7
+
8
+ // -----------------------------------------------------------------------------
9
+
10
+ // eslint-disable-next-line default-param-last
11
+ const reducer = (state: State = initialState, action: UpdateReviewStatus): State => {
12
+ switch (action.type) {
13
+ case UPDATE_REVIEW_STATUS: {
14
+ return action.payload;
15
+ }
16
+ default:
17
+ return state;
18
+ }
19
+ };
20
+
21
+ // -----------------------------------------------------------------------------
22
+
23
+ export default reducer;