Passed
Push — task/combine-skills-modal-and-... ( 975c6d...76e782 )
by Yonathan
05:12
created

resources/assets/js/models/localizedConstants.tsx   A

Complexity

Total Complexity 11
Complexity/F 0

Size

Lines of Code 1330
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 11
eloc 1060
c 0
b 0
f 0
dl 0
loc 1330
rs 9.36
mnd 11
bc 11
fnc 0
bpm 0
cpm 0
noi 0
1
/* eslint camelcase: "off" */
2
import { defineMessages, MessageDescriptor, IntlShape } from "react-intl";
3
import {
4
  AssessmentTypeId,
5
  AssessmentTypeIdValues,
6
  CriteriaTypeId,
7
  CriteriaTypeIdValues,
8
  SkillLevelId,
9
  SkillLevelIdValues,
10
  SkillTypeId,
11
  SkillTypeIdValues,
12
  ProvinceId,
13
  SecurityClearanceId,
14
  LanguageRequirementId,
15
  FrequencyId,
16
  OvertimeRequirementId,
17
  TravelRequirementId,
18
  LocationId,
19
  ResponseScreeningBuckets as ResponseBuckets,
20
  ReviewStatusId,
21
  ReviewStatusName,
22
} from "./lookupConstants";
23
import { getOrThrowError } from "../helpers/queries";
24
import { Experience } from "./types";
25
26
const skillLevelDescriptions = defineMessages({
27
  hardBasic: {
28
    id: "skillLevel.hard.basic.description",
29
    defaultMessage:
30
      "You have the ability to accomplish basic tasks with steady supervision and clear direction. The tasks you’re assigned are clear and don’t involve significant complexity. Their impact is usually locally felt. As you advance in this category, you should be developing the ability to accomplish tasks of moderate complexity with steady supervision. You will also need to be able to accomplish basic tasks with little or no supervision. This level is usually associated with tasks that form the bulk of the work for lower level positions, such as junior analysts or entry level developers.",
31
    description: "Description of basic hard skill level.",
32
  },
33
  hardIntermediate: {
34
    id: "skillLevel.hard.intermediate.description",
35
    defaultMessage:
36
      "You have the ability to accomplish tasks of moderate complexity or moderate impact with supervision. The approach to the tasks, and how they are delivered, is determined by the supervisor. You contribute input and advice. You are able to advance the task, even in the face of small to moderate hurdles and complications. As you advance in this category, you should be developing the ability to accomplish tasks of significant complexity or larger impact with steady supervision. You will also need to be able to accomplish tasks of moderate complexity or impact with little or no supervision. This level is usually associated with tasks that form the bulk of the work for mid-level positions, such as analysts or developers.",
37
    description: "Description of intermediate skill level.",
38
  },
39
  hardAdvanced: {
40
    id: "skillLevel.hard.advanced.description",
41
    defaultMessage:
42
      "You have the ability to accomplish tasks of significant complexity or impact with supervision. You provide advice and input on the approach to the tasks, and how they are delivered, for the supervisor’s consideration. You are able to advance the task, even in the face of moderate to large hurdles and complications. As you advance in this category, you should be developing the ability to accomplish tasks of significant complexity or larger impact with only light levels of supervision, where you are effectively the lead on the initiative. You may also take on a role of training others in this skills set or take on a light supervisory role for those at lower levels. This level is usually associated with tasks that form the bulk of the work for higher level positions, such as senior analysts or senior developers.",
43
    description: "Description of advanced hard skill level.",
44
  },
45
  hardExpert: {
46
    id: "skillLevel.hard.expert.description",
47
    defaultMessage:
48
      "You have the ability to accomplish tasks of significant complexity or impact, where you call the shots and answer to the organization’s senior management for your decisions. You bring forward the tasks, the approach and the delivery plan for senior management consideration. You often supervise others (individuals or teams) in delivering tasks of high complexity or system wide impact. You are able to advance these tasks, even in the face of significant unforeseen hurdles and complications. As you advance in this category, you should be developing the ability to assess others at more junior levels, becoming able to clearly identify the difference between beginner, intermediate and advanced tasks. You should be able to build teams, set direction and provide supervision. This level is usually associated with tasks that form the bulk of the work for management and executive level positions.",
49
    description: "Description of expert hard skill level.",
50
  },
51
  softBasic: {
52
    id: "skillLevel.soft.basic.description",
53
    defaultMessage:
54
      "You’re working on acquiring this skill or attribute. You are able to demonstrate it under favourable conditions (low stress, minimal difficulty) and can apply it in a work context intermittently.",
55
    description: "Description of soft basic skill level.",
56
  },
57
  softIntermediate: {
58
    id: "skillLevel.soft.intermediate.description",
59
    defaultMessage:
60
      "You’re able to consistently demonstrate this skill or attribute in the workplace, including under conditions of low-to-moderate stress or difficulty. Your peers and supervisors are able to attest to the fact that you have been able to demonstrate this skill or attribute on a regular basis.",
61
    description: "Description of soft intermediate skill level.",
62
  },
63
  softAdvanced: {
64
    id: "skillLevel.soft.advanced.description",
65
    defaultMessage:
66
      "You’re able to consistently demonstrate this skill or attribute in the workplace, including under conditions of high stress or difficulty. Your peers and supervisors recognize this as a strength you demonstrate in the workplace.",
67
    description: "Description of soft advanced skill level.",
68
  },
69
  softExpert: {
70
    id: "skillLevel.soft.expert.description",
71
    defaultMessage:
72
      "This is a foundational part of who you are. You consistently demonstrate this skill or attribute, even under conditions of extreme stress or difficulty. Your peers and supervisors recognize this as a significant strength you demonstrate in the workplace, providing an example to others.",
73
    description: "Description of expert soft skill level.",
74
  },
75
  asset: {
76
    id: "skillLevel.asset.description",
77
    defaultMessage:
78
      "This skill isn't required for the employee to do the job, but it provides an added benefit to their skillset and will improve the speed or effectiveness of their work.",
79
    description: "Description of what it means to be an 'Asset' skill.",
80
  },
81
});
82
83
const skillLevelNames = defineMessages({
84
  hardBasic: {
85
    id: "skillLevel.hard.basic.name",
86
    defaultMessage: "Beginner",
87
    description: "Single-word descriptor of basic hard skill level.",
88
  },
89
  hardIntermediate: {
90
    id: "skillLevel.hard.intermediate.name",
91
    defaultMessage: "Intermediate",
92
    description: "Single-word descriptor of intermediate hard skill level.",
93
  },
94
  hardAdvanced: {
95
    id: "skillLevel.hard.advanced.name",
96
    defaultMessage: "Advanced",
97
    description: "Single-word descriptor of advanced hard skill level.",
98
  },
99
  hardExpert: {
100
    id: "skillLevel.hard.expert.name",
101
    defaultMessage: "Expert",
102
    description: "Single-word descriptor of expert hard skill level.",
103
  },
104
  softBasic: {
105
    id: "skillLevel.soft.basic.name",
106
    defaultMessage: "In Early Development",
107
    description: "Single-word descriptor of soft basic skill level.",
108
  },
109
  softIntermediate: {
110
    id: "skillLevel.soft.intermediate.name",
111
    defaultMessage: "Moderately in Evidence",
112
    description: "Single-word descriptor of soft intermediate skill level.",
113
  },
114
  softAdvanced: {
115
    id: "skillLevel.soft.advanced.name",
116
    defaultMessage: "Strongly in Evidence",
117
    description: "Single-word descriptor of soft advanced skill level.",
118
  },
119
  softExpert: {
120
    id: "skillLevel.soft.expert.name",
121
    defaultMessage: "Deep Level Demonstration",
122
    description: "Single-word descriptor of soft expert skill level.",
123
  },
124
  asset: {
125
    id: "skillLevel.asset.name",
126
    defaultMessage: "Asset / No Level Required",
127
    description: "Name for 'Asset' skills.",
128
  },
129
});
130
131
const skillLevelL10n = (
132
  skillLevelId: number,
133
  skillTypeId: number,
134
  l10nObj: Record<
135
    string,
136
    {
137
      id: string;
138
      defaultMessage: string;
139
      description: string;
140
    }
141
  >,
142
): MessageDescriptor => {
143
  if (!SkillLevelIdValues.includes(skillLevelId)) {
144
    throw new Error("invalid SkillLevelIdValue");
145
  }
146
  if (!SkillTypeIdValues.includes(skillTypeId)) {
147
    throw new Error("invalid SkillTypeIdValue");
148
  }
149
  const basicKey = SkillLevelId.Basic.toString();
150
  const intermediateKey = SkillLevelId.Intermediate.toString();
151
  const advancedKey = SkillLevelId.Advanced.toString();
152
  const expertKey = SkillLevelId.Expert.toString();
153
  return {
154
    [SkillTypeId.Hard.toString()]: {
155
      [basicKey]: l10nObj.hardBasic,
156
      [intermediateKey]: l10nObj.hardIntermediate,
157
      [advancedKey]: l10nObj.hardAdvanced,
158
      [expertKey]: l10nObj.hardExpert,
159
    },
160
    [SkillTypeId.Soft.toString()]: {
161
      [basicKey]: l10nObj.softBasic,
162
      [intermediateKey]: l10nObj.softIntermediate,
163
      [advancedKey]: l10nObj.softAdvanced,
164
      [expertKey]: l10nObj.softExpert,
165
    },
166
  }[skillTypeId.toString()][skillLevelId.toString()];
167
};
168
169
export const skillLevelDescription = (
170
  skillLevelId: number,
171
  skillTypeId: number,
172
): MessageDescriptor =>
173
  skillLevelL10n(skillLevelId, skillTypeId, skillLevelDescriptions);
174
175
export const skillLevelName = (
176
  skillLevelId: number,
177
  skillTypeId: number,
178
): MessageDescriptor =>
179
  skillLevelL10n(skillLevelId, skillTypeId, skillLevelNames);
180
181
const assessmentTypes = defineMessages({
182
  narrativeAssessment: {
183
    id: "assessmentType.narrativeAssessment",
184
    defaultMessage: "Narrative Review",
185
    description: "Title of an assessment type.",
186
  },
187
  applicationScreeningQuestion: {
188
    id: "assessmentType.applicationScreeningQuestion",
189
    defaultMessage: "Application Screening Question",
190
    description: "Title of an assessment type.",
191
  },
192
  groupTest: {
193
    id: "assessmentType.groupTest",
194
    defaultMessage: "Group Test",
195
    description: "Title of an assessment type.",
196
  },
197
  informalPhoneConversation: {
198
    id: "assessmentType.informalPhoneConversation",
199
    defaultMessage: "Informal Phone Conversation",
200
    description: "Title of an assessment type.",
201
  },
202
  interview: {
203
    id: "assessmentType.interview",
204
    defaultMessage: "Interview",
205
    description: "Title of an assessment type.",
206
  },
207
  onlineExam: {
208
    id: "assessmentType.onlineExam",
209
    defaultMessage: "Online Exam",
210
    description: "Title of an assessment type.",
211
  },
212
  onSiteExam: {
213
    id: "assessmentType.onSiteExam",
214
    defaultMessage: "On-Site Exam",
215
    description: "Title of an assessment type.",
216
  },
217
  takeHomeExam: {
218
    id: "assessmentType.takeHomeExam",
219
    defaultMessage: "Take Home Exam",
220
    description: "Title of an assessment type.",
221
  },
222
  portfolioReview: {
223
    id: "assessmentType.portfolioReview",
224
    defaultMessage: "Portfolio Review",
225
    description: "Title of an assessment type.",
226
  },
227
  referenceCheck: {
228
    id: "assessmentType.referenceCheck",
229
    defaultMessage: "Reference Check",
230
    description: "Title of an assessment type.",
231
  },
232
  seriousGames: {
233
    id: "assessmentType.seriousGames",
234
    defaultMessage: "Serious Games",
235
    description: "Title of an assessment type.",
236
  },
237
});
238
239
export const assetSkillName = (): MessageDescriptor => skillLevelNames.asset;
240
export const assetSkillDescription = (): MessageDescriptor =>
241
  skillLevelDescriptions.asset;
242
243
export const assessmentType = (assessmentTypeId: number): MessageDescriptor => {
244
  if (!AssessmentTypeIdValues.includes(assessmentTypeId)) {
245
    throw new Error("invalid AssessmentTypeValue");
246
  }
247
  return {
248
    [AssessmentTypeId.ApplicationScreeningQuestion]:
249
      assessmentTypes.applicationScreeningQuestion,
250
    [AssessmentTypeId.GroupTest]: assessmentTypes.groupTest,
251
    [AssessmentTypeId.InformalPhoneConversation]:
252
      assessmentTypes.informalPhoneConversation,
253
    [AssessmentTypeId.Interview]: assessmentTypes.interview,
254
    [AssessmentTypeId.NarrativeAssessment]: assessmentTypes.narrativeAssessment,
255
    [AssessmentTypeId.OnSiteExam]: assessmentTypes.onSiteExam,
256
    [AssessmentTypeId.OnlineExam]: assessmentTypes.onlineExam,
257
    [AssessmentTypeId.PortfolioReview]: assessmentTypes.portfolioReview,
258
    [AssessmentTypeId.ReferenceCheck]: assessmentTypes.referenceCheck,
259
    [AssessmentTypeId.SeriousGames]: assessmentTypes.seriousGames,
260
    [AssessmentTypeId.TakeHomeExam]: assessmentTypes.takeHomeExam,
261
  }[assessmentTypeId.toString()];
262
};
263
264
const criteriaTypes = defineMessages({
265
  asset: {
266
    id: "criteriaType.asset",
267
    defaultMessage: "Asset",
268
    description: "Title of an asset criteria type.",
269
  },
270
  essential: {
271
    id: "criteriaType.essential",
272
    defaultMessage: "Essential",
273
    description: "Title of an essential criteria type.",
274
  },
275
});
276
277
export const criteriaType = (criteriaTypeId: number): MessageDescriptor => {
278
  if (!CriteriaTypeIdValues.includes(criteriaTypeId)) {
279
    throw new Error("invalid CriteriaTypeValue");
280
  }
281
  return {
282
    [CriteriaTypeId.Asset]: criteriaTypes.asset,
283
    [CriteriaTypeId.Essential]: criteriaTypes.essential,
284
  }[criteriaTypeId.toString()];
285
};
286
287
const assessmentTypeDescriptions = defineMessages({
288
  narrativeAssessment: {
289
    id: "assessmentType.narrativeAssessment.description",
290
    defaultMessage:
291
      "This is a description requested during the application process, in which applicants to self-identify and describe their experience and level of expertise with a skill.",
292
    description:
293
      "Description of an assessment type, to help a manager understand when to use it.",
294
  },
295
  applicationScreeningQuestion: {
296
    id: "assessmentType.applicationScreeningQuestion.description",
297
    defaultMessage:
298
      "These questions appear in the application form, and are submitted through Talent Cloud, they allow a first glance at the applicant’s understanding, process, knowledge, or cultural fit for the position.",
299
    description:
300
      "Description of an assessment type, to help a manager understand when to use it.",
301
  },
302
  groupTest: {
303
    id: "assessmentType.groupTest.description",
304
    defaultMessage:
305
      "Applicants perform this test in real-time in conjunction with other applicants, team members, or facilitators, to determine their skill prowess, team communication, and performance in a collaborative environment.",
306
    description:
307
      "Description of an assessment type, to help a manager understand when to use it.",
308
  },
309
  informalPhoneConversation: {
310
    id: "assessmentType.informalPhoneConversation.description",
311
    defaultMessage:
312
      "A loose structure chat between a member of the hiring board and an applicant, aimed at discovering the applicant’s knowledge, aptitudes, or personality traits, conversations may vary between applicants.",
313
    description:
314
      "Description of an assessment type, to help a manager understand when to use it.",
315
  },
316
  interview: {
317
    id: "assessmentType.interview.description",
318
    defaultMessage:
319
      "A formal question-and-answer examination performed in real-time between the hiring-board and an applicant. Questions are aimed at assessing skill expertise, level, and approach. Each question is crafted beforehand and follows the same structure between all interviewed applicants.",
320
    description:
321
      "Description of an assessment type, to help a manager understand when to use it.",
322
  },
323
  onlineExam: {
324
    id: "assessmentType.onlineExam.description",
325
    defaultMessage:
326
      "Prepared examination that does not require supervision, and can be performed from any location through internet access, with a defined time-frame for completion.",
327
    description:
328
      "Description of an assessment type, to help a manager understand when to use it.",
329
  },
330
  onSiteExam: {
331
    id: "assessmentType.onSiteExam.description",
332
    defaultMessage:
333
      "Prepared examination that requires the applicant to perform a test at a specific location under supervision, aimed at assessing skill expertise and technique.",
334
    description:
335
      "Description of an assessment type, to help a manager understand when to use it.",
336
  },
337
  takeHomeExam: {
338
    id: "assessmentType.takeHomeExam.description",
339
    defaultMessage:
340
      "Applicants receive a physical package containing the assessment tools, they complete the assessment at their own leisure and at their preferred location without supervision, and must return the materials before a specific deadline.",
341
    description:
342
      "Description of an assessment type, to help a manager understand when to use it.",
343
  },
344
  portfolioReview: {
345
    id: "assessmentType.portfolioReview.description",
346
    defaultMessage:
347
      "During the application process, applicants provide access to samples of their work to exhibit their skill level, and back-up their skill claims. ",
348
    description:
349
      "Description of an assessment type, to help a manager understand when to use it.",
350
  },
351
  referenceCheck: {
352
    id: "assessmentType.referenceCheck.description",
353
    defaultMessage:
354
      "During the application process, applicants provide contact information to an acquaintance who can validate and confirm their skill expertise, knowledge or aptitude.",
355
    description:
356
      "Description of an assessment type, to help a manager understand when to use it.",
357
  },
358
  seriousGames: {
359
    id: "assessmentType.seriousGames.description",
360
    defaultMessage:
361
      "Test involving the use of games to explore a candidate’s communication skills, resilience, emotional intelligence, among many other soft skills.",
362
    description:
363
      "Description of an assessment type, to help a manager understand when to use it.",
364
  },
365
});
366
367
export const assessmentTypeDescription = (
368
  assessmentTypeId: number,
369
): MessageDescriptor => {
370
  if (!AssessmentTypeIdValues.includes(assessmentTypeId)) {
371
    throw new Error("invalid AssessmentTypeValue");
372
  }
373
  return {
374
    [AssessmentTypeId.ApplicationScreeningQuestion]:
375
      assessmentTypeDescriptions.applicationScreeningQuestion,
376
    [AssessmentTypeId.GroupTest]: assessmentTypeDescriptions.groupTest,
377
    [AssessmentTypeId.InformalPhoneConversation]:
378
      assessmentTypeDescriptions.informalPhoneConversation,
379
    [AssessmentTypeId.Interview]: assessmentTypeDescriptions.interview,
380
    [AssessmentTypeId.NarrativeAssessment]:
381
      assessmentTypeDescriptions.narrativeAssessment,
382
    [AssessmentTypeId.OnSiteExam]: assessmentTypeDescriptions.onSiteExam,
383
    [AssessmentTypeId.OnlineExam]: assessmentTypeDescriptions.onlineExam,
384
    [AssessmentTypeId.PortfolioReview]:
385
      assessmentTypeDescriptions.portfolioReview,
386
    [AssessmentTypeId.ReferenceCheck]:
387
      assessmentTypeDescriptions.referenceCheck,
388
    [AssessmentTypeId.SeriousGames]: assessmentTypeDescriptions.seriousGames,
389
    [AssessmentTypeId.TakeHomeExam]: assessmentTypeDescriptions.takeHomeExam,
390
  }[assessmentTypeId];
391
};
392
393
const standardAssessmentText = defineMessages({
394
  narrativeReviewQuestion: {
395
    id: "assessmentType.narrativeReview.standardQuestion",
396
    defaultMessage:
397
      "Narrative Review of skill includes all descriptions added by the applicant in their application.",
398
    description:
399
      "Description which replaces 'interview question' for the Narrative Review assessment type.",
400
  },
401
  narrativeReviewAnswer: {
402
    id: "assessmentType.narrativeReview.standardAnswer",
403
    defaultMessage:
404
      "The provided description contains sufficient evidence to advance this candidate to the next screening steps.",
405
    description:
406
      "Standard evalutation statement which replaces 'expected answer' for all skills under the Narrative Review assessment type.",
407
  },
408
});
409
410
const provinceNames = defineMessages({
411
  [ProvinceId.AB]: {
412
    id: "province.ab",
413
    defaultMessage: "Alberta",
414
  },
415
  [ProvinceId.BC]: {
416
    id: "province.bc",
417
    defaultMessage: "British Columbia",
418
  },
419
  [ProvinceId.MB]: {
420
    id: "province.mb",
421
    defaultMessage: "Manitoba",
422
  },
423
  [ProvinceId.NL]: {
424
    id: "province.nl",
425
    defaultMessage: "Newfoundland and Labrador",
426
  },
427
  [ProvinceId.NB]: {
428
    id: "province.nb",
429
    defaultMessage: "New Brunswick",
430
  },
431
  [ProvinceId.NS]: {
432
    id: "province.ns",
433
    defaultMessage: "Nova Scotia",
434
  },
435
  [ProvinceId.NU]: {
436
    id: "province.nu",
437
    defaultMessage: "Nunavut",
438
  },
439
  [ProvinceId.NT]: {
440
    id: "province.nt",
441
    defaultMessage: "Northwest Territories",
442
  },
443
  [ProvinceId.ON]: {
444
    id: "province.on",
445
    defaultMessage: "Ontario",
446
  },
447
  [ProvinceId.PE]: {
448
    id: "province.pe",
449
    defaultMessage: "Prince Edward Island",
450
  },
451
  [ProvinceId.QC]: {
452
    id: "province.qc",
453
    defaultMessage: "Quebec",
454
  },
455
  [ProvinceId.SK]: {
456
    id: "province.sk",
457
    defaultMessage: "Saskatchewan",
458
  },
459
  [ProvinceId.YT]: {
460
    id: "province.yk",
461
    defaultMessage: "Yukon",
462
  },
463
});
464
465
export const provinceName = (provinceId: number): MessageDescriptor =>
466
  getOrThrowError(provinceNames, provinceId, "invalid ProvinceId");
467
468
const provinceAbreviations = defineMessages({
469
  [ProvinceId.AB]: {
470
    id: "province.ab.abreviation",
471
    defaultMessage: "Alb.",
472
  },
473
  [ProvinceId.BC]: {
474
    id: "province.bc.abreviation",
475
    defaultMessage: "B.C.",
476
  },
477
  [ProvinceId.MB]: {
478
    id: "province.mb.abreviation",
479
    defaultMessage: "Man.",
480
  },
481
  [ProvinceId.NL]: {
482
    id: "province.nl.abreviation",
483
    defaultMessage: "N.L.",
484
  },
485
  [ProvinceId.NB]: {
486
    id: "province.nb.abreviation",
487
    defaultMessage: "N.B.",
488
  },
489
  [ProvinceId.NS]: {
490
    id: "province.ns.abreviation",
491
    defaultMessage: "N.S.",
492
  },
493
  [ProvinceId.NU]: {
494
    id: "province.nu.abreviation",
495
    defaultMessage: "Nvt.",
496
  },
497
  [ProvinceId.NT]: {
498
    id: "province.nt.abreviation",
499
    defaultMessage: "N.W.T.",
500
  },
501
  [ProvinceId.ON]: {
502
    id: "province.on.abreviation",
503
    defaultMessage: "Ont.",
504
  },
505
  [ProvinceId.PE]: {
506
    id: "province.pe.abreviation",
507
    defaultMessage: "P.E.I.",
508
  },
509
  [ProvinceId.QC]: {
510
    id: "province.qc.abreviation",
511
    defaultMessage: "Que.",
512
  },
513
  [ProvinceId.SK]: {
514
    id: "province.sk.abreviation",
515
    defaultMessage: "Sask.",
516
  },
517
  [ProvinceId.YT]: {
518
    id: "province.yk.abreviation",
519
    defaultMessage: "Y.T.",
520
  },
521
});
522
523
export const provinceAbreviation = (provinceId: number): MessageDescriptor =>
524
  getOrThrowError(provinceAbreviations, provinceId, "invalid ProvinceId");
525
526
const securityClearances = defineMessages({
527
  [SecurityClearanceId.reliability]: {
528
    id: "securityClearance.reliability",
529
    defaultMessage: "Reliability",
530
  },
531
  [SecurityClearanceId.secret]: {
532
    id: "securityClearance.secret",
533
    defaultMessage: "Secret",
534
  },
535
  [SecurityClearanceId.topSecret]: {
536
    id: "securityClearance.topSecret",
537
    defaultMessage: "Top Secret",
538
  },
539
});
540
541
export const securityClearance = (
542
  securityClearanceId: number,
543
): MessageDescriptor =>
544
  getOrThrowError(
545
    securityClearances,
546
    securityClearanceId,
547
    "invalid security clearance id",
548
  );
549
550
const languageRequirements = defineMessages({
551
  [LanguageRequirementId.english]: {
552
    id: "languageRequirement.english",
553
    defaultMessage: "English Essential",
554
  },
555
  [LanguageRequirementId.french]: {
556
    id: "languageRequirement.french",
557
    defaultMessage: "French Essential",
558
  },
559
  [LanguageRequirementId.bilingualIntermediate]: {
560
    id: "languageRequirement.bilingualIntermediate",
561
    defaultMessage: "Bilingual - Intermediate",
562
  },
563
  [LanguageRequirementId.bilingualAdvanced]: {
564
    id: "languageRequirement.bilingualAdvanced",
565
    defaultMessage: "Bilingual - Advanced",
566
  },
567
  [LanguageRequirementId.englishOrFrench]: {
568
    id: "languageRequirement.englishOrFrench",
569
    defaultMessage: "English or French",
570
  },
571
});
572
573
export const languageRequirement = (
574
  languageRequirementId: number,
575
): MessageDescriptor =>
576
  getOrThrowError(
577
    languageRequirements,
578
    languageRequirementId,
579
    "invalid LanguageRequirementId",
580
  );
581
582
const languageRequirementDescriptions = defineMessages({
583
  [LanguageRequirementId.english]: {
584
    id: "languageRequirement.description.english",
585
    defaultMessage:
586
      "This position requires fluency in English in both written and verbal communication. As part of the assessment of your language abilities, the hiring manager may ask you to complete some assessment steps in English, such as interview questions or an exam.",
587
  },
588
  [LanguageRequirementId.french]: {
589
    id: "languageRequirement.description.french",
590
    defaultMessage:
591
      "This position requires fluency in French in both written and verbal communication. As part of the assessment of your language abilities, the hiring manager may ask you to complete some assessment steps in French, such as interview questions or an exam.",
592
  },
593
  [LanguageRequirementId.bilingualIntermediate]: {
594
    id: "languageRequirement.description.bilingualIntermediate",
595
    // TODO: turn "Public Service Commission of Canada" into a link to https://www.canada.ca/en/public-service-commission/jobs/services/gc-jobs/information-candidates/language-requirements-candidates.html
596
    defaultMessage:
597
      "This position requires working knowledge of both French and English. This means that you can take on job duties in either French or English, and you have intermediate reading, writing and verbal communication skills in both official languages. As part of this selection process, your language abilities will be tested by the Public Service Commission of Canada.",
598
  },
599
  [LanguageRequirementId.bilingualAdvanced]: {
600
    id: "languageRequirement.description.bilingualAdvanced",
601
    // TODO: turn "Public Service Commission of Canada" into a link to https://www.canada.ca/en/public-service-commission/jobs/services/gc-jobs/information-candidates/language-requirements-candidates.html
602
    defaultMessage:
603
      "This position requires advanced knowledge of both French and English. This means that you can take on job duties in either French or English, and you have strong reading, writing and verbal communication skills in both official languages. As part of this selection process, your language abilities will be tested by the Public Service Commission of Canada Public Service Commission of Canada.",
604
  },
605
  [LanguageRequirementId.englishOrFrench]: {
606
    id: "languageRequirement.description.englishOrFrench",
607
    defaultMessage:
608
      "For this position, you meet the language requirements if you have strong reading, writing and verbal communication skills in either English or French, or both (bilingual).",
609
  },
610
});
611
612
export const languageRequirementDescription = (
613
  languageRequirementId: number,
614
): MessageDescriptor =>
615
  getOrThrowError(
616
    languageRequirementDescriptions,
617
    languageRequirementId,
618
    "invalid LanguageRequirementId",
619
  );
620
621
const languageRequirementContexts = defineMessages({
622
  basic: {
623
    id: "languageRequirement.context.basic",
624
    defaultMessage:
625
      "You can submit this initial application in either official language of your choice (English or French).",
626
  },
627
  expanded: {
628
    id: "languageRequirement.context.expanded",
629
    defaultMessage:
630
      "You can complete all other steps of this assessment process in the official language of your choice, including the initial application, interview, exam and any other evaluation components.",
631
  },
632
});
633
634
export const languageRequirementContext = (
635
  languageRequirementId: number,
636
): MessageDescriptor => {
637
  switch (languageRequirementId) {
638
    case LanguageRequirementId.bilingualIntermediate:
639
    case LanguageRequirementId.bilingualAdvanced:
640
      return languageRequirementContexts.expanded;
641
642
    case LanguageRequirementId.englishOrFrench:
643
    case LanguageRequirementId.english:
644
    case LanguageRequirementId.french:
645
    default:
646
      return languageRequirementContexts.basic;
647
  }
648
};
649
650
export const narrativeReviewStandardQuestion = (): MessageDescriptor =>
651
  standardAssessmentText.narrativeReviewQuestion;
652
653
export const narrativeReviewStandardAnswer = (): MessageDescriptor =>
654
  standardAssessmentText.narrativeReviewAnswer;
655
656
const frequencyMessages = defineMessages({
657
  [FrequencyId.always]: {
658
    id: "jobBuilder.details.frequencyAlwaysLabel",
659
    defaultMessage: "Almost Always",
660
    description: "The form label displayed on 'always' frequency options.",
661
  },
662
  [FrequencyId.often]: {
663
    id: "jobBuilder.details.frequencyFrequentlyLabel",
664
    defaultMessage: "Frequently",
665
    description: "The form label displayed on 'frequently' frequency options.",
666
  },
667
  [FrequencyId.sometimes]: {
668
    id: "jobBuilder.details.frequencySometimesLabel",
669
    defaultMessage: "Sometimes",
670
    description: "The form label displayed on 'sometimes' frequency options.",
671
  },
672
  [FrequencyId.rarely]: {
673
    id: "jobBuilder.details.frequencyOccasionallyLabel",
674
    defaultMessage: "Occasionally",
675
    description:
676
      "The form label displayed on 'occasionally' frequency options.",
677
  },
678
  [FrequencyId.never]: {
679
    id: "jobBuilder.details.frequencyNeverLabel",
680
    defaultMessage: "Never",
681
    description: "The form label displayed on 'never' frequency options.",
682
  },
683
});
684
685
export const frequencyName = (frequencyId: number): MessageDescriptor =>
686
  getOrThrowError(frequencyMessages, frequencyId, "invalid FrequencyId");
687
688
const overtimeRequirmentDescriptions = defineMessages({
689
  [OvertimeRequirementId.frequently]: {
690
    id: "jobBuilder.details.overtimeFrequentlyLabel",
691
    defaultMessage: "Yes, overtime is frequently required for the position.",
692
    description: "The form label displayed on 'frequently' overtime options",
693
  },
694
  [OvertimeRequirementId.available]: {
695
    id: "jobBuilder.details.overtimeOpportunitiesAvailableLabel",
696
    defaultMessage:
697
      "Yes, overtime opportunities are available for those that are interested.",
698
    description:
699
      "The form label displayed on 'overtime opportunities available' overtime options",
700
  },
701
  [OvertimeRequirementId.none]: {
702
    id: "jobBuilder.details.overtimeNoneRequiredLabel",
703
    defaultMessage: "No, overtime is not required for the position.",
704
    description:
705
      "The form label displayed on 'no overtime required' overtime options",
706
  },
707
});
708
709
export const overtimeRequirementDescription = (
710
  overtimeRequirementId: number,
711
): MessageDescriptor =>
712
  getOrThrowError(
713
    overtimeRequirmentDescriptions,
714
    overtimeRequirementId,
715
    "invalid OvertimeRequirementId",
716
  );
717
718
const travelRequirementDescriptions = defineMessages({
719
  [TravelRequirementId.frequently]: {
720
    id: "jobBuilder.details.travelFrequentlyLabel",
721
    defaultMessage: "Yes, travel is frequently required for the position.",
722
    description: "The form label displayed on 'frequently' travel options",
723
  },
724
  [TravelRequirementId.available]: {
725
    id: "jobBuilder.details.travelOpportunitiesAvailableLabel",
726
    defaultMessage:
727
      "Yes, travel opportunities are available for those that are interested.",
728
    description:
729
      "The form label displayed on 'travel opportunities available' travel options",
730
  },
731
  [TravelRequirementId.none]: {
732
    id: "jobBuilder.details.travelNoneRequiredLabel",
733
    defaultMessage: "No, travel is not required for the position.",
734
    description:
735
      "The form label displayed on 'no travel required' travel options",
736
  },
737
});
738
739
export const travelRequirementDescription = (
740
  travelRequirementId: number,
741
): MessageDescriptor =>
742
  getOrThrowError(
743
    travelRequirementDescriptions,
744
    travelRequirementId,
745
    "invalid TravelRequirementId",
746
  );
747
748
export const generalLocations = defineMessages({
749
  [LocationId.jobGeneric]: {
750
    id: "activityfeed.locations.review",
751
    defaultMessage: "Job Poster Builder",
752
    description: "Location where the activity is located.",
753
  },
754
  [LocationId.summary]: {
755
    id: "activityfeed.locations.hr.summary",
756
    defaultMessage: "HR Summary Page",
757
    description: "Location where the activity is located.",
758
  },
759
  [LocationId.preview]: {
760
    id: "activityfeed.locations.hr.preview",
761
    defaultMessage: "HR Preview Page",
762
    description: "Location where the activity is located.",
763
  },
764
  [LocationId.applicantsGeneric]: {
765
    id: "activityfeed.locations.applications",
766
    defaultMessage: "Applicant Review Page",
767
    description: "Location where the activity is located.",
768
  },
769
  [LocationId.screeningPlan]: {
770
    id: "activityfeed.locations.screeningPlan",
771
    defaultMessage: "Assessment Plan",
772
    description: "Location where the activity is located.",
773
  },
774
  notFound: {
775
    id: "activityfeed.locations.notFound",
776
    defaultMessage: "Location not found",
777
    description: "Error message if location id is not recognized",
778
  },
779
});
780
781
export const generalLocationOption = (
782
  locationId: string,
783
): MessageDescriptor => {
784
  switch (locationId) {
785
    /* Job Poster Review Page */
786
    case LocationId.jobGeneric:
787
    case LocationId.heading:
788
    case LocationId.basicInfo:
789
    case LocationId.impact:
790
    case LocationId.tasks:
791
    case LocationId.skills:
792
    case LocationId.langRequirements:
793
    case LocationId.environment:
794
      return generalLocations[LocationId.jobGeneric];
795
    /* Applicant Review Page */
796
    case LocationId.applicantsGeneric:
797
    case LocationId.underConsideration:
798
    case LocationId.optionalConsideration:
799
    case LocationId.notUnderConsideration:
800
      return generalLocations[LocationId.applicantsGeneric];
801
    /* Assessment Plan */
802
    case LocationId.screeningPlan:
803
    case LocationId.screeningPlanBuilder:
804
    case LocationId.screeningPlanSummary:
805
    case LocationId.screeningPlanRatings:
806
      return generalLocations[LocationId.screeningPlan];
807
    /* Hr Portal */
808
    case LocationId.summary:
809
      return generalLocations[LocationId.summary];
810
    case LocationId.preview:
811
      return generalLocations[LocationId.preview];
812
813
    default:
814
      return generalLocations.notFound;
815
  }
816
};
817
818
export const jobReviewLocations = defineMessages({
819
  [LocationId.jobGeneric]: {
820
    id: "activityfeed.locations.review.general",
821
    defaultMessage: "General",
822
    description: "Location of the activity.",
823
  },
824
  [LocationId.heading]: {
825
    id: "activityfeed.locations.review.heading",
826
    defaultMessage: "Job Page Heading",
827
    description: "Location of the activity.",
828
  },
829
  [LocationId.basicInfo]: {
830
    id: "activityfeed.locations.review.basicInfo",
831
    defaultMessage: "Basic Information",
832
    description: "Location of the activity.",
833
  },
834
  [LocationId.impact]: {
835
    id: "activityfeed.locations.review.impact",
836
    defaultMessage: "Impact",
837
    description: "Location of the activity.",
838
  },
839
  [LocationId.tasks]: {
840
    id: "activityfeed.locations.review.tasks",
841
    defaultMessage: "Tasks",
842
    description: "Location of the activity.",
843
  },
844
  [LocationId.skills]: {
845
    id: "activityfeed.locations.review.skills",
846
    defaultMessage: "Skills",
847
    description: "Location of the activity.",
848
  },
849
  [LocationId.langRequirements]: {
850
    id: "activityfeed.locations.review.langRequirements",
851
    defaultMessage: "Language Requirements",
852
    description: "Location of the activity.",
853
  },
854
  [LocationId.environment]: {
855
    id: "activityfeed.locations.review.environment",
856
    defaultMessage: "Environment",
857
    description: "Location of the activity.",
858
  },
859
});
860
861
export const applicantReviewLocations = defineMessages({
862
  [LocationId.applicantsGeneric]: {
863
    id: "activityfeed.locations.applicantReview.general",
864
    defaultMessage: "General",
865
    description: "Location of the activity.",
866
  },
867
  [LocationId.underConsideration]: {
868
    id: "activityfeed.locations.applicantReview.underConsideration",
869
    defaultMessage: "Under Consideration",
870
    description: "Location of the activity.",
871
  },
872
  [LocationId.optionalConsideration]: {
873
    id: "activityfeed.locations.applicantReview.optionalConsideration",
874
    defaultMessage: "Optional Consideration",
875
    description: "Location of the activity.",
876
  },
877
  [LocationId.notUnderConsideration]: {
878
    id: "activityfeed.locations.applicantReview.notUnderConsideration",
879
    defaultMessage: "No Longer Under Consideration",
880
    description: "Location of the activity.",
881
  },
882
});
883
884
export const screeningPlanLocations = defineMessages({
885
  [LocationId.screeningPlan]: {
886
    id: "activityfeed.locations.screeningPlan.general",
887
    defaultMessage: "General",
888
    description: "Location of the activity.",
889
  },
890
  [LocationId.screeningPlanBuilder]: {
891
    id: "activityfeed.locations.screeningPlan.builder",
892
    defaultMessage: "Assessment Plan Builder",
893
    description: "Location of the activity.",
894
  },
895
  [LocationId.screeningPlanSummary]: {
896
    id: "activityfeed.locations.screeningPlan.summary",
897
    defaultMessage: "Assessment Plan Summary",
898
    description: "Location of the activity.",
899
  },
900
  [LocationId.screeningPlanRatings]: {
901
    id: "activityfeed.locations.screeningPlan.ratings",
902
    defaultMessage: "Ratings Guide Builder",
903
    description: "Location of the activity.",
904
  },
905
});
906
export const hrPortalLocations = {
907
  [LocationId.summary]: jobReviewLocations[LocationId.jobGeneric],
908
  [LocationId.preview]: jobReviewLocations[LocationId.jobGeneric],
909
};
910
911
export const specificLocationOption = (locationId: string): MessageDescriptor =>
912
  getOrThrowError(
913
    {
914
      ...jobReviewLocations,
915
      ...applicantReviewLocations,
916
      ...hrPortalLocations,
917
      ...screeningPlanLocations,
918
    },
919
    locationId,
920
    "Invalid LocationId",
921
  );
922
923
export const ResponseScreeningBuckets = {
924
  [ResponseBuckets.Consideration]: defineMessages({
925
    title: {
926
      id: "responseScreening.buckets.consideration.title",
927
      defaultMessage: "Employees Under Consideration",
928
      description:
929
        "Label for the 'Under Consideration' response screening bucket.",
930
    },
931
    description: {
932
      id: "responseScreening.buckets.consideration.description",
933
      defaultMessage:
934
        "Employees in this category have volunteered to be placed in a team with a critical needs shortage. Employees in this category are: Pending initial application review ({iconReceived}), indicating that a submission has been received, but it has not yet been assessed by a member of the review team; Ready for reference checks and home-department approval ({iconReady}), indicating that the employee is heading to the Ready to Allocate category if references and approval are in order; and Further Assessment Required ({iconAssessment}), indicating that the review team is unsure of their qualifications for this role and is undertaking further assessment.",
935
      description:
936
        "Descriptive text for the 'Under Consideration' response screening bucket. Takes three icons (iconReceived, iconReady, and iconAssessment) as input.",
937
    },
938
  }),
939
  [ResponseBuckets.ReadyToAllocate]: defineMessages({
940
    title: {
941
      id: "responseScreening.buckets.readyToAllocate.title",
942
      defaultMessage: "Ready to Allocate",
943
      description:
944
        "Label for the 'Ready to Allocate' response screening bucket.",
945
    },
946
    description: {
947
      id: "responseScreening.buckets.readyToAllocate.description",
948
      defaultMessage:
949
        "Employees in this category have the necessary skills for this stream of work, have successfully completed reference checks and have been given preliminary authorization to participate by a member of their management team. They are currently working in their substantive position, awaiting a request from a department with a critical talent gap.",
950
      description:
951
        "Descriptive text for the 'Ready to Allocate' response screening bucket.",
952
    },
953
  }),
954
  [ResponseBuckets.Allocated]: defineMessages({
955
    title: {
956
      id: "responseScreening.buckets.allocated.title",
957
      defaultMessage: "Allocated",
958
      description: "Label for the 'Allocated' response screening bucket.",
959
    },
960
    description: {
961
      id: "responseScreening.buckets.allocated.description",
962
      defaultMessage:
963
        'Employees in this category have been allocated to a department. Their name has been removed from all other GC Reserve processes to which they have applied (and will appear in those processes under "Not Currently Available".) Following the completion of an allocation, employees may elect to be placed back in the Ready to Allocate category, should they be needed again.',
964
      description:
965
        "Descriptive text for the 'Allocated' response screening bucket.",
966
    },
967
  }),
968
  [ResponseBuckets.Unavailable]: defineMessages({
969
    title: {
970
      id: "responseScreening.buckets.unavailable.title",
971
      defaultMessage: "Currently Unavailable",
972
      description: "Label for the 'Unavailable' response screening bucket.",
973
    },
974
    description: {
975
      id: "responseScreening.buckets.unavailable.description",
976
      defaultMessage:
977
        "Employees in this stream have been allocated to a department in need or have temporarily removed their names from consideration for a specific period of time (e.g. illness, family care needs), and wish to be considered for allocation at a later date. Employees in this category have been qualified for this talent stream, and will be placed back into the Ready to Allocate when they become available again. (If an employee permanently withdraws their name, their submission will be removed from the GC Talent Reserve.)",
978
      description:
979
        "Descriptive text for the 'Currently Unavailable' response screening bucket.",
980
    },
981
  }),
982
  [ResponseBuckets.DoesNotQualify]: defineMessages({
983
    title: {
984
      id: "responseScreening.buckets.doesNotQualify.title",
985
      defaultMessage: "Does Not Qualify",
986
      description:
987
        "Label for the 'Does Not Qualify' response screening bucket.",
988
    },
989
    description: {
990
      id: "responseScreening.buckets.doesNotQualify.description",
991
      defaultMessage:
992
        "Employees in this category have volunteered their names, but a review of their application and/or reference checks has led the review team to conclude that the employee would not be an asset to a department needing to fill a critical talent gap in this field of work. This determination is, in no way, reflected in the employee's performance status with their home department, and does not affect their evaluation for other GC Reserve talent streams to which they may have applied.",
993
      description:
994
        "Descriptive text for the 'Does Not Qualify' response screening bucket.",
995
    },
996
  }),
997
};
998
999
export const ReviewStatusMessages = defineMessages({
1000
  screened_out: {
1001
    id: "reviewStatus.screenedOut",
1002
    defaultMessage: "Screened Out",
1003
    description: "Select option text for the 'Screened Out' review status.",
1004
  },
1005
  still_thinking: {
1006
    id: "reviewStatus.stillThinking",
1007
    defaultMessage: "Still Thinking",
1008
    description: "Select option text for the 'Still Thinking' review status.",
1009
  },
1010
  still_in: {
1011
    id: "reviewStatus.stillIn",
1012
    defaultMessage: "Still In",
1013
    description: "Select option text for the 'Still In' review status.",
1014
  },
1015
});
1016
1017
export const ReviewStatuses: {
1018
  [key in ReviewStatusName]: { id: ReviewStatusId; name: MessageDescriptor };
1019
} = {
1020
  screened_out: {
1021
    id: ReviewStatusId.ScreenedOut,
1022
    name: ReviewStatusMessages.screened_out,
1023
  },
1024
  still_thinking: {
1025
    id: ReviewStatusId.StillThinking,
1026
    name: ReviewStatusMessages.still_thinking,
1027
  },
1028
  still_in: {
1029
    id: ReviewStatusId.StillIn,
1030
    name: ReviewStatusMessages.still_in,
1031
  },
1032
};
1033
1034
export const ResponseReviewStatusMessages = defineMessages({
1035
  screened_out: {
1036
    id: "responseReviewStatus.screenedOut",
1037
    defaultMessage: "Does Not Qualify",
1038
    description: "Select option text for the 'Does Not Qualify' review status.",
1039
  },
1040
  ready_for_reference: {
1041
    id: "responseReviewStatus.readyForReference",
1042
    defaultMessage: "Ready for Reference Check",
1043
    description:
1044
      "Select option text for the 'Ready for Reference Check' review status.",
1045
  },
1046
  ready_to_allocate: {
1047
    id: "responseReviewStatus.readyToAllocate",
1048
    defaultMessage: "Ready to Allocate",
1049
    description:
1050
      "Select option text for the 'Ready to Allocate' review status.",
1051
  },
1052
  assessment_required: {
1053
    id: "responseReviewStatus.assessmentRequired",
1054
    defaultMessage: "Further Assessment Required",
1055
    description:
1056
      "Select option text for the 'Further Assessment Required' review status.",
1057
  },
1058
  allocated: {
1059
    id: "responseReviewStatus.allocated",
1060
    defaultMessage: "Allocated",
1061
    description: "Select option text for the 'Allocated' review status.",
1062
  },
1063
  not_available: {
1064
    id: "responseReviewStatus.notAvailable",
1065
    defaultMessage: "Not Available",
1066
    description: "Select option text for the 'Not Available' review status.",
1067
  },
1068
});
1069
1070
export const ResponseReviewStatuses = {
1071
  assessment_required: {
1072
    id: 6,
1073
    name: ResponseReviewStatusMessages.assessment_required,
1074
  },
1075
  ready_for_reference: {
1076
    id: 4,
1077
    name: ResponseReviewStatusMessages.ready_for_reference,
1078
  },
1079
  ready_to_allocate: {
1080
    id: 5,
1081
    name: ResponseReviewStatusMessages.ready_to_allocate,
1082
  },
1083
  allocated: {
1084
    id: 7,
1085
    name: ResponseReviewStatusMessages.allocated,
1086
  },
1087
  not_available: {
1088
    id: 8,
1089
    name: ResponseReviewStatusMessages.not_available,
1090
  },
1091
  screened_out: {
1092
    id: 1,
1093
    name: ResponseReviewStatusMessages.screened_out,
1094
  },
1095
};
1096
1097
const experienceHeadings = defineMessages({
1098
  award: {
1099
    id: "application.skills.awardHeading",
1100
    defaultMessage: "{title} from {issuedBy}",
1101
    description: "Accordion heading for experience on the Skills page.",
1102
  },
1103
  community: {
1104
    id: "application.skills.communityHeading",
1105
    defaultMessage: "{title} with {group}",
1106
    description: "Accordion heading for experience on the Skills page.",
1107
  },
1108
  education: {
1109
    id: "application.skills.educationHeading",
1110
    defaultMessage: "{areaOfStudy} at {institution}",
1111
    description: "Accordion heading for experience on the Skills page.",
1112
  },
1113
  personal: {
1114
    id: "application.skills.personalHeading",
1115
    defaultMessage: "{title}",
1116
    description: "Accordion heading for experience on the Skills page.",
1117
  },
1118
  work: {
1119
    id: "application.skills.workHeading",
1120
    defaultMessage: "{title} at {organization}",
1121
    description: "Accordion heading for experience on the Skills page.",
1122
  },
1123
  unknown: {
1124
    id: "application.skills.unknownHeading",
1125
    defaultMessage: "Error: Unknown experience type.",
1126
    description:
1127
      "Accordion heading error when an unknown experience type is used.",
1128
  },
1129
});
1130
1131
/**
1132
 * Returns a formatted localized heading for the accordion on
1133
 * the Skill UI page of the Job Application. Makes use of experienceHeadings
1134
 * messages defined above.
1135
 *
1136
 * @param experience Given Experience of multiple types defined by the user to apply to a certain Criteria.
1137
 * @param intl react-intl object used in formatting messages.
1138
 *
1139
 * @returns Formatted localized string.
1140
 */
1141
export const getExperienceHeading = (
1142
  experience: Experience,
1143
  intl: IntlShape,
1144
): string => {
1145
  let heading: string;
1146
1147
  switch (experience.type) {
1148
    case "experience_award":
1149
      heading = intl.formatMessage(experienceHeadings.award, {
1150
        title: experience.title,
1151
        issuedBy: experience.issued_by,
1152
      });
1153
      break;
1154
    case "experience_community":
1155
      heading = intl.formatMessage(experienceHeadings.community, {
1156
        title: experience.title,
1157
        group: experience.group,
1158
      });
1159
      break;
1160
    case "experience_education":
1161
      heading = intl.formatMessage(experienceHeadings.education, {
1162
        areaOfStudy: experience.area_of_study,
1163
        institution: experience.institution,
1164
      });
1165
      break;
1166
    case "experience_personal":
1167
      heading = intl.formatMessage(experienceHeadings.personal, {
1168
        title: experience.title,
1169
      });
1170
      break;
1171
    case "experience_work":
1172
      heading = intl.formatMessage(experienceHeadings.work, {
1173
        title: experience.title,
1174
        organization: experience.organization,
1175
      });
1176
      break;
1177
    default:
1178
      heading = intl.formatMessage(experienceHeadings.unknown);
1179
  }
1180
1181
  return heading;
1182
};
1183
1184
/**
1185
 * Returns a formatted localized subheading for the accordion on
1186
 * the Skill UI page of the Job Application. Makes use of date formatting
1187
 * to provide a range.
1188
 *
1189
 * @param experience Given Experience of multiple types defined by the user to apply to a certain Criteria.
1190
 * @param intl react-intl object used in formatting messages.
1191
 *
1192
 * @returns Formatted localized string.
1193
 */
1194
export const getExperienceSubheading = (
1195
  experience: Experience,
1196
  intl: IntlShape,
1197
): string => {
1198
  let subHeading: string;
1199
  let startDate: string;
1200
  let endDate: string;
1201
1202
  switch (experience.type) {
1203
    case "experience_award":
1204
      subHeading = intl.formatDate(experience.awarded_date, {
1205
        month: "short",
1206
        year: "numeric",
1207
      });
1208
      break;
1209
    case "experience_community":
1210
    case "experience_education":
1211
    case "experience_personal":
1212
    case "experience_work":
1213
      startDate = intl.formatDate(experience.start_date, {
1214
        month: "short",
1215
        year: "numeric",
1216
      });
1217
1218
      if (experience.end_date !== null && !experience.is_active) {
1219
        endDate = intl.formatDate(experience.end_date, {
1220
          month: "short",
1221
          year: "numeric",
1222
        });
1223
      } else {
1224
        endDate = intl.formatMessage({
1225
          id: "application.skills.currentSubheading",
1226
          defaultMessage: "Current",
1227
          description:
1228
            "Text for the end date of a current experience on the Skills page.",
1229
        });
1230
      }
1231
1232
      subHeading = `${startDate} - ${endDate}`;
1233
      break;
1234
    default:
1235
      subHeading = intl.formatMessage(experienceHeadings.unknown);
1236
  }
1237
1238
  return subHeading;
1239
};
1240
1241
const experienceJustificationLabels = defineMessages({
1242
  award: {
1243
    id: "application.skills.awardJustificationLabel",
1244
    defaultMessage: "How I used {skillName} to achieve {title}",
1245
    description: "Accordion heading for experience on the Skills page.",
1246
  },
1247
  community: {
1248
    id: "application.skills.communityJustificationLabel",
1249
    defaultMessage: "How I used {skillName} with {group}",
1250
    description: "Accordion heading for experience on the Skills page.",
1251
  },
1252
  education: {
1253
    id: "application.skills.educationJustificationLabel",
1254
    defaultMessage: "How I used {skillName} at {institution}",
1255
    description: "Accordion heading for experience on the Skills page.",
1256
  },
1257
  personal: {
1258
    id: "application.skills.personalJustificationLabel",
1259
    defaultMessage: "How I used {skillName} for {title}",
1260
    description: "Accordion heading for experience on the Skills page.",
1261
  },
1262
  work: {
1263
    id: "application.skills.workJustificationLabel",
1264
    defaultMessage: "How I used {skillName} at {organization}",
1265
    description: "Accordion heading for experience on the Skills page.",
1266
  },
1267
  unknown: {
1268
    id: "application.skills.unknownJustificationLabel",
1269
    defaultMessage: "Error: Unknown experience type.",
1270
    description:
1271
      "Accordion heading error when an unknown experience type is used.",
1272
  },
1273
});
1274
1275
/**
1276
 * Returns a formatted localized input label for the text area
1277
 * inside the experience accordion on the Skill UI page of the
1278
 * Job Application. Makes use of experienceJustificationLabels
1279
 * messages defined above.
1280
 *
1281
 * @param experience Given Experience of multiple types defined by the user to apply to a certain Criteria.
1282
 * @param intl react-intl object used in formatting messages.
1283
 *
1284
 * @returns Formatted localized string.
1285
 */
1286
export const getExperienceJustificationLabel = (
1287
  experience: Experience,
1288
  intl: IntlShape,
1289
  skillName: string,
1290
): string => {
1291
  let label: string;
1292
1293
  switch (experience.type) {
1294
    case "experience_award":
1295
      label = intl.formatMessage(experienceJustificationLabels.award, {
1296
        skillName,
1297
        title: experience.title,
1298
      });
1299
      break;
1300
    case "experience_community":
1301
      label = intl.formatMessage(experienceJustificationLabels.community, {
1302
        skillName,
1303
        group: experience.group,
1304
      });
1305
      break;
1306
    case "experience_education":
1307
      label = intl.formatMessage(experienceJustificationLabels.education, {
1308
        skillName,
1309
        institution: experience.institution,
1310
      });
1311
      break;
1312
    case "experience_personal":
1313
      label = intl.formatMessage(experienceJustificationLabels.personal, {
1314
        skillName,
1315
        title: experience.title,
1316
      });
1317
      break;
1318
    case "experience_work":
1319
      label = intl.formatMessage(experienceJustificationLabels.work, {
1320
        skillName,
1321
        organization: experience.organization,
1322
      });
1323
      break;
1324
    default:
1325
      label = intl.formatMessage(experienceHeadings.unknown);
1326
  }
1327
1328
  return label;
1329
};
1330