@coorpacademy/app-review 0.1.18 → 0.1.20

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 (34) hide show
  1. package/es/actions/api/post-answer.js +9 -8
  2. package/es/actions/api/test/post-answer.test.js +6 -6
  3. package/es/reducers/data/test/progression.test.js +4 -3
  4. package/es/services/post-answer.d.ts +1 -1
  5. package/es/services/post-answer.js +3 -1
  6. package/es/services/test/post-answer.test.js +27 -4
  7. package/es/test/util/services.mock.d.ts +2 -1
  8. package/es/test/util/services.mock.js +264 -23
  9. package/es/types/common.d.ts +11 -9
  10. package/es/views/slides/index.d.ts +1 -0
  11. package/es/views/slides/index.js +24 -8
  12. package/es/views/slides/test/index.test.js +518 -203
  13. package/lib/actions/api/post-answer.js +10 -9
  14. package/lib/actions/api/test/post-answer.test.js +6 -6
  15. package/lib/reducers/data/test/progression.test.js +4 -3
  16. package/lib/services/post-answer.d.ts +1 -1
  17. package/lib/services/post-answer.js +4 -2
  18. package/lib/services/test/post-answer.test.js +27 -4
  19. package/lib/test/util/services.mock.d.ts +2 -1
  20. package/lib/test/util/services.mock.js +265 -23
  21. package/lib/types/common.d.ts +11 -9
  22. package/lib/views/slides/index.d.ts +1 -0
  23. package/lib/views/slides/index.js +23 -7
  24. package/lib/views/slides/test/index.test.js +521 -203
  25. package/package.json +3 -4
  26. package/src/actions/api/post-answer.ts +9 -9
  27. package/src/actions/api/test/post-answer.test.ts +6 -6
  28. package/src/reducers/data/test/progression.test.ts +4 -3
  29. package/src/services/post-answer.ts +3 -2
  30. package/src/services/test/post-answer.test.ts +28 -4
  31. package/src/test/util/services.mock.ts +274 -24
  32. package/src/types/common.ts +13 -10
  33. package/src/views/slides/index.ts +35 -10
  34. package/src/views/slides/test/index.test.ts +559 -228
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coorpacademy/app-review",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "",
5
5
  "engines": {
6
6
  "node": ">=16.15.0"
@@ -41,7 +41,7 @@
41
41
  "./package.json": "./package.json"
42
42
  },
43
43
  "dependencies": {
44
- "@coorpacademy/components": "10.22.12",
44
+ "@coorpacademy/components": "10.22.14",
45
45
  "@coorpacademy/redux-task": "^1.1.5",
46
46
  "cross-fetch": "^3.1.5",
47
47
  "jwt-decode": "^3.1.2",
@@ -77,6 +77,5 @@
77
77
  "react-dom": "^17.0.2",
78
78
  "ts-node": "^10.9.1",
79
79
  "typescript": "^4.7.4"
80
- },
81
- "gitHead": "2b9abf8c945cd56a6a47091836e4961917580782"
80
+ }
82
81
  }
@@ -23,22 +23,22 @@ export const postAnswer = async (
23
23
  getState: () => StoreState,
24
24
  {services}: Options
25
25
  ): Promise<void> => {
26
+ const state = getState();
27
+ const token = get('data.token', state);
28
+ const answer = get('ui.answers', state);
29
+ const progression = state.data.progression;
30
+ if (!progression) throw new Error('cannot answer question of inexisting progression');
31
+
26
32
  const action = buildTask({
27
33
  types: [POST_ANSWER_REQUEST, POST_ANSWER_SUCCESS, POST_ANSWER_FAILURE],
28
34
  task: () => {
29
- const state = getState();
30
- const token = get('data.token', state);
31
- const answer = get('ui.answers', state);
32
- const progressionId = get('data.progression._id', state);
33
- const skillRef = get('data.progression.content.ref', state);
34
- return services.postAnswer(skillRef, token, progressionId, answer);
35
+ return services.postAnswer(progression, token, answer);
35
36
  }
36
37
  });
37
38
  const response = await dispatch(action);
38
-
39
39
  if (response.type === POST_ANSWER_SUCCESS) {
40
- const progression = response.payload;
41
- const slideRef = progression.state.nextContent.ref;
40
+ const updatedProgression = response.payload;
41
+ const slideRef = updatedProgression.state.nextContent.ref;
42
42
  await dispatch(fetchSlide(slideRef));
43
43
  }
44
44
  };
@@ -1,6 +1,6 @@
1
1
  import test from 'ava';
2
2
  import {createTestStore} from '../../test/create-test-store';
3
- import {postAnswerResponse, services} from '../../../test/util/services.mock';
3
+ import {postAnswerResponses, services} from '../../../test/util/services.mock';
4
4
  import {
5
5
  postAnswer,
6
6
  POST_ANSWER_FAILURE,
@@ -29,7 +29,7 @@ const initialState: StoreState = {
29
29
  allAnswers: [],
30
30
  isCorrect: true,
31
31
  nextContent: {
32
- ref: 'sli_VJYjJnJhg',
32
+ ref: freeTextSlide.id,
33
33
  type: 'slide'
34
34
  },
35
35
  pendingSlides: [],
@@ -47,7 +47,7 @@ const initialState: StoreState = {
47
47
  token: '1234'
48
48
  },
49
49
  ui: {
50
- currentSlideRef: 'sli_VJYjJnJhg',
50
+ currentSlideRef: freeTextSlide.id,
51
51
  navigation: ['skills', 'slides'],
52
52
  answers: answer,
53
53
  slide: {
@@ -61,12 +61,12 @@ test('should dispatch POST_ANSWER_REQUEST, then POST_ANSWER_SUCCESS when the upd
61
61
  {type: POST_ANSWER_REQUEST},
62
62
  {
63
63
  type: POST_ANSWER_SUCCESS,
64
- payload: postAnswerResponse
64
+ payload: postAnswerResponses[freeTextSlide.id]
65
65
  },
66
- {type: SLIDE_FETCH_REQUEST, meta: {slideRef: 'sli_VkSQroQnx'}},
66
+ {type: SLIDE_FETCH_REQUEST, meta: {slideRef: qcmGraphicSlide.id}},
67
67
  {
68
68
  type: SLIDE_FETCH_SUCCESS,
69
- meta: {slideRef: 'sli_VkSQroQnx'},
69
+ meta: {slideRef: qcmGraphicSlide.id},
70
70
  payload: qcmGraphicSlide
71
71
  },
72
72
  {type: SET_CURRENT_SLIDE, payload: qcmGraphicSlide}
@@ -2,7 +2,8 @@ import test from 'ava';
2
2
  import reducer from '../progression';
3
3
  import {POST_PROGRESSION_SUCCESS, ReceivedProgression} from '../../../actions/api/post-progression';
4
4
  import {POST_ANSWER_SUCCESS} from '../../../actions/api/post-answer';
5
- import {postAnswerResponse, postProgressionResponse} from '../../../test/util/services.mock';
5
+ import {postAnswerResponses, postProgressionResponse} from '../../../test/util/services.mock';
6
+ import {freeTextSlide} from '../../../views/slides/test/fixtures/free-text';
6
7
 
7
8
  test('should have initial value', t => {
8
9
  const state = reducer(undefined, {} as ReceivedProgression);
@@ -20,7 +21,7 @@ test('should set the value of POST_PROGRESSION_SUCCESS action', t => {
20
21
  test('should set the value of POST_ANSWER_SUCCESS action', t => {
21
22
  const state = reducer(null, {
22
23
  type: POST_ANSWER_SUCCESS,
23
- payload: postAnswerResponse
24
+ payload: postAnswerResponses[freeTextSlide.universalRef]
24
25
  });
25
- t.deepEqual(state, postAnswerResponse);
26
+ t.deepEqual(state, postAnswerResponses[freeTextSlide.universalRef]);
26
27
  });
@@ -5,11 +5,12 @@ import {JWT, ProgressionFromAPI} from '../types/common';
5
5
  import {toJSON} from './tools/fetch-responses';
6
6
 
7
7
  export const postAnswer = async (
8
- skillRef: string,
8
+ progression: ProgressionFromAPI,
9
9
  token: string,
10
- progressionId: string,
11
10
  answer: string[]
12
11
  ): Promise<ProgressionFromAPI> => {
12
+ const progressionId = progression._id;
13
+ const skillRef = progression.content.ref;
13
14
  const {host}: JWT = decode(token);
14
15
  const response = await crossFetch(`${host}/api/v2/progressions/${progressionId}/answers`, {
15
16
  method: 'post',
@@ -3,10 +3,34 @@ import nock from 'nock';
3
3
  import type {ProgressionFromAPI} from '../../types/common';
4
4
  import {postAnswer} from '../post-answer';
5
5
 
6
- const progressionId = '123456789123';
7
6
  const skillRef = '_skill-ref';
8
7
  const answer = ['Lister vos tâches pour vous libérer l’esprit', 'Vous isoler dans un lieu calme'];
9
8
 
9
+ const initProgression: ProgressionFromAPI = {
10
+ content: {
11
+ type: 'skill',
12
+ ref: skillRef
13
+ },
14
+ engine: {
15
+ ref: 'review'
16
+ },
17
+ _id: '123456123456',
18
+ state: {
19
+ allAnswers: [],
20
+ isCorrect: true,
21
+ nextContent: {
22
+ type: 'slide',
23
+ ref: 'sli_NkvrWPFF2'
24
+ },
25
+ pendingSlides: [],
26
+ slides: [],
27
+ step: {
28
+ current: 1
29
+ },
30
+ stars: 0
31
+ }
32
+ };
33
+
10
34
  const result: ProgressionFromAPI = {
11
35
  content: {
12
36
  type: 'skill',
@@ -44,7 +68,7 @@ const result: ProgressionFromAPI = {
44
68
 
45
69
  test.before(() => {
46
70
  const moocApi = nock('http://localhost:3000');
47
- moocApi.post(`/api/v2/progressions/${progressionId}/answers`).reply(200, result);
71
+ moocApi.post('/api/v2/progressions/123456123456/answers').reply(200, result);
48
72
  });
49
73
 
50
74
  test.after(() => {
@@ -53,13 +77,13 @@ test.after(() => {
53
77
 
54
78
  test('should post the answers successfully', async t => {
55
79
  const token = process.env.API_TEST_TOKEN || '';
56
- const progression = await postAnswer(skillRef, token, progressionId, answer);
80
+ const progression = await postAnswer(initProgression, token, answer);
57
81
  t.deepEqual(result, progression);
58
82
  });
59
83
 
60
84
  test('should reject bad token', async t => {
61
85
  const badToken = 'token is not a jwt';
62
- const error = await t.throwsAsync(() => postAnswer(skillRef, badToken, progressionId, answer));
86
+ const error = await t.throwsAsync(() => postAnswer(initProgression, badToken, answer));
63
87
 
64
88
  t.is(
65
89
  error?.message,
@@ -1,9 +1,25 @@
1
+ import get from 'lodash/fp/get';
1
2
  import {qcmSlide} from '../../views/slides/test/fixtures/qcm';
2
3
  import {qcmGraphicSlide} from '../../views/slides/test/fixtures/qcm-graphic';
3
4
  import {freeTextSlide} from '../../views/slides/test/fixtures/free-text';
4
5
  import {sliderSlide} from '../../views/slides/test/fixtures/slider';
5
6
  import {templateSlide} from '../../views/slides/test/fixtures/template';
6
- import {ProgressionFromAPI, Services, SlideFromAPI} from '../../types/common';
7
+ import {
8
+ ProgressionFromAPI,
9
+ ReviewContent,
10
+ ReviewEngine,
11
+ Services,
12
+ SlideFromAPI
13
+ } from '../../types/common';
14
+
15
+ const content: ReviewContent = {
16
+ ref: '_skill-ref',
17
+ type: 'skill'
18
+ };
19
+
20
+ const engine: ReviewEngine = {
21
+ ref: 'review'
22
+ };
7
23
 
8
24
  const getSlideFixture = (ref: string): SlideFromAPI => {
9
25
  switch (ref) {
@@ -37,18 +53,13 @@ const fetchSkillsResponse = [
37
53
 
38
54
  export const postProgressionResponse: ProgressionFromAPI = {
39
55
  _id: '62b1d1087aa12f00253f40ee',
40
- content: {
41
- ref: '_skill-ref',
42
- type: 'skill'
43
- },
44
- engine: {
45
- ref: 'review'
46
- },
56
+ content,
57
+ engine,
47
58
  state: {
48
59
  allAnswers: [],
49
60
  isCorrect: true,
50
61
  nextContent: {
51
- ref: 'sli_VJYjJnJhg',
62
+ ref: freeTextSlide.universalRef,
52
63
  type: 'slide'
53
64
  },
54
65
  pendingSlides: [],
@@ -60,38 +71,274 @@ export const postProgressionResponse: ProgressionFromAPI = {
60
71
  }
61
72
  };
62
73
 
63
- export const postAnswerResponse: ProgressionFromAPI = {
64
- _id: '62b1d1087aa12f00253f40ee',
65
- content: {
66
- ref: '_skill-ref',
67
- type: 'skill'
74
+ export const postAnswerResponses: Record<string, ProgressionFromAPI> = {
75
+ [freeTextSlide.universalRef]: {
76
+ _id: '62b1d1087aa12f00253f40ee',
77
+ content,
78
+ engine,
79
+ state: {
80
+ allAnswers: [
81
+ {
82
+ slideRef: freeTextSlide.universalRef,
83
+ isCorrect: true,
84
+ answer: ['Benchmark']
85
+ }
86
+ ],
87
+ isCorrect: true,
88
+ nextContent: {
89
+ ref: qcmGraphicSlide.universalRef,
90
+ type: 'slide'
91
+ },
92
+ content: {
93
+ ref: freeTextSlide.universalRef,
94
+ type: 'slide'
95
+ },
96
+ pendingSlides: [],
97
+ slides: [freeTextSlide.universalRef],
98
+ step: {
99
+ current: 2
100
+ },
101
+ stars: 8
102
+ }
103
+ },
104
+ [qcmGraphicSlide.universalRef]: {
105
+ _id: '62b1d1087aa12f00253f40ee',
106
+ content,
107
+ engine,
108
+ state: {
109
+ allAnswers: [
110
+ {
111
+ slideRef: freeTextSlide.universalRef,
112
+ isCorrect: true,
113
+ answer: ['Benchmark']
114
+ },
115
+ {
116
+ slideRef: qcmGraphicSlide.universalRef,
117
+ isCorrect: true,
118
+ answer: ['Faux']
119
+ }
120
+ ],
121
+ isCorrect: true,
122
+ nextContent: {
123
+ ref: qcmSlide.universalRef,
124
+ type: 'slide'
125
+ },
126
+ content: {
127
+ ref: qcmGraphicSlide.universalRef,
128
+ type: 'slide'
129
+ },
130
+ pendingSlides: [],
131
+ slides: [freeTextSlide.universalRef, qcmGraphicSlide.universalRef],
132
+ step: {
133
+ current: 3
134
+ },
135
+ stars: 16
136
+ }
137
+ },
138
+ [qcmSlide.universalRef]: {
139
+ _id: '62b1d1087aa12f00253f40ee',
140
+ content,
141
+ engine,
142
+ state: {
143
+ allAnswers: [
144
+ {
145
+ slideRef: freeTextSlide.universalRef,
146
+ isCorrect: true,
147
+ answer: ['Benchmark']
148
+ },
149
+ {
150
+ slideRef: qcmGraphicSlide.universalRef,
151
+ isCorrect: true,
152
+ answer: ['Faux']
153
+ },
154
+ {
155
+ slideRef: qcmSlide.universalRef,
156
+ isCorrect: true,
157
+ answer: ['Le créateur peut fixer un pourcentage pour chaque transaction future']
158
+ }
159
+ ],
160
+ isCorrect: true,
161
+ nextContent: {
162
+ ref: sliderSlide.universalRef,
163
+ type: 'slide'
164
+ },
165
+ content: {
166
+ ref: qcmSlide.universalRef,
167
+ type: 'slide'
168
+ },
169
+ pendingSlides: [],
170
+ slides: [freeTextSlide.universalRef, qcmGraphicSlide.universalRef, qcmSlide.universalRef],
171
+ step: {
172
+ current: 4
173
+ },
174
+ stars: 24
175
+ }
68
176
  },
69
- engine: {
70
- ref: 'review'
177
+ [sliderSlide.universalRef]: {
178
+ _id: '62b1d1087aa12f00253f40ee',
179
+ content,
180
+ engine,
181
+ state: {
182
+ allAnswers: [
183
+ {
184
+ slideRef: freeTextSlide.universalRef,
185
+ isCorrect: true,
186
+ answer: ['Benchmark']
187
+ },
188
+ {
189
+ slideRef: qcmGraphicSlide.universalRef,
190
+ isCorrect: true,
191
+ answer: ['Faux']
192
+ },
193
+ {
194
+ slideRef: qcmSlide.universalRef,
195
+ isCorrect: true,
196
+ answer: ['Le créateur peut fixer un pourcentage pour chaque transaction future']
197
+ },
198
+ {
199
+ slideRef: sliderSlide.universalRef,
200
+ isCorrect: true,
201
+ answer: ['7']
202
+ }
203
+ ],
204
+ isCorrect: true,
205
+ nextContent: {
206
+ ref: templateSlide.universalRef,
207
+ type: 'slide'
208
+ },
209
+ content: {
210
+ ref: sliderSlide.universalRef,
211
+ type: 'slide'
212
+ },
213
+ pendingSlides: [],
214
+ slides: [
215
+ freeTextSlide.universalRef,
216
+ qcmGraphicSlide.universalRef,
217
+ qcmSlide.universalRef,
218
+ sliderSlide.universalRef
219
+ ],
220
+ step: {
221
+ current: 5
222
+ },
223
+ stars: 32
224
+ }
71
225
  },
226
+ [templateSlide.universalRef]: {
227
+ _id: '62b1d1087aa12f00253f40ee',
228
+ content,
229
+ engine,
230
+ state: {
231
+ allAnswers: [
232
+ {
233
+ slideRef: freeTextSlide.universalRef,
234
+ isCorrect: true,
235
+ answer: ['Benchmark']
236
+ },
237
+ {
238
+ slideRef: qcmGraphicSlide.universalRef,
239
+ isCorrect: true,
240
+ answer: ['Faux']
241
+ },
242
+ {
243
+ slideRef: qcmSlide.universalRef,
244
+ isCorrect: true,
245
+ answer: ['Le créateur peut fixer un pourcentage pour chaque transaction future']
246
+ },
247
+ {
248
+ slideRef: sliderSlide.universalRef,
249
+ isCorrect: true,
250
+ answer: ['7']
251
+ },
252
+ {
253
+ slideRef: templateSlide.universalRef,
254
+ isCorrect: true,
255
+ answer: ['Leaderboard', 'utilisateurs', 'étoiles']
256
+ }
257
+ ],
258
+ isCorrect: true,
259
+ nextContent: {
260
+ ref: 'successExitNode',
261
+ type: 'success'
262
+ },
263
+ content: {
264
+ ref: templateSlide.universalRef,
265
+ type: 'slide'
266
+ },
267
+ pendingSlides: [],
268
+ slides: [
269
+ freeTextSlide.universalRef,
270
+ qcmGraphicSlide.universalRef,
271
+ qcmSlide.universalRef,
272
+ sliderSlide.universalRef,
273
+ templateSlide.universalRef
274
+ ],
275
+ step: {
276
+ current: 6
277
+ },
278
+ stars: 40
279
+ }
280
+ }
281
+ };
282
+
283
+ export const progressionSlideWithPendingSlide: ProgressionFromAPI = {
284
+ _id: '62b1d1087aa12f00253f40ee',
285
+ content,
286
+ engine,
72
287
  state: {
73
288
  allAnswers: [
74
289
  {
75
- slideRef: 'sli_VJYjJnJhg',
290
+ slideRef: freeTextSlide.universalRef,
291
+ isCorrect: false,
292
+ answer: ['Wrong']
293
+ },
294
+ {
295
+ slideRef: qcmGraphicSlide.universalRef,
296
+ isCorrect: true,
297
+ answer: ['Faux']
298
+ },
299
+ {
300
+ slideRef: qcmSlide.universalRef,
301
+ isCorrect: false,
302
+ answer: ['Wrong']
303
+ },
304
+ {
305
+ slideRef: sliderSlide.universalRef,
306
+ isCorrect: true,
307
+ answer: ['7']
308
+ },
309
+ {
310
+ slideRef: templateSlide.universalRef,
311
+ isCorrect: true,
312
+ answer: ['Leaderboard', 'utilisateurs', 'étoiles']
313
+ },
314
+ {
315
+ slideRef: freeTextSlide.universalRef,
76
316
  isCorrect: true,
77
317
  answer: ['Benchmark']
78
318
  }
79
319
  ],
80
320
  isCorrect: true,
81
321
  nextContent: {
82
- ref: 'sli_VkSQroQnx',
322
+ ref: qcmSlide.universalRef,
83
323
  type: 'slide'
84
324
  },
85
325
  content: {
86
- ref: 'sli_VJYjJnJhg',
326
+ ref: freeTextSlide.universalRef,
87
327
  type: 'slide'
88
328
  },
89
- pendingSlides: [],
90
- slides: ['sli_VJYjJnJhg'],
329
+ pendingSlides: [qcmSlide.universalRef],
330
+ slides: [
331
+ freeTextSlide.universalRef,
332
+ qcmGraphicSlide.universalRef,
333
+ qcmSlide.universalRef,
334
+ sliderSlide.universalRef,
335
+ templateSlide.universalRef,
336
+ freeTextSlide.universalRef
337
+ ],
91
338
  step: {
92
- current: 2
339
+ current: 7
93
340
  },
94
- stars: 4
341
+ stars: 32
95
342
  }
96
343
  };
97
344
 
@@ -99,5 +346,8 @@ export const services: Services = {
99
346
  fetchSkills: () => Promise.resolve(fetchSkillsResponse),
100
347
  fetchSlide: ref => Promise.resolve({...getSlideFixture(ref), universalRef: ref, id: ref}),
101
348
  postProgression: () => Promise.resolve(postProgressionResponse),
102
- postAnswer: () => Promise.resolve(postAnswerResponse)
349
+ postAnswer: progression => {
350
+ const currentSlide = progression.state.nextContent.ref;
351
+ return Promise.resolve(get(currentSlide, postAnswerResponses));
352
+ }
103
353
  };
@@ -90,7 +90,7 @@ export type SlideFromAPI = {
90
90
  };
91
91
  };
92
92
 
93
- type ProgressionAnswerItem = {
93
+ export type ProgressionAnswerItem = {
94
94
  isCorrect: boolean;
95
95
  slideRef: string;
96
96
  answer: string[];
@@ -115,15 +115,19 @@ export type ProgressionState = {
115
115
  stars: number;
116
116
  };
117
117
 
118
+ export type ReviewContent = {
119
+ type: 'skill';
120
+ ref: string;
121
+ };
122
+
123
+ export type ReviewEngine = {
124
+ ref: 'review';
125
+ };
126
+
118
127
  export type ProgressionFromAPI = {
119
128
  _id: string;
120
- content: {
121
- type: 'skill';
122
- ref: string;
123
- };
124
- engine: {
125
- ref: 'review';
126
- };
129
+ content: ReviewContent;
130
+ engine: ReviewEngine;
127
131
  state: ProgressionState;
128
132
  };
129
133
 
@@ -139,9 +143,8 @@ export type Services = {
139
143
  fetchSlide(slideRef: string, token: string): Promise<SlideFromAPI | void>;
140
144
  postProgression(skillRef: string, token: string): Promise<ProgressionFromAPI>;
141
145
  postAnswer(
142
- skillRef: string,
146
+ progression: ProgressionFromAPI,
143
147
  token: string,
144
- progressionId: string,
145
148
  answer: string[]
146
149
  ): Promise<ProgressionFromAPI>;
147
150
  };
@@ -1,15 +1,15 @@
1
1
  import concat from 'lodash/fp/concat';
2
-
2
+ import findLast from 'lodash/fp/findLast';
3
3
  import get from 'lodash/fp/get';
4
4
  import getOr from 'lodash/fp/getOr';
5
- import isEmpty from 'lodash/fp/isEmpty';
5
+ import last from 'lodash/fp/last';
6
6
  import pipe from 'lodash/fp/pipe';
7
7
  import reduce from 'lodash/fp/reduce';
8
8
  import set from 'lodash/fp/set';
9
9
  import slice from 'lodash/fp/slice';
10
10
  import toInteger from 'lodash/fp/toInteger';
11
11
  import {Dispatch} from 'redux';
12
- import {ProgressionFromAPI} from '../../types/common';
12
+ import {ProgressionAnswerItem, ProgressionFromAPI} from '../../types/common';
13
13
  import {SlideIndexes} from '../../common';
14
14
  import {StoreState} from '../../reducers';
15
15
  import {AnswerUI} from '../../types/slides';
@@ -181,7 +181,19 @@ const buildStackSlides = (state: StoreState, dispatch: Dispatch): SlidesStack =>
181
181
  return stack;
182
182
  };
183
183
 
184
- const buildStepItems = (state: StoreState): StepItem[] => {
184
+ const getIconForCurrentStep = (
185
+ slideRef: string,
186
+ lastGivenAnswerForSlide: ProgressionAnswerItem,
187
+ currentSlideRef: string,
188
+ lastGivenAsnswer: ProgressionAnswerItem
189
+ ): IconValue => {
190
+ if (slideRef !== currentSlideRef) return lastGivenAnswerForSlide.isCorrect ? 'right' : 'wrong';
191
+
192
+ if (lastGivenAsnswer.slideRef !== slideRef) return 'no-answer';
193
+ return lastGivenAnswerForSlide.isCorrect ? 'right' : 'wrong';
194
+ };
195
+
196
+ export const buildStepItems = (state: StoreState): StepItem[] => {
185
197
  const {progression} = state.data;
186
198
  const {currentSlideRef} = state.ui;
187
199
  if (!progression) return [];
@@ -214,23 +226,36 @@ const buildStepItems = (state: StoreState): StepItem[] => {
214
226
  }
215
227
  ];
216
228
 
229
+ const slideRefs = getProgressionSlidesRefs(progression);
217
230
  const allAnswers = progression.state.allAnswers;
218
231
  const step = progression.state.step;
219
- if (isEmpty(allAnswers)) return defaultProps;
232
+ const nextContentRef = progression.state.nextContent.ref;
233
+ const lastGivenAnswer = last(allAnswers);
234
+ if (!lastGivenAnswer) return defaultProps;
220
235
 
221
236
  const steps = defaultProps.map((stepItem, index): StepItem => {
222
- const givenAnswer = allAnswers[index];
223
- if (!givenAnswer) {
237
+ const slideRef = slideRefs[index];
238
+ if (!slideRef) return stepItem; // non fecthed slide pour given index
239
+
240
+ const lastGivenAnswerForSlide = findLast(answer => answer.slideRef === slideRef, allAnswers);
241
+ // never answered slide
242
+ if (!lastGivenAnswerForSlide) {
224
243
  return {
225
244
  ...stepItem,
226
- current: step.current === index + 1
245
+ current: nextContentRef === currentSlideRef && step.current === index + 1
227
246
  };
228
247
  }
229
248
 
249
+ // already answered slide, we computed based on the lastGivenAnswer
230
250
  return {
231
251
  ...stepItem,
232
- icon: givenAnswer.isCorrect ? 'right' : 'wrong',
233
- current: givenAnswer.slideRef === currentSlideRef
252
+ icon: getIconForCurrentStep(
253
+ slideRef,
254
+ lastGivenAnswerForSlide,
255
+ currentSlideRef,
256
+ lastGivenAnswer
257
+ ),
258
+ current: lastGivenAnswerForSlide.slideRef === currentSlideRef
234
259
  };
235
260
  });
236
261
  return steps;