Passed
Push — feature/azure-webapp-pipeline-... ( f7c88d...cc7783 )
by Grant
05:46 queued 13s
created

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

Complexity

Total Complexity 11
Complexity/F 0

Size

Lines of Code 1293
Function Count 0

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

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