@ministryofjustice/hmpps-arns-frontend-components-lib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # hmpps-arns-frontend-components-lib
2
+ ARNS front-end library for risk score visualisations
@@ -0,0 +1,10 @@
1
+ import type { AuthOptions } from '@ministryofjustice/hmpps-rest-client';
2
+ import type { AuthenticationClient } from '@ministryofjustice/hmpps-auth-clients';
3
+ import type Logger from 'bunyan';
4
+ import type { ArnsComponentsConfig } from './types/ArnsComponentsConfig';
5
+ import type { RiskData } from './types/RiskData';
6
+ export default class ArnsComponents {
7
+ private readonly restClient;
8
+ constructor(authenticationClient: AuthenticationClient, config: ArnsComponentsConfig, logger?: Logger | Console);
9
+ getRiskData(authOptions: AuthOptions | string, identifierType: string, identifierValue: string): Promise<RiskData>;
10
+ }
package/dist/_all.scss ADDED
@@ -0,0 +1,5 @@
1
+ // ARNS Frontend Components Library
2
+ // Import this file into your project's main SCSS file
3
+ // Requires govuk-frontend to be imported first
4
+
5
+ @import "./arns/components/badge/predictor-badge";
@@ -0,0 +1,66 @@
1
+ $very-high-score-colour: #942514;
2
+ $very-high-score-colour--light: #ffac9f;
3
+ $very-high-score-colour__text: #711a0d;
4
+ $high-score-colour: #d4351c;
5
+ $high-score-colour--light: #f6d7d2;
6
+ $high-score-colour__text: #942514;
7
+ $medium-score-colour: #f47738;
8
+ $medium-score-colour--light: #f9e8bd;
9
+ $medium-score-colour__text: #a34e00;
10
+ $low-score-colour: #85994b;
11
+ $low-score-colour--light: #dee9bd;
12
+ $low-score-colour__text: #485b10;
13
+
14
+ @mixin predictor-badge-base($primary-colour, $secondary-colour, $text-colour) {
15
+ display: inline-flex;
16
+ outline: 2px solid $primary-colour;
17
+
18
+ & .predictor-badge__type_and_level {
19
+ @include govuk-font(19, "regular");
20
+ color: $text-colour;
21
+
22
+ padding: 2px 10px;
23
+ }
24
+
25
+ & .predictor-badge__score {
26
+ @include govuk-font(19, "bold");
27
+ color: govuk-colour("black");
28
+
29
+ background-color: $secondary-colour;
30
+ border-left: 2px solid $primary-colour;
31
+
32
+ padding: 2px 2px;
33
+ align-content: center;
34
+ }
35
+
36
+ & .predictor-badge__static_or_dynamic {
37
+ @include govuk-font(19, "regular");
38
+ color: #282D30;
39
+
40
+ background-color: #E5E6E7;
41
+ border-left: 2px solid $primary-colour;
42
+
43
+ padding: 2px 2px;
44
+ align-content: center;
45
+ }
46
+ }
47
+
48
+ .predictor-badge--very-high {
49
+ @include predictor-badge-base(
50
+ $very-high-score-colour,
51
+ $very-high-score-colour--light,
52
+ $very-high-score-colour__text
53
+ );
54
+ }
55
+
56
+ .predictor-badge--high {
57
+ @include predictor-badge-base($high-score-colour, $high-score-colour--light, $high-score-colour__text);
58
+ }
59
+
60
+ .predictor-badge--medium {
61
+ @include predictor-badge-base($medium-score-colour, $medium-score-colour--light, $medium-score-colour__text);
62
+ }
63
+
64
+ .predictor-badge--low {
65
+ @include predictor-badge-base($low-score-colour, $low-score-colour--light, $low-score-colour__text);
66
+ }
@@ -0,0 +1,25 @@
1
+ {#
2
+ ARNS Predictor Badge Component
3
+
4
+ Displays risk predictor score badges.
5
+
6
+ Usage:
7
+ In route handler:
8
+ const riskData = await arnsComponents.getRiskData(token, 'crn', 'X123456')
9
+ res.render('page', { riskData })
10
+
11
+ In template:
12
+ {% from "components/badge/macro.njk" import predictorBadge %}
13
+ {{ predictorBadge({ data: riskData }) }}
14
+
15
+ With options:
16
+ {{ predictorBadge({ data: riskData, showScore: true }) }}
17
+
18
+ @param {object} params
19
+ @param {RiskData} params.data - Risk data from ArnsComponents.getRiskData()
20
+ @param {boolean} [params.showScore=false] - Whether to display the percentage score
21
+ @param {string} [params.classes] - Additional CSS classes
22
+ #}
23
+ {% macro predictorBadge(params) %}
24
+ {%- include "./template.njk" -%}
25
+ {% endmacro %}
@@ -0,0 +1,59 @@
1
+ {#
2
+ ARNS Predictor Badge Component
3
+
4
+ Displays risk predictor score badges.
5
+
6
+ Usage:
7
+ In route handler:
8
+ const riskData = await arnsComponents.getRiskData(token, 'crn', 'X123456')
9
+ res.render('page', { riskData })
10
+
11
+ In template:
12
+ {% from "components/badge/macro.njk" import predictorBadge %}
13
+ {{ predictorBadge({ data: riskData }) }}
14
+
15
+ With options:
16
+ {{ predictorBadge({ data: riskData, showScore: true }) }}
17
+
18
+ @param {object} params
19
+ @param {RiskData} params.data - Risk data from ArnsComponents.getRiskData()
20
+ @param {boolean} [params.showScore=false] - Whether to display the percentage score
21
+ @param {string} [params.classes] - Additional CSS classes
22
+ #}
23
+
24
+ {% set badges = params.data.badges if params.data else [] %}
25
+ {% set showScore = params.showScore if params.showScore else false %}
26
+
27
+ {% if badges and badges.length %}
28
+ <div class="predictor-badges{% if params.classes %} {{ params.classes }}{% endif %}">
29
+ {% for entry in badges %}
30
+ {% for key, predictor in entry %}
31
+ {% if predictor %}
32
+ {% set badgeClass = '' %}
33
+ {% switch predictor.level %}
34
+ {% case 'VERY_HIGH' %}
35
+ {% set badgeClass = 'predictor-badge--very-high' %}
36
+ {% case 'HIGH' %}
37
+ {% set badgeClass = 'predictor-badge--high' %}
38
+ {% case 'MEDIUM' %}
39
+ {% set badgeClass = 'predictor-badge--medium' %}
40
+ {% case 'LOW' %}
41
+ {% set badgeClass = 'predictor-badge--low' %}
42
+ {% endswitch %}
43
+
44
+ <div class="{{ badgeClass }}">
45
+ <span class="predictor-badge__type_and_level">{{ predictor.type | upper }} <strong>{{ predictor.level | replace('_', ' ') }}</strong></span>
46
+
47
+ {% if showScore and predictor.score %}
48
+ <span class="predictor-badge__score">{{ predictor.score }}%</span>
49
+ {% endif %}
50
+
51
+ {% if predictor.staticOrDynamic %}
52
+ <span class="predictor-badge__static_or_dynamic">{{ predictor.staticOrDynamic | capitalize }}</span>
53
+ {% endif %}
54
+ </div>
55
+ {% endif %}
56
+ {% endfor %}
57
+ {% endfor %}
58
+ </div>
59
+ {% endif %}
@@ -0,0 +1,3 @@
1
+ import { AllPredictorVersionedDto } from '../../types/dtos/allPredictorVersionedDto';
2
+ import { BadgeEntry } from '../../types/badgeData';
3
+ export declare function transformBadgeData(dto: AllPredictorVersionedDto[]): BadgeEntry[];
@@ -0,0 +1,187 @@
1
+ 'use strict';
2
+
3
+ var hmppsRestClient = require('@ministryofjustice/hmpps-rest-client');
4
+
5
+ function transformBadgeData(dto) {
6
+ const badgeEntries = [];
7
+ dto.forEach(listEntry => {
8
+ if (listEntry.outputVersion === '1') {
9
+ const ogrs3 = listEntry.output.groupReconvictionScore;
10
+ const ovp = listEntry.output.violencePredictorScore;
11
+ const ogp = listEntry.output.generalPredictorScore;
12
+ const rsr = listEntry.output.riskOfSeriousRecidivismScore;
13
+ const osp = listEntry.output.sexualPredictorScore;
14
+ if (ogrs3) {
15
+ const entry = {
16
+ ogrs3PredictorScore: {
17
+ level: ogrs3.scoreLevel,
18
+ score: ogrs3.twoYears,
19
+ type: 'OGRS3',
20
+ staticOrDynamic: null,
21
+ completedDate: listEntry.completedDate.toString(),
22
+ },
23
+ };
24
+ badgeEntries.push(entry);
25
+ }
26
+ if (ovp) {
27
+ const entry = {
28
+ ovpPredictorScore: {
29
+ level: ovp.ovpRisk,
30
+ score: ovp.twoYears,
31
+ type: 'OVP',
32
+ staticOrDynamic: null,
33
+ completedDate: listEntry.completedDate.toString(),
34
+ },
35
+ };
36
+ badgeEntries.push(entry);
37
+ }
38
+ if (ogp) {
39
+ const entry = {
40
+ ogpPredictorScore: {
41
+ level: ogp.ogpRisk,
42
+ score: ogp.ogp2Year,
43
+ type: 'OGP',
44
+ staticOrDynamic: null,
45
+ completedDate: listEntry.completedDate.toString(),
46
+ },
47
+ };
48
+ badgeEntries.push(entry);
49
+ }
50
+ if (rsr) {
51
+ const entry = {
52
+ rsrPredictorScore: {
53
+ level: rsr.scoreLevel,
54
+ score: rsr.percentageScore,
55
+ type: 'RSR',
56
+ staticOrDynamic: rsr.staticOrDynamic,
57
+ completedDate: listEntry.completedDate.toString(),
58
+ },
59
+ };
60
+ badgeEntries.push(entry);
61
+ }
62
+ if (osp) {
63
+ const entry = {
64
+ ospdcPredictorScore: {
65
+ level: osp.ospIndecentScoreLevel,
66
+ score: osp.ospIndecentPercentageScore,
67
+ type: 'OSP/DC',
68
+ staticOrDynamic: null,
69
+ completedDate: listEntry.completedDate.toString(),
70
+ },
71
+ };
72
+ badgeEntries.push(entry);
73
+ }
74
+ if (osp) {
75
+ const entry = {
76
+ ospiicPredictorScore: {
77
+ level: osp.ospIndecentScoreLevel,
78
+ score: osp.ospIndecentPercentageScore,
79
+ type: 'OSP/IIC',
80
+ staticOrDynamic: null,
81
+ completedDate: listEntry.completedDate.toString(),
82
+ },
83
+ };
84
+ badgeEntries.push(entry);
85
+ }
86
+ }
87
+ else if (listEntry.outputVersion === '2') {
88
+ const ogrs4 = listEntry.output.allReoffendingPredictor;
89
+ const ovp2 = listEntry.output.violentReoffendingPredictor;
90
+ const snsv = listEntry.output.seriousViolentReoffendingPredictor;
91
+ const ospdc = listEntry.output.directContactSexualReoffendingPredictor;
92
+ const ospiic = listEntry.output.indirectImageContactSexualReoffendingPredictor;
93
+ const rsr = listEntry.output.combinedSeriousReoffendingPredictor;
94
+ if (ogrs4) {
95
+ const entry = {
96
+ allReoffendingPredictor: {
97
+ level: ogrs4.band,
98
+ score: ogrs4.score,
99
+ type: 'All reoffending predictor',
100
+ staticOrDynamic: ogrs4.staticOrDynamic,
101
+ completedDate: listEntry.completedDate.toString(),
102
+ },
103
+ };
104
+ badgeEntries.push(entry);
105
+ }
106
+ if (ovp2) {
107
+ const entry = {
108
+ violentReoffendingPredictor: {
109
+ level: ovp2.band,
110
+ score: ovp2.score,
111
+ type: 'Violent reoffending predictor',
112
+ staticOrDynamic: ovp2.staticOrDynamic,
113
+ completedDate: listEntry.completedDate.toString(),
114
+ },
115
+ };
116
+ badgeEntries.push(entry);
117
+ }
118
+ if (snsv) {
119
+ const entry = {
120
+ seriousViolentReoffendingPredictor: {
121
+ level: snsv.band,
122
+ score: snsv.score,
123
+ type: 'Serious violent reoffending predictor',
124
+ staticOrDynamic: snsv.staticOrDynamic,
125
+ completedDate: listEntry.completedDate.toString(),
126
+ },
127
+ };
128
+ badgeEntries.push(entry);
129
+ }
130
+ if (ospdc) {
131
+ const entry = {
132
+ directContactSexualReoffendingPredictor: {
133
+ level: ospdc.band,
134
+ score: ospdc.score,
135
+ type: 'Direct contact sexual reoffending predictor',
136
+ staticOrDynamic: null,
137
+ completedDate: listEntry.completedDate.toString(),
138
+ },
139
+ };
140
+ badgeEntries.push(entry);
141
+ }
142
+ if (ospiic) {
143
+ const entry = {
144
+ indirectImageContactSexualReoffendingPredictor: {
145
+ level: ospiic.band,
146
+ score: ospiic.score,
147
+ type: 'Indirect image contact sexual reoffending predictor',
148
+ staticOrDynamic: null,
149
+ completedDate: listEntry.completedDate.toString(),
150
+ },
151
+ };
152
+ badgeEntries.push(entry);
153
+ }
154
+ if (rsr) {
155
+ const entry = {
156
+ combinedSeriousReoffendingPredictor: {
157
+ level: rsr.band,
158
+ score: rsr.score,
159
+ type: 'Combined serious reoffending predictor',
160
+ staticOrDynamic: rsr.staticOrDynamic,
161
+ completedDate: listEntry.completedDate.toString(),
162
+ },
163
+ };
164
+ badgeEntries.push(entry);
165
+ }
166
+ }
167
+ else
168
+ throw new Error('unexpected version');
169
+ });
170
+ return badgeEntries;
171
+ }
172
+
173
+ class ArnsComponents {
174
+ constructor(authenticationClient, config, logger = console) {
175
+ this.restClient = new hmppsRestClient.RestClient('ARNS API', config, logger, authenticationClient);
176
+ }
177
+ async getRiskData(authOptions, identifierType, identifierValue) {
178
+ const response = await this.restClient.get({ path: `/risks/predictors/all/${identifierType}/${identifierValue}` }, authOptions);
179
+ return {
180
+ badges: transformBadgeData(response),
181
+ raw: response,
182
+ };
183
+ }
184
+ }
185
+
186
+ exports.ArnsComponents = ArnsComponents;
187
+ //# sourceMappingURL=index.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/components/badge/transformation.ts","../src/ArnsComponents.ts"],"sourcesContent":[null,null],"names":["RestClient"],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import { ApiConfig, AuthOptions } from '@ministryofjustice/hmpps-rest-client';
2
+ import { AuthenticationClient } from '@ministryofjustice/hmpps-auth-clients';
3
+ import Logger from 'bunyan';
4
+
5
+ interface ArnsComponentsConfig extends ApiConfig {
6
+ }
7
+
8
+ declare enum StaticOrDynamic {
9
+ STATIC = "STATIC",
10
+ DYNAMIC = "DYNAMIC"
11
+ }
12
+
13
+ declare enum BandLevel {
14
+ LOW = "LOW",
15
+ MEDIUM = "MEDIUM",
16
+ HIGH = "HIGH",
17
+ VERY_HIGH = "VERY_HIGH",
18
+ NOT_APPLICABLE = "NOT_APPLICABLE"
19
+ }
20
+
21
+ interface BadgeData {
22
+ level: `${BandLevel}`;
23
+ score: number;
24
+ type: string;
25
+ staticOrDynamic: `${StaticOrDynamic}`;
26
+ completedDate: string;
27
+ }
28
+ interface BadgeEntry {
29
+ [key: string]: BadgeData;
30
+ }
31
+
32
+ declare enum AssessmentStatusDto {
33
+ COMPLETE = "COMPLETE",
34
+ LOCKED_INCOMPLETE = "LOCKED_INCOMPLETE"
35
+ }
36
+
37
+ interface BasePredictorDto {
38
+ score: number;
39
+ band: `${BandLevel}`;
40
+ }
41
+
42
+ interface StaticOrDynamicPredictorDto extends BasePredictorDto {
43
+ staticOrDynamic: `${StaticOrDynamic}`;
44
+ }
45
+
46
+ interface VersionedStaticOrDynamicPredictorDto extends StaticOrDynamicPredictorDto {
47
+ algorithmVersion: string;
48
+ }
49
+
50
+ interface OgrScoreDto {
51
+ oneYear: number;
52
+ twoYears: number;
53
+ scoreLevel: `${BandLevel}`;
54
+ }
55
+
56
+ interface OvpScoreDto {
57
+ ovpStaticWeightedScore: number;
58
+ ovpDynamicWeightedScore: number;
59
+ ovpTotalWeightedScore: number;
60
+ oneYear: number;
61
+ twoYears: number;
62
+ ovpRisk: `${BandLevel}`;
63
+ }
64
+
65
+ interface OgpScoreDto {
66
+ ogpStaticWeightedScore: number;
67
+ ogpDynamicWeightedScore: number;
68
+ ogpTotalWeightedScore: number;
69
+ ogp1Year: number;
70
+ ogp2Year: number;
71
+ ogpRisk: `${BandLevel}`;
72
+ }
73
+
74
+ declare enum RsrScoreSourceDto {
75
+ OASYS = "OASYS"
76
+ }
77
+
78
+ interface RsrScoreDto {
79
+ percentageScore: number;
80
+ staticOrDynamic: `${StaticOrDynamic}`;
81
+ source: `${RsrScoreSourceDto}`;
82
+ algorithmVersion: string;
83
+ scoreLevel: `${BandLevel}`;
84
+ }
85
+
86
+ interface OspScoreDto {
87
+ ospIndecentPercentageScore: number;
88
+ ospContactPercentageScore: number;
89
+ ospIndecentScoreLevel: `${BandLevel}`;
90
+ ospContactScoreLevel: `${BandLevel}`;
91
+ }
92
+
93
+ interface AllPredictorDto {
94
+ allReoffendingPredictor?: StaticOrDynamicPredictorDto;
95
+ violentReoffendingPredictor?: StaticOrDynamicPredictorDto;
96
+ seriousViolentReoffendingPredictor?: StaticOrDynamicPredictorDto;
97
+ directContactSexualReoffendingPredictor?: BasePredictorDto;
98
+ indirectImageContactSexualReoffendingPredictor?: BasePredictorDto;
99
+ combinedSeriousReoffendingPredictor?: VersionedStaticOrDynamicPredictorDto;
100
+ groupReconvictionScore?: OgrScoreDto;
101
+ violencePredictorScore?: OvpScoreDto;
102
+ generalPredictorScore?: OgpScoreDto;
103
+ riskOfSeriousRecidivismScore?: RsrScoreDto;
104
+ sexualPredictorScore?: OspScoreDto;
105
+ }
106
+
107
+ interface AllPredictorVersionedDto {
108
+ completedDate: string;
109
+ status: `${AssessmentStatusDto}`;
110
+ outputVersion: string;
111
+ output?: AllPredictorDto;
112
+ }
113
+
114
+ interface RiskData {
115
+ badges: BadgeEntry[];
116
+ raw: AllPredictorVersionedDto[];
117
+ }
118
+
119
+ declare class ArnsComponents {
120
+ private readonly restClient;
121
+ constructor(authenticationClient: AuthenticationClient, config: ArnsComponentsConfig, logger?: Logger | Console);
122
+ getRiskData(authOptions: AuthOptions | string, identifierType: string, identifierValue: string): Promise<RiskData>;
123
+ }
124
+
125
+ export { ArnsComponents };
126
+ export type { ArnsComponentsConfig, BadgeData, BadgeEntry, RiskData };
@@ -0,0 +1,185 @@
1
+ import { RestClient } from '@ministryofjustice/hmpps-rest-client';
2
+
3
+ function transformBadgeData(dto) {
4
+ const badgeEntries = [];
5
+ dto.forEach(listEntry => {
6
+ if (listEntry.outputVersion === '1') {
7
+ const ogrs3 = listEntry.output.groupReconvictionScore;
8
+ const ovp = listEntry.output.violencePredictorScore;
9
+ const ogp = listEntry.output.generalPredictorScore;
10
+ const rsr = listEntry.output.riskOfSeriousRecidivismScore;
11
+ const osp = listEntry.output.sexualPredictorScore;
12
+ if (ogrs3) {
13
+ const entry = {
14
+ ogrs3PredictorScore: {
15
+ level: ogrs3.scoreLevel,
16
+ score: ogrs3.twoYears,
17
+ type: 'OGRS3',
18
+ staticOrDynamic: null,
19
+ completedDate: listEntry.completedDate.toString(),
20
+ },
21
+ };
22
+ badgeEntries.push(entry);
23
+ }
24
+ if (ovp) {
25
+ const entry = {
26
+ ovpPredictorScore: {
27
+ level: ovp.ovpRisk,
28
+ score: ovp.twoYears,
29
+ type: 'OVP',
30
+ staticOrDynamic: null,
31
+ completedDate: listEntry.completedDate.toString(),
32
+ },
33
+ };
34
+ badgeEntries.push(entry);
35
+ }
36
+ if (ogp) {
37
+ const entry = {
38
+ ogpPredictorScore: {
39
+ level: ogp.ogpRisk,
40
+ score: ogp.ogp2Year,
41
+ type: 'OGP',
42
+ staticOrDynamic: null,
43
+ completedDate: listEntry.completedDate.toString(),
44
+ },
45
+ };
46
+ badgeEntries.push(entry);
47
+ }
48
+ if (rsr) {
49
+ const entry = {
50
+ rsrPredictorScore: {
51
+ level: rsr.scoreLevel,
52
+ score: rsr.percentageScore,
53
+ type: 'RSR',
54
+ staticOrDynamic: rsr.staticOrDynamic,
55
+ completedDate: listEntry.completedDate.toString(),
56
+ },
57
+ };
58
+ badgeEntries.push(entry);
59
+ }
60
+ if (osp) {
61
+ const entry = {
62
+ ospdcPredictorScore: {
63
+ level: osp.ospIndecentScoreLevel,
64
+ score: osp.ospIndecentPercentageScore,
65
+ type: 'OSP/DC',
66
+ staticOrDynamic: null,
67
+ completedDate: listEntry.completedDate.toString(),
68
+ },
69
+ };
70
+ badgeEntries.push(entry);
71
+ }
72
+ if (osp) {
73
+ const entry = {
74
+ ospiicPredictorScore: {
75
+ level: osp.ospIndecentScoreLevel,
76
+ score: osp.ospIndecentPercentageScore,
77
+ type: 'OSP/IIC',
78
+ staticOrDynamic: null,
79
+ completedDate: listEntry.completedDate.toString(),
80
+ },
81
+ };
82
+ badgeEntries.push(entry);
83
+ }
84
+ }
85
+ else if (listEntry.outputVersion === '2') {
86
+ const ogrs4 = listEntry.output.allReoffendingPredictor;
87
+ const ovp2 = listEntry.output.violentReoffendingPredictor;
88
+ const snsv = listEntry.output.seriousViolentReoffendingPredictor;
89
+ const ospdc = listEntry.output.directContactSexualReoffendingPredictor;
90
+ const ospiic = listEntry.output.indirectImageContactSexualReoffendingPredictor;
91
+ const rsr = listEntry.output.combinedSeriousReoffendingPredictor;
92
+ if (ogrs4) {
93
+ const entry = {
94
+ allReoffendingPredictor: {
95
+ level: ogrs4.band,
96
+ score: ogrs4.score,
97
+ type: 'All reoffending predictor',
98
+ staticOrDynamic: ogrs4.staticOrDynamic,
99
+ completedDate: listEntry.completedDate.toString(),
100
+ },
101
+ };
102
+ badgeEntries.push(entry);
103
+ }
104
+ if (ovp2) {
105
+ const entry = {
106
+ violentReoffendingPredictor: {
107
+ level: ovp2.band,
108
+ score: ovp2.score,
109
+ type: 'Violent reoffending predictor',
110
+ staticOrDynamic: ovp2.staticOrDynamic,
111
+ completedDate: listEntry.completedDate.toString(),
112
+ },
113
+ };
114
+ badgeEntries.push(entry);
115
+ }
116
+ if (snsv) {
117
+ const entry = {
118
+ seriousViolentReoffendingPredictor: {
119
+ level: snsv.band,
120
+ score: snsv.score,
121
+ type: 'Serious violent reoffending predictor',
122
+ staticOrDynamic: snsv.staticOrDynamic,
123
+ completedDate: listEntry.completedDate.toString(),
124
+ },
125
+ };
126
+ badgeEntries.push(entry);
127
+ }
128
+ if (ospdc) {
129
+ const entry = {
130
+ directContactSexualReoffendingPredictor: {
131
+ level: ospdc.band,
132
+ score: ospdc.score,
133
+ type: 'Direct contact sexual reoffending predictor',
134
+ staticOrDynamic: null,
135
+ completedDate: listEntry.completedDate.toString(),
136
+ },
137
+ };
138
+ badgeEntries.push(entry);
139
+ }
140
+ if (ospiic) {
141
+ const entry = {
142
+ indirectImageContactSexualReoffendingPredictor: {
143
+ level: ospiic.band,
144
+ score: ospiic.score,
145
+ type: 'Indirect image contact sexual reoffending predictor',
146
+ staticOrDynamic: null,
147
+ completedDate: listEntry.completedDate.toString(),
148
+ },
149
+ };
150
+ badgeEntries.push(entry);
151
+ }
152
+ if (rsr) {
153
+ const entry = {
154
+ combinedSeriousReoffendingPredictor: {
155
+ level: rsr.band,
156
+ score: rsr.score,
157
+ type: 'Combined serious reoffending predictor',
158
+ staticOrDynamic: rsr.staticOrDynamic,
159
+ completedDate: listEntry.completedDate.toString(),
160
+ },
161
+ };
162
+ badgeEntries.push(entry);
163
+ }
164
+ }
165
+ else
166
+ throw new Error('unexpected version');
167
+ });
168
+ return badgeEntries;
169
+ }
170
+
171
+ class ArnsComponents {
172
+ constructor(authenticationClient, config, logger = console) {
173
+ this.restClient = new RestClient('ARNS API', config, logger, authenticationClient);
174
+ }
175
+ async getRiskData(authOptions, identifierType, identifierValue) {
176
+ const response = await this.restClient.get({ path: `/risks/predictors/all/${identifierType}/${identifierValue}` }, authOptions);
177
+ return {
178
+ badges: transformBadgeData(response),
179
+ raw: response,
180
+ };
181
+ }
182
+ }
183
+
184
+ export { ArnsComponents };
185
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/components/badge/transformation.ts","../src/ArnsComponents.ts"],"sourcesContent":[null,null],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ApiConfig } from '@ministryofjustice/hmpps-rest-client';
2
+ export interface ArnsComponentsConfig extends ApiConfig {
3
+ }
@@ -0,0 +1,6 @@
1
+ import { BadgeEntry } from './badgeData';
2
+ import { AllPredictorVersionedDto } from './dtos/allPredictorVersionedDto';
3
+ export interface RiskData {
4
+ badges: BadgeEntry[];
5
+ raw: AllPredictorVersionedDto[];
6
+ }
@@ -0,0 +1,12 @@
1
+ import { StaticOrDynamic } from './staticOrDynamic';
2
+ import { BandLevel } from './bandLevel';
3
+ export interface BadgeData {
4
+ level: `${BandLevel}`;
5
+ score: number;
6
+ type: string;
7
+ staticOrDynamic: `${StaticOrDynamic}`;
8
+ completedDate: string;
9
+ }
10
+ export interface BadgeEntry {
11
+ [key: string]: BadgeData;
12
+ }
@@ -0,0 +1,7 @@
1
+ export declare enum BandLevel {
2
+ LOW = "LOW",
3
+ MEDIUM = "MEDIUM",
4
+ HIGH = "HIGH",
5
+ VERY_HIGH = "VERY_HIGH",
6
+ NOT_APPLICABLE = "NOT_APPLICABLE"
7
+ }
@@ -0,0 +1,21 @@
1
+ import { BasePredictorDto } from './basePredictorDto';
2
+ import { StaticOrDynamicPredictorDto } from './staticOrDynamicPredictorDto';
3
+ import { VersionedStaticOrDynamicPredictorDto } from './versionedStaticOrDynamicPredictorDto';
4
+ import { OgrScoreDto } from './ogrScoreDto';
5
+ import { OvpScoreDto } from './ovpScoreDto';
6
+ import { OgpScoreDto } from './ogpScoreDto';
7
+ import { RsrScoreDto } from './rsrScoreDto';
8
+ import { OspScoreDto } from './ospScoreDto';
9
+ export interface AllPredictorDto {
10
+ allReoffendingPredictor?: StaticOrDynamicPredictorDto;
11
+ violentReoffendingPredictor?: StaticOrDynamicPredictorDto;
12
+ seriousViolentReoffendingPredictor?: StaticOrDynamicPredictorDto;
13
+ directContactSexualReoffendingPredictor?: BasePredictorDto;
14
+ indirectImageContactSexualReoffendingPredictor?: BasePredictorDto;
15
+ combinedSeriousReoffendingPredictor?: VersionedStaticOrDynamicPredictorDto;
16
+ groupReconvictionScore?: OgrScoreDto;
17
+ violencePredictorScore?: OvpScoreDto;
18
+ generalPredictorScore?: OgpScoreDto;
19
+ riskOfSeriousRecidivismScore?: RsrScoreDto;
20
+ sexualPredictorScore?: OspScoreDto;
21
+ }
@@ -0,0 +1,8 @@
1
+ import { AssessmentStatusDto } from './assessmentStatusDto';
2
+ import { AllPredictorDto } from './allPredictorDto';
3
+ export interface AllPredictorVersionedDto {
4
+ completedDate: string;
5
+ status: `${AssessmentStatusDto}`;
6
+ outputVersion: string;
7
+ output?: AllPredictorDto;
8
+ }
@@ -0,0 +1,4 @@
1
+ export declare enum AssessmentStatusDto {
2
+ COMPLETE = "COMPLETE",
3
+ LOCKED_INCOMPLETE = "LOCKED_INCOMPLETE"
4
+ }
@@ -0,0 +1,5 @@
1
+ import { BandLevel } from '../bandLevel';
2
+ export interface BasePredictorDto {
3
+ score: number;
4
+ band: `${BandLevel}`;
5
+ }
@@ -0,0 +1,9 @@
1
+ import { BandLevel } from '../bandLevel';
2
+ export interface OgpScoreDto {
3
+ ogpStaticWeightedScore: number;
4
+ ogpDynamicWeightedScore: number;
5
+ ogpTotalWeightedScore: number;
6
+ ogp1Year: number;
7
+ ogp2Year: number;
8
+ ogpRisk: `${BandLevel}`;
9
+ }
@@ -0,0 +1,6 @@
1
+ import { BandLevel } from '../bandLevel';
2
+ export interface OgrScoreDto {
3
+ oneYear: number;
4
+ twoYears: number;
5
+ scoreLevel: `${BandLevel}`;
6
+ }
@@ -0,0 +1,7 @@
1
+ import { BandLevel } from '../bandLevel';
2
+ export interface OspScoreDto {
3
+ ospIndecentPercentageScore: number;
4
+ ospContactPercentageScore: number;
5
+ ospIndecentScoreLevel: `${BandLevel}`;
6
+ ospContactScoreLevel: `${BandLevel}`;
7
+ }
@@ -0,0 +1,9 @@
1
+ import { BandLevel } from '../bandLevel';
2
+ export interface OvpScoreDto {
3
+ ovpStaticWeightedScore: number;
4
+ ovpDynamicWeightedScore: number;
5
+ ovpTotalWeightedScore: number;
6
+ oneYear: number;
7
+ twoYears: number;
8
+ ovpRisk: `${BandLevel}`;
9
+ }
@@ -0,0 +1,10 @@
1
+ import { StaticOrDynamic } from '../staticOrDynamic';
2
+ import { BandLevel } from '../bandLevel';
3
+ import { RsrScoreSourceDto } from './rsrScoreSourceDto';
4
+ export interface RsrScoreDto {
5
+ percentageScore: number;
6
+ staticOrDynamic: `${StaticOrDynamic}`;
7
+ source: `${RsrScoreSourceDto}`;
8
+ algorithmVersion: string;
9
+ scoreLevel: `${BandLevel}`;
10
+ }
@@ -0,0 +1,3 @@
1
+ export declare enum RsrScoreSourceDto {
2
+ OASYS = "OASYS"
3
+ }
@@ -0,0 +1,5 @@
1
+ import { StaticOrDynamic } from '../staticOrDynamic';
2
+ import { BasePredictorDto } from './basePredictorDto';
3
+ export interface StaticOrDynamicPredictorDto extends BasePredictorDto {
4
+ staticOrDynamic: `${StaticOrDynamic}`;
5
+ }
@@ -0,0 +1,4 @@
1
+ import { StaticOrDynamicPredictorDto } from './staticOrDynamicPredictorDto';
2
+ export interface VersionedStaticOrDynamicPredictorDto extends StaticOrDynamicPredictorDto {
3
+ algorithmVersion: string;
4
+ }
@@ -0,0 +1,4 @@
1
+ export declare enum StaticOrDynamic {
2
+ STATIC = "STATIC",
3
+ DYNAMIC = "DYNAMIC"
4
+ }
package/package.json ADDED
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "@ministryofjustice/hmpps-arns-frontend-components-lib",
3
+ "version": "0.0.1",
4
+ "description": "ARNS front-end library for risk score visualisations",
5
+ "main": "./dist/index.cjs.js",
6
+ "module": "./dist/index.esm.js",
7
+ "types": "./dist/index.d.ts",
8
+ "sass": "./dist/_all.scss",
9
+ "files": [
10
+ "dist/**/*"
11
+ ],
12
+ "scripts": {
13
+ "prepare": "hmpps-precommit-hooks-prepare",
14
+ "build": "rollup -c rollup.config.ts --bundleConfigAsCjs",
15
+ "clean": "rm -rf ./dist/ && find . -name '.eslintcache' -delete",
16
+ "test": "jest",
17
+ "test:ci": "jest --runInBand --passWithNoTests",
18
+ "typecheck": "tsc --noEmit",
19
+ "lint": "eslint . --cache --max-warnings 0",
20
+ "lint:fix": "eslint . --cache --max-warnings 0 --fix",
21
+ "security_audit": "npx audit-ci --config audit-ci.json",
22
+ "precommit:secrets": "gitleaks git --pre-commit --redact --staged --verbose --config .gitleaks/config.toml",
23
+ "precommit:lint": "node_modules/.bin/lint-staged",
24
+ "precommit:verify": "npm run typecheck",
25
+ "setup": "npm ci && hmpps-npm-script-run-allowlist"
26
+ },
27
+ "lint-staged": {
28
+ "*.{ts,css}": [
29
+ "prettier --write",
30
+ "eslint --fix"
31
+ ],
32
+ "*.json": [
33
+ "prettier --write"
34
+ ]
35
+ },
36
+ "jest": {
37
+ "transform": {
38
+ "^.+\\.tsx?$": [
39
+ "ts-jest",
40
+ {
41
+ "isolatedModules": true
42
+ }
43
+ ]
44
+ },
45
+ "testMatch": [
46
+ "<rootDir>/**/**/?(*.)(cy|test).{ts,js,jsx,mjs}"
47
+ ],
48
+ "testEnvironment": "node",
49
+ "reporters": [
50
+ "default",
51
+ [
52
+ "jest-junit",
53
+ {
54
+ "outputDirectory": "test_results/jest/"
55
+ }
56
+ ],
57
+ [
58
+ "./node_modules/jest-html-reporter",
59
+ {
60
+ "outputPath": "test_results/unit-test-reports.html"
61
+ }
62
+ ]
63
+ ],
64
+ "moduleFileExtensions": [
65
+ "web.js",
66
+ "js",
67
+ "json",
68
+ "node",
69
+ "ts"
70
+ ]
71
+ },
72
+ "repository": {
73
+ "type": "git",
74
+ "url": "git+https://github.com/ministryofjustice/hmpps-arns-frontend-components-lib.git"
75
+ },
76
+ "keywords": [],
77
+ "author": "",
78
+ "license": "ISC",
79
+ "type": "commonjs",
80
+ "bugs": {
81
+ "url": "https://github.com/ministryofjustice/hmpps-arns-frontend-components-lib/issues"
82
+ },
83
+ "homepage": "https://github.com/ministryofjustice/hmpps-arns-frontend-components-lib#readme",
84
+ "devDependencies": {
85
+ "@ministryofjustice/eslint-config-hmpps": "^1.0.2",
86
+ "@ministryofjustice/hmpps-npm-script-allowlist": "0.0.3",
87
+ "@ministryofjustice/hmpps-precommit-hooks": "^1.0.2",
88
+ "@rollup/plugin-node-resolve": "^16.0.3",
89
+ "@rollup/plugin-typescript": "^12.3.0",
90
+ "@types/bunyan": "^1.8.11",
91
+ "@types/jest": "^30.0.0",
92
+ "@types/superagent": "^8.1.9",
93
+ "@types/supertest": "^6.0.3",
94
+ "@typescript-eslint/eslint-plugin": "^8.53.1",
95
+ "cheerio": "^1.0.0",
96
+ "eslint-import-resolver-typescript": "^4.4.4",
97
+ "eslint-plugin-no-only-tests": "^3.3.0",
98
+ "express": "^5.2.1",
99
+ "govuk-frontend": "^5.14.0",
100
+ "jest": "^30.2.0",
101
+ "jest-html-reporter": "^4.3.0",
102
+ "jest-junit": "^16.0.0",
103
+ "lint-staged": "^16.1.2",
104
+ "nock": "^14.0.10",
105
+ "rollup": "^4.56.0",
106
+ "rollup-plugin-copy": "^3.5.0",
107
+ "rollup-plugin-dts": "^6.3.0",
108
+ "supertest": "^7.1.1",
109
+ "ts-jest": "^29.3.4",
110
+ "tslib": "^2.8.1",
111
+ "typescript": "^5.9.3"
112
+ },
113
+ "dependencies": {
114
+ "@ministryofjustice/hmpps-auth-clients": "^1.0.1",
115
+ "@ministryofjustice/hmpps-rest-client": "^1.0.0",
116
+ "@types/express": "^5.0.6",
117
+ "@types/node": "22.19.7",
118
+ "@types/nunjucks": "^3.2.6",
119
+ "nunjucks": "^3.2.4",
120
+ "superagent": "^10.3.0"
121
+ }
122
+ }