Skip to content

Commit 3705667

Browse files
committed
Define colorSelector for PER rating, area, benchmark
- Define types for PER rating, area, benchmark - Add union type in PieChart for colors / colorSelector
1 parent 8a8e88c commit 3705667

File tree

7 files changed

+104
-94
lines changed

7 files changed

+104
-94
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
2-
"namespace": "perAssessmentSummary",
2+
"namespace": "common",
33
"strings": {
44
"perArea": "Area {areaId}",
55
"benchmarksAssessed": "{totalQuestionCount} benchmarks assessed",
66
"perAssessmentSummaryHeading": "Summary",
7-
"benchmarksAssessedTitle": "benchmarks assessed : {allAnsweredResponses} / {totalQuestionCount}"
7+
"benchmarksAssessedTitle": "Benchmarks assessed : {allAnsweredResponses} / {totalQuestionCount}"
88
}
99
}

app/src/components/domain/PerAssessmentSummary/index.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ import {
2323
import { PartialForm } from '@togglecorp/toggle-form';
2424

2525
import {
26-
PER_FALLBACK_COLOR,
27-
perAreaColorMap,
28-
perRatingColorMap,
26+
getPerAreaColor,
27+
getPerRatingColor,
2928
} from '#utils/domain/per';
3029
import { type GoApiResponse } from '#utils/restRequest';
3130

@@ -55,10 +54,7 @@ function numberOfComponentsSelector({ components } : { components: unknown[]}) {
5554
}
5655

5756
function perRatingColorSelector({ ratingValue }: { ratingValue: number | undefined }) {
58-
if (isDefined(ratingValue)) {
59-
return perRatingColorMap[ratingValue];
60-
}
61-
return PER_FALLBACK_COLOR;
57+
return getPerRatingColor(ratingValue);
6258
}
6359

6460
function perRatingLabelSelector({
@@ -269,7 +265,7 @@ function PerAssessmentSummary(props: Props) {
269265
className={styles.filledBar}
270266
style={{
271267
height: `${getPercentage(rating.rating, averageRatingByAreaList.length)}%`,
272-
backgroundColor: perAreaColorMap[Number(rating.areaId)],
268+
backgroundColor: getPerAreaColor(Number(rating.areaId)),
273269
}}
274270
/>
275271
</div>

app/src/utils/domain/per.ts

Lines changed: 59 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -39,72 +39,84 @@ export function getCurrentPerProcessStep(status: PerProcessStatusResponse | unde
3939

4040
export function getFormattedComponentName(component: PerComponent): string {
4141
const { component_num, component_letter, title } = component;
42-
4342
const prefix = [component_num, component_letter].filter(isDefined).join(' ').trim();
44-
45-
return `${prefix} : ${title}`;
43+
return `${prefix}: ${title}`;
4644
}
4745

48-
export const perRatingColors = [
49-
'var(--go-ui-color-dark-blue-40)',
50-
'var(--go-ui-color-dark-blue-30)',
51-
'var(--go-ui-color-dark-blue-20)',
52-
'var(--go-ui-color-dark-blue-10)',
53-
'var(--go-ui-color-gray-40)',
54-
'var(--go-ui-color-gray-30)',
55-
];
56-
57-
export const perRatingColorMap: {
58-
[key: string]: string;
59-
} = {
60-
5: 'var(--go-ui-color-dark-blue-40)',
61-
4: 'var(--go-ui-color-dark-blue-30)',
62-
3: 'var(--go-ui-color-dark-blue-20)',
63-
2: 'var(--go-ui-color-dark-blue-10)',
64-
1: 'var(--go-ui-color-gray-40)',
65-
0: 'var(--go-ui-color-gray-30)',
66-
};
46+
export const PER_FALLBACK_COLOR = 'var(--go-ui-color-gray-40)';
6747

68-
export const perAreaColorMap: { [key: number]: string } = {
69-
1: 'var(--go-ui-color-purple-per)',
70-
2: 'var(--go-ui-color-orange-per)',
71-
3: 'var(--go-ui-color-blue-per)',
72-
4: 'var(--go-ui-color-teal-per)',
73-
5: 'var(--go-ui-color-red-per)',
48+
export type PerRatingValue = 0 | 1 | 2 | 3 | 4 | 5;
49+
const PER_RATING_VALUE_NOT_REVIEWED = 0 satisfies PerRatingValue;
50+
const PER_RATING_VALUE_DOES_NOT_EXIST = 1 satisfies PerRatingValue;
51+
const PER_RATING_VALUE_PARTIALLY_EXISTS = 2 satisfies PerRatingValue;
52+
const PER_RATING_VALUE_NEEDS_IMPROVEMENT = 3 satisfies PerRatingValue;
53+
const PER_RATING_VALUE_EXISTS_COULD_BE_STRENGTHENED = 4 satisfies PerRatingValue;
54+
const PER_RATING_VALUE_HIGH_PERFORMANCE = 5 satisfies PerRatingValue;
55+
56+
const perRatingColorMap: Record<PerRatingValue, string> = {
57+
[PER_RATING_VALUE_HIGH_PERFORMANCE]: 'var(--go-ui-color-dark-blue-40)',
58+
[PER_RATING_VALUE_EXISTS_COULD_BE_STRENGTHENED]: 'var(--go-ui-color-dark-blue-30)',
59+
[PER_RATING_VALUE_NEEDS_IMPROVEMENT]: 'var(--go-ui-color-dark-blue-20)',
60+
[PER_RATING_VALUE_PARTIALLY_EXISTS]: 'var(--go-ui-color-dark-blue-10)',
61+
[PER_RATING_VALUE_DOES_NOT_EXIST]: 'var(--go-ui-color-gray-40)',
62+
[PER_RATING_VALUE_NOT_REVIEWED]: 'var(--go-ui-color-gray-30)',
7463
};
7564

76-
export const perBenchmarkColorMap: {
77-
[key: string]: string;
78-
} = {
79-
1: 'var(--go-ui-color-dark-blue-40)',
80-
2: 'var(--go-ui-color-dark-blue-30)',
81-
5: 'var(--go-ui-color-dark-blue-10)',
82-
};
65+
export function getPerRatingColor(value: number | undefined) {
66+
if (isDefined(value)) {
67+
return perRatingColorMap[value as PerRatingValue] ?? PER_FALLBACK_COLOR;
68+
}
69+
return PER_FALLBACK_COLOR;
70+
}
71+
export function perRatingColorSelector(item: { value: number | undefined }) {
72+
return getPerRatingColor(item.value);
73+
}
8374

84-
export const PER_FALLBACK_COLOR = 'var(--go-ui-color-gray-40)';
75+
export type PerAreaNumber = 1 | 2 | 3 | 4 | 5;
76+
const PER_AREA_NUMBER_1 = 1 satisfies PerAreaNumber;
77+
const PER_AREA_NUMBER_2 = 2 satisfies PerAreaNumber;
78+
const PER_AREA_NUMBER_3 = 3 satisfies PerAreaNumber;
79+
const PER_AREA_NUMBER_4 = 4 satisfies PerAreaNumber;
80+
const PER_AREA_NUMBER_5 = 5 satisfies PerAreaNumber;
81+
82+
const perAreaColorMap: Record<PerAreaNumber, string> = {
83+
[PER_AREA_NUMBER_1]: 'var(--go-ui-color-purple-per)',
84+
[PER_AREA_NUMBER_2]: 'var(--go-ui-color-orange-per)',
85+
[PER_AREA_NUMBER_3]: 'var(--go-ui-color-blue-per)',
86+
[PER_AREA_NUMBER_4]: 'var(--go-ui-color-teal-per)',
87+
[PER_AREA_NUMBER_5]: 'var(--go-ui-color-red-per)',
88+
};
8589

86-
export function perRatingColorSelector(item: {
87-
value: number | undefined;
88-
}) {
89-
if (isDefined(item.value)) {
90-
return perRatingColorMap[item.value];
90+
export function getPerAreaColor(value: number | undefined) {
91+
if (isDefined(value)) {
92+
return perAreaColorMap[value as PerAreaNumber] ?? PER_FALLBACK_COLOR;
9193
}
9294
return PER_FALLBACK_COLOR;
9395
}
94-
9596
export function perAreaColorSelector(item: {
9697
value: number | undefined;
9798
}) {
98-
if (isDefined(item.value)) {
99-
return perRatingColorMap[item.value];
100-
}
101-
return PER_FALLBACK_COLOR;
99+
return getPerAreaColor(item.value);
102100
}
103101

102+
type PerBenchmarkId = 1 | 2 | 5;
103+
const PER_BENCHMARK_YES = 1 satisfies PerBenchmarkId;
104+
const PER_BENCHMARK_NO = 2 satisfies PerBenchmarkId;
105+
const PER_BENCHMARK_PARTIALLY_EXISTS = 5 satisfies PerBenchmarkId;
106+
107+
const perBenchmarkColorMap: Record<PerBenchmarkId, string> = {
108+
[PER_BENCHMARK_YES]: 'var(--go-ui-color-dark-blue-40)',
109+
[PER_BENCHMARK_NO]: 'var(--go-ui-color-dark-blue-30)',
110+
[PER_BENCHMARK_PARTIALLY_EXISTS]: 'var(--go-ui-color-dark-blue-10)',
111+
};
112+
113+
export function getPerBenchmarkColor(id: number | undefined) {
114+
return perBenchmarkColorMap[id as PerBenchmarkId] ?? PER_FALLBACK_COLOR;
115+
}
104116
export function perBenchmarkColorSelector(item: {
105117
id: number;
106118
label: string;
107119
count: number;
108120
}) {
109-
return perBenchmarkColorMap[item.id];
121+
return getPerBenchmarkColor(item.id);
110122
}

app/src/views/CountryPreparedness/PrivateCountryPreparedness/index.tsx

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,8 @@ import WikiLink from '#components/WikiLink';
5151
import useRouting from '#hooks/useRouting';
5252
import {
5353
getFormattedComponentName,
54-
PER_FALLBACK_COLOR,
55-
perAreaColorMap,
54+
getPerAreaColor,
5655
perBenchmarkColorSelector,
57-
perRatingColors,
5856
perRatingColorSelector,
5957
} from '#utils/domain/per';
6058
import {
@@ -250,9 +248,7 @@ function PrivateCountryPreparedness() {
250248
id: groupedComponentList[0].area.id,
251249
areaNum: groupedComponentList[0].area.area_num,
252250
title: groupedComponentList[0].area.title,
253-
color: isDefined(groupedComponentList[0].area.area_num)
254-
? perAreaColorMap[groupedComponentList[0].area.area_num]
255-
: PER_FALLBACK_COLOR,
251+
color: getPerAreaColor(groupedComponentList[0].area.area_num),
256252
value: getAverage(
257253
groupedComponentList.map(
258254
(component) => (
@@ -525,7 +521,6 @@ function PrivateCountryPreparedness() {
525521
labelSelector={(item) => item.title ?? '??'}
526522
keySelector={numericIdSelector}
527523
colorSelector={perRatingColorSelector}
528-
colors={perRatingColors}
529524
/>
530525
</Container>
531526
)}
@@ -604,9 +599,7 @@ function PrivateCountryPreparedness() {
604599
>
605600
{prioritizationStats.componentsToBeStrengthened.map(
606601
(priorityComponent) => {
607-
const progressBarColor = isDefined(priorityComponent.areaNumber)
608-
? perAreaColorMap[priorityComponent.areaNumber]
609-
: PER_FALLBACK_COLOR;
602+
const progressBarColor = getPerAreaColor(priorityComponent.areaNumber);
610603

611604
return (
612605
<div
@@ -651,7 +644,7 @@ function PrivateCountryPreparedness() {
651644
if (isNotDefined(perFormArea.area_num)) {
652645
return null;
653646
}
654-
const color = perAreaColorMap?.[perFormArea?.area_num];
647+
const color = getPerAreaColor(perFormArea?.area_num);
655648
return (
656649
<LegendItem
657650
key={perFormArea.id}
@@ -670,9 +663,7 @@ function PrivateCountryPreparedness() {
670663
)}
671664
>
672665
{assessmentStats.topRatedComponents.map((component) => {
673-
const progressBarColor = isDefined(component.area.area_num)
674-
? perAreaColorMap[component.area.area_num]
675-
: PER_FALLBACK_COLOR;
666+
const progressBarColor = getPerAreaColor(component.area.area_num);
676667

677668
return (
678669
<Fragment

app/src/views/CountryPreparedness/RatingByAreaChart/i18n.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"namespace": "ratingByAreaChart",
2+
"namespace": "countryPreparedness",
33
"strings": {
44
"perArea": "Area {areaNumber}: {areaTitle}"
55
}

app/src/views/PerExport/index.tsx

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ import {
3838
import ifrcLogo from '#assets/icons/ifrc-square.png';
3939
import {
4040
getFormattedComponentName,
41-
PER_FALLBACK_COLOR,
42-
perAreaColorMap,
41+
getPerAreaColor,
4342
perBenchmarkColorSelector,
44-
perRatingColors,
4543
perRatingColorSelector,
4644
} from '#utils/domain/per';
4745
import { useRequest } from '#utils/restRequest';
@@ -247,9 +245,7 @@ export function Component() {
247245
id: groupedComponentList[0].area.id,
248246
areaNum: groupedComponentList[0].area.area_num,
249247
title: groupedComponentList[0].area.title,
250-
color: isDefined(groupedComponentList[0].area.area_num)
251-
? perAreaColorMap[groupedComponentList[0].area.area_num]
252-
: PER_FALLBACK_COLOR,
248+
color: getPerAreaColor(groupedComponentList[0].area.area_num),
253249
value: getAverage(
254250
groupedComponentList.map(
255251
(component) => (
@@ -428,7 +424,6 @@ export function Component() {
428424
labelSelector={(item) => item.title ?? '??'}
429425
keySelector={numericIdSelector}
430426
colorSelector={perRatingColorSelector}
431-
colors={perRatingColors}
432427
showPercentageInLegend
433428
/>
434429
</Container>
@@ -507,9 +502,7 @@ export function Component() {
507502
headingLevel={3}
508503
>
509504
{assessmentStats.topRatedComponents.map((component) => {
510-
const progressBarColor = isDefined(component.area.area_num)
511-
? perAreaColorMap[component.area.area_num]
512-
: PER_FALLBACK_COLOR;
505+
const progressBarColor = getPerAreaColor(component.area.area_num);
513506

514507
return (
515508
<Fragment
@@ -547,7 +540,7 @@ export function Component() {
547540
return null;
548541
}
549542

550-
const color = perAreaColorMap?.[perFormArea.area_num];
543+
const color = getPerAreaColor(perFormArea.area_num);
551544
return (
552545
<LegendItem
553546
key={perFormArea.id}

packages/ui/src/components/PieChart/index.tsx

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,23 @@ function getPathData(radius: number, startAngle: number, endAngleFromParams: num
6868
return d.join(' ');
6969
}
7070

71-
export interface Props<D> {
71+
export type Props<D> = {
7272
className?: string;
7373
legendClassName?: string;
7474
data: D[] | undefined | null;
7575
valueSelector: (datum: D) => number | undefined | null;
7676
labelSelector: (datum: D) => React.ReactNode;
7777
keySelector: (datum: D) => number | string;
78-
colorSelector?: (datum: D) => string;
79-
colors: string[];
8078
pieRadius?: number;
8179
chartPadding?: number;
8280
showPercentageInLegend?: boolean;
83-
}
81+
} & ({
82+
colorSelector: (datum: D) => string;
83+
colors?: never;
84+
} | {
85+
colors: string[];
86+
colorSelector?: never;
87+
})
8488

8589
function PieChart<D>(props: Props<D>) {
8690
const {
@@ -103,7 +107,8 @@ function PieChart<D>(props: Props<D>) {
103107
const renderingData = useMemo(
104108
() => {
105109
let endAngle = 0;
106-
return data?.map((datum) => {
110+
111+
const result = data?.map((datum) => {
107112
const value = valueSelector(datum);
108113
if (isNotDefined(value)) {
109114
return undefined;
@@ -115,15 +120,28 @@ function PieChart<D>(props: Props<D>) {
115120
return {
116121
key: keySelector(datum),
117122
value,
118-
color: isDefined(colorSelector) ? colorSelector(datum) : undefined,
119123
label: labelSelector(datum),
120124
startAngle: endAngle - currentAngle,
121125
percentage: getPercentage(value, totalValueSafe),
122126
endAngle,
127+
128+
datum,
123129
};
124130
}).filter(isDefined) ?? [];
131+
132+
if (colorSelector) {
133+
return result.map(({ datum, ...other }) => ({
134+
...other,
135+
color: colorSelector(datum),
136+
}));
137+
}
138+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
139+
return result.map(({ datum, ...other }, i) => ({
140+
...other,
141+
color: colors[i % colors.length],
142+
}));
125143
},
126-
[data, keySelector, valueSelector, labelSelector, totalValueSafe, colorSelector],
144+
[data, keySelector, valueSelector, labelSelector, totalValueSafe, colorSelector, colors],
127145
);
128146

129147
return (
@@ -136,12 +154,12 @@ function PieChart<D>(props: Props<D>) {
136154
}}
137155
>
138156
<g style={{ transform: `translate(${chartPadding / 2}px, ${chartPadding / 2}px)` }}>
139-
{renderingData.map((datum, i) => (
157+
{renderingData.map((datum) => (
140158
<path
141159
key={datum.key}
142160
className={styles.path}
143161
d={getPathData(pieRadius, datum.startAngle, datum.endAngle)}
144-
fill={isDefined(datum.color) ? datum.color : colors[i % colors.length]}
162+
fill={datum.color}
145163
>
146164
<Tooltip
147165
description={(
@@ -156,7 +174,7 @@ function PieChart<D>(props: Props<D>) {
156174
</g>
157175
</svg>
158176
<div className={_cs(styles.legend, legendClassName)}>
159-
{renderingData.map((datum, i) => (
177+
{renderingData.map((datum) => (
160178
<LegendItem
161179
className={styles.legendItem}
162180
key={datum.key}
@@ -170,7 +188,7 @@ function PieChart<D>(props: Props<D>) {
170188
withoutLabelColon
171189
/>
172190
) : datum.label}
173-
color={isDefined(datum.color) ? datum.color : colors[i % colors.length]}
191+
color={datum.color}
174192
/>
175193
))}
176194
</div>

0 commit comments

Comments
 (0)