Passed
Push — task/applicant-profile-api ( bae4f4...980451 )
by Yonathan
11:46 queued 03:46
created

resources/assets/js/store/Application/applicationReducer.ts   A

Complexity

Total Complexity 3
Complexity/F 0

Size

Lines of Code 395
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 3
eloc 306
dl 0
loc 395
rs 10
c 0
b 0
f 0
mnd 3
bc 3
fnc 0
bpm 0
cpm 0
noi 0
1
import { combineReducers } from "redux";
2
import {
3
  ApplicationNormalized,
4
  ApplicationReview,
5
  Email,
6
  JobApplicationAnswer,
7
} from "../../models/types";
8
import {
9
  ApplicationAction,
10
  FETCH_APPLICATION_SUCCEEDED,
11
  FETCH_APPLICATION_FAILED,
12
  FETCH_APPLICATION_STARTED,
13
  FETCH_APPLICATIONS_FOR_JOB_SUCCEEDED,
14
  FETCH_APPLICATIONS_FOR_JOB_STARTED,
15
  FETCH_APPLICATIONS_FOR_JOB_FAILED,
16
  UPDATE_APPLICATION_SUCCEEDED,
17
  UPDATE_APPLICATION_STARTED,
18
  UPDATE_APPLICATION_FAILED,
19
  UPDATE_APPLICATION_REVIEW_SUCCEEDED,
20
  UPDATE_APPLICATION_REVIEW_STARTED,
21
  UPDATE_APPLICATION_REVIEW_FAILED,
22
  FETCH_REFERENCE_EMAILS_SUCCEEDED,
23
  FETCH_REFERENCE_EMAILS_STARTED,
24
  FETCH_REFERENCE_EMAILS_FAILED,
25
  SEND_REFERENCE_EMAIL_STARTED,
26
  SEND_REFERENCE_EMAIL_SUCCEEDED,
27
  SEND_REFERENCE_EMAIL_FAILED,
28
  TOUCH_JOB_APPLICATION_STEP_SUCCEEDED,
29
  TOUCH_JOB_APPLICATION_STEP_STARTED,
30
  TOUCH_JOB_APPLICATION_STEP_FAILED,
31
  SUBMIT_APPLICATION_SUCCEEDED,
32
} from "./applicationActions";
33
import {
34
  mapToObject,
35
  getId,
36
  notEmpty,
37
  mapToObjectTrans,
38
  deleteProperty,
39
} from "../../helpers/queries";
40
import {
41
  CREATE_JOB_APPLICATION_ANSWER_SUCCEEDED,
42
  UPDATE_JOB_APPLICATION_ANSWER_SUCCEEDED,
43
} from "../JobApplicationAnswer/jobApplicationAnswerActions";
44
import {
45
  ApplicationStep,
46
  ProgressBarStatus,
47
} from "../../models/lookupConstants";
48
49
export interface EntityState {
50
  applications: {
51
    [id: number]: ApplicationNormalized;
52
  };
53
  jobApplicationAnswers: {
54
    [id: number]: JobApplicationAnswer;
55
  };
56
  jobApplicationSteps: { [step in ApplicationStep]: ProgressBarStatus };
57
  applicationReviews: {
58
    byId: {
59
      [id: number]: ApplicationReview;
60
    };
61
    idByApplicationId: {
62
      [applicationId: number]: number;
63
    };
64
  };
65
  microReferenceEmails: {
66
    director: {
67
      byApplicationId: {
68
        [applicationId: number]: Email;
69
      };
70
    };
71
    secondary: {
72
      byApplicationId: {
73
        [applicationId: number]: Email;
74
      };
75
    };
76
  };
77
}
78
79
export interface UiState {
80
  applicationIsUpdating: {
81
    [id: number]: boolean;
82
  };
83
  fetchingApplications: boolean;
84
  fetchingReferenceEmailsForApplication: {
85
    [applicationId: number]: boolean;
86
  };
87
  sendingReferenceEmailForApplication: {
88
    [applicationId: number]: boolean;
89
  };
90
  updatingSteps: boolean;
91
}
92
93
export interface ApplicationState {
94
  entities: EntityState;
95
  ui: UiState;
96
}
97
98
export const initEntities = (): EntityState => ({
99
  applications: {},
100
  jobApplicationAnswers: {},
101
  jobApplicationSteps: {
102
    basic: "default",
103
    experience: "default",
104
    skills: "default",
105
    fit: "default",
106
    review: "default",
107
    submission: "default",
108
  },
109
  applicationReviews: {
110
    byId: {},
111
    idByApplicationId: {},
112
  },
113
  microReferenceEmails: {
114
    director: {
115
      byApplicationId: {},
116
    },
117
    secondary: {
118
      byApplicationId: {},
119
    },
120
  },
121
});
122
123
export const initUi = (): UiState => ({
124
  applicationIsUpdating: {},
125
  fetchingApplications: false,
126
  fetchingReferenceEmailsForApplication: {},
127
  sendingReferenceEmailForApplication: {},
128
  updatingSteps: false,
129
});
130
131
export const initApplicationState = (): ApplicationState => ({
132
  entities: initEntities(),
133
  ui: initUi(),
134
});
135
136
export const entitiesReducer = (
137
  state = initEntities(),
138
  action: ApplicationAction,
139
): EntityState => {
140
  switch (action.type) {
141
    case FETCH_APPLICATION_SUCCEEDED:
142
      return {
143
        ...state,
144
        applications: {
145
          ...state.applications,
146
          [action.payload.application.id]: deleteProperty(
147
            action.payload.application,
148
            "application_review",
149
          ),
150
        },
151
        applicationReviews: action.payload.application.application_review
152
          ? {
153
              byId: {
154
                ...state.applicationReviews.byId,
155
                [action.payload.application.application_review.id]:
156
                  action.payload.application.application_review,
157
              },
158
              idByApplicationId: {
159
                ...state.applicationReviews.idByApplicationId,
160
                [action.payload.application.id]:
161
                  action.payload.application.application_review.id,
162
              },
163
            }
164
          : state.applicationReviews,
165
        jobApplicationAnswers: {
166
          ...mapToObject(action.payload.jobApplicationAnswers, getId),
167
        },
168
        jobApplicationSteps: action.payload.jobApplicationSteps,
169
      };
170
    case FETCH_APPLICATIONS_FOR_JOB_SUCCEEDED:
171
      return {
172
        ...state,
173
        applications: {
174
          ...state.applications,
175
          ...mapToObjectTrans(
176
            action.payload,
177
            getId,
178
            (application): ApplicationNormalized =>
179
              deleteProperty(application, "application_review"),
180
          ),
181
        },
182
        applicationReviews: {
183
          byId: {
184
            ...state.applicationReviews.byId,
185
            ...mapToObject(
186
              action.payload
187
                .map((application) => application.application_review)
188
                .filter(notEmpty),
189
              getId,
190
            ),
191
          },
192
          idByApplicationId: {
193
            ...state.applicationReviews.idByApplicationId,
194
            ...mapToObjectTrans(
195
              action.payload
196
                .map((application) => application.application_review)
197
                .filter(notEmpty),
198
              (review) => review.job_application_id,
199
              (review) => review.id,
200
            ),
201
          },
202
        },
203
      };
204
    case UPDATE_APPLICATION_SUCCEEDED:
205
    case SUBMIT_APPLICATION_SUCCEEDED:
206
      return {
207
        ...state,
208
        applications: {
209
          ...state.applications,
210
          [action.payload.id]: {
211
            ...state.applications[action.payload.id],
212
            ...action.payload,
213
          },
214
        },
215
      };
216
    case UPDATE_APPLICATION_REVIEW_SUCCEEDED:
217
      return {
218
        ...state,
219
        applicationReviews: {
220
          byId: {
221
            ...state.applicationReviews.byId,
222
            [action.payload.id]: action.payload,
223
          },
224
          idByApplicationId: {
225
            ...state.applicationReviews.idByApplicationId,
226
            [action.payload.job_application_id]: action.payload.id,
227
          },
228
        },
229
      };
230
    case FETCH_REFERENCE_EMAILS_SUCCEEDED:
231
      return {
232
        ...state,
233
        microReferenceEmails: {
234
          director: {
235
            byApplicationId: {
236
              ...state.microReferenceEmails.director.byApplicationId,
237
              [action.meta.applicationId]: action.payload.director,
238
            },
239
          },
240
          secondary: {
241
            byApplicationId: {
242
              ...state.microReferenceEmails.secondary.byApplicationId,
243
              [action.meta.applicationId]: action.payload.secondary,
244
            },
245
          },
246
        },
247
      };
248
    case CREATE_JOB_APPLICATION_ANSWER_SUCCEEDED:
249
    case UPDATE_JOB_APPLICATION_ANSWER_SUCCEEDED:
250
      return {
251
        ...state,
252
        jobApplicationAnswers: {
253
          ...state.jobApplicationAnswers,
254
          [action.payload.id]: action.payload,
255
        },
256
      };
257
    case TOUCH_JOB_APPLICATION_STEP_SUCCEEDED:
258
      return {
259
        ...state,
260
        jobApplicationSteps: {
261
          ...state.jobApplicationSteps,
262
          ...action.payload,
263
        },
264
      };
265
    default:
266
      return state;
267
  }
268
};
269
270
export const uiReducer = (
271
  state = initUi(),
272
  action: ApplicationAction,
273
): UiState => {
274
  switch (action.type) {
275
    case FETCH_APPLICATION_STARTED:
276
      return {
277
        ...state,
278
        applicationIsUpdating: {
279
          ...state.applicationIsUpdating,
280
          [action.meta.id]: true,
281
        },
282
        updatingSteps: true,
283
      };
284
    case FETCH_APPLICATION_SUCCEEDED:
285
    case FETCH_APPLICATION_FAILED:
286
      return {
287
        ...state,
288
        applicationIsUpdating: {
289
          ...state.applicationIsUpdating,
290
          [action.meta.id]: false,
291
        },
292
        updatingSteps: false,
293
      };
294
    case FETCH_APPLICATIONS_FOR_JOB_STARTED:
295
      return {
296
        ...state,
297
        fetchingApplications: true,
298
      };
299
    case FETCH_APPLICATIONS_FOR_JOB_SUCCEEDED:
300
    case FETCH_APPLICATIONS_FOR_JOB_FAILED:
301
      return {
302
        ...state,
303
        fetchingApplications: false,
304
      };
305
    case UPDATE_APPLICATION_STARTED:
306
      return {
307
        ...state,
308
        applicationIsUpdating: {
309
          ...state.applicationIsUpdating,
310
          [action.meta.id]: true,
311
        },
312
      };
313
    case UPDATE_APPLICATION_SUCCEEDED:
314
    case UPDATE_APPLICATION_FAILED:
315
      return {
316
        ...state,
317
        applicationIsUpdating: {
318
          ...state.applicationIsUpdating,
319
          [action.meta.id]: false,
320
        },
321
      };
322
    case UPDATE_APPLICATION_REVIEW_STARTED:
323
      return {
324
        ...state,
325
        applicationIsUpdating: {
326
          ...state.applicationIsUpdating,
327
          [action.meta.applicationId]: true,
328
        },
329
      };
330
    case UPDATE_APPLICATION_REVIEW_SUCCEEDED:
331
    case UPDATE_APPLICATION_REVIEW_FAILED:
332
      return {
333
        ...state,
334
        applicationIsUpdating: {
335
          ...state.applicationIsUpdating,
336
          [action.meta.applicationId]: false,
337
        },
338
      };
339
    case FETCH_REFERENCE_EMAILS_STARTED:
340
      return {
341
        ...state,
342
        fetchingReferenceEmailsForApplication: {
343
          ...state.fetchingReferenceEmailsForApplication,
344
          [action.meta.applicationId]: true,
345
        },
346
      };
347
    case FETCH_REFERENCE_EMAILS_SUCCEEDED:
348
    case FETCH_REFERENCE_EMAILS_FAILED:
349
      return {
350
        ...state,
351
        fetchingReferenceEmailsForApplication: {
352
          ...state.fetchingReferenceEmailsForApplication,
353
          [action.meta.applicationId]: false,
354
        },
355
      };
356
    case SEND_REFERENCE_EMAIL_STARTED:
357
      return {
358
        ...state,
359
        sendingReferenceEmailForApplication: {
360
          ...state.sendingReferenceEmailForApplication,
361
          [action.meta.applicationId]: true,
362
        },
363
      };
364
    case SEND_REFERENCE_EMAIL_SUCCEEDED:
365
    case SEND_REFERENCE_EMAIL_FAILED:
366
      return {
367
        ...state,
368
        sendingReferenceEmailForApplication: {
369
          ...state.sendingReferenceEmailForApplication,
370
          [action.meta.applicationId]: false,
371
        },
372
      };
373
    case TOUCH_JOB_APPLICATION_STEP_STARTED:
374
      return {
375
        ...state,
376
        updatingSteps: true,
377
      };
378
    case TOUCH_JOB_APPLICATION_STEP_SUCCEEDED:
379
    case TOUCH_JOB_APPLICATION_STEP_FAILED:
380
      return {
381
        ...state,
382
        updatingSteps: false,
383
      };
384
    default:
385
      return state;
386
  }
387
};
388
389
export const applicationReducer = combineReducers({
390
  entities: entitiesReducer,
391
  ui: uiReducer,
392
});
393
394
export default applicationReducer;
395