Passed
Push — feature/experience-step-functi... ( 08ee43...953886 )
by Tristan
04:33
created

helpers.ts ➔ applicationCategory   C

Complexity

Conditions 10

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 16
dl 0
loc 25
rs 5.9999
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like helpers.ts ➔ applicationCategory often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/* eslint-disable camelcase */
2
import { Application } from "../../models/types";
3
import { ReviewStatusId } from "../../models/lookupConstants";
4
5
type Bucket = "priority" | "citizen" | "non-citizen" | "unqualified";
6
7
type Category = "primary" | "optional" | "screened-out";
8
9
/**
10
 * Return the bucket this application belongs to. Either:
11
 *  priority
12
 *  citizen
13
 *  secondary
14
 *  unqualified
15
 *
16
 */
17
export function applicationBucket(application: Application): Bucket {
18
  if (!application.meets_essential_criteria) {
19
    if (application.citizenship_declaration.name !== "citizen") {
20
      return "non-citizen";
21
    }
22
    return "unqualified";
23
  }
24
25
  if (application.applicant.user.is_priority) {
26
    return "priority";
27
  }
28
29
  if (application.citizenship_declaration.name === "citizen") {
30
    return "citizen";
31
  }
32
33
  return "non-citizen";
34
}
35
36
/**
37
 * Return the category this application belongs to. Either:
38
 *  primary
39
 *  optional
40
 *  screened-out
41
 * @param {Application} application
42
 */
43
export function applicationCategory(application: Application): Category {
44
  if (application?.application_review?.review_status?.name === "screened_out") {
45
    return "screened-out";
46
  }
47
  if (application?.application_review?.review_status?.name === "still_in") {
48
    return "primary";
49
  }
50
  const bucket = applicationBucket(application);
51
52
  switch (bucket) {
53
    case "priority":
54
    case "citizen":
55
      return "primary";
56
    case "non-citizen":
57
    case "unqualified":
58
    default:
59
      return "optional";
60
  }
61
}
62
63
function isVet(application: Application): boolean {
64
  return application.veteran_status.name !== "none";
65
}
66
67
/**
68
 * Compare function used for sorting applications
69
 */
70
export function applicationCompare(
71
  first: Application,
72
  second: Application,
73
): number {
74
  // Sort by status in the following order:
75
  // "still_in", "Not Reviewed", "still_thinking", "screened_out",
76
  const score = (application: Application): number => {
77
    switch (
78
      application.application_review
79
        ? application.application_review.review_status_id
80
        : null
81
    ) {
82
      case ReviewStatusId.StillIn:
83
        return 1;
84
      case null:
85
        return 2;
86
      case ReviewStatusId.StillThinking:
87
        return 3;
88
      case ReviewStatusId.ScreenedOut:
89
        return 4;
90
      default:
91
        return 2; // Treat default same as "Not Reviewed"
92
    }
93
  };
94
95
  // Add a preference for veterans within each status group
96
  const scoreVet = (application: Application): number =>
97
    score(application) - (isVet(application) ? 0.1 : 0);
98
  const scoreDiff = scoreVet(first) - scoreVet(second);
99
100
  if (scoreDiff !== 0) {
101
    return scoreDiff;
102
  }
103
104
  // Otherwise, sort alphabetically by name;
105
  return first.applicant.user.last_name.localeCompare(
106
    second.applicant.user.last_name,
107
  );
108
}
109
110
/**
111
 * Compare function used for sorting applications, which prioritizes veterans over all others.
112
 */
113
export function applicationComparePrioritizeVeterans(
114
  first: Application,
115
  second: Application,
116
): number {
117
  // Veterans come before others
118
  if (isVet(first) && !isVet(second)) {
119
    return -1;
120
  }
121
  if (!isVet(first) && isVet(second)) {
122
    return 1;
123
  }
124
  return applicationCompare(first, second);
125
}
126